x86: mask all LAPIC vectors early, before BSP interrupts are enabled
If APIC is left in somewhat bad state, with some source hot (not masked and active, e.g. timers after kexec or due to BIOS bug), we get the interrupt too early. Reported by: jmg Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D54543
This commit is contained in:
@@ -428,6 +428,7 @@ lapic_is_x2apic(void)
|
||||
(APICBASE_X2APIC | APICBASE_ENABLED));
|
||||
}
|
||||
|
||||
static void lapic_early_mask_vecs(void);
|
||||
static void lapic_enable(void);
|
||||
static void lapic_resume(struct pic *pic, bool suspend_cancelled);
|
||||
static void lapic_timer_oneshot(struct lapic *);
|
||||
@@ -553,6 +554,7 @@ lapic_init(vm_paddr_t addr)
|
||||
|
||||
/* Perform basic initialization of the BSP's local APIC. */
|
||||
lapic_enable();
|
||||
lapic_early_mask_vecs();
|
||||
|
||||
/* Set BSP's per-CPU local APIC ID. */
|
||||
PCPU_SET(apic_id, lapic_id());
|
||||
@@ -791,6 +793,32 @@ lapic_xapic_mode(void)
|
||||
intr_restore(saveintr);
|
||||
}
|
||||
|
||||
static void
|
||||
lapic_early_mask_vec(const struct lvt *l)
|
||||
{
|
||||
uint32_t v;
|
||||
|
||||
if (l->lvt_masked != 0) {
|
||||
v = lapic_read32(l->lvt_reg);
|
||||
v |= APIC_LVT_M;
|
||||
lapic_write32(l->lvt_reg, v);
|
||||
}
|
||||
}
|
||||
|
||||
/* Done on BSP only */
|
||||
static void
|
||||
lapic_early_mask_vecs(void)
|
||||
{
|
||||
int elvt_count, i;
|
||||
|
||||
for (i = 0; i < APIC_LVT_MAX; i++)
|
||||
lapic_early_mask_vec(&lvts[i]);
|
||||
|
||||
elvt_count = amd_read_elvt_count();
|
||||
for (i = 0; i < elvt_count; i++)
|
||||
lapic_early_mask_vec(&elvts[i]);
|
||||
}
|
||||
|
||||
void
|
||||
lapic_setup(int boot)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user