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
This commit is contained in:
parent
78907598c0
commit
f3f4fff664
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user