[SeaBIOS] [PATCH v3 3/3] support booting with more than 255 CPUs

Igor Mammedov imammedo at redhat.com
Wed Aug 10 12:59:16 CEST 2016


On Mon, 8 Aug 2016 18:42:07 -0400
"Kevin O'Connor" <kevin at koconnor.net> wrote:

> On Fri, Aug 05, 2016 at 12:47:29PM +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>
> > ---
> > v2:
> >   * merge handle_x2apic() into apic_id_init()
> > ---
> >  src/x86.h    |  1 +
> >  src/fw/smp.c | 26 +++++++++++++++++++++-----
> >  2 files changed, 22 insertions(+), 5 deletions(-)
> > 
> > diff --git a/src/x86.h b/src/x86.h
> > index 53378e9..a770e6f 100644
> > --- a/src/x86.h
> > +++ b/src/x86.h
> > @@ -68,6 +68,7 @@ static inline void wbinvd(void)
> >  #define CPUID_MSR (1 << 5)
> >  #define CPUID_APIC (1 << 9)
> >  #define CPUID_MTRR (1 << 12)
> > +#define CPUID_X2APIC (1 << 21)
> >  static inline void __cpuid(u32 index, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
> >  {
> >      asm("cpuid"
> > diff --git a/src/fw/smp.c b/src/fw/smp.c
> > index 2c5670c..352f52e 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_msr[32];
> >  static u32 smp_msr_count;
> > @@ -46,6 +49,7 @@ smp_write_msrs(void)
> >  }
> >  
> >  u32 MaxCountCPUs;
> > +static u16 boot_cpus_count;
> >  static u32 CountCPUs;
> >  // 256 bits for the found APIC IDs
> >  static u32 FoundAPICIDs[256/32];
> > @@ -58,13 +62,24 @@ int apic_id_is_present(u8 apic_id)
> >  static int
> >  apic_id_init(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);
> > +    } else if (ecx & CPUID_X2APIC) {
> > +        // switch to x2APIC mode
> > +        u64 apic_base = rdmsr(MSR_IA32_APIC_BASE);
> > +        wrmsr(MSR_IA32_APIC_BASE, apic_base | MSR_IA32_APICBASE_EXTD);
> > +        apic_id = rdmsr(MSR_LOCAL_APIC_ID);
> > +    } else {
> > +        // x2APIC is masked by CPUID
> > +        apic_id = -1;
> > +    }
> >  
> >      return apic_id;
> >  }
> > @@ -132,8 +147,7 @@ smp_scan(void)
> >      apic_id_init();
> >  
> >      // Wait for other CPUs to process the SIPI.
> > -    u8 cmos_smp_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
> > -    while (cmos_smp_count != CountCPUs)
> > +    while (boot_cpus_count != CountCPUs)
> >          asm volatile(
> >              // Release lock and allow other processors to use the stack.
> >              "  movl %%esp, %1\n"
> > @@ -164,6 +178,8 @@ smp_setup(void)
> >      if (MaxCountCPUs < cmos_smp_count)
> >          MaxCountCPUs = cmos_smp_count;
> >  
> > +    boot_cpus_count = romfile_loadint("etc/boot-cpus", cmos_smp_count);
> > +  
> 
> Wouldn't boot_cpus_count then also need to be updated in smp_resume()?
> If the user hotplugs a new cpu between system start and prior to an s3
> resume event, then the new could should be handled during that resume.
when I try to put romfile_loadint() into smp_scan(), it breaks compilation with:

ERROR: .data.varinit../src/romfile.c.13 is VARVERIFY32INIT but used from ['.text.runtime../src/resume.c.142', '.text.smp_scan', '.text.romfile_loadint', '.text.romfile_find']

I'm not sure how to fix it








More information about the SeaBIOS mailing list