[SeaBIOS] [PATCH] restore MSRs on S3 resume

Paolo Bonzini pbonzini at redhat.com
Thu Jul 7 18:15:24 CEST 2016


> On Thu, Jul 07, 2016 at 04:00:40PM +0200, Paolo Bonzini wrote:
> > Currently the MTRRs and MSR_IA32_FEATURE_CONTROL are not restored on S3
> > resume.  Because these have to be applied to all processors, SMP setup
> > has to be added to S3 resume.
> > 
> > There are two differences between the boot and resume paths.  First,
> > romfile_* is not usable in the resume paths so we move the call out
> > of smp_setup and into a new function smp_boot_setup.  Second,
> > smp_msr has to be walked on the BSP as well, so we extract that
> > out of handle_smp and into a new function smp_write_msrs.  Then,
> > resume can call smp_write_msrs on the BSP followed by smp_setup to
> > initialize the APs.
> 
> In general, looks good to me.  Are you okay with the slightly modified
> patch below?  Three differences - check CONFIG_QEMU in smp_resume(),
> only modify MaxCountCPUs during the init phase, and only export
> smp_setup() and smp_resume() from smp.c.

Yes, of course.  Thanks!  Gerd, can you get this in QEMU 2.7 too?

Paolo

> BTW, this will conflict with Igor's pending series, but it doesn't
> look too invasive.
> 
> -Kevin
> 
> 
> commit 54e3a88609da074aaae2f04e592026ebf82169dc
> Author: Paolo Bonzini <pbonzini at redhat.com>
> Date:   Thu Jul 7 16:00:40 2016 +0200
> 
>     smp: restore MSRs on S3 resume
>     
>     Currently the MTRRs and MSR_IA32_FEATURE_CONTROL are not restored on S3
>     resume.  Because these have to be applied to all processors, SMP setup
>     has to be added to S3 resume.
>     
>     There are two differences between the boot and resume paths.  First,
>     romfile_* is not usable in the resume paths so we separate out the
>     remaining common code to a new smp_scan function.  Second, smp_msr has
>     to be walked on the BSP as well, so we extract that out of handle_smp
>     and into a new function smp_write_msrs.  Then, resume can call
>     smp_write_msrs on the BSP followed by smp_scan to initialize the APs.
>     
>     Reported-by: Laszlo Ersek <lersek at redhat.com>
>     Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
>     Signed-off-by: Kevin O'Connor <kevin at koconnor.net>
> 
> diff --git a/src/fw/smp.c b/src/fw/smp.c
> index 6e706e4..719d51d 100644
> --- a/src/fw/smp.c
> +++ b/src/fw/smp.c
> @@ -36,6 +36,15 @@ wrmsr_smp(u32 index, u64 val)
>      smp_msr_count++;
>  }
>  
> +static void
> +smp_write_msrs(void)
> +{
> +    // MTRR and MSR_IA32_FEATURE_CONTROL setup
> +    int i;
> +    for (i=0; i<smp_msr_count; i++)
> +        wrmsr(smp_msr[i].index, smp_msr[i].val);
> +}
> +
>  u32 MaxCountCPUs;
>  static u32 CountCPUs;
>  // 256 bits for the found APIC IDs
> @@ -58,10 +67,7 @@ handle_smp(void)
>      u8 apic_id = ebx>>24;
>      dprintf(DEBUG_HDL_smp, "handle_smp: apic_id=%d\n", apic_id);
>  
> -    // MTRR and MSR_IA32_FEATURE_CONTROL setup
> -    int i;
> -    for (i=0; i<smp_msr_count; i++)
> -        wrmsr(smp_msr[i].index, smp_msr[i].val);
> +    smp_write_msrs();
>  
>      // Set bit on FoundAPICIDs
>      FoundAPICIDs[apic_id/32] |= (1 << (apic_id % 32));
> @@ -74,12 +80,9 @@ u32 SMPLock __VISIBLE;
>  u32 SMPStack __VISIBLE;
>  
>  // find and initialize the CPUs by launching a SIPI to them
> -void
> -smp_setup(void)
> +static void
> +smp_scan(void)
>  {
> -    if (!CONFIG_QEMU)
> -        return;
> -
>      ASSERT32FLAT();
>      u32 eax, ebx, ecx, cpuid_features;
>      cpuid(1, &eax, &ebx, &ecx, &cpuid_features);
> @@ -87,7 +90,6 @@ smp_setup(void)
>          // No apic - only the main cpu is present.
>          dprintf(1, "No apic - only the main cpu is present.\n");
>          CountCPUs= 1;
> -        MaxCountCPUs = 1;
>          return;
>      }
>  
> @@ -141,10 +143,30 @@ smp_setup(void)
>      // Restore memory.
>      *(u64*)BUILD_AP_BOOT_ADDR = old;
>  
> -    MaxCountCPUs = romfile_loadint("etc/max-cpus", 0);
> -    if (!MaxCountCPUs || MaxCountCPUs < CountCPUs)
> -        MaxCountCPUs = CountCPUs;
> -
>      dprintf(1, "Found %d cpu(s) max supported %d cpu(s)\n", CountCPUs,
>              MaxCountCPUs);
>  }
> +
> +void
> +smp_setup(void)
> +{
> +    if (!CONFIG_QEMU)
> +        return;
> +
> +    MaxCountCPUs = romfile_loadint("etc/max-cpus", 0);
> +    u8 cmos_smp_count = rtc_read(CMOS_BIOS_SMP_COUNT) + 1;
> +    if (MaxCountCPUs < cmos_smp_count)
> +        MaxCountCPUs = cmos_smp_count;
> +
> +    smp_scan();
> +}
> +
> +void
> +smp_resume(void)
> +{
> +    if (!CONFIG_QEMU)
> +        return;
> +
> +    smp_write_msrs();
> +    smp_scan();
> +}
> diff --git a/src/resume.c b/src/resume.c
> index afeadcf..e67cfce 100644
> --- a/src/resume.c
> +++ b/src/resume.c
> @@ -97,6 +97,7 @@ s3_resume(void)
>  
>      pic_setup();
>      smm_setup();
> +    smp_resume();
>  
>      pci_resume();
>  
> diff --git a/src/util.h b/src/util.h
> index 7b41207..7bfd2b8 100644
> --- a/src/util.h
> +++ b/src/util.h
> @@ -135,6 +135,7 @@ void smm_setup(void);
>  extern u32 MaxCountCPUs;
>  void wrmsr_smp(u32 index, u64 val);
>  void smp_setup(void);
> +void smp_resume(void);
>  int apic_id_is_present(u8 apic_id);
>  
>  // hw/dma.c
> 



More information about the SeaBIOS mailing list