From nobody Tue Oct 7 20:16:32 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1561688927; cv=none; d=zoho.com; s=zohoarc; b=SX0C9GHDKf+2yJZuxjpVdhYvGmyVFrXq7oI7/TvJ1lp1bvU9PM9olSbyS+kPqKSQJXF7/rC6Cba4w2GTJ2Z+1LeflQ+luSUlzP7tC/Gn8EcguJrBxE3vgwTA3WL0rVd2xirjUd1YwL4K/8JnwhRqXabrn13ruIuIHRWHVx0q14g= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zoho.com; s=zohoarc; t=1561688927; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:Message-ID:References:Sender:Subject:To:ARC-Authentication-Results; bh=ASNt4z2zUTC+tDaRAzd+3KtA1KLG/GjaDok71e/7hMk=; b=P3PwGg9bhrwrdTqPprl81H9Lt4WcvmpEP/Ux5xPxi/Yp4uLcDPPRnZZbrGkKx6mT2T+wMjW5WJeHV41ifG7GtxRmoV7+rn9irG3U1DjdctgKTx1OcTQxnKzD5qgwgcptohP2XBW+8YLkr7W38GYy/iNXjwZbqavYcp9mXULFTLI= ARC-Authentication-Results: i=1; mx.zoho.com; spf=pass (zoho.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1561688927396329.9151063735119; Thu, 27 Jun 2019 19:28:47 -0700 (PDT) Received: from localhost ([::1]:55808 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hggcy-0001iH-JM for importer@patchew.org; Thu, 27 Jun 2019 22:28:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:50220) by lists.gnu.org with esmtp (Exim 4.86_2) (envelope-from ) id 1hgg8p-00011W-QE for qemu-devel@nongnu.org; Thu, 27 Jun 2019 21:57:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1hgg8m-0001in-4E for qemu-devel@nongnu.org; Thu, 27 Jun 2019 21:57:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:41216) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1hgg8l-0001Yw-Pm for qemu-devel@nongnu.org; Thu, 27 Jun 2019 21:57:28 -0400 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.23]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 069C33082AFF; Fri, 28 Jun 2019 01:57:24 +0000 (UTC) Received: from localhost (ovpn-116-7.gru2.redhat.com [10.97.116.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 3BA8E19C70; Fri, 28 Jun 2019 01:57:23 +0000 (UTC) From: Eduardo Habkost To: Peter Maydell , qemu-devel@nongnu.org, Marcel Apfelbaum Date: Thu, 27 Jun 2019 22:56:05 -0300 Message-Id: <20190628015606.32107-29-ehabkost@redhat.com> In-Reply-To: <20190628015606.32107-1-ehabkost@redhat.com> References: <20190628015606.32107-1-ehabkost@redhat.com> X-Scanned-By: MIMEDefang 2.84 on 10.5.11.23 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.45]); Fri, 28 Jun 2019 01:57:24 +0000 (UTC) X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 209.132.183.28 Subject: [Qemu-devel] [PULL 28/29] machine: Refactor smp_parse() in vl.c as MachineClass::smp_parse() X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Paolo Bonzini , Like Xu , Richard Henderson Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: Like Xu To make smp_parse() more flexible and expansive, a smp_parse function pointer is added to MachineClass that machine types could override. The generic smp_parse() code in vl.c is moved to hw/core/machine.c, and become the default implementation of MachineClass::smp_parse. A PC-specific function called pc_smp_parse() has been added to hw/i386/pc.c, which in this patch changes nothing against the default one . Suggested-by: Eduardo Habkost Signed-off-by: Like Xu Reviewed-by: Eduardo Habkost Message-Id: <20190620054525.37188-3-like.xu@linux.intel.com> Signed-off-by: Eduardo Habkost --- include/hw/boards.h | 5 +++ include/hw/i386/pc.h | 1 + hw/core/machine.c | 76 ++++++++++++++++++++++++++++++++++++++++++ hw/i386/pc.c | 79 ++++++++++++++++++++++++++++++++++++++++++++ vl.c | 75 ++--------------------------------------- 5 files changed, 163 insertions(+), 73 deletions(-) diff --git a/include/hw/boards.h b/include/hw/boards.h index 47cba6ce6c..72b0e60176 100644 --- a/include/hw/boards.h +++ b/include/hw/boards.h @@ -161,6 +161,10 @@ typedef struct { * computed based on other criteria such as the host kernel capabilitie= s. * @numa_mem_supported: * true if '--numa node.mem' option is supported and false otherwise + * @smp_parse: + * The function pointer to hook different machine specific functions for + * parsing "smp-opts" from QemuOpts to MachineState::CpuTopology and mo= re + * machine specific topology fields, such as smp_dies for PCMachine. */ struct MachineClass { /*< private >*/ @@ -177,6 +181,7 @@ struct MachineClass { void (*reset)(MachineState *state); void (*hot_add_cpu)(MachineState *state, const int64_t id, Error **err= p); int (*kvm_type)(MachineState *machine, const char *arg); + void (*smp_parse)(MachineState *ms, QemuOpts *opts); =20 BlockInterfaceType block_default_type; int units_per_default_bus; diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index 764996e6b4..ee79d71ccc 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -189,6 +189,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int l= evel); =20 void pc_cpus_init(PCMachineState *pcms); void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp); +void pc_smp_parse(MachineState *ms, QemuOpts *opts); =20 void pc_guest_info_init(PCMachineState *pcms); =20 diff --git a/hw/core/machine.c b/hw/core/machine.c index 7a44adab39..4be0599e82 100644 --- a/hw/core/machine.c +++ b/hw/core/machine.c @@ -11,6 +11,9 @@ */ =20 #include "qemu/osdep.h" +#include "qemu/option.h" +#include "qapi/qmp/qerror.h" +#include "sysemu/replay.h" #include "qemu/units.h" #include "hw/boards.h" #include "qapi/error.h" @@ -725,6 +728,78 @@ void machine_set_cpu_numa_node(MachineState *machine, } } =20 +static void smp_parse(MachineState *ms, QemuOpts *opts) +{ + if (opts) { + unsigned cpus =3D qemu_opt_get_number(opts, "cpus", 0); + unsigned sockets =3D qemu_opt_get_number(opts, "sockets", 0); + unsigned cores =3D qemu_opt_get_number(opts, "cores", 0); + unsigned threads =3D qemu_opt_get_number(opts, "threads", 0); + + /* compute missing values, prefer sockets over cores over threads = */ + if (cpus =3D=3D 0 || sockets =3D=3D 0) { + cores =3D cores > 0 ? cores : 1; + threads =3D threads > 0 ? threads : 1; + if (cpus =3D=3D 0) { + sockets =3D sockets > 0 ? sockets : 1; + cpus =3D cores * threads * sockets; + } else { + ms->smp.max_cpus =3D + qemu_opt_get_number(opts, "maxcpus", cpus); + sockets =3D ms->smp.max_cpus / (cores * threads); + } + } else if (cores =3D=3D 0) { + threads =3D threads > 0 ? threads : 1; + cores =3D cpus / (sockets * threads); + cores =3D cores > 0 ? cores : 1; + } else if (threads =3D=3D 0) { + threads =3D cpus / (cores * sockets); + threads =3D threads > 0 ? threads : 1; + } else if (sockets * cores * threads < cpus) { + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) < " + "smp_cpus (%u)", + sockets, cores, threads, cpus); + exit(1); + } + + ms->smp.max_cpus =3D + qemu_opt_get_number(opts, "maxcpus", cpus); + + if (ms->smp.max_cpus < cpus) { + error_report("maxcpus must be equal to or greater than smp"); + exit(1); + } + + if (sockets * cores * threads > ms->smp.max_cpus) { + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) > " + "maxcpus (%u)", + sockets, cores, threads, + ms->smp.max_cpus); + exit(1); + } + + if (sockets * cores * threads !=3D ms->smp.max_cpus) { + warn_report("Invalid CPU topology deprecated: " + "sockets (%u) * cores (%u) * threads (%u) " + "!=3D maxcpus (%u)", + sockets, cores, threads, + ms->smp.max_cpus); + } + + ms->smp.cpus =3D cpus; + ms->smp.cores =3D cores; + ms->smp.threads =3D threads; + } + + if (ms->smp.cpus > 1) { + Error *blocker =3D NULL; + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); + replay_add_blocker(blocker); + } +} + static void machine_class_init(ObjectClass *oc, void *data) { MachineClass *mc =3D MACHINE_CLASS(oc); @@ -732,6 +807,7 @@ static void machine_class_init(ObjectClass *oc, void *d= ata) /* Default 128 MB as guest ram size */ mc->default_ram_size =3D 128 * MiB; mc->rom_file_has_mr =3D true; + mc->smp_parse =3D smp_parse; =20 /* numa node memory size aligned on 8MB by default. * On Linux, each node's border has to be 8MB aligned diff --git a/hw/i386/pc.c b/hw/i386/pc.c index 114fd5f8d4..b9c25bed35 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -79,6 +79,8 @@ #include "hw/i386/intel_iommu.h" #include "hw/net/ne2000-isa.h" #include "standard-headers/asm-x86/bootparam.h" +#include "sysemu/replay.h" +#include "qapi/qmp/qerror.h" =20 /* debug PC/ISA interrupts */ //#define DEBUG_IRQ @@ -1537,6 +1539,82 @@ static void pc_new_cpu(PCMachineState *pcms, int64_t= apic_id, Error **errp) error_propagate(errp, local_err); } =20 +/* + * This function is very similar to smp_parse() + * in hw/core/machine.c but includes CPU die support. + */ +void pc_smp_parse(MachineState *ms, QemuOpts *opts) +{ + if (opts) { + unsigned cpus =3D qemu_opt_get_number(opts, "cpus", 0); + unsigned sockets =3D qemu_opt_get_number(opts, "sockets", 0); + unsigned cores =3D qemu_opt_get_number(opts, "cores", 0); + unsigned threads =3D qemu_opt_get_number(opts, "threads", 0); + + /* compute missing values, prefer sockets over cores over threads = */ + if (cpus =3D=3D 0 || sockets =3D=3D 0) { + cores =3D cores > 0 ? cores : 1; + threads =3D threads > 0 ? threads : 1; + if (cpus =3D=3D 0) { + sockets =3D sockets > 0 ? sockets : 1; + cpus =3D cores * threads * sockets; + } else { + ms->smp.max_cpus =3D + qemu_opt_get_number(opts, "maxcpus", cpus); + sockets =3D ms->smp.max_cpus / (cores * threads); + } + } else if (cores =3D=3D 0) { + threads =3D threads > 0 ? threads : 1; + cores =3D cpus / (sockets * threads); + cores =3D cores > 0 ? cores : 1; + } else if (threads =3D=3D 0) { + threads =3D cpus / (cores * sockets); + threads =3D threads > 0 ? threads : 1; + } else if (sockets * cores * threads < cpus) { + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) < " + "smp_cpus (%u)", + sockets, cores, threads, cpus); + exit(1); + } + + ms->smp.max_cpus =3D + qemu_opt_get_number(opts, "maxcpus", cpus); + + if (ms->smp.max_cpus < cpus) { + error_report("maxcpus must be equal to or greater than smp"); + exit(1); + } + + if (sockets * cores * threads > ms->smp.max_cpus) { + error_report("cpu topology: " + "sockets (%u) * cores (%u) * threads (%u) > " + "maxcpus (%u)", + sockets, cores, threads, + ms->smp.max_cpus); + exit(1); + } + + if (sockets * cores * threads !=3D ms->smp.max_cpus) { + warn_report("Invalid CPU topology deprecated: " + "sockets (%u) * cores (%u) * threads (%u) " + "!=3D maxcpus (%u)", + sockets, cores, threads, + ms->smp.max_cpus); + } + + ms->smp.cpus =3D cpus; + ms->smp.cores =3D cores; + ms->smp.threads =3D threads; + } + + if (ms->smp.cpus > 1) { + Error *blocker =3D NULL; + error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); + replay_add_blocker(blocker); + } +} + void pc_hot_add_cpu(MachineState *ms, const int64_t id, Error **errp) { int64_t apic_id =3D x86_cpu_apic_id_from_index(ms, id); @@ -2782,6 +2860,7 @@ static void pc_machine_class_init(ObjectClass *oc, vo= id *data) mc->has_hotpluggable_cpus =3D true; mc->default_boot_order =3D "cad"; mc->hot_add_cpu =3D pc_hot_add_cpu; + mc->smp_parse =3D pc_smp_parse; mc->block_default_type =3D IF_IDE; mc->max_cpus =3D 255; mc->reset =3D pc_machine_reset; diff --git a/vl.c b/vl.c index 1729410e92..f6e591b80c 100644 --- a/vl.c +++ b/vl.c @@ -1247,78 +1247,6 @@ static QemuOptsList qemu_smp_opts =3D { }, }; =20 -static void smp_parse(QemuOpts *opts) -{ - if (opts) { - unsigned cpus =3D qemu_opt_get_number(opts, "cpus", 0); - unsigned sockets =3D qemu_opt_get_number(opts, "sockets", 0); - unsigned cores =3D qemu_opt_get_number(opts, "cores", 0); - unsigned threads =3D qemu_opt_get_number(opts, "threads", 0); - - /* compute missing values, prefer sockets over cores over threads = */ - if (cpus =3D=3D 0 || sockets =3D=3D 0) { - cores =3D cores > 0 ? cores : 1; - threads =3D threads > 0 ? threads : 1; - if (cpus =3D=3D 0) { - sockets =3D sockets > 0 ? sockets : 1; - cpus =3D cores * threads * sockets; - } else { - current_machine->smp.max_cpus =3D - qemu_opt_get_number(opts, "maxcpus", cpus); - sockets =3D current_machine->smp.max_cpus / (cores * threa= ds); - } - } else if (cores =3D=3D 0) { - threads =3D threads > 0 ? threads : 1; - cores =3D cpus / (sockets * threads); - cores =3D cores > 0 ? cores : 1; - } else if (threads =3D=3D 0) { - threads =3D cpus / (cores * sockets); - threads =3D threads > 0 ? threads : 1; - } else if (sockets * cores * threads < cpus) { - error_report("cpu topology: " - "sockets (%u) * cores (%u) * threads (%u) < " - "smp_cpus (%u)", - sockets, cores, threads, cpus); - exit(1); - } - - current_machine->smp.max_cpus =3D - qemu_opt_get_number(opts, "maxcpus", cpus); - - if (current_machine->smp.max_cpus < cpus) { - error_report("maxcpus must be equal to or greater than smp"); - exit(1); - } - - if (sockets * cores * threads > current_machine->smp.max_cpus) { - error_report("cpu topology: " - "sockets (%u) * cores (%u) * threads (%u) > " - "maxcpus (%u)", - sockets, cores, threads, - current_machine->smp.max_cpus); - exit(1); - } - - if (sockets * cores * threads !=3D current_machine->smp.max_cpus) { - warn_report("Invalid CPU topology deprecated: " - "sockets (%u) * cores (%u) * threads (%u) " - "!=3D maxcpus (%u)", - sockets, cores, threads, - current_machine->smp.max_cpus); - } - - current_machine->smp.cpus =3D cpus; - current_machine->smp.cores =3D cores; - current_machine->smp.threads =3D threads; - } - - if (current_machine->smp.cpus > 1) { - Error *blocker =3D NULL; - error_setg(&blocker, QERR_REPLAY_NOT_SUPPORTED, "smp"); - replay_add_blocker(blocker); - } -} - static void realtime_init(void) { if (enable_mlock) { @@ -4060,7 +3988,8 @@ int main(int argc, char **argv, char **envp) current_machine->smp.cores =3D 1; current_machine->smp.threads =3D 1; =20 - smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); + machine_class->smp_parse(current_machine, + qemu_opts_find(qemu_find_opts("smp-opts"), NULL)); =20 /* sanity-check smp_cpus and max_cpus against machine_class */ if (current_machine->smp.cpus < machine_class->min_cpus) { --=20 2.18.0.rc1.1.g3f1ff2140