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-stable
mailing list