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:
parent
066adacfb1
commit
5f99d9e2ba
@ -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