From c8d26c01584f6a41a6a5e79924742af5d83454f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ky=C3=B6sti=20M=C3=A4lkki?= Date: Sun, 6 Jun 2021 17:07:25 +0300 Subject: cpu/x86/lapic: Support switching to X2APIC mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 Reviewed-on: https://review.coreboot.org/c/coreboot/+/55262 Tested-by: build bot (Jenkins) Reviewed-by: Arthur Heymans Reviewed-by: Wonkyu Kim --- src/cpu/x86/lapic/lapic.c | 44 +++++++++++++++++++++++++++++++++++++------- src/cpu/x86/mp_init.c | 3 --- 2 files changed, 37 insertions(+), 10 deletions(-) (limited to 'src/cpu/x86') diff --git a/src/cpu/x86/lapic/lapic.c b/src/cpu/x86/lapic/lapic.c index b4d3c4de42..9003534485 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 #include #include #include @@ -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); + } + + 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."); + } - printk(BIOS_INFO, "Setting up local APIC 0x%x\n", lapicid()); } 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 888c97fff2..e1979c81cb 100644 --- a/src/cpu/x86/mp_init.c +++ b/src/cpu/x86/mp_init.c @@ -454,9 +454,6 @@ static enum cb_err start_aps(struct bus *cpu_bus, int ap_count, atomic_t *num_ap 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) { -- cgit v1.2.3