[SeaBIOS] [PATCH 3/3] Take in account hot(un)plugged cpus on reboot

Gleb Natapov gleb at redhat.com
Sun Mar 11 11:58:25 CET 2012


On Sat, Mar 10, 2012 at 12:47:28PM +0100, Igor Mammedov wrote:
> Initial count of active cpus is communicated to bios from qemu via
> CMOS_BIOS_SMP_COUNT io port. However if cpus are hotplugged after
> boot and then guest is rebooted without taking down qemu then
> bios might be stuck at smp_probe
>    while (cmos_smp_count + 1 != readl(&CountCPUs))
>       yield();
> where cmos_smp_count + 1 will be less that CountCPUs due to
> additional hotplugged cpus.
> 
> One way to fix bug is to take in account hotplugged cpus and count
> online cpus in cpu status bitmap that qemu provides at 0xaf00 and
> bios uses for ACPI cpu hotplug in acpi-dsdt.dsl.
> 
> Alternative ways to fix issue was disscussed on following thread:
>   http://www.seabios.org/pipermail/seabios/2011-August/002147.html
> without any conclusion
> 
> Rationale why counting cpus in cpu_sts bitmap at 0xaf00 might be
> better that updating CMOS_BIOS_SMP_COUNT in qemu.
>   feeble one: we are already relying on cpu_sts at 0xaf00 for ACPI
>        cpu hotplug machinery and it seems that there is no standard
>        way to pass this info (so we are now using "board extension").
>   2nd: another possible use for cpu_sts bitmap is when cpus are able
>        to be (hot)plugged in nonconsecutive order, MADT + CPON
>        package should be build taking in account info about which
>        cpus are (un)plugged.
> 
> v2 changes:
>   - access cpu_sts only if qemu advertise its support
>   - unconditionally use acpi_cpu_online_count if available to cover
>     unplug case as well
> 
Why not update cmos in qemu during cpu hot plug instead?

> Signed-off-by: Igor Mammedov <imammedo at redhat.com>
> ---
>  src/smp.c |   23 +++++++++++++++++++++++
>  1 files changed, 23 insertions(+), 0 deletions(-)
> 
> diff --git a/src/smp.c b/src/smp.c
> index 9933ac6..835b766 100644
> --- a/src/smp.c
> +++ b/src/smp.c
> @@ -17,6 +17,9 @@
>  
>  #define APIC_ENABLED 0x0100
>  
> +#define ACPI_CPU_STATUS_MAP 0xaf00
> +#define ACPI_CPU_STATUS_MAP_SZ 32
> +
>  struct { u32 ecx, eax, edx; } smp_mtrr[32] VAR16VISIBLE;
>  u32 smp_mtrr_count VAR16VISIBLE;
>  
> @@ -115,6 +118,26 @@ smp_probe(void)
>          msleep(10);
>      } else {
>          u8 cmos_smp_count = inb_cmos(CMOS_BIOS_SMP_COUNT);
> +        dprintf(1, "Powered-on with %d cpu(s)\n", cmos_smp_count + 1);
> +
> +        if (qemu_cfg_have_acpi_cpus_map()) {
> +            u8 i = 0, acpi_cpu_online_count = 0;
> +            /* count plugged in cpus in acpi PRST bitmap */
> +            while (i < ACPI_CPU_STATUS_MAP_SZ) {
> +                u8 j = 0, status = inb(ACPI_CPU_STATUS_MAP + (i++));
> +                while (j < 8)
> +                    if ((status >> j++) & 1)
> +                        ++acpi_cpu_online_count;
> +            }
> +
> +            dprintf(1, "Counted %d present cpu(s) in ACPI cpus status map\n",
> +                    acpi_cpu_online_count);
> +            /* if cpu(s) were hot(un)plugged then on reboot
> +             * we should wait for an actual cpus number, so use
> +             * acpi_cpu_online_count instead of cmos_smp_count */
> +            cmos_smp_count = acpi_cpu_online_count - 1;
> +        }
> +
>          while (cmos_smp_count + 1 != readl(&CountCPUs)) {
>              if (cmos_smp_count + 1 < readl(&CountCPUs)) {
>                  dprintf(1, "BUG: Expected %d cpu(s) but %d cpus started\n",
> -- 
> 1.7.7.6

--
			Gleb.



More information about the SeaBIOS mailing list