Author: jhb
Date: Mon Mar 29 19:13:34 2010
New Revision: 205851
URL: http://svn.freebsd.org/changeset/base/205851

Log:
  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.
  
  MFC after:    1 week

Modified:
  head/sys/amd64/amd64/apic_vector.S
  head/sys/amd64/amd64/local_apic.c
  head/sys/amd64/include/apicvar.h
  head/sys/i386/i386/apic_vector.s
  head/sys/i386/i386/local_apic.c
  head/sys/i386/include/apicvar.h

Modified: head/sys/amd64/amd64/apic_vector.S
==============================================================================
--- head/sys/amd64/amd64/apic_vector.S  Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/amd64/amd64/apic_vector.S  Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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: head/sys/amd64/amd64/local_apic.c
==============================================================================
--- head/sys/amd64/amd64/local_apic.c   Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/amd64/amd64/local_apic.c   Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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: head/sys/amd64/include/apicvar.h
==============================================================================
--- head/sys/amd64/include/apicvar.h    Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/amd64/include/apicvar.h    Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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: head/sys/i386/i386/apic_vector.s
==============================================================================
--- head/sys/i386/i386/apic_vector.s    Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/i386/i386/apic_vector.s    Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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: head/sys/i386/i386/local_apic.c
==============================================================================
--- head/sys/i386/i386/local_apic.c     Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/i386/i386/local_apic.c     Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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: head/sys/i386/include/apicvar.h
==============================================================================
--- head/sys/i386/include/apicvar.h     Mon Mar 29 18:47:04 2010        
(r205850)
+++ head/sys/i386/include/apicvar.h     Mon Mar 29 19:13:34 2010        
(r205851)
@@ -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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to