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);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to