Kyösti Mälkki has submitted this change. ( https://review.coreboot.org/c/coreboot/+/55262 )
Change subject: cpu/x86/lapic: Support switching to X2APIC mode ......................................................................
cpu/x86/lapic: Support switching to X2APIC mode
The options X2APIC_ONLY and X2APIC_RUNTIME were already user-visible choices in menuconfig, but the functionality was not actually provided except for platforms where FSP presumably enabled X2APIC.
Add the logic and related logging for switching to X2APIC operation.
TEST: qemu-system-x86_64 -M Q35 -accel kvm -bios coreboot.rom -serial stdio -smp 2
PARALLEL_MP, and either X2APIC_ONLY or X2APIC_RUNTIME, need to be selected for the build of emulation/qemu-q35.
Change-Id: I19a990ba287d21ccddaa64601923f1c4830e95e9 Signed-off-by: Kyösti Mälkki kyosti.malkki@gmail.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/55262 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Arthur Heymans arthur@aheymans.xyz Reviewed-by: Wonkyu Kim wonkyu.kim@intel.com --- M src/cpu/x86/lapic/lapic.c M src/cpu/x86/mp_init.c M src/include/cpu/x86/lapic.h M src/include/cpu/x86/msr.h 4 files changed, 39 insertions(+), 11 deletions(-)
Approvals: build bot (Jenkins): Verified Arthur Heymans: Looks good to me, approved Wonkyu Kim: Looks good to me, but someone else must approve
diff --git a/src/cpu/x86/lapic/lapic.c b/src/cpu/x86/lapic/lapic.c index b4d3c4d..9003534 100644 --- a/src/cpu/x86/lapic/lapic.c +++ b/src/cpu/x86/lapic/lapic.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */
+#include <assert.h> #include <cpu/cpu.h> #include <cpu/x86/lapic.h> #include <cpu/x86/lapic_def.h> @@ -10,23 +11,52 @@
void enable_lapic(void) { + uintptr_t apic_base; + bool use_x2apic; msr_t msr;
msr = rdmsr(LAPIC_BASE_MSR); - msr.hi &= 0xffffff00; - msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK; - msr.lo |= LAPIC_DEFAULT_BASE; - msr.lo |= LAPIC_BASE_MSR_ENABLE; - wrmsr(LAPIC_BASE_MSR, msr); + if (!(msr.lo & LAPIC_BASE_MSR_ENABLE)) { + msr.hi &= 0xffffff00; + msr.lo &= ~LAPIC_BASE_MSR_ADDR_MASK; + msr.lo |= LAPIC_DEFAULT_BASE; + msr.lo |= LAPIC_BASE_MSR_ENABLE; + wrmsr(LAPIC_BASE_MSR, msr); + msr = rdmsr(LAPIC_BASE_MSR); + }
- printk(BIOS_INFO, "Setting up local APIC 0x%x\n", lapicid()); + ASSERT(msr.lo & LAPIC_BASE_MSR_ENABLE); + + apic_base = msr.lo & LAPIC_BASE_MSR_ADDR_MASK; + ASSERT(apic_base == LAPIC_DEFAULT_BASE); + + if (CONFIG(XAPIC_ONLY)) { + use_x2apic = false; + } else { + use_x2apic = !!(cpu_get_feature_flags_ecx() & CPUID_X2APIC); + ASSERT(CONFIG(X2APIC_RUNTIME) || use_x2apic); + } + + if (use_x2apic == !!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE)) { + printk(BIOS_INFO, "LAPIC 0x%x in %s mode.\n", lapicid(), + use_x2apic ? "X2APIC" : "XAPIC"); + } else if (use_x2apic) { + msr.lo |= LAPIC_BASE_MSR_X2APIC_MODE; + wrmsr(LAPIC_BASE_MSR, msr); + msr = rdmsr(LAPIC_BASE_MSR); + ASSERT(!!(msr.lo & LAPIC_BASE_MSR_X2APIC_MODE)); + printk(BIOS_INFO, "LAPIC 0x%x switched to X2APIC mode.\n", lapicid()); + } else { + die("Switching from X2APIC to XAPIC mode is not implemented."); + } + }
void disable_lapic(void) { msr_t msr; msr = rdmsr(LAPIC_BASE_MSR); - msr.lo &= ~LAPIC_BASE_MSR_ENABLE; + msr.lo &= ~(LAPIC_BASE_MSR_ENABLE | LAPIC_BASE_MSR_X2APIC_MODE); wrmsr(LAPIC_BASE_MSR, msr); }
diff --git a/src/cpu/x86/mp_init.c b/src/cpu/x86/mp_init.c index 888c97f..e1979c8 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -454,9 +454,6 @@
printk(BIOS_DEBUG, "Attempting to start %d APs\n", ap_count);
- int x2apic_mode = is_x2apic_mode(); - printk(BIOS_DEBUG, "Starting CPUs in %s mode\n", x2apic_mode ? "x2apic" : "xapic"); - if (lapic_busy()) { printk(BIOS_DEBUG, "Waiting for ICR not to be busy...\n"); if (apic_wait_timeout(1000 /* 1 ms */, 50) != CB_SUCCESS) { diff --git a/src/include/cpu/x86/lapic.h b/src/include/cpu/x86/lapic.h index 537fa97..af0793b 100644 --- a/src/include/cpu/x86/lapic.h +++ b/src/include/cpu/x86/lapic.h @@ -59,7 +59,7 @@ wrmsr(X2APIC_MSR_ICR_ADDRESS, icr); }
-static inline bool is_x2apic_mode(void) +static __always_inline bool is_x2apic_mode(void) { if (CONFIG(XAPIC_ONLY)) return false; diff --git a/src/include/cpu/x86/msr.h b/src/include/cpu/x86/msr.h index a8d5e22..4d1cb68 100644 --- a/src/include/cpu/x86/msr.h +++ b/src/include/cpu/x86/msr.h @@ -24,6 +24,7 @@ #define CPUID_VMX (1 << 5) #define CPUID_SMX (1 << 6) #define CPUID_DCA (1 << 18) +#define CPUID_X2APIC (1 << 21) #define CPUID_AES (1 << 25) #define SGX_GLOBAL_ENABLE (1 << 18) #define PLATFORM_INFO_SET_TDP (1 << 29)