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.
This commit is contained in:
John Baldwin 2010-04-14 15:00:46 +00:00
parent 066adacfb1
commit 5f99d9e2ba
6 changed files with 90 additions and 40 deletions

View File

@ -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.

View File

@ -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)
{

View File

@ -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);

View File

@ -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.

View File

@ -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)
{

View File

@ -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);