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

Kevin O'Connor kevin at koconnor.net
Tue May 10 17:35:28 CEST 2016


On Tue, May 10, 2016 at 05:31:33PM +0200, Igor Mammedov wrote:
> On Tue, 10 May 2016 11:20:54 -0400
> "Kevin O'Connor" <kevin at koconnor.net> wrote:
> 
> > 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.
> sure
> 
> perhaps 's/count_cpu/apic_id_init/'

Great.  Thanks.
-Kevin



More information about the SeaBIOS mailing list