From: Laszlo Ersek <lersek@redhat.com>
To: Eduardo Habkost <ehabkost@redhat.com>, qemu-devel@nongnu.org
Cc: "Igor Mammedov" <imammedo@redhat.com>,
"Andreas Färber" <afaerber@suse.de>,
"Michael S. Tsirkin" <mst@redhat.com>
Subject: Re: [Qemu-devel] [PATCH v2 4/4] pc: Refuse max_cpus if it results in too large APIC ID
Date: Wed, 12 Mar 2014 23:07:38 +0100 [thread overview]
Message-ID: <5320DAAA.7060307@redhat.com> (raw)
In-Reply-To: <1394648890-933-5-git-send-email-ehabkost@redhat.com>
comments below
On 03/12/14 19:28, Eduardo Habkost wrote:
> This changes the PC initialization code to reject max_cpus if it results
> in an APIC ID that's too large, instead of aborting or erroring out when
> it is already too late.
>
> Currently there are two limits we need to check: the CPU hotplug APIC ID
> limit (due to the AcpiCpuHotplug.sts array length), and the
> MAX_CPUMASK_BITS limit (that's used for CPU bitmaps on NUMA code and
> hw/i386/acpi-build.c).
>
> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
> ---
> hw/i386/pc.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index 74cb4f9..50376a3 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -992,6 +992,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
> int i;
> X86CPU *cpu = NULL;
> Error *error = NULL;
> + unsigned long apic_id_limit;
Seems unnecessary, pc_apic_id_limit() returns "unsigned int".
>
> /* init CPUs */
> if (cpu_model == NULL) {
> @@ -1003,6 +1004,14 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
> }
> current_cpu_model = cpu_model;
>
> + apic_id_limit = pc_apic_id_limit(max_cpus);
OK, so keep in mind this is an exclusive limit...
> + if (apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT
... hence this comparison is correct, because ACPI_CPU_HOTPLUG_ID_LIMIT
is also an exclusive limit.
> + || apic_id_limit > MAX_CPUMASK_BITS) {
However, this check is off-by-one, because MAX_CPUMASK_BITS is an
inclusive limit. It should say (apic_id_limit > MAX_CPUMASK_BITS + 1).
(1) See the type definition AcpiCpuInfo in "hw/i386/acpi-build.c":
typedef struct AcpiCpuInfo {
DECLARE_BITMAP(found_cpus, MAX_CPUMASK_BITS + 1);
} AcpiCpuInfo;
(2) The acpi_add_cpu_info() function in the same file:
assert(apic_id <= MAX_CPUMASK_BITS);
On the other hand:
(3) numa_node_parse_cpus():
if (endvalue >= MAX_CPUMASK_BITS) {
endvalue = MAX_CPUMASK_BITS - 1;
fprintf(stderr,
"qemu: NUMA: A max of %d VCPUs are supported\n",
MAX_CPUMASK_BITS);
}
implies an exclusive limit, and:
(4) the two uses in main() also imply an exclusive limit. (Although I
honestly can't find the definition of the bitmap_new() function!)
Since you authored (3) -- in commit c881e20e --, I *think*
MAX_CPUMASK_BITS could indeed be exclusive: then your new patch is
correct, but (1) and (2) -- which seem to be ports from SeaBIOS -- are
"wrong" (as in, "too permissive").
So which is it?
... Aaaah, I understand now! (1) and (2) should actually use
ACPI_CPU_HOTPLUG_ID_LIMIT (which you are just introducing). Basically,
your patchset is completely unrelated to NUMA, the impression arises
*only* because "acpi-build.c" creatively repurposed MAX_CPUMASK_BITS. So
here goes:
- AcpiCpuInfo is already correct *numerically*:
MAX_CPUMASK_BITS == 255
MAX_CPUMASK_BITS + 1 == 256 == ACPI_CPU_HOTPLUG_ID_LIMIT
but it has nothing to do with NUMA -- it should actually use
ACPI_CPU_HOTPLUG_ID_LIMIT. Please include another patch to convert this use.
- acpi_add_cpu_info() is already correct *numerically*:
assert(apic_id <= MAX_CPUMASK_BITS);
assert(apic_id < MAX_CPUMASK_BITS + 1);
assert(apic_id < ACPI_CPU_HOTPLUG_ID_LIMIT);
but it has nothing to do with NUMA. Please convert this comparison in
the same additional patch as the AcpiCpuInfo typedef.
- numa_node_parse_cpus() is correct (MAX_CPUMASK_BITS is exclusive). No
need to care about it in this patchset though -- it's NUMA.
- The two "node_cpumask" uses in main() are correct (MAX_CPUMASK_BITS is
exclusive). No need to care about them either in this patchset.
As a result, *this* patch of yours won't mention MAX_CPUMASK_BITS at
all. A single
(apic_id_limit > ACPI_CPU_HOTPLUG_ID_LIMIT)
check will suffice, because ACPI code will use ACPI_CPU_HOTPLUG_ID_LIMIT
exclusively and uniformly, and NUMA code will use the completely
independent MAX_CPUMASK_BITS. (numa_node_parse_cpus(), which is the
function that sets bit segments in the node masks, doesn't care about
APIC IDs at all.)
> + error_report("max_cpus is too large. APIC ID of last CPU is %lu",
> + apic_id_limit - 1);
> + exit(1);
> + }
> +
If you update the type of "apic_id_limit" to "unsigned int" (I'm not
saying that you should), don't forget to update the conversion specifier
here.
> for (i = 0; i < smp_cpus; i++) {
> cpu = pc_new_cpu(cpu_model, x86_cpu_apic_id_from_index(i),
> icc_bridge, &error);
>
Thanks!
Laszlo
next prev parent reply other threads:[~2014-03-12 22:07 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-03-12 18:28 [Qemu-devel] [PATCH v2 0/4] pc: Ensure APIC ID limits before aborting or corrupting memory Eduardo Habkost
2014-03-12 18:28 ` [Qemu-devel] [PATCH v2 1/4] acpi: Add ACPI_CPU_HOTPLUG_ID_LIMIT macro Eduardo Habkost
2014-03-12 21:17 ` Laszlo Ersek
2014-03-12 21:18 ` Laszlo Ersek
2014-03-13 0:12 ` Eduardo Habkost
2014-03-13 0:29 ` Laszlo Ersek
2014-03-12 18:28 ` [Qemu-devel] [PATCH v2 2/4] pc: Refuse CPU hotplug if the resulting APIC ID is too large Eduardo Habkost
2014-03-12 21:19 ` Laszlo Ersek
2014-03-12 18:28 ` [Qemu-devel] [PATCH v2 3/4] acpi: Assert sts array limit on AcpiCpuHotplug_add() Eduardo Habkost
2014-03-12 21:19 ` Laszlo Ersek
2014-03-12 18:28 ` [Qemu-devel] [PATCH v2 4/4] pc: Refuse max_cpus if it results in too large APIC ID Eduardo Habkost
2014-03-12 22:07 ` Laszlo Ersek [this message]
2014-03-13 0:34 ` Eduardo Habkost
2014-03-12 18:58 ` [Qemu-devel] [PATCH v2 0/4] pc: Ensure APIC ID limits before aborting or corrupting memory Eduardo Habkost
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5320DAAA.7060307@redhat.com \
--to=lersek@redhat.com \
--cc=afaerber@suse.de \
--cc=ehabkost@redhat.com \
--cc=imammedo@redhat.com \
--cc=mst@redhat.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.