diff options
author | jhb <jhb@FreeBSD.org> | 2010-03-29 19:13:34 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2010-03-29 19:13:34 +0000 |
commit | f3f4fff664d11e6372ad59b8fc307ab0244a8f71 (patch) | |
tree | 6f6f6806b0f1caeb147f69e12a3fa672cec7b4b5 /sys/i386 | |
parent | 78907598c04661c36428e3f5b02ee6a80af4aac5 (diff) | |
download | FreeBSD-src-f3f4fff664d11e6372ad59b8fc307ab0244a8f71.zip FreeBSD-src-f3f4fff664d11e6372ad59b8fc307ab0244a8f71.tar.gz |
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
Diffstat (limited to 'sys/i386')
-rw-r--r-- | sys/i386/i386/apic_vector.s | 13 | ||||
-rw-r--r-- | sys/i386/i386/local_apic.c | 48 | ||||
-rw-r--r-- | sys/i386/include/apicvar.h | 5 |
3 files changed, 46 insertions, 20 deletions
diff --git a/sys/i386/i386/apic_vector.s b/sys/i386/i386/apic_vector.s index d4dd90b..c4c5b01 100644 --- a/sys/i386/i386/apic_vector.s +++ b/sys/i386/i386/apic_vector.s @@ -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. diff --git a/sys/i386/i386/local_apic.c b/sys/i386/i386/local_apic.c index 6c62200..302535f 100644 --- a/sys/i386/i386/local_apic.c +++ b/sys/i386/i386/local_apic.c @@ -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) { diff --git a/sys/i386/include/apicvar.h b/sys/i386/include/apicvar.h index 208ffb5..bcb84a0 100644 --- a/sys/i386/include/apicvar.h +++ b/sys/i386/include/apicvar.h @@ -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); |