[SeaBIOS] [PATCH 3/4] support booting with more than 255 CPUs
Kevin O'Connor
kevin at koconnor.net
Tue May 10 17:20:54 CEST 2016
On Tue, May 10, 2016 at 04:43:33PM +0200, Igor Mammedov wrote:
> SDM[*1] says that if there are CPUs with APIC ID
> greater than 254, BIOS is to pass control to OS
> in x2APIC mode. Use the fact that QEMU passes in
> "etc/max-cpus" max possible "APIC ID + 1" to
> detect need for x2APIC mode. Also instead of
> CMOS_BIOS_SMP_COUNT which is limited to 256 CPUs
> use a new rom file "etc/boot-cpus" that QEMU
> supporting more than 256 CPUs will provide.
>
> *1) SDM: Volume 3: EXTENDED XAPIC (X2APIC):
> Initialization by System Software
>
> Signed-off-by: Igor Mammedov <imammedo at redhat.com>
> ---
> src/fw/smp.c | 40 ++++++++++++++++++++++++++++++++++------
> src/x86.h | 1 +
> 2 files changed, 35 insertions(+), 6 deletions(-)
>
> diff --git a/src/fw/smp.c b/src/fw/smp.c
> index ad98a5f..18a4c77 100644
> --- a/src/fw/smp.c
> +++ b/src/fw/smp.c
> @@ -19,6 +19,9 @@
> #define APIC_LINT1 ((u8*)BUILD_APIC_ADDR + 0x360)
>
> #define APIC_ENABLED 0x0100
> +#define MSR_IA32_APIC_BASE 0x01B
> +#define MSR_LOCAL_APIC_ID 0x802
> +#define MSR_IA32_APICBASE_EXTD (1ULL << 10) /* Enable x2APIC mode */
>
> static struct { u32 index; u64 val; } smp_mtrr[32];
> static u32 smp_mtrr_count;
> @@ -49,23 +52,46 @@ int apic_id_is_present(u8 apic_id)
> static int
> count_cpu(void)
> {
> + u32 apic_id;
> CountCPUs++;
>
> - // Track found apic id for use in legacy internal bios tables
> u32 eax, ebx, ecx, cpuid_features;
> cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
> - u8 apic_id = ebx>>24;
> - FoundAPICIDs[apic_id/32] |= 1 << (apic_id % 32);
> + apic_id = ebx>>24;
> + if (MaxCountCPUs < 256) { // xAPIC mode
> + // Track found apic id for use in legacy internal bios tables
> + FoundAPICIDs[apic_id/32] |= 1 << (apic_id % 32);
> + }
> + if (rdmsr(MSR_IA32_APIC_BASE) & MSR_IA32_APICBASE_EXTD) { // x2APIC mode
> + apic_id = rdmsr(MSR_LOCAL_APIC_ID);
> + }
>
> return apic_id;
> }
>
> +static void
> +handle_x2apic(void)
> +{
> + if (MaxCountCPUs < 256)
> + return;
> +
> + u32 eax, ebx, ecx, edx;
> + cpuid(1, &eax, &ebx, &ecx, &edx);
> + if (!(ecx & CPUID_X2APIC))
> + return;
> +
> + // switch to x2APIC mode
> + u64 apic_base = rdmsr(MSR_IA32_APIC_BASE);
> + wrmsr(MSR_IA32_APIC_BASE, apic_base | MSR_IA32_APICBASE_EXTD);
> +}
Can we integrate handle_x2apic() into count_cpu() as in:
static int
count_cpu(void)
{
CountCPUs++;
u32 eax, ebx, ecx, cpuid_features;
cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
if (MaxCountCPUs < 256) { // xAPIC mode
// Track found apic id for use in legacy internal bios tables
FoundAPICIDs[apic_id/32] |= 1 << (apic_id % 32);
return ebx>>24;
}
// x2APIC mode
if (!(ecx & CPUID_X2APIC))
return -1;
u64 apic_base = rdmsr(MSR_IA32_APIC_BASE);
wrmsr(MSR_IA32_APIC_BASE, apic_base | MSR_IA32_APICBASE_EXTD);
return rdmsr(MSR_LOCAL_APIC_ID);
}
count_cpu may be a poor choice of name, but if we could put all the
apic stuff in one function and call it from both handle_smp() and
smp_setup() I think it would make the code a little easier to
understand.
-Kevin
More information about the SeaBIOS
mailing list