diff --git a/system/cpuid.h b/system/cpuid.h index 8bd8683..54acafc 100644 --- a/system/cpuid.h +++ b/system/cpuid.h @@ -84,7 +84,9 @@ typedef union { uint32_t smx : 1; uint32_t eist : 1; uint32_t tm2 : 1; - uint32_t : 23; // ECX feature flags, bit 31 + uint32_t : 12; // ECX feature flags, bit 20 + uint32_t x2apic : 1; + uint32_t : 10; // ECX feature flags, bit 31 uint32_t : 29; // EDX extended feature flags, bit 0 uint32_t lm : 1; uint32_t : 2; // EDX extended feature flags, bit 31 diff --git a/system/msr.h b/system/msr.h index 1e46c85..e044c74 100644 --- a/system/msr.h +++ b/system/msr.h @@ -4,7 +4,7 @@ /* * Provides access to the CPU machine-specific registers. * - * Copyright (C) 2020 Martin Whitaker. + * Copyright (C) 2020-2022 Martin Whitaker. */ #define MSR_PLATFORM_INFO 0xce @@ -12,6 +12,7 @@ #define MSR_EBC_FREQUENCY_ID 0x2c #define MSR_IA32_PLATFORM_ID 0x17 +#define MSR_IA32_APIC_BASE 0x1b #define MSR_IA32_EBL_CR_POWERON 0x2a #define MSR_IA32_MCG_CTL 0x17b #define MSR_IA32_PERF_STATUS 0x198 diff --git a/system/smp.c b/system/smp.c index 8151938..4a97dd5 100644 --- a/system/smp.c +++ b/system/smp.c @@ -21,6 +21,7 @@ #include "cpuid.h" #include "memsize.h" +#include "msr.h" #include "pmem.h" #include "string.h" #include "unistd.h" @@ -58,6 +59,11 @@ #define APIC_DELMODE_STARTUP 6 #define APIC_DELMODE_EXTINT 7 +// IA32_APIC_BASE MSR bits + +#define IA32_APIC_ENABLED (1 << 11) +#define IA32_APIC_EXTENDED (1 << 10) + // Table signatures #define FPSignature ('_' | ('M' << 8) | ('P' << 16) | ('_' << 24)) @@ -660,6 +666,15 @@ void smp_init(bool smp_enable) num_available_cpus = 1; + if (cpuid_info.flags.x2apic) { + uint32_t msrl, msrh; + rdmsr(MSR_IA32_APIC_BASE, msrl, msrh); + if ((msrl & IA32_APIC_ENABLED) && (msrl & IA32_APIC_EXTENDED)) { + // We don't currently support x2APIC mode. + smp_enable = false; + } + } + if (smp_enable) { (void)(find_cpus_in_rsdp() || find_cpus_in_floating_mp_struct());