svn commit: r206598 - in stable/8/sys: amd64/amd64 amd64/include i386/i386 i386/include

John Baldwin jhb at FreeBSD.org
Wed Apr 14 15:00:47 UTC 2010


Author: jhb
Date: Wed Apr 14 15:00:46 2010
New Revision: 206598
URL: http://svn.freebsd.org/changeset/base/206598

Log:
  MFC 205851:
  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/8/sys/amd64/amd64/apic_vector.S
  stable/8/sys/amd64/amd64/local_apic.c
  stable/8/sys/amd64/include/apicvar.h
  stable/8/sys/i386/i386/apic_vector.s
  stable/8/sys/i386/i386/local_apic.c
  stable/8/sys/i386/include/apicvar.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/amd64/amd64/apic_vector.S
==============================================================================
--- stable/8/sys/amd64/amd64/apic_vector.S	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/amd64/amd64/apic_vector.S	Wed Apr 14 15:00:46 2010	(r206598)
@@ -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/8/sys/amd64/amd64/local_apic.c
==============================================================================
--- stable/8/sys/amd64/amd64/local_apic.c	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/amd64/amd64/local_apic.c	Wed Apr 14 15:00:46 2010	(r206598)
@@ -115,14 +115,12 @@ struct lapic {
 	int la_ioint_irqs[APIC_NUM_IOINTS + 1];
 } 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 */
 };
@@ -225,7 +223,10 @@ lapic_init(vm_paddr_t addr)
 	/* Local APIC timer interrupt. */
 	setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYSIGT, SEL_KPL, 0);
 
-	/* XXX: error/thermal interrupts */
+	/* Local APIC error interrupt. */
+	setidt(APIC_ERROR_INT, IDTVEC(errorint), SDT_SYSIGT, SEL_KPL, 0);
+
+	/* XXX: Thermal interrupt */
 }
 
 /*
@@ -278,7 +279,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);
 }
@@ -326,7 +327,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 */
 
 	intr_restore(eflags);
 }
@@ -725,18 +730,6 @@ lapic_eoi(void)
 	lapic->eoi = 0;
 }
 
-/*
- * Read the contents of the error status register.  We have to write
- * to the register first before reading from it.
- */
-u_int
-lapic_error(void)
-{
-
-	lapic->esr = 0;
-	return (lapic->esr);
-}
-
 void
 lapic_handle_intr(int vector, struct trapframe *frame)
 {
@@ -863,6 +856,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();
+}
+
 u_int
 apic_cpuid(u_int apic_id)
 {

Modified: stable/8/sys/amd64/include/apicvar.h
==============================================================================
--- stable/8/sys/amd64/include/apicvar.h	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/amd64/include/apicvar.h	Wed Apr 14 15:00:46 2010	(r206598)
@@ -179,7 +179,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;
 extern int apic_cpuids[];
@@ -211,13 +212,13 @@ void	lapic_disable_pmc(void);
 void	lapic_dump(const char *str);
 int	lapic_enable_pmc(void);
 void	lapic_eoi(void);
-u_int	lapic_error(void);
 int	lapic_id(void);
 void	lapic_init(vm_paddr_t addr);
 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/8/sys/i386/i386/apic_vector.s
==============================================================================
--- stable/8/sys/i386/i386/apic_vector.s	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/i386/i386/apic_vector.s	Wed Apr 14 15:00:46 2010	(r206598)
@@ -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/8/sys/i386/i386/local_apic.c
==============================================================================
--- stable/8/sys/i386/i386/local_apic.c	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/i386/i386/local_apic.c	Wed Apr 14 15:00:46 2010	(r206598)
@@ -116,14 +116,12 @@ struct lapic {
 	int la_ioint_irqs[APIC_NUM_IOINTS + 1];
 } 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 */
 };
@@ -228,7 +226,11 @@ lapic_init(vm_paddr_t addr)
 	setidt(APIC_TIMER_INT, IDTVEC(timerint), SDT_SYS386IGT, SEL_KPL,
 	    GSEL(GCODE_SEL, SEL_KPL));
 
-	/* 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 */
 }
 
 /*
@@ -281,7 +283,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);
 }
@@ -329,7 +331,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 */
 
 	intr_restore(eflags);
 }
@@ -725,18 +731,6 @@ lapic_eoi(void)
 	lapic->eoi = 0;
 }
 
-/*
- * Read the contents of the error status register.  We have to write
- * to the register first before reading from it.
- */
-u_int
-lapic_error(void)
-{
-
-	lapic->esr = 0;
-	return (lapic->esr);
-}
-
 void
 lapic_handle_intr(int vector, struct trapframe *frame)
 {
@@ -863,6 +857,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();
+}
+
 u_int
 apic_cpuid(u_int apic_id)
 {

Modified: stable/8/sys/i386/include/apicvar.h
==============================================================================
--- stable/8/sys/i386/include/apicvar.h	Wed Apr 14 13:44:22 2010	(r206597)
+++ stable/8/sys/i386/include/apicvar.h	Wed Apr 14 15:00:46 2010	(r206598)
@@ -208,7 +208,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;
 extern int apic_cpuids[];
@@ -240,13 +241,13 @@ void	lapic_disable_pmc(void);
 void	lapic_dump(const char *str);
 int	lapic_enable_pmc(void);
 void	lapic_eoi(void);
-u_int	lapic_error(void);
 int	lapic_id(void);
 void	lapic_init(vm_paddr_t addr);
 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-stable mailing list