[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