From: Jonathan Cameron <Jonathan.Cameron@Huawei.com>
To: Zhao Liu <zhao1.liu@intel.com>
Cc: "Daniel P . Berrangé" <berrange@redhat.com>,
"Igor Mammedov" <imammedo@redhat.com>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Yanan Wang" <wangyanan55@huawei.com>,
"Michael S . Tsirkin" <mst@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Sergio Lopez" <slp@redhat.com>,
"Jason Wang" <jasowang@redhat.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Anthony PERARD" <anthony@xenproject.org>,
"Paul Durrant" <paul@xen.org>,
"Edgar E . Iglesias" <edgar.iglesias@gmail.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Peter Maydell" <peter.maydell@linaro.org>,
qemu-devel@nongnu.org, kvm@vger.kernel.org, qemu-arm@nongnu.org,
"Zhenyu Wang" <zhenyu.z.wang@intel.com>,
"Dapeng Mi" <dapeng1.mi@linux.intel.com>,
"Yongwei Ma" <yongwei.ma@intel.com>
Subject: Re: [RFC v2 05/12] hw/core/machine: Introduce custom CPU topology with max limitations
Date: Tue, 8 Oct 2024 11:16:51 +0100 [thread overview]
Message-ID: <20241008111651.000025ab@Huawei.com> (raw)
In-Reply-To: <20240919061128.769139-6-zhao1.liu@intel.com>
On Thu, 19 Sep 2024 14:11:21 +0800
Zhao Liu <zhao1.liu@intel.com> wrote:
> Custom topology allows user to create CPU topology totally via -device
> from CLI.
>
> Once custom topology is enabled, machine will stop the default CPU
> creation and expect user's CPU topology tree built from CLI.
>
> With custom topology, any CPU topology, whether symmetric or hybrid
> (aka, heterogeneous), can be created naturally.
>
> However, custom topology also needs to be restricted because
> possible_cpus[] requires some preliminary topology information for
> initialization, which is the max limitation (the new max parameters in
> -smp). Custom topology will be subject to this max limitation.
>
> Max limitations are necessary because creating custom topology before
> initializing possible_cpus[] would compromise future hotplug scalability.
>
> Max limitations are placed in -smp, even though custom topology can be
> defined as hybrid. From an implementation perspective, any hybrid
> topology can be considered a subset of a complete SMP structure.
> Therefore, semantically, using max limitations to constrain hybrid
> topology is consistent.
>
> Introduce custom CPU topology related properties in MachineClass. At the
> same time, add and parse max parameters from -smp, and store the max
> limitations in CPUSlot.
>
> Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
A few code style comments inline.
J
> diff --git a/hw/cpu/cpu-slot.c b/hw/cpu/cpu-slot.c
> index 1cc3b32ed675..2d16a2729501 100644
> --- a/hw/cpu/cpu-slot.c
> +++ b/hw/cpu/cpu-slot.c
> +
> +bool machine_parse_custom_topo_config(MachineState *ms,
> + const SMPConfiguration *config,
> + Error **errp)
> +{
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + CPUSlot *slot = ms->topo;
> + bool is_valid;
> + int maxcpus;
> +
> + if (!slot) {
> + return true;
> + }
> +
> + is_valid = config->has_maxsockets && config->maxsockets;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
> + is_valid ? config->maxsockets : ms->smp.sockets;
> + } else if (is_valid) {
> + error_setg(errp, "maxsockets > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
> + ms->smp.sockets;
> + }
Having the error condition in the middle is rather confusing to
read to my eyes. Playing with equivalents I wonder what works best..
if (!is_valid) {
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
ms->smp.sockets;
} else if (mc->smp_props.custom_topo_supported) {
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
config->max_sockets;
} else {
error_setg...
return false;
}
or take the bad case out first. Maybe this is a little obscure
though (assuming I even got it right) as it relies on the fact
that is_valid must be false for the legacy path.
if (!mc->smp_props.custom_topo_supported && is_valid) {
error_setg();
return false;
}
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
is_valid ? config->maxsockets : ms->smp.sockets;
Similar for other cases.
> +
> + is_valid = config->has_maxdies && config->maxdies;
> + if (mc->smp_props.custom_topo_supported &&
> + mc->smp_props.dies_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_DIE].max_limit =
> + is_valid ? config->maxdies : ms->smp.dies;
> + } else if (is_valid) {
> + error_setg(errp, "maxdies > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_DIE].max_limit =
> + ms->smp.dies;
> + }
> +
> + is_valid = config->has_maxmodules && config->maxmodules;
> + if (mc->smp_props.custom_topo_supported &&
> + mc->smp_props.modules_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_MODULE].max_limit =
> + is_valid ? config->maxmodules : ms->smp.modules;
> + } else if (is_valid) {
> + error_setg(errp, "maxmodules > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_MODULE].max_limit =
> + ms->smp.modules;
> + }
> +
> + is_valid = config->has_maxcores && config->maxcores;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_CORE].max_limit =
> + is_valid ? config->maxcores : ms->smp.cores;
> + } else if (is_valid) {
> + error_setg(errp, "maxcores > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_CORE].max_limit =
> + ms->smp.cores;
> + }
> +
> + is_valid = config->has_maxthreads && config->maxthreads;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_THREAD].max_limit =
> + is_valid ? config->maxthreads : ms->smp.threads;
> + } else if (is_valid) {
> + error_setg(errp, "maxthreads > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_THREAD].max_limit =
> + ms->smp.threads;
> + }
> +
> + maxcpus = 1;
> + /* Initizlize max_limit to 1, as members of CpuTopology. */
> + for (int i = 0; i < CPU_TOPOLOGY_LEVEL__MAX; i++) {
> + maxcpus *= slot->stat.entries[i].max_limit;
> + }
> +
> + if (!config->has_maxcpus) {
> + ms->smp.max_cpus = maxcpus;
Maybe early return here to get rid of need for the else?
> + } else {
> + if (maxcpus != ms->smp.max_cpus) {
Unless this is going to get more complex later, else if probably appropriate here
(if you don't drop the else above.
> + error_setg(errp, "maxcpus (%d) should be equal to "
> + "the product of the remaining max parameters (%d)",
> + ms->smp.max_cpus, maxcpus);
> + return false;
> + }
> + }
> +
> + return true;
> +}
WARNING: multiple messages have this Message-ID (diff)
From: Jonathan Cameron via <qemu-devel@nongnu.org>
To: Zhao Liu <zhao1.liu@intel.com>
Cc: "Daniel P . Berrangé" <berrange@redhat.com>,
"Igor Mammedov" <imammedo@redhat.com>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Yanan Wang" <wangyanan55@huawei.com>,
"Michael S . Tsirkin" <mst@redhat.com>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Richard Henderson" <richard.henderson@linaro.org>,
"Sergio Lopez" <slp@redhat.com>,
"Jason Wang" <jasowang@redhat.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Anthony PERARD" <anthony@xenproject.org>,
"Paul Durrant" <paul@xen.org>,
"Edgar E . Iglesias" <edgar.iglesias@gmail.com>,
"Eric Blake" <eblake@redhat.com>,
"Markus Armbruster" <armbru@redhat.com>,
"Alex Bennée" <alex.bennee@linaro.org>,
"Peter Maydell" <peter.maydell@linaro.org>,
qemu-devel@nongnu.org, kvm@vger.kernel.org, qemu-arm@nongnu.org,
"Zhenyu Wang" <zhenyu.z.wang@intel.com>,
"Dapeng Mi" <dapeng1.mi@linux.intel.com>,
"Yongwei Ma" <yongwei.ma@intel.com>
Subject: Re: [RFC v2 05/12] hw/core/machine: Introduce custom CPU topology with max limitations
Date: Tue, 8 Oct 2024 11:16:51 +0100 [thread overview]
Message-ID: <20241008111651.000025ab@Huawei.com> (raw)
In-Reply-To: <20240919061128.769139-6-zhao1.liu@intel.com>
On Thu, 19 Sep 2024 14:11:21 +0800
Zhao Liu <zhao1.liu@intel.com> wrote:
> Custom topology allows user to create CPU topology totally via -device
> from CLI.
>
> Once custom topology is enabled, machine will stop the default CPU
> creation and expect user's CPU topology tree built from CLI.
>
> With custom topology, any CPU topology, whether symmetric or hybrid
> (aka, heterogeneous), can be created naturally.
>
> However, custom topology also needs to be restricted because
> possible_cpus[] requires some preliminary topology information for
> initialization, which is the max limitation (the new max parameters in
> -smp). Custom topology will be subject to this max limitation.
>
> Max limitations are necessary because creating custom topology before
> initializing possible_cpus[] would compromise future hotplug scalability.
>
> Max limitations are placed in -smp, even though custom topology can be
> defined as hybrid. From an implementation perspective, any hybrid
> topology can be considered a subset of a complete SMP structure.
> Therefore, semantically, using max limitations to constrain hybrid
> topology is consistent.
>
> Introduce custom CPU topology related properties in MachineClass. At the
> same time, add and parse max parameters from -smp, and store the max
> limitations in CPUSlot.
>
> Signed-off-by: Zhao Liu <zhao1.liu@intel.com>
A few code style comments inline.
J
> diff --git a/hw/cpu/cpu-slot.c b/hw/cpu/cpu-slot.c
> index 1cc3b32ed675..2d16a2729501 100644
> --- a/hw/cpu/cpu-slot.c
> +++ b/hw/cpu/cpu-slot.c
> +
> +bool machine_parse_custom_topo_config(MachineState *ms,
> + const SMPConfiguration *config,
> + Error **errp)
> +{
> + MachineClass *mc = MACHINE_GET_CLASS(ms);
> + CPUSlot *slot = ms->topo;
> + bool is_valid;
> + int maxcpus;
> +
> + if (!slot) {
> + return true;
> + }
> +
> + is_valid = config->has_maxsockets && config->maxsockets;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
> + is_valid ? config->maxsockets : ms->smp.sockets;
> + } else if (is_valid) {
> + error_setg(errp, "maxsockets > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
> + ms->smp.sockets;
> + }
Having the error condition in the middle is rather confusing to
read to my eyes. Playing with equivalents I wonder what works best..
if (!is_valid) {
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
ms->smp.sockets;
} else if (mc->smp_props.custom_topo_supported) {
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
config->max_sockets;
} else {
error_setg...
return false;
}
or take the bad case out first. Maybe this is a little obscure
though (assuming I even got it right) as it relies on the fact
that is_valid must be false for the legacy path.
if (!mc->smp_props.custom_topo_supported && is_valid) {
error_setg();
return false;
}
slot->stat.entries[CPU_TOPOLOGY_LEVEL_SOCKET].max_limit =
is_valid ? config->maxsockets : ms->smp.sockets;
Similar for other cases.
> +
> + is_valid = config->has_maxdies && config->maxdies;
> + if (mc->smp_props.custom_topo_supported &&
> + mc->smp_props.dies_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_DIE].max_limit =
> + is_valid ? config->maxdies : ms->smp.dies;
> + } else if (is_valid) {
> + error_setg(errp, "maxdies > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_DIE].max_limit =
> + ms->smp.dies;
> + }
> +
> + is_valid = config->has_maxmodules && config->maxmodules;
> + if (mc->smp_props.custom_topo_supported &&
> + mc->smp_props.modules_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_MODULE].max_limit =
> + is_valid ? config->maxmodules : ms->smp.modules;
> + } else if (is_valid) {
> + error_setg(errp, "maxmodules > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_MODULE].max_limit =
> + ms->smp.modules;
> + }
> +
> + is_valid = config->has_maxcores && config->maxcores;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_CORE].max_limit =
> + is_valid ? config->maxcores : ms->smp.cores;
> + } else if (is_valid) {
> + error_setg(errp, "maxcores > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_CORE].max_limit =
> + ms->smp.cores;
> + }
> +
> + is_valid = config->has_maxthreads && config->maxthreads;
> + if (mc->smp_props.custom_topo_supported) {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_THREAD].max_limit =
> + is_valid ? config->maxthreads : ms->smp.threads;
> + } else if (is_valid) {
> + error_setg(errp, "maxthreads > 0 not supported "
> + "by this machine's CPU topology");
> + return false;
> + } else {
> + slot->stat.entries[CPU_TOPOLOGY_LEVEL_THREAD].max_limit =
> + ms->smp.threads;
> + }
> +
> + maxcpus = 1;
> + /* Initizlize max_limit to 1, as members of CpuTopology. */
> + for (int i = 0; i < CPU_TOPOLOGY_LEVEL__MAX; i++) {
> + maxcpus *= slot->stat.entries[i].max_limit;
> + }
> +
> + if (!config->has_maxcpus) {
> + ms->smp.max_cpus = maxcpus;
Maybe early return here to get rid of need for the else?
> + } else {
> + if (maxcpus != ms->smp.max_cpus) {
Unless this is going to get more complex later, else if probably appropriate here
(if you don't drop the else above.
> + error_setg(errp, "maxcpus (%d) should be equal to "
> + "the product of the remaining max parameters (%d)",
> + ms->smp.max_cpus, maxcpus);
> + return false;
> + }
> + }
> +
> + return true;
> +}
next prev parent reply other threads:[~2024-10-08 10:16 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-09-19 6:11 [RFC v2 00/12] Introduce Hybrid CPU Topology via Custom Topology Tree Zhao Liu
2024-09-19 6:11 ` [RFC v2 01/12] qdev: Allow qdev_device_add() to add specific category device Zhao Liu
2024-10-08 9:14 ` Jonathan Cameron
2024-10-08 9:14 ` Jonathan Cameron via
2024-10-09 6:09 ` Zhao Liu
2024-09-19 6:11 ` [RFC v2 02/12] qdev: Introduce new device category to cover basic topology device Zhao Liu
2024-09-19 6:11 ` [RFC v2 03/12] system/vl: Create CPU topology devices from CLI early Zhao Liu
2024-10-08 9:50 ` Jonathan Cameron
2024-10-08 9:50 ` Jonathan Cameron via
2024-10-09 6:31 ` Zhao Liu
2024-10-08 9:55 ` Jonathan Cameron
2024-10-08 9:55 ` Jonathan Cameron via
2024-10-09 6:11 ` Zhao Liu
2024-09-19 6:11 ` [RFC v2 04/12] hw/core/machine: Split machine initialization around qemu_add_cli_devices_early() Zhao Liu
2024-09-19 6:11 ` [RFC v2 05/12] hw/core/machine: Introduce custom CPU topology with max limitations Zhao Liu
2024-10-08 10:16 ` Jonathan Cameron [this message]
2024-10-08 10:16 ` Jonathan Cameron via
2024-10-09 6:46 ` Zhao Liu
2024-09-19 6:11 ` [RFC v2 06/12] hw/cpu: Constrain CPU topology tree with max_limit Zhao Liu
2024-09-19 6:11 ` [RFC v2 07/12] hw/core: Re-implement topology helpers to honor max limitations Zhao Liu
2024-09-19 6:11 ` [RFC v2 08/12] hw/i386: Use get_max_topo_by_level() to get topology information Zhao Liu
2024-09-19 6:11 ` [RFC v2 09/12] i386: Introduce x86 CPU core abstractions Zhao Liu
2024-09-19 6:11 ` [RFC v2 10/12] i386/cpu: Support Intel hybrid CPUID Zhao Liu
2024-09-19 6:11 ` [RFC v2 11/12] i386/machine: Split machine initialization after CPU creation into post_init() Zhao Liu
2024-09-19 6:11 ` [RFC v2 12/12] i386: Support custom topology for microvm, pc-i440fx and pc-q35 Zhao Liu
2024-10-08 10:30 ` [RFC v2 00/12] Introduce Hybrid CPU Topology via Custom Topology Tree Jonathan Cameron
2024-10-08 10:30 ` Jonathan Cameron via
2024-10-09 6:01 ` Zhao Liu
2024-10-09 6:51 ` Zhao Liu
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=20241008111651.000025ab@Huawei.com \
--to=jonathan.cameron@huawei.com \
--cc=alex.bennee@linaro.org \
--cc=anthony@xenproject.org \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=eblake@redhat.com \
--cc=edgar.iglesias@gmail.com \
--cc=eduardo@habkost.net \
--cc=imammedo@redhat.com \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=marcel.apfelbaum@gmail.com \
--cc=mst@redhat.com \
--cc=paul@xen.org \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=philmd@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=slp@redhat.com \
--cc=sstabellini@kernel.org \
--cc=wangyanan55@huawei.com \
--cc=yongwei.ma@intel.com \
--cc=zhao1.liu@intel.com \
--cc=zhenyu.z.wang@intel.com \
/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.