Force use of xAPIC to retrieve the APIC ID during TSS setup to fix an issue where an AP can switch apic_ops to point at x2apic_ops before setup_tss() completes, leading to a #GP and triple fault due to trying to read an x2APIC MSR without x2APIC being enabled. A future patch will make apic_ops a per-cpu pointer, but that's not of any help for 32-bit, which uses the APIC ID to determine the GS selector, i.e. 32-bit KUT has a chicken-and-egg problem. All setup_tss() callers ensure the local APIC is in xAPIC mode, so just force use of xAPIC in this case. Fixes: 7e33895 ("x86: Move 32-bit GDT and TSS to desc.c") Fixes: dbd3800 ("x86: Move 64-bit GDT and TSS to desc.c") Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx> --- lib/x86/apic.c | 5 +++++ lib/x86/apic.h | 2 ++ lib/x86/setup.c | 4 ++-- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/x86/apic.c b/lib/x86/apic.c index da8f3013..b404d580 100644 --- a/lib/x86/apic.c +++ b/lib/x86/apic.c @@ -48,6 +48,11 @@ static uint32_t xapic_id(void) return xapic_read(APIC_ID) >> 24; } +uint32_t pre_boot_apic_id(void) +{ + return xapic_id(); +} + static const struct apic_ops xapic_ops = { .reg_read = xapic_read, .reg_write = xapic_write, diff --git a/lib/x86/apic.h b/lib/x86/apic.h index c4821716..7844324b 100644 --- a/lib/x86/apic.h +++ b/lib/x86/apic.h @@ -53,6 +53,8 @@ bool apic_read_bit(unsigned reg, int n); void apic_write(unsigned reg, uint32_t val); void apic_icr_write(uint32_t val, uint32_t dest); uint32_t apic_id(void); +uint32_t pre_boot_apic_id(void); + int enable_x2apic(void); void disable_apic(void); diff --git a/lib/x86/setup.c b/lib/x86/setup.c index bbd34682..64217add 100644 --- a/lib/x86/setup.c +++ b/lib/x86/setup.c @@ -109,7 +109,7 @@ unsigned long setup_tss(u8 *stacktop) u32 id; tss64_t *tss_entry; - id = apic_id(); + id = pre_boot_apic_id(); /* Runtime address of current TSS */ tss_entry = &tss[id]; @@ -129,7 +129,7 @@ unsigned long setup_tss(u8 *stacktop) u32 id; tss32_t *tss_entry; - id = apic_id(); + id = pre_boot_apic_id(); /* Runtime address of current TSS */ tss_entry = &tss[id]; -- 2.35.0.rc0.227.g00780c9af4-goog