svn commit: r206599 - in stable/7/sys: amd64/amd64 amd64/include i386/i386 i386/include

John Baldwin jhb at FreeBSD.org
Wed Apr 14 15:01:49 UTC 2010


Author: jhb
Date: Wed Apr 14 15:01:49 2010
New Revision: 206599
URL: http://svn.freebsd.org/changeset/base/206599

Log:
  MFC 185933,205851:
  - Add constants for fields in the local APIC error status register.
  - Add a handler for the local APIC error interrupt.  For now it just prints
    out the current value of the local APIC error register when the interrupt
    fires.

Modified:
  stable/7/sys/amd64/amd64/apic_vector.S
  stable/7/sys/amd64/amd64/local_apic.c
  stable/7/sys/amd64/include/apicreg.h
  stable/7/sys/amd64/include/apicvar.h
  stable/7/sys/i386/i386/apic_vector.s
  stable/7/sys/i386/i386/local_apic.c
  stable/7/sys/i386/include/apicreg.h
  stable/7/sys/i386/include/apicvar.h
Directory Properties:
  stable/7/sys/   (props changed)
  stable/7/sys/cddl/contrib/opensolaris/   (props changed)
  stable/7/sys/contrib/dev/acpica/   (props changed)
  stable/7/sys/contrib/pf/   (props changed)

Modified: stable/7/sys/amd64/amd64/apic_vector.S
==============================================================================
--- stable/7/sys/amd64/amd64/apic_vector.S	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/amd64/amd64/apic_vector.S	Wed Apr 14 15:01:49 2010	(r206599)
@@ -104,6 +104,18 @@ IDTVEC(timerint)
 	MEXITCOUNT
 	jmp	doreti
 
+/*
+ * Local APIC error interrupt handler.
+ */
+	.text
+	SUPERALIGN_TEXT
+IDTVEC(errorint)
+	PUSH_FRAME
+	FAKE_MCOUNT(TF_RIP(%rsp))
+	call	lapic_handle_error
+	MEXITCOUNT
+	jmp	doreti
+
 #ifdef SMP
 /*
  * Global address space TLB shootdown.

Modified: stable/7/sys/amd64/amd64/local_apic.c
==============================================================================
--- stable/7/sys/amd64/amd64/local_apic.c	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/amd64/amd64/local_apic.c	Wed Apr 14 15:01:49 2010	(r206599)
@@ -111,14 +111,12 @@ struct lapic {
 	u_long la_prof_ticks;
 } static lapics[MAX_APIC_ID + 1];
 
-/* XXX: should thermal be an NMI? */
-
 /* Global defaults for local APIC LVT entries. */
 static struct lvt lvts[LVT_MAX + 1] = {
 	{ 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 },	/* LINT0: masked ExtINT */
 	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* LINT1: NMI */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },	/* Timer */
-	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
+	{ 1, 1, 0, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
 	{ 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },	/* Thermal */
 };
@@ -224,7 +222,10 @@ lapic_init(vm_paddr_t addr)
 	setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYSIGT, SEL_KPL, 0);
 	ioint_irqs[APIC_TIMER_INT - APIC_IO_INTS] = IRQ_TIMER;
 
-	/* XXX: error/thermal interrupts */
+	/* Local APIC error interrupt. */
+	setidt(APIC_ERROR_INT, IDTVEC(errorint), SDT_SYSIGT, SEL_KPL, 0);
+
+	/* XXX: Thermal interrupt */
 }
 
 /*
@@ -272,7 +273,7 @@ lapic_dump(const char* str)
 	    lapic->id, lapic->version, lapic->ldr, lapic->dfr);
 	printf("  lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
 	    lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr);
-	printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pcm: 0x%08x\n",
+	printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pmc: 0x%08x\n",
 	    lapic->lvt_timer, lapic->lvt_thermal, lapic->lvt_error,
 	    lapic->lvt_pcint);
 }
@@ -299,6 +300,7 @@ lapic_setup(int boot)
 	/* Program LINT[01] LVT entries. */
 	lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
 	lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
+
 	/* Program the PMC LVT entry if present. */
 	if (maxlvt >= LVT_PMC)
 		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
@@ -319,7 +321,11 @@ lapic_setup(int boot)
 		lapic_timer_enable_intr();
 	}
 
-	/* XXX: Error and thermal LVTs */
+	/* Program error LVT and clear any existing errors. */
+	lapic->lvt_error = lvt_mode(la, LVT_ERROR, lapic->lvt_error);
+	lapic->esr = 0;
+
+	/* XXX: Thermal LVT */
 
 	if (cpu_vendor_id == CPU_VENDOR_AMD) {
 		/*
@@ -846,6 +852,24 @@ lapic_timer_enable_intr(void)
 	lapic->lvt_timer = value;
 }
 
+void
+lapic_handle_error(void)
+{
+	u_int32_t esr;
+
+	/*
+	 * Read the contents of the error status register.  Write to
+	 * the register first before reading from it to force the APIC
+	 * to update its value to indicate any errors that have
+	 * occurred since the previous write to the register.
+	 */
+	lapic->esr = 0;
+	esr = lapic->esr;
+
+	printf("CPU%d: local APIC error 0x%x\n", PCPU_GET(cpuid), esr);
+	lapic_eoi();
+}
+
 /* Request a free IDT vector to be used by the specified IRQ. */
 u_int
 apic_alloc_vector(u_int irq)

Modified: stable/7/sys/amd64/include/apicreg.h
==============================================================================
--- stable/7/sys/amd64/include/apicreg.h	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/amd64/include/apicreg.h	Wed Apr 14 15:01:49 2010	(r206599)
@@ -260,6 +260,14 @@ typedef struct IOAPIC ioapic_t;
 # define APIC_TPR_INT		0x000000f0
 # define APIC_TPR_SUB		0x0000000f
 
+/* fields in ESR */
+#define	APIC_ESR_SEND_CS_ERROR		0x00000001
+#define	APIC_ESR_RECEIVE_CS_ERROR	0x00000002
+#define	APIC_ESR_SEND_ACCEPT		0x00000004
+#define	APIC_ESR_RECEIVE_ACCEPT		0x00000008
+#define	APIC_ESR_SEND_ILLEGAL_VECTOR	0x00000020
+#define	APIC_ESR_RECEIVE_ILLEGAL_VECTOR	0x00000040
+#define	APIC_ESR_ILLEGAL_REGISTER	0x00000080
 
 /* fields in ICR_LOW */
 #define APIC_VECTOR_MASK	0x000000ff

Modified: stable/7/sys/amd64/include/apicvar.h
==============================================================================
--- stable/7/sys/amd64/include/apicvar.h	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/amd64/include/apicvar.h	Wed Apr 14 15:01:49 2010	(r206599)
@@ -173,7 +173,8 @@ struct apic_enumerator {
 inthand_t
 	IDTVEC(apic_isr1), IDTVEC(apic_isr2), IDTVEC(apic_isr3),
 	IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6),
-	IDTVEC(apic_isr7), IDTVEC(spuriousint), IDTVEC(timerint);
+	IDTVEC(apic_isr7), IDTVEC(errorint), IDTVEC(spuriousint),
+	IDTVEC(timerint);
 
 extern vm_paddr_t lapic_paddr;
 
@@ -208,6 +209,7 @@ int	lapic_intr_pending(u_int vector);
 void	lapic_ipi_raw(register_t icrlo, u_int dest);
 void	lapic_ipi_vectored(u_int vector, int dest);
 int	lapic_ipi_wait(int delay);
+void	lapic_handle_error(void);
 void	lapic_handle_intr(int vector, struct trapframe *frame);
 void	lapic_handle_timer(struct trapframe *frame);
 void	lapic_reenable_pmc(void);

Modified: stable/7/sys/i386/i386/apic_vector.s
==============================================================================
--- stable/7/sys/i386/i386/apic_vector.s	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/i386/i386/apic_vector.s	Wed Apr 14 15:01:49 2010	(r206599)
@@ -110,6 +110,19 @@ IDTVEC(timerint)
 	MEXITCOUNT
 	jmp	doreti
 
+/*
+ * Local APIC error interrupt handler.
+ */
+	.text
+	SUPERALIGN_TEXT
+IDTVEC(errorint)
+	PUSH_FRAME
+	SET_KERNEL_SREGS
+	FAKE_MCOUNT(TF_EIP(%esp))
+	call	lapic_handle_error
+	MEXITCOUNT
+	jmp	doreti
+
 #ifdef SMP
 /*
  * Global address space TLB shootdown.

Modified: stable/7/sys/i386/i386/local_apic.c
==============================================================================
--- stable/7/sys/i386/i386/local_apic.c	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/i386/i386/local_apic.c	Wed Apr 14 15:01:49 2010	(r206599)
@@ -111,14 +111,12 @@ struct lapic {
 	u_long la_prof_ticks;
 } static lapics[MAX_APIC_ID + 1];
 
-/* XXX: should thermal be an NMI? */
-
 /* Global defaults for local APIC LVT entries. */
 static struct lvt lvts[LVT_MAX + 1] = {
 	{ 1, 1, 1, 1, APIC_LVT_DM_EXTINT, 0 },	/* LINT0: masked ExtINT */
 	{ 1, 1, 0, 1, APIC_LVT_DM_NMI, 0 },	/* LINT1: NMI */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_TIMER_INT },	/* Timer */
-	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
+	{ 1, 1, 0, 1, APIC_LVT_DM_FIXED, APIC_ERROR_INT },	/* Error */
 	{ 1, 1, 1, 1, APIC_LVT_DM_NMI, 0 },	/* PMC */
 	{ 1, 1, 1, 1, APIC_LVT_DM_FIXED, APIC_THERMAL_INT },	/* Thermal */
 };
@@ -226,7 +224,11 @@ lapic_init(vm_paddr_t addr)
 	    GSEL(GCODE_SEL, SEL_KPL));
 	ioint_irqs[APIC_TIMER_INT - APIC_IO_INTS] = IRQ_TIMER;
 
-	/* XXX: error/thermal interrupts */
+	/* Local APIC error interrupt. */
+	setidt(APIC_ERROR_INT, IDTVEC(errorint), SDT_SYS386IGT, SEL_KPL,
+	    GSEL(GCODE_SEL, SEL_KPL));
+
+	/* XXX: Thermal interrupt */
 }
 
 /*
@@ -274,7 +276,7 @@ lapic_dump(const char* str)
 	    lapic->id, lapic->version, lapic->ldr, lapic->dfr);
 	printf("  lint0: 0x%08x lint1: 0x%08x TPR: 0x%08x SVR: 0x%08x\n",
 	    lapic->lvt_lint0, lapic->lvt_lint1, lapic->tpr, lapic->svr);
-	printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pcm: 0x%08x\n",
+	printf("  timer: 0x%08x therm: 0x%08x err: 0x%08x pmc: 0x%08x\n",
 	    lapic->lvt_timer, lapic->lvt_thermal, lapic->lvt_error,
 	    lapic->lvt_pcint);
 }
@@ -301,6 +303,7 @@ lapic_setup(int boot)
 	/* Program LINT[01] LVT entries. */
 	lapic->lvt_lint0 = lvt_mode(la, LVT_LINT0, lapic->lvt_lint0);
 	lapic->lvt_lint1 = lvt_mode(la, LVT_LINT1, lapic->lvt_lint1);
+
 	/* Program the PMC LVT entry if present. */
 	if (maxlvt >= LVT_PMC)
 		lapic->lvt_pcint = lvt_mode(la, LVT_PMC, lapic->lvt_pcint);
@@ -321,7 +324,11 @@ lapic_setup(int boot)
 		lapic_timer_enable_intr();
 	}
 
-	/* XXX: Error and thermal LVTs */
+	/* Program error LVT and clear any existing errors. */
+	lapic->lvt_error = lvt_mode(la, LVT_ERROR, lapic->lvt_error);
+	lapic->esr = 0;
+
+	/* XXX: Thermal LVT */
 
 	if (cpu_vendor_id == CPU_VENDOR_AMD) {
 		/*
@@ -848,6 +855,24 @@ lapic_timer_enable_intr(void)
 	lapic->lvt_timer = value;
 }
 
+void
+lapic_handle_error(void)
+{
+	u_int32_t esr;
+
+	/*
+	 * Read the contents of the error status register.  Write to
+	 * the register first before reading from it to force the APIC
+	 * to update its value to indicate any errors that have
+	 * occurred since the previous write to the register.
+	 */
+	lapic->esr = 0;
+	esr = lapic->esr;
+
+	printf("CPU%d: local APIC error 0x%x\n", PCPU_GET(cpuid), esr);
+	lapic_eoi();
+}
+
 /* Request a free IDT vector to be used by the specified IRQ. */
 u_int
 apic_alloc_vector(u_int irq)

Modified: stable/7/sys/i386/include/apicreg.h
==============================================================================
--- stable/7/sys/i386/include/apicreg.h	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/i386/include/apicreg.h	Wed Apr 14 15:01:49 2010	(r206599)
@@ -260,6 +260,14 @@ typedef struct IOAPIC ioapic_t;
 # define APIC_TPR_INT		0x000000f0
 # define APIC_TPR_SUB		0x0000000f
 
+/* fields in ESR */
+#define	APIC_ESR_SEND_CS_ERROR		0x00000001
+#define	APIC_ESR_RECEIVE_CS_ERROR	0x00000002
+#define	APIC_ESR_SEND_ACCEPT		0x00000004
+#define	APIC_ESR_RECEIVE_ACCEPT		0x00000008
+#define	APIC_ESR_SEND_ILLEGAL_VECTOR	0x00000020
+#define	APIC_ESR_RECEIVE_ILLEGAL_VECTOR	0x00000040
+#define	APIC_ESR_ILLEGAL_REGISTER	0x00000080
 
 /* fields in ICR_LOW */
 #define APIC_VECTOR_MASK	0x000000ff

Modified: stable/7/sys/i386/include/apicvar.h
==============================================================================
--- stable/7/sys/i386/include/apicvar.h	Wed Apr 14 15:00:46 2010	(r206598)
+++ stable/7/sys/i386/include/apicvar.h	Wed Apr 14 15:01:49 2010	(r206599)
@@ -172,7 +172,8 @@ struct apic_enumerator {
 inthand_t
 	IDTVEC(apic_isr1), IDTVEC(apic_isr2), IDTVEC(apic_isr3),
 	IDTVEC(apic_isr4), IDTVEC(apic_isr5), IDTVEC(apic_isr6),
-	IDTVEC(apic_isr7), IDTVEC(spuriousint), IDTVEC(timerint);
+	IDTVEC(apic_isr7), IDTVEC(errorint), IDTVEC(spuriousint),
+	IDTVEC(timerint);
 
 extern vm_paddr_t lapic_paddr;
 
@@ -207,6 +208,7 @@ int	lapic_intr_pending(u_int vector);
 void	lapic_ipi_raw(register_t icrlo, u_int dest);
 void	lapic_ipi_vectored(u_int vector, int dest);
 int	lapic_ipi_wait(int delay);
+void	lapic_handle_error(void);
 void	lapic_handle_intr(int vector, struct trapframe *frame);
 void	lapic_handle_timer(struct trapframe *frame);
 void	lapic_reenable_pmc(void);


More information about the svn-src-all mailing list