[kvm-unit-tests PATCH 1/8] x86: Always use legacy xAPIC to get APIC ID during TSS setup

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux