qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v12 00/16] machine: smp parsing fixes and improvement
@ 2021-09-29  2:58 Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 01/16] qapi/machine: Fix an incorrect comment of SMPConfiguration Yanan Wang
                   ` (16 more replies)
  0 siblings, 17 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Hi,

This is a new version (v12) with minor update suggested by Daniel
and Philippe. Two new commits (#1 and #16) are added. Thanks!

Summary of v12:
1) Specifying a CPU topology parameter as zero was implicitly allowed
but undocumented before, while now it's explicitly deprecated.

2) Refactor/fixes of the smp parsers.

3) For consistency, maxcpus is now uniformly used to calculate the
omitted topology members.

4) Improve the error reporting of the parsers.

5) It's also suggested that we should start to prefer cores over sockets
over threads on the newer machine types, which will make the computed
virtual topology more reflective of the real hardware. Related discussion
can be found in [1].
[1] https://lore.kernel.org/qemu-devel/YNIgInK00yNNI4Dy@redhat.com/

6) In order to reduce code duplication and ease the code maintenance,
smp_parse() is converted into a generic enough parser for all arches,
so that the arch-specific ones (e.g. pc_smp_parse) can be removed.
It's also convenient to introduce more topology members to the generic
parser in the future. Related discussions can be found in [2] and [3].
[2] https://lore.kernel.org/qemu-devel/20210630115602.txmvmfe2jrzu7o67@gator.home/
[3] https://lore.kernel.org/qemu-devel/YPFN83pKBt7F97kW@redhat.com/

Changelogs:

v11->v12:
- add an extra commit 16/16 to make smp_parse() return a boolean (Philippe)
- split the machine.json Doc fix out into a separate patch 01/16 (Daniel)
- add R-bs for the series from Daniel and Philippe, thanks!
- v11: https://lore.kernel.org/qemu-devel/20210928035755.11684-1-wangyanan55@huawei.com/

v10->v11:
- only update patch 11/14
  use GString APIs to build the cpu topology hierarchy string (Daniel)
  refine the comments of smp_parse()
- v10: https://lore.kernel.org/qemu-devel/20210926084541.17352-1-wangyanan55@huawei.com/

v9->v10:
- rebased on latest upstream commit 11a1199846.
  there is no change of the patches in v10, except minor update
  in 08/14 to resolve merge conflict with master.
- To make this series more acceptable, drop the last two patches
  about SMP unit test, since the scalability of the test is not
  optimally designed after rethinking of it. So I will resend the
  test related patches separately after refining them.
- v9: https://lore.kernel.org/qemu-devel/20210910073025.16480-1-wangyanan55@huawei.com/

Yanan Wang (16):
  qapi/machine: Fix an incorrect comment of SMPConfiguration
  machine: Deprecate "parameter=0" SMP configurations
  machine: Minor refactor/fix for the smp parsers
  machine: Uniformly use maxcpus to calculate the omitted parameters
  machine: Set the value of cpus to match maxcpus if it's omitted
  machine: Improve the error reporting of smp parsing
  qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg
  qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split
  machine: Prefer cores over sockets in smp parsing since 6.2
  machine: Use ms instead of global current_machine in sanity-check
  machine: Tweak the order of topology members in struct CpuTopology
  machine: Make smp_parse generic enough for all arches
  machine: Remove smp_parse callback from MachineClass
  machine: Move smp_prefer_sockets to struct SMPCompatProps
  machine: Put all sanity-check in the generic SMP parser
  machine: Make smp_parse return a boolean

 docs/about/deprecated.rst  |  15 +++
 hw/arm/virt.c              |   1 +
 hw/core/machine.c          | 206 ++++++++++++++++++++++++++-----------
 hw/i386/pc.c               |  63 +-----------
 hw/i386/pc_piix.c          |   1 +
 hw/i386/pc_q35.c           |   1 +
 hw/ppc/spapr.c             |   1 +
 hw/s390x/s390-virtio-ccw.c |   1 +
 include/hw/boards.h        |  23 +++--
 qapi/machine.json          |   2 +-
 qemu-options.hx            |  24 +++--
 tests/qtest/numa-test.c    |   6 +-
 12 files changed, 201 insertions(+), 143 deletions(-)

--
2.19.1



^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v12 01/16] qapi/machine: Fix an incorrect comment of SMPConfiguration
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 02/16] machine: Deprecate "parameter=0" SMP configurations Yanan Wang
                   ` (15 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

The explanation of @cores should be "number of cores per die" but
not "number of cores per thread". Let's fix it.

Fixes: 1e63fe685804 ("machine: pass QAPI struct to mc->smp_parse")
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 qapi/machine.json | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/qapi/machine.json b/qapi/machine.json
index 32d47f4e35..227e75d8af 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -1331,7 +1331,7 @@
 #
 # @dies: number of dies per socket in the CPU topology
 #
-# @cores: number of cores per thread in the CPU topology
+# @cores: number of cores per die in the CPU topology
 #
 # @threads: number of threads per core in the CPU topology
 #
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 02/16] machine: Deprecate "parameter=0" SMP configurations
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 01/16] qapi/machine: Fix an incorrect comment of SMPConfiguration Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 03/16] machine: Minor refactor/fix for the smp parsers Yanan Wang
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

In the SMP configuration, we should either provide a topology
parameter with a reasonable value (greater than zero) or just
omit it and QEMU will compute the missing value.

The users shouldn't provide a configuration with any parameter
of it specified as zero (e.g. -smp 8,sockets=0) which could
possibly cause unexpected results in the -smp parsing. So we
deprecate this kind of configurations since 6.2 by adding the
explicit sanity check.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 docs/about/deprecated.rst | 15 +++++++++++++++
 hw/core/machine.c         | 14 ++++++++++++++
 qemu-options.hx           | 12 +++++++-----
 3 files changed, 36 insertions(+), 5 deletions(-)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 3c2be84d80..97415dbecd 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -160,6 +160,21 @@ Use ``-display sdl`` instead.
 
 Use ``-display curses`` instead.
 
+``-smp`` ("parameter=0" SMP configurations) (since 6.2)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Specified CPU topology parameters must be greater than zero.
+
+In the SMP configuration, users should either provide a CPU topology
+parameter with a reasonable value (greater than zero) or just omit it
+and QEMU will compute the missing value.
+
+However, historically it was implicitly allowed for users to provide
+a parameter with zero value, which is meaningless and could also possibly
+cause unexpected results in the -smp parsing. So support for this kind of
+configurations (e.g. -smp 8,sockets=0) is deprecated since 6.2 and will
+be removed in the near future, users have to ensure that all the topology
+members described with -smp are greater than zero.
 
 Plugin argument passing through ``arg=<string>`` (since 6.1)
 ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 067f42b528..4e409261c9 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -835,6 +835,20 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
         return;
     }
 
+    /*
+     * Specified CPU topology parameters must be greater than zero,
+     * explicit configuration like "cpus=0" is not allowed.
+     */
+    if ((config->has_cpus && config->cpus == 0) ||
+        (config->has_sockets && config->sockets == 0) ||
+        (config->has_dies && config->dies == 0) ||
+        (config->has_cores && config->cores == 0) ||
+        (config->has_threads && config->threads == 0) ||
+        (config->has_maxcpus && config->maxcpus == 0)) {
+        warn_report("Deprecated CPU topology (considered invalid): "
+                    "CPU topology parameters must be greater than zero");
+    }
+
     mc->smp_parse(ms, config, errp);
     if (*errp) {
         goto out_free;
diff --git a/qemu-options.hx b/qemu-options.hx
index 8f603cc7e6..91d859aa29 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -227,11 +227,13 @@ SRST
     of computing the CPU maximum count.
 
     Either the initial CPU count, or at least one of the topology parameters
-    must be specified. Values for any omitted parameters will be computed
-    from those which are given. Historically preference was given to the
-    coarsest topology parameters when computing missing values (ie sockets
-    preferred over cores, which were preferred over threads), however, this
-    behaviour is considered liable to change.
+    must be specified. The specified parameters must be greater than zero,
+    explicit configuration like "cpus=0" is not allowed. Values for any
+    omitted parameters will be computed from those which are given.
+    Historically preference was given to the coarsest topology parameters
+    when computing missing values (ie sockets preferred over cores, which
+    were preferred over threads), however, this behaviour is considered
+    liable to change.
 ERST
 
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 03/16] machine: Minor refactor/fix for the smp parsers
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 01/16] qapi/machine: Fix an incorrect comment of SMPConfiguration Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 02/16] machine: Deprecate "parameter=0" SMP configurations Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 04/16] machine: Uniformly use maxcpus to calculate the omitted parameters Yanan Wang
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

To pave the way for the functional improvement in later patches,
make some refactor/cleanup for the smp parsers, including using
local maxcpus instead of ms->smp.max_cpus in the calculation,
defaulting dies to 0 initially like other members, cleanup the
sanity check for dies.

We actually also fix a hidden defect by avoiding directly using
the provided *zero value* in the calculation, which could cause
a segment fault (e.g. using dies=0 in the calculation).

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c | 18 ++++++++++--------
 hw/i386/pc.c      | 23 ++++++++++++++---------
 2 files changed, 24 insertions(+), 17 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 4e409261c9..8e719e2932 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -752,8 +752,9 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     unsigned sockets = config->has_sockets ? config->sockets : 0;
     unsigned cores   = config->has_cores ? config->cores : 0;
     unsigned threads = config->has_threads ? config->threads : 0;
+    unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
-    if (config->has_dies && config->dies != 0 && config->dies != 1) {
+    if (config->has_dies && config->dies > 1) {
         error_setg(errp, "dies not supported by this machine's CPU topology");
         return;
     }
@@ -766,8 +767,8 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
             sockets = sockets > 0 ? sockets : 1;
             cpus = cores * threads * sockets;
         } else {
-            ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
-            sockets = ms->smp.max_cpus / (cores * threads);
+            maxcpus = maxcpus > 0 ? maxcpus : cpus;
+            sockets = maxcpus / (cores * threads);
         }
     } else if (cores == 0) {
         threads = threads > 0 ? threads : 1;
@@ -784,26 +785,27 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
         return;
     }
 
-    ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
+    maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-    if (ms->smp.max_cpus < cpus) {
+    if (maxcpus < cpus) {
         error_setg(errp, "maxcpus must be equal to or greater than smp");
         return;
     }
 
-    if (sockets * cores * threads != ms->smp.max_cpus) {
+    if (sockets * cores * threads != maxcpus) {
         error_setg(errp, "Invalid CPU topology: "
                    "sockets (%u) * cores (%u) * threads (%u) "
                    "!= maxcpus (%u)",
                    sockets, cores, threads,
-                   ms->smp.max_cpus);
+                   maxcpus);
         return;
     }
 
     ms->smp.cpus = cpus;
+    ms->smp.sockets = sockets;
     ms->smp.cores = cores;
     ms->smp.threads = threads;
-    ms->smp.sockets = sockets;
+    ms->smp.max_cpus = maxcpus;
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 557d49c9f8..93dc322a97 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -718,9 +718,13 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
 {
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
     unsigned sockets = config->has_sockets ? config->sockets : 0;
-    unsigned dies    = config->has_dies ? config->dies : 1;
+    unsigned dies    = config->has_dies ? config->dies : 0;
     unsigned cores   = config->has_cores ? config->cores : 0;
     unsigned threads = config->has_threads ? config->threads : 0;
+    unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
+
+    /* directly default dies to 1 if it's omitted */
+    dies = dies > 0 ? dies : 1;
 
     /* compute missing values, prefer sockets over cores over threads */
     if (cpus == 0 || sockets == 0) {
@@ -730,8 +734,8 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
             sockets = sockets > 0 ? sockets : 1;
             cpus = cores * threads * dies * sockets;
         } else {
-            ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
-            sockets = ms->smp.max_cpus / (cores * threads * dies);
+            maxcpus = maxcpus > 0 ? maxcpus : cpus;
+            sockets = maxcpus / (dies * cores * threads);
         }
     } else if (cores == 0) {
         threads = threads > 0 ? threads : 1;
@@ -748,27 +752,28 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
         return;
     }
 
-    ms->smp.max_cpus = config->has_maxcpus ? config->maxcpus : cpus;
+    maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-    if (ms->smp.max_cpus < cpus) {
+    if (maxcpus < cpus) {
         error_setg(errp, "maxcpus must be equal to or greater than smp");
         return;
     }
 
-    if (sockets * dies * cores * threads != ms->smp.max_cpus) {
+    if (sockets * dies * cores * threads != maxcpus) {
         error_setg(errp, "Invalid CPU topology deprecated: "
                    "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
                    "!= maxcpus (%u)",
                    sockets, dies, cores, threads,
-                   ms->smp.max_cpus);
+                   maxcpus);
         return;
     }
 
     ms->smp.cpus = cpus;
-    ms->smp.cores = cores;
-    ms->smp.threads = threads;
     ms->smp.sockets = sockets;
     ms->smp.dies = dies;
+    ms->smp.cores = cores;
+    ms->smp.threads = threads;
+    ms->smp.max_cpus = maxcpus;
 }
 
 static
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 04/16] machine: Uniformly use maxcpus to calculate the omitted parameters
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (2 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 03/16] machine: Minor refactor/fix for the smp parsers Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 05/16] machine: Set the value of cpus to match maxcpus if it's omitted Yanan Wang
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

We are currently using maxcpus to calculate the omitted sockets
but using cpus to calculate the omitted cores/threads. This makes
cmdlines like:
  -smp cpus=8,maxcpus=16
  -smp cpus=8,cores=4,maxcpus=16
  -smp cpus=8,threads=2,maxcpus=16
work fine but the ones like:
  -smp cpus=8,sockets=2,maxcpus=16
  -smp cpus=8,sockets=2,cores=4,maxcpus=16
  -smp cpus=8,sockets=2,threads=2,maxcpus=16
break the sanity check.

Since we require for a valid config that the product of "sockets * cores
* threads" should equal to the maxcpus, we should uniformly use maxcpus
to calculate their omitted values.

Also the if-branch of "cpus == 0 || sockets == 0" was split into two
branches of "cpus == 0" and "sockets == 0" so that we can clearly read
that we are parsing the configuration with a preference on cpus over
sockets over cores over threads.

Note: change in this patch won't affect any existing working cmdlines
but improves consistency and allows more incomplete configs to be valid.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c | 30 +++++++++++++++---------------
 hw/i386/pc.c      | 30 +++++++++++++++---------------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 8e719e2932..596e758133 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -760,24 +760,26 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     }
 
     /* compute missing values, prefer sockets over cores over threads */
-    if (cpus == 0 || sockets == 0) {
+    maxcpus = maxcpus > 0 ? maxcpus : cpus;
+
+    if (cpus == 0) {
+        sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
         threads = threads > 0 ? threads : 1;
-        if (cpus == 0) {
-            sockets = sockets > 0 ? sockets : 1;
-            cpus = cores * threads * sockets;
-        } else {
-            maxcpus = maxcpus > 0 ? maxcpus : cpus;
-            sockets = maxcpus / (cores * threads);
-        }
+        cpus = sockets * cores * threads;
+        maxcpus = maxcpus > 0 ? maxcpus : cpus;
+    } else if (sockets == 0) {
+        cores = cores > 0 ? cores : 1;
+        threads = threads > 0 ? threads : 1;
+        sockets = maxcpus / (cores * threads);
     } else if (cores == 0) {
         threads = threads > 0 ? threads : 1;
-        cores = cpus / (sockets * threads);
-        cores = cores > 0 ? cores : 1;
+        cores = maxcpus / (sockets * threads);
     } else if (threads == 0) {
-        threads = cpus / (cores * sockets);
-        threads = threads > 0 ? threads : 1;
-    } else if (sockets * cores * threads < cpus) {
+        threads = maxcpus / (sockets * cores);
+    }
+
+    if (sockets * cores * threads < cpus) {
         error_setg(errp, "cpu topology: "
                    "sockets (%u) * cores (%u) * threads (%u) < "
                    "smp_cpus (%u)",
@@ -785,8 +787,6 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
         return;
     }
 
-    maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
     if (maxcpus < cpus) {
         error_setg(errp, "maxcpus must be equal to or greater than smp");
         return;
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 93dc322a97..87c06d3991 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -727,24 +727,26 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
     dies = dies > 0 ? dies : 1;
 
     /* compute missing values, prefer sockets over cores over threads */
-    if (cpus == 0 || sockets == 0) {
+    maxcpus = maxcpus > 0 ? maxcpus : cpus;
+
+    if (cpus == 0) {
+        sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
         threads = threads > 0 ? threads : 1;
-        if (cpus == 0) {
-            sockets = sockets > 0 ? sockets : 1;
-            cpus = cores * threads * dies * sockets;
-        } else {
-            maxcpus = maxcpus > 0 ? maxcpus : cpus;
-            sockets = maxcpus / (dies * cores * threads);
-        }
+        cpus = sockets * dies * cores * threads;
+        maxcpus = maxcpus > 0 ? maxcpus : cpus;
+    } else if (sockets == 0) {
+        cores = cores > 0 ? cores : 1;
+        threads = threads > 0 ? threads : 1;
+        sockets = maxcpus / (dies * cores * threads);
     } else if (cores == 0) {
         threads = threads > 0 ? threads : 1;
-        cores = cpus / (sockets * dies * threads);
-        cores = cores > 0 ? cores : 1;
+        cores = maxcpus / (sockets * dies * threads);
     } else if (threads == 0) {
-        threads = cpus / (cores * dies * sockets);
-        threads = threads > 0 ? threads : 1;
-    } else if (sockets * dies * cores * threads < cpus) {
+        threads = maxcpus / (sockets * dies * cores);
+    }
+
+    if (sockets * dies * cores * threads < cpus) {
         error_setg(errp, "cpu topology: "
                    "sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
                    "smp_cpus (%u)",
@@ -752,8 +754,6 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
         return;
     }
 
-    maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
     if (maxcpus < cpus) {
         error_setg(errp, "maxcpus must be equal to or greater than smp");
         return;
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 05/16] machine: Set the value of cpus to match maxcpus if it's omitted
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (3 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 04/16] machine: Uniformly use maxcpus to calculate the omitted parameters Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 06/16] machine: Improve the error reporting of smp parsing Yanan Wang
                   ` (11 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Currently we directly calculate the omitted cpus based on the given
incomplete collection of parameters. This makes some cmdlines like:
  -smp maxcpus=16
  -smp sockets=2,maxcpus=16
  -smp sockets=2,dies=2,maxcpus=16
  -smp sockets=2,cores=4,maxcpus=16
not work. We should probably set the value of cpus to match maxcpus
if it's omitted, which will make above configs start to work.

So the calculation logic of cpus/maxcpus after this patch will be:
When both maxcpus and cpus are omitted, maxcpus will be calculated
from the given parameters and cpus will be set equal to maxcpus.
When only one of maxcpus and cpus is given then the omitted one
will be set to its counterpart's value. Both maxcpus and cpus may
be specified, but maxcpus must be equal to or greater than cpus.

Note: change in this patch won't affect any existing working cmdlines
but allows more incomplete configs to be valid.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c | 29 ++++++++++++++++-------------
 hw/i386/pc.c      | 29 ++++++++++++++++-------------
 qemu-options.hx   | 11 ++++++++---
 3 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 596e758133..d8f458db60 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -760,25 +760,28 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     }
 
     /* compute missing values, prefer sockets over cores over threads */
-    maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-    if (cpus == 0) {
+    if (cpus == 0 && maxcpus == 0) {
         sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
         threads = threads > 0 ? threads : 1;
-        cpus = sockets * cores * threads;
+    } else {
         maxcpus = maxcpus > 0 ? maxcpus : cpus;
-    } else if (sockets == 0) {
-        cores = cores > 0 ? cores : 1;
-        threads = threads > 0 ? threads : 1;
-        sockets = maxcpus / (cores * threads);
-    } else if (cores == 0) {
-        threads = threads > 0 ? threads : 1;
-        cores = maxcpus / (sockets * threads);
-    } else if (threads == 0) {
-        threads = maxcpus / (sockets * cores);
+
+        if (sockets == 0) {
+            cores = cores > 0 ? cores : 1;
+            threads = threads > 0 ? threads : 1;
+            sockets = maxcpus / (cores * threads);
+        } else if (cores == 0) {
+            threads = threads > 0 ? threads : 1;
+            cores = maxcpus / (sockets * threads);
+        } else if (threads == 0) {
+            threads = maxcpus / (sockets * cores);
+        }
     }
 
+    maxcpus = maxcpus > 0 ? maxcpus : sockets * cores * threads;
+    cpus = cpus > 0 ? cpus : maxcpus;
+
     if (sockets * cores * threads < cpus) {
         error_setg(errp, "cpu topology: "
                    "sockets (%u) * cores (%u) * threads (%u) < "
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 87c06d3991..d9382b7d57 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -727,25 +727,28 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
     dies = dies > 0 ? dies : 1;
 
     /* compute missing values, prefer sockets over cores over threads */
-    maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-    if (cpus == 0) {
+    if (cpus == 0 && maxcpus == 0) {
         sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
         threads = threads > 0 ? threads : 1;
-        cpus = sockets * dies * cores * threads;
+    } else {
         maxcpus = maxcpus > 0 ? maxcpus : cpus;
-    } else if (sockets == 0) {
-        cores = cores > 0 ? cores : 1;
-        threads = threads > 0 ? threads : 1;
-        sockets = maxcpus / (dies * cores * threads);
-    } else if (cores == 0) {
-        threads = threads > 0 ? threads : 1;
-        cores = maxcpus / (sockets * dies * threads);
-    } else if (threads == 0) {
-        threads = maxcpus / (sockets * dies * cores);
+
+        if (sockets == 0) {
+            cores = cores > 0 ? cores : 1;
+            threads = threads > 0 ? threads : 1;
+            sockets = maxcpus / (dies * cores * threads);
+        } else if (cores == 0) {
+            threads = threads > 0 ? threads : 1;
+            cores = maxcpus / (sockets * dies * threads);
+        } else if (threads == 0) {
+            threads = maxcpus / (sockets * dies * cores);
+        }
     }
 
+    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
+    cpus = cpus > 0 ? cpus : maxcpus;
+
     if (sockets * dies * cores * threads < cpus) {
         error_setg(errp, "cpu topology: "
                    "sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
diff --git a/qemu-options.hx b/qemu-options.hx
index 91d859aa29..9d71a661bb 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -214,9 +214,14 @@ SRST
     Simulate a SMP system with '\ ``n``\ ' CPUs initially present on
     the machine type board. On boards supporting CPU hotplug, the optional
     '\ ``maxcpus``\ ' parameter can be set to enable further CPUs to be
-    added at runtime. If omitted the maximum number of CPUs will be
-    set to match the initial CPU count. Both parameters are subject to
-    an upper limit that is determined by the specific machine type chosen.
+    added at runtime. When both parameters are omitted, the maximum number
+    of CPUs will be calculated from the provided topology members and the
+    initial CPU count will match the maximum number. When only one of them
+    is given then the omitted one will be set to its counterpart's value.
+    Both parameters may be specified, but the maximum number of CPUs must
+    be equal to or greater than the initial CPU count. Both parameters are
+    subject to an upper limit that is determined by the specific machine
+    type chosen.
 
     To control reporting of CPU topology information, the number of sockets,
     dies per socket, cores per die, and threads per core can be specified.
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 06/16] machine: Improve the error reporting of smp parsing
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (4 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 05/16] machine: Set the value of cpus to match maxcpus if it's omitted Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 07/16] qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg Yanan Wang
                   ` (10 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

We have two requirements for a valid SMP configuration:
the product of "sockets * cores * threads" must represent all the
possible cpus, i.e., max_cpus, and then must include the initially
present cpus, i.e., smp_cpus.

So we only need to ensure 1) "sockets * cores * threads == maxcpus"
at first and then ensure 2) "maxcpus >= cpus". With a reasonable
order of the sanity check, we can simplify the error reporting code.
When reporting an error message we also report the exact value of
each topology member to make users easily see what's going on.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/core/machine.c | 22 +++++++++-------------
 hw/i386/pc.c      | 24 ++++++++++--------------
 2 files changed, 19 insertions(+), 27 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index d8f458db60..e38ab760e6 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -782,25 +782,21 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     maxcpus = maxcpus > 0 ? maxcpus : sockets * cores * threads;
     cpus = cpus > 0 ? cpus : maxcpus;
 
-    if (sockets * cores * threads < cpus) {
-        error_setg(errp, "cpu topology: "
-                   "sockets (%u) * cores (%u) * threads (%u) < "
-                   "smp_cpus (%u)",
-                   sockets, cores, threads, cpus);
+    if (sockets * cores * threads != maxcpus) {
+        error_setg(errp, "Invalid CPU topology: "
+                   "product of the hierarchy must match maxcpus: "
+                   "sockets (%u) * cores (%u) * threads (%u) "
+                   "!= maxcpus (%u)",
+                   sockets, cores, threads, maxcpus);
         return;
     }
 
     if (maxcpus < cpus) {
-        error_setg(errp, "maxcpus must be equal to or greater than smp");
-        return;
-    }
-
-    if (sockets * cores * threads != maxcpus) {
         error_setg(errp, "Invalid CPU topology: "
+                   "maxcpus must be equal to or greater than smp: "
                    "sockets (%u) * cores (%u) * threads (%u) "
-                   "!= maxcpus (%u)",
-                   sockets, cores, threads,
-                   maxcpus);
+                   "== maxcpus (%u) < smp_cpus (%u)",
+                   sockets, cores, threads, maxcpus, cpus);
         return;
     }
 
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index d9382b7d57..a37eef8057 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -749,25 +749,21 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
     maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
     cpus = cpus > 0 ? cpus : maxcpus;
 
-    if (sockets * dies * cores * threads < cpus) {
-        error_setg(errp, "cpu topology: "
-                   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) < "
-                   "smp_cpus (%u)",
-                   sockets, dies, cores, threads, cpus);
+    if (sockets * dies * cores * threads != maxcpus) {
+        error_setg(errp, "Invalid CPU topology: "
+                   "product of the hierarchy must match maxcpus: "
+                   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
+                   "!= maxcpus (%u)",
+                   sockets, dies, cores, threads, maxcpus);
         return;
     }
 
     if (maxcpus < cpus) {
-        error_setg(errp, "maxcpus must be equal to or greater than smp");
-        return;
-    }
-
-    if (sockets * dies * cores * threads != maxcpus) {
-        error_setg(errp, "Invalid CPU topology deprecated: "
+        error_setg(errp, "Invalid CPU topology: "
+                   "maxcpus must be equal to or greater than smp: "
                    "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
-                   "!= maxcpus (%u)",
-                   sockets, dies, cores, threads,
-                   maxcpus);
+                   "== maxcpus (%u) < smp_cpus (%u)",
+                   sockets, dies, cores, threads, maxcpus, cpus);
         return;
     }
 
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 07/16] qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (5 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 06/16] machine: Improve the error reporting of smp parsing Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 08/16] qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split Yanan Wang
                   ` (9 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Since commit 80d7835749 (qemu-options: rewrite help for -smp options),
the preference of sockets/cores in -smp parsing is considered liable
to change, and actually we are going to change it in a coming commit.
So it'll be more stable to use detailed -smp CLIs in testing if we
have strong dependency on the parsing results.

pc_dynamic_cpu_cfg currently assumes/needs that there will be 2 CPU
sockets with "-smp 2". To avoid breaking the test because of parsing
logic change, now explicitly use "-smp 2,sockets=2".

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 tests/qtest/numa-test.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
index c677cd63c4..fd7a2e80a0 100644
--- a/tests/qtest/numa-test.c
+++ b/tests/qtest/numa-test.c
@@ -265,7 +265,8 @@ static void pc_dynamic_cpu_cfg(const void *data)
     QTestState *qs;
     g_autofree char *cli = NULL;
 
-    cli = make_cli(data, "-nodefaults --preconfig -machine smp.cpus=2");
+    cli = make_cli(data, "-nodefaults --preconfig "
+                         "-machine smp.cpus=2,smp.sockets=2");
     qs = qtest_init(cli);
 
     /* create 2 numa nodes */
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 08/16] qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (6 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 07/16] qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 09/16] machine: Prefer cores over sockets in smp parsing since 6.2 Yanan Wang
                   ` (8 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Since commit 80d7835749 (qemu-options: rewrite help for -smp options),
the preference of sockets/cores in -smp parsing is considered liable
to change, and actually we are going to change it in a coming commit.
So it'll be more stable to use detailed -smp CLIs in the testcases
that have strong dependency on the parsing results.

Currently, test_def_cpu_split use "-smp 8" and will get 8 CPU sockets
based on current parsing rule. But if we change to prefer cores over
sockets we will get one CPU socket with 8 cores, and this testcase
will not get expected numa set by default on x86_64 (Ok on aarch64).

So now explicitly use "-smp 8,sockets=8" to avoid affect from parsing
logic change.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 tests/qtest/numa-test.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/qtest/numa-test.c b/tests/qtest/numa-test.c
index fd7a2e80a0..90bf68a5b3 100644
--- a/tests/qtest/numa-test.c
+++ b/tests/qtest/numa-test.c
@@ -42,7 +42,8 @@ static void test_def_cpu_split(const void *data)
     g_autofree char *s = NULL;
     g_autofree char *cli = NULL;
 
-    cli = make_cli(data, "-machine smp.cpus=8 -numa node,memdev=ram -numa node");
+    cli = make_cli(data, "-machine smp.cpus=8,smp.sockets=8 "
+                         "-numa node,memdev=ram -numa node");
     qts = qtest_init(cli);
 
     s = qtest_hmp(qts, "info numa");
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 09/16] machine: Prefer cores over sockets in smp parsing since 6.2
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (7 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 08/16] qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 10/16] machine: Use ms instead of global current_machine in sanity-check Yanan Wang
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

In the real SMP hardware topology world, it's much more likely that
we have high cores-per-socket counts and few sockets totally. While
the current preference of sockets over cores in smp parsing results
in a virtual cpu topology with low cores-per-sockets counts and a
large number of sockets, which is just contrary to the real world.

Given that it is better to make the virtual cpu topology be more
reflective of the real world and also for the sake of compatibility,
we start to prefer cores over sockets over threads in smp parsing
since machine type 6.2 for different arches.

In this patch, a boolean "smp_prefer_sockets" is added, and we only
enable the old preference on older machines and enable the new one
since type 6.2 for all arches by using the machine compat mechanism.

Suggested-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Acked-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/arm/virt.c              |  1 +
 hw/core/machine.c          | 35 ++++++++++++++++++++++++++---------
 hw/i386/pc.c               | 35 ++++++++++++++++++++++++++---------
 hw/i386/pc_piix.c          |  1 +
 hw/i386/pc_q35.c           |  1 +
 hw/ppc/spapr.c             |  1 +
 hw/s390x/s390-virtio-ccw.c |  1 +
 include/hw/boards.h        |  1 +
 qemu-options.hx            |  3 ++-
 9 files changed, 60 insertions(+), 19 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1d59f0e59f..8c13deb5db 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2815,6 +2815,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
 
     virt_machine_6_2_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+    mc->smp_prefer_sockets = true;
 
     /* qemu ITS was introduced with 6.2 */
     vmc->no_tcg_its = true;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index e38ab760e6..f2a34d98c0 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -748,6 +748,7 @@ void machine_set_cpu_numa_node(MachineState *machine,
 
 static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
     unsigned sockets = config->has_sockets ? config->sockets : 0;
     unsigned cores   = config->has_cores ? config->cores : 0;
@@ -759,7 +760,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
         return;
     }
 
-    /* compute missing values, prefer sockets over cores over threads */
+    /* compute missing values based on the provided ones */
     if (cpus == 0 && maxcpus == 0) {
         sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
@@ -767,14 +768,30 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     } else {
         maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-        if (sockets == 0) {
-            cores = cores > 0 ? cores : 1;
-            threads = threads > 0 ? threads : 1;
-            sockets = maxcpus / (cores * threads);
-        } else if (cores == 0) {
-            threads = threads > 0 ? threads : 1;
-            cores = maxcpus / (sockets * threads);
-        } else if (threads == 0) {
+        if (mc->smp_prefer_sockets) {
+            /* prefer sockets over cores before 6.2 */
+            if (sockets == 0) {
+                cores = cores > 0 ? cores : 1;
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (cores * threads);
+            } else if (cores == 0) {
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * threads);
+            }
+        } else {
+            /* prefer cores over sockets since 6.2 */
+            if (cores == 0) {
+                sockets = sockets > 0 ? sockets : 1;
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * threads);
+            } else if (sockets == 0) {
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (cores * threads);
+            }
+        }
+
+        /* try to calculate omitted threads at last */
+        if (threads == 0) {
             threads = maxcpus / (sockets * cores);
         }
     }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index a37eef8057..447114e57a 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -716,6 +716,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
  */
 static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
     unsigned sockets = config->has_sockets ? config->sockets : 0;
     unsigned dies    = config->has_dies ? config->dies : 0;
@@ -726,7 +727,7 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
     /* directly default dies to 1 if it's omitted */
     dies = dies > 0 ? dies : 1;
 
-    /* compute missing values, prefer sockets over cores over threads */
+    /* compute missing values based on the provided ones */
     if (cpus == 0 && maxcpus == 0) {
         sockets = sockets > 0 ? sockets : 1;
         cores = cores > 0 ? cores : 1;
@@ -734,14 +735,30 @@ static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **err
     } else {
         maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-        if (sockets == 0) {
-            cores = cores > 0 ? cores : 1;
-            threads = threads > 0 ? threads : 1;
-            sockets = maxcpus / (dies * cores * threads);
-        } else if (cores == 0) {
-            threads = threads > 0 ? threads : 1;
-            cores = maxcpus / (sockets * dies * threads);
-        } else if (threads == 0) {
+        if (mc->smp_prefer_sockets) {
+            /* prefer sockets over cores before 6.2 */
+            if (sockets == 0) {
+                cores = cores > 0 ? cores : 1;
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (dies * cores * threads);
+            } else if (cores == 0) {
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * dies * threads);
+            }
+        } else {
+            /* prefer cores over sockets since 6.2 */
+            if (cores == 0) {
+                sockets = sockets > 0 ? sockets : 1;
+                threads = threads > 0 ? threads : 1;
+                cores = maxcpus / (sockets * dies * threads);
+            } else if (sockets == 0) {
+                threads = threads > 0 ? threads : 1;
+                sockets = maxcpus / (dies * cores * threads);
+            }
+        }
+
+        /* try to calculate omitted threads at last */
+        if (threads == 0) {
             threads = maxcpus / (sockets * dies * cores);
         }
     }
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c5da7739ce..077644ee9c 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -431,6 +431,7 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
     m->is_default = false;
     compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
     compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
+    m->smp_prefer_sockets = true;
 }
 
 DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 46cd542d17..2d97c0ab3e 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -371,6 +371,7 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
     m->alias = NULL;
     compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
     compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
+    m->smp_prefer_sockets = true;
 }
 
 DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index d39fd4e644..a481fade51 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4702,6 +4702,7 @@ static void spapr_machine_6_1_class_options(MachineClass *mc)
 {
     spapr_machine_6_2_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+    mc->smp_prefer_sockets = true;
 }
 
 DEFINE_SPAPR_MACHINE(6_1, "6.1", false);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 61aeccb163..5401c985cf 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -814,6 +814,7 @@ static void ccw_machine_6_1_class_options(MachineClass *mc)
 {
     ccw_machine_6_2_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
+    mc->smp_prefer_sockets = true;
 }
 DEFINE_CCW_MACHINE(6_1, "6.1", false);
 
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 463a5514f9..2ae039b74f 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -247,6 +247,7 @@ struct MachineClass {
     bool nvdimm_supported;
     bool numa_mem_supported;
     bool auto_enable_numa;
+    bool smp_prefer_sockets;
     const char *default_ram_id;
 
     HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
diff --git a/qemu-options.hx b/qemu-options.hx
index 9d71a661bb..5c1b0311c0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -238,7 +238,8 @@ SRST
     Historically preference was given to the coarsest topology parameters
     when computing missing values (ie sockets preferred over cores, which
     were preferred over threads), however, this behaviour is considered
-    liable to change.
+    liable to change. Prior to 6.2 the preference was sockets over cores
+    over threads. Since 6.2 the preference is cores over sockets over threads.
 ERST
 
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 10/16] machine: Use ms instead of global current_machine in sanity-check
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (8 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 09/16] machine: Prefer cores over sockets in smp parsing since 6.2 Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 11/16] machine: Tweak the order of topology members in struct CpuTopology Yanan Wang
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

In the sanity-check of smp_cpus and max_cpus against mc in function
machine_set_smp(), we are now using ms->smp.max_cpus for the check
but using current_machine->smp.max_cpus in the error message.
Tweak this by uniformly using the local ms.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/core/machine.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index f2a34d98c0..12d7416053 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -881,7 +881,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
     } else if (ms->smp.max_cpus > mc->max_cpus) {
         error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
                    "supported by machine '%s' is %d",
-                   current_machine->smp.max_cpus,
+                   ms->smp.max_cpus,
                    mc->name, mc->max_cpus);
     }
 
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 11/16] machine: Tweak the order of topology members in struct CpuTopology
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (9 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 10/16] machine: Use ms instead of global current_machine in sanity-check Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 12/16] machine: Make smp_parse generic enough for all arches Yanan Wang
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Now that all the possible topology parameters are integrated in struct
CpuTopology, tweak the order of topology members to be "cpus/sockets/
dies/cores/threads/maxcpus" for readability and consistency. We also
tweak the comment by adding explanation of dies parameter.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>
---
 hw/core/machine.c   | 8 ++++----
 include/hw/boards.h | 7 ++++---
 2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 12d7416053..83cbdcce47 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -829,11 +829,11 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
 {
     MachineState *ms = MACHINE(obj);
     SMPConfiguration *config = &(SMPConfiguration){
-        .has_cores = true, .cores = ms->smp.cores,
+        .has_cpus = true, .cpus = ms->smp.cpus,
         .has_sockets = true, .sockets = ms->smp.sockets,
         .has_dies = true, .dies = ms->smp.dies,
+        .has_cores = true, .cores = ms->smp.cores,
         .has_threads = true, .threads = ms->smp.threads,
-        .has_cpus = true, .cpus = ms->smp.cpus,
         .has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
     };
     if (!visit_type_SMPConfiguration(v, name, &config, &error_abort)) {
@@ -1060,10 +1060,10 @@ static void machine_initfn(Object *obj)
     /* default to mc->default_cpus */
     ms->smp.cpus = mc->default_cpus;
     ms->smp.max_cpus = mc->default_cpus;
-    ms->smp.cores = 1;
+    ms->smp.sockets = 1;
     ms->smp.dies = 1;
+    ms->smp.cores = 1;
     ms->smp.threads = 1;
-    ms->smp.sockets = 1;
 }
 
 static void machine_finalize(Object *obj)
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2ae039b74f..2a1bba86c0 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -275,17 +275,18 @@ typedef struct DeviceMemoryState {
 /**
  * CpuTopology:
  * @cpus: the number of present logical processors on the machine
- * @cores: the number of cores in one package
- * @threads: the number of threads in one core
  * @sockets: the number of sockets on the machine
+ * @dies: the number of dies in one socket
+ * @cores: the number of cores in one die
+ * @threads: the number of threads in one core
  * @max_cpus: the maximum number of logical processors on the machine
  */
 typedef struct CpuTopology {
     unsigned int cpus;
+    unsigned int sockets;
     unsigned int dies;
     unsigned int cores;
     unsigned int threads;
-    unsigned int sockets;
     unsigned int max_cpus;
 } CpuTopology;
 
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 12/16] machine: Make smp_parse generic enough for all arches
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (10 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 11/16] machine: Tweak the order of topology members in struct CpuTopology Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 13/16] machine: Remove smp_parse callback from MachineClass Yanan Wang
                   ` (4 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Currently the only difference between smp_parse and pc_smp_parse
is the support of dies parameter and the related error reporting.
With some arch compat variables like "bool dies_supported", we can
make smp_parse generic enough for all arches and the PC specific
one can be removed.

Making smp_parse() generic enough can reduce code duplication and
ease the code maintenance, and also allows extending the topology
with more arch specific members (e.g., clusters) in the future.

Suggested-by: Andrew Jones <drjones@redhat.com>
Suggested-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c   | 91 +++++++++++++++++++++++++++++++++++----------
 hw/i386/pc.c        | 84 +----------------------------------------
 include/hw/boards.h |  9 +++++
 3 files changed, 81 insertions(+), 103 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 83cbdcce47..12872d7715 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -746,20 +746,69 @@ void machine_set_cpu_numa_node(MachineState *machine,
     }
 }
 
+/*
+ * Report information of a machine's supported CPU topology hierarchy.
+ * Topology members will be ordered from the largest to the smallest
+ * in the string.
+ */
+static char *cpu_hierarchy_to_string(MachineState *ms)
+{
+    MachineClass *mc = MACHINE_GET_CLASS(ms);
+    GString *s = g_string_new(NULL);
+
+    g_string_append_printf(s, "sockets (%u)", ms->smp.sockets);
+
+    if (mc->smp_props.dies_supported) {
+        g_string_append_printf(s, " * dies (%u)", ms->smp.dies);
+    }
+
+    g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
+    g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
+
+    return g_string_free(s, false);
+}
+
+/*
+ * smp_parse - Generic function used to parse the given SMP configuration
+ *
+ * Any missing parameter in "cpus/maxcpus/sockets/cores/threads" will be
+ * automatically computed based on the provided ones.
+ *
+ * In the calculation of omitted sockets/cores/threads: we prefer sockets
+ * over cores over threads before 6.2, while preferring cores over sockets
+ * over threads since 6.2.
+ *
+ * In the calculation of cpus/maxcpus: When both maxcpus and cpus are omitted,
+ * maxcpus will be computed from the given parameters and cpus will be set
+ * equal to maxcpus. When only one of maxcpus and cpus is given then the
+ * omitted one will be set to its given counterpart's value. Both maxcpus and
+ * cpus may be specified, but maxcpus must be equal to or greater than cpus.
+ *
+ * For compatibility, apart from the parameters that will be computed, newly
+ * introduced topology members which are likely to be target specific should
+ * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
+ */
 static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
     unsigned sockets = config->has_sockets ? config->sockets : 0;
+    unsigned dies    = config->has_dies ? config->dies : 0;
     unsigned cores   = config->has_cores ? config->cores : 0;
     unsigned threads = config->has_threads ? config->threads : 0;
     unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
-    if (config->has_dies && config->dies > 1) {
+    /*
+     * If not supported by the machine, a topology parameter must be
+     * omitted or specified equal to 1.
+     */
+    if (!mc->smp_props.dies_supported && dies > 1) {
         error_setg(errp, "dies not supported by this machine's CPU topology");
         return;
     }
 
+    dies = dies > 0 ? dies : 1;
+
     /* compute missing values based on the provided ones */
     if (cpus == 0 && maxcpus == 0) {
         sockets = sockets > 0 ? sockets : 1;
@@ -773,55 +822,57 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
             if (sockets == 0) {
                 cores = cores > 0 ? cores : 1;
                 threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (cores * threads);
+                sockets = maxcpus / (dies * cores * threads);
             } else if (cores == 0) {
                 threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * threads);
+                cores = maxcpus / (sockets * dies * threads);
             }
         } else {
             /* prefer cores over sockets since 6.2 */
             if (cores == 0) {
                 sockets = sockets > 0 ? sockets : 1;
                 threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * threads);
+                cores = maxcpus / (sockets * dies * threads);
             } else if (sockets == 0) {
                 threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (cores * threads);
+                sockets = maxcpus / (dies * cores * threads);
             }
         }
 
         /* try to calculate omitted threads at last */
         if (threads == 0) {
-            threads = maxcpus / (sockets * cores);
+            threads = maxcpus / (sockets * dies * cores);
         }
     }
 
-    maxcpus = maxcpus > 0 ? maxcpus : sockets * cores * threads;
+    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
     cpus = cpus > 0 ? cpus : maxcpus;
 
-    if (sockets * cores * threads != maxcpus) {
+    ms->smp.cpus = cpus;
+    ms->smp.sockets = sockets;
+    ms->smp.dies = dies;
+    ms->smp.cores = cores;
+    ms->smp.threads = threads;
+    ms->smp.max_cpus = maxcpus;
+
+    /* sanity-check of the computed topology */
+    if (sockets * dies * cores * threads != maxcpus) {
+        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
         error_setg(errp, "Invalid CPU topology: "
                    "product of the hierarchy must match maxcpus: "
-                   "sockets (%u) * cores (%u) * threads (%u) "
-                   "!= maxcpus (%u)",
-                   sockets, cores, threads, maxcpus);
+                   "%s != maxcpus (%u)",
+                   topo_msg, maxcpus);
         return;
     }
 
     if (maxcpus < cpus) {
+        g_autofree char *topo_msg = cpu_hierarchy_to_string(ms);
         error_setg(errp, "Invalid CPU topology: "
                    "maxcpus must be equal to or greater than smp: "
-                   "sockets (%u) * cores (%u) * threads (%u) "
-                   "== maxcpus (%u) < smp_cpus (%u)",
-                   sockets, cores, threads, maxcpus, cpus);
+                   "%s == maxcpus (%u) < smp_cpus (%u)",
+                   topo_msg, maxcpus, cpus);
         return;
     }
-
-    ms->smp.cpus = cpus;
-    ms->smp.sockets = sockets;
-    ms->smp.cores = cores;
-    ms->smp.threads = threads;
-    ms->smp.max_cpus = maxcpus;
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 447114e57a..468fe8e0fb 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -710,88 +710,6 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level)
     }
 }
 
-/*
- * This function is very similar to smp_parse()
- * in hw/core/machine.c but includes CPU die support.
- */
-static void pc_smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
-{
-    MachineClass *mc = MACHINE_GET_CLASS(ms);
-    unsigned cpus    = config->has_cpus ? config->cpus : 0;
-    unsigned sockets = config->has_sockets ? config->sockets : 0;
-    unsigned dies    = config->has_dies ? config->dies : 0;
-    unsigned cores   = config->has_cores ? config->cores : 0;
-    unsigned threads = config->has_threads ? config->threads : 0;
-    unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
-
-    /* directly default dies to 1 if it's omitted */
-    dies = dies > 0 ? dies : 1;
-
-    /* compute missing values based on the provided ones */
-    if (cpus == 0 && maxcpus == 0) {
-        sockets = sockets > 0 ? sockets : 1;
-        cores = cores > 0 ? cores : 1;
-        threads = threads > 0 ? threads : 1;
-    } else {
-        maxcpus = maxcpus > 0 ? maxcpus : cpus;
-
-        if (mc->smp_prefer_sockets) {
-            /* prefer sockets over cores before 6.2 */
-            if (sockets == 0) {
-                cores = cores > 0 ? cores : 1;
-                threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
-            } else if (cores == 0) {
-                threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
-            }
-        } else {
-            /* prefer cores over sockets since 6.2 */
-            if (cores == 0) {
-                sockets = sockets > 0 ? sockets : 1;
-                threads = threads > 0 ? threads : 1;
-                cores = maxcpus / (sockets * dies * threads);
-            } else if (sockets == 0) {
-                threads = threads > 0 ? threads : 1;
-                sockets = maxcpus / (dies * cores * threads);
-            }
-        }
-
-        /* try to calculate omitted threads at last */
-        if (threads == 0) {
-            threads = maxcpus / (sockets * dies * cores);
-        }
-    }
-
-    maxcpus = maxcpus > 0 ? maxcpus : sockets * dies * cores * threads;
-    cpus = cpus > 0 ? cpus : maxcpus;
-
-    if (sockets * dies * cores * threads != maxcpus) {
-        error_setg(errp, "Invalid CPU topology: "
-                   "product of the hierarchy must match maxcpus: "
-                   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
-                   "!= maxcpus (%u)",
-                   sockets, dies, cores, threads, maxcpus);
-        return;
-    }
-
-    if (maxcpus < cpus) {
-        error_setg(errp, "Invalid CPU topology: "
-                   "maxcpus must be equal to or greater than smp: "
-                   "sockets (%u) * dies (%u) * cores (%u) * threads (%u) "
-                   "== maxcpus (%u) < smp_cpus (%u)",
-                   sockets, dies, cores, threads, maxcpus, cpus);
-        return;
-    }
-
-    ms->smp.cpus = cpus;
-    ms->smp.sockets = sockets;
-    ms->smp.dies = dies;
-    ms->smp.cores = cores;
-    ms->smp.threads = threads;
-    ms->smp.max_cpus = maxcpus;
-}
-
 static
 void pc_machine_done(Notifier *notifier, void *data)
 {
@@ -1742,7 +1660,6 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     mc->auto_enable_numa_with_memdev = true;
     mc->has_hotpluggable_cpus = true;
     mc->default_boot_order = "cad";
-    mc->smp_parse = pc_smp_parse;
     mc->block_default_type = IF_IDE;
     mc->max_cpus = 255;
     mc->reset = pc_machine_reset;
@@ -1753,6 +1670,7 @@ static void pc_machine_class_init(ObjectClass *oc, void *data)
     hc->unplug = pc_machine_device_unplug_cb;
     mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE;
     mc->nvdimm_supported = true;
+    mc->smp_props.dies_supported = true;
     mc->default_ram_id = "pc.ram";
 
     object_class_property_add(oc, PC_MACHINE_MAX_RAM_BELOW_4G, "size",
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 2a1bba86c0..72a23e4e0f 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -108,6 +108,14 @@ typedef struct {
     CPUArchId cpus[];
 } CPUArchIdList;
 
+/**
+ * SMPCompatProps:
+ * @dies_supported - whether dies are supported by the machine
+ */
+typedef struct {
+    bool dies_supported;
+} SMPCompatProps;
+
 /**
  * MachineClass:
  * @deprecation_reason: If set, the machine is marked as deprecated. The
@@ -248,6 +256,7 @@ struct MachineClass {
     bool numa_mem_supported;
     bool auto_enable_numa;
     bool smp_prefer_sockets;
+    SMPCompatProps smp_props;
     const char *default_ram_id;
 
     HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 13/16] machine: Remove smp_parse callback from MachineClass
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (11 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 12/16] machine: Make smp_parse generic enough for all arches Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 14/16] machine: Move smp_prefer_sockets to struct SMPCompatProps Yanan Wang
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Now we have a generic smp parser for all arches, and there will
not be any other arch specific ones, so let's remove the callback
from MachineClass and call the parser directly.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c   | 3 +--
 include/hw/boards.h | 5 -----
 2 files changed, 1 insertion(+), 7 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 12872d7715..8b0f1aed83 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -918,7 +918,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
                     "CPU topology parameters must be greater than zero");
     }
 
-    mc->smp_parse(ms, config, errp);
+    smp_parse(ms, config, errp);
     if (*errp) {
         goto out_free;
     }
@@ -947,7 +947,6 @@ static void machine_class_init(ObjectClass *oc, void *data)
     /* Default 128 MB as guest ram size */
     mc->default_ram_size = 128 * MiB;
     mc->rom_file_has_mr = true;
-    mc->smp_parse = smp_parse;
 
     /* numa node memory size aligned on 8MB by default.
      * On Linux, each node's border has to be 8MB aligned
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 72a23e4e0f..fa284e01e9 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -177,10 +177,6 @@ typedef struct {
  *    kvm-type may be NULL if it is not needed.
  * @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 more
- *    machine specific topology fields, such as smp_dies for PCMachine.
  * @hotplug_allowed:
  *    If the hook is provided, then it'll be called for each device
  *    hotplug to check whether the device hotplug is allowed.  Return
@@ -217,7 +213,6 @@ struct MachineClass {
     void (*reset)(MachineState *state);
     void (*wakeup)(MachineState *state);
     int (*kvm_type)(MachineState *machine, const char *arg);
-    void (*smp_parse)(MachineState *ms, SMPConfiguration *config, Error **errp);
 
     BlockInterfaceType block_default_type;
     int units_per_default_bus;
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 14/16] machine: Move smp_prefer_sockets to struct SMPCompatProps
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (12 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 13/16] machine: Remove smp_parse callback from MachineClass Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 15/16] machine: Put all sanity-check in the generic SMP parser Yanan Wang
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Now we have a common structure SMPCompatProps used to store information
about SMP compatibility stuff, so we can also move smp_prefer_sockets
there for cleaner code.

No functional change intended.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/arm/virt.c              | 2 +-
 hw/core/machine.c          | 2 +-
 hw/i386/pc_piix.c          | 2 +-
 hw/i386/pc_q35.c           | 2 +-
 hw/ppc/spapr.c             | 2 +-
 hw/s390x/s390-virtio-ccw.c | 2 +-
 include/hw/boards.h        | 3 ++-
 7 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 8c13deb5db..7170aaacd5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -2815,7 +2815,7 @@ static void virt_machine_6_1_options(MachineClass *mc)
 
     virt_machine_6_2_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-    mc->smp_prefer_sockets = true;
+    mc->smp_props.prefer_sockets = true;
 
     /* qemu ITS was introduced with 6.2 */
     vmc->no_tcg_its = true;
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 8b0f1aed83..54f04a5ac6 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -817,7 +817,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     } else {
         maxcpus = maxcpus > 0 ? maxcpus : cpus;
 
-        if (mc->smp_prefer_sockets) {
+        if (mc->smp_props.prefer_sockets) {
             /* prefer sockets over cores before 6.2 */
             if (sockets == 0) {
                 cores = cores > 0 ? cores : 1;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 077644ee9c..5efb6f1949 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -431,7 +431,7 @@ static void pc_i440fx_6_1_machine_options(MachineClass *m)
     m->is_default = false;
     compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
     compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
-    m->smp_prefer_sockets = true;
+    m->smp_props.prefer_sockets = true;
 }
 
 DEFINE_I440FX_MACHINE(v6_1, "pc-i440fx-6.1", NULL,
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 2d97c0ab3e..9eae40e32c 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -371,7 +371,7 @@ static void pc_q35_6_1_machine_options(MachineClass *m)
     m->alias = NULL;
     compat_props_add(m->compat_props, hw_compat_6_1, hw_compat_6_1_len);
     compat_props_add(m->compat_props, pc_compat_6_1, pc_compat_6_1_len);
-    m->smp_prefer_sockets = true;
+    m->smp_props.prefer_sockets = true;
 }
 
 DEFINE_Q35_MACHINE(v6_1, "pc-q35-6.1", NULL,
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a481fade51..efdea43c0d 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4702,7 +4702,7 @@ static void spapr_machine_6_1_class_options(MachineClass *mc)
 {
     spapr_machine_6_2_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-    mc->smp_prefer_sockets = true;
+    mc->smp_props.prefer_sockets = true;
 }
 
 DEFINE_SPAPR_MACHINE(6_1, "6.1", false);
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 5401c985cf..653587ea62 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -814,7 +814,7 @@ static void ccw_machine_6_1_class_options(MachineClass *mc)
 {
     ccw_machine_6_2_class_options(mc);
     compat_props_add(mc->compat_props, hw_compat_6_1, hw_compat_6_1_len);
-    mc->smp_prefer_sockets = true;
+    mc->smp_props.prefer_sockets = true;
 }
 DEFINE_CCW_MACHINE(6_1, "6.1", false);
 
diff --git a/include/hw/boards.h b/include/hw/boards.h
index fa284e01e9..5adbcbb99b 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -110,9 +110,11 @@ typedef struct {
 
 /**
  * SMPCompatProps:
+ * @prefer_sockets - whether sockets are preferred over cores in smp parsing
  * @dies_supported - whether dies are supported by the machine
  */
 typedef struct {
+    bool prefer_sockets;
     bool dies_supported;
 } SMPCompatProps;
 
@@ -250,7 +252,6 @@ struct MachineClass {
     bool nvdimm_supported;
     bool numa_mem_supported;
     bool auto_enable_numa;
-    bool smp_prefer_sockets;
     SMPCompatProps smp_props;
     const char *default_ram_id;
 
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 15/16] machine: Put all sanity-check in the generic SMP parser
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (13 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 14/16] machine: Move smp_prefer_sockets to struct SMPCompatProps Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
  2021-09-29 12:39 ` [PATCH v12 00/16] machine: smp parsing fixes and improvement Paolo Bonzini
  16 siblings, 0 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Put both sanity-check of the input SMP configuration and sanity-check
of the output SMP configuration uniformly in the generic parser. Then
machine_set_smp() will become cleaner, also all the invalid scenarios
can be tested only by calling the parser.

Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
Reviewed-by: Andrew Jones <drjones@redhat.com>
Reviewed-by: Pankaj Gupta <pankaj.gupta@ionos.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
---
 hw/core/machine.c | 63 +++++++++++++++++++++++------------------------
 1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 54f04a5ac6..4dc936732e 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -798,6 +798,20 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
     unsigned threads = config->has_threads ? config->threads : 0;
     unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
 
+    /*
+     * Specified CPU topology parameters must be greater than zero,
+     * explicit configuration like "cpus=0" is not allowed.
+     */
+    if ((config->has_cpus && config->cpus == 0) ||
+        (config->has_sockets && config->sockets == 0) ||
+        (config->has_dies && config->dies == 0) ||
+        (config->has_cores && config->cores == 0) ||
+        (config->has_threads && config->threads == 0) ||
+        (config->has_maxcpus && config->maxcpus == 0)) {
+        warn_report("Deprecated CPU topology (considered invalid): "
+                    "CPU topology parameters must be greater than zero");
+    }
+
     /*
      * If not supported by the machine, a topology parameter must be
      * omitted or specified equal to 1.
@@ -873,6 +887,22 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
                    topo_msg, maxcpus, cpus);
         return;
     }
+
+    if (ms->smp.cpus < mc->min_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
+                   "supported by machine '%s' is %d",
+                   ms->smp.cpus,
+                   mc->name, mc->min_cpus);
+        return;
+    }
+
+    if (ms->smp.max_cpus > mc->max_cpus) {
+        error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
+                   "supported by machine '%s' is %d",
+                   ms->smp.max_cpus,
+                   mc->name, mc->max_cpus);
+        return;
+    }
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
@@ -895,7 +925,6 @@ static void machine_get_smp(Object *obj, Visitor *v, const char *name,
 static void machine_set_smp(Object *obj, Visitor *v, const char *name,
                             void *opaque, Error **errp)
 {
-    MachineClass *mc = MACHINE_GET_CLASS(obj);
     MachineState *ms = MACHINE(obj);
     SMPConfiguration *config;
     ERRP_GUARD();
@@ -904,40 +933,10 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    /*
-     * Specified CPU topology parameters must be greater than zero,
-     * explicit configuration like "cpus=0" is not allowed.
-     */
-    if ((config->has_cpus && config->cpus == 0) ||
-        (config->has_sockets && config->sockets == 0) ||
-        (config->has_dies && config->dies == 0) ||
-        (config->has_cores && config->cores == 0) ||
-        (config->has_threads && config->threads == 0) ||
-        (config->has_maxcpus && config->maxcpus == 0)) {
-        warn_report("Deprecated CPU topology (considered invalid): "
-                    "CPU topology parameters must be greater than zero");
-    }
-
     smp_parse(ms, config, errp);
     if (*errp) {
-        goto out_free;
-    }
-
-    /* sanity-check smp_cpus and max_cpus against mc */
-    if (ms->smp.cpus < mc->min_cpus) {
-        error_setg(errp, "Invalid SMP CPUs %d. The min CPUs "
-                   "supported by machine '%s' is %d",
-                   ms->smp.cpus,
-                   mc->name, mc->min_cpus);
-    } else if (ms->smp.max_cpus > mc->max_cpus) {
-        error_setg(errp, "Invalid SMP CPUs %d. The max CPUs "
-                   "supported by machine '%s' is %d",
-                   ms->smp.max_cpus,
-                   mc->name, mc->max_cpus);
+        qapi_free_SMPConfiguration(config);
     }
-
-out_free:
-    qapi_free_SMPConfiguration(config);
 }
 
 static void machine_class_init(ObjectClass *oc, void *data)
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (14 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 15/16] machine: Put all sanity-check in the generic SMP parser Yanan Wang
@ 2021-09-29  2:58 ` Yanan Wang
  2021-09-29  8:27   ` Philippe Mathieu-Daudé
                     ` (3 more replies)
  2021-09-29 12:39 ` [PATCH v12 00/16] machine: smp parsing fixes and improvement Paolo Bonzini
  16 siblings, 4 replies; 33+ messages in thread
From: Yanan Wang @ 2021-09-29  2:58 UTC (permalink / raw)
  To: Eduardo Habkost, Paolo Bonzini, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, qemu-ppc, David Gibson

Quoting one of the Rules described in include/qapi/error.h:
"
Whenever practical, also return a value that indicates success /
failure.  This can make the error checking more concise, and can
avoid useless error object creation and destruction.  Note that
we still have many functions returning void.  We recommend
• bool-valued functions return true on success / false on failure,
• pointer-valued functions return non-null / null pointer, and
• integer-valued functions return non-negative / negative.
"

So make smp_parse() return true on success and false on failure,
so that we can more laconically check whether the parsing has
succeeded without touching the errp.

Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
---
 hw/core/machine.c | 17 +++++++++--------
 1 file changed, 9 insertions(+), 8 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 4dc936732e..3e3a2707af 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -788,7 +788,7 @@ static char *cpu_hierarchy_to_string(MachineState *ms)
  * introduced topology members which are likely to be target specific should
  * be directly set as 1 if they are omitted (e.g. dies for PC since 4.1).
  */
-static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
+static bool smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
 {
     MachineClass *mc = MACHINE_GET_CLASS(ms);
     unsigned cpus    = config->has_cpus ? config->cpus : 0;
@@ -818,7 +818,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
      */
     if (!mc->smp_props.dies_supported && dies > 1) {
         error_setg(errp, "dies not supported by this machine's CPU topology");
-        return;
+        return false;
     }
 
     dies = dies > 0 ? dies : 1;
@@ -876,7 +876,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
                    "product of the hierarchy must match maxcpus: "
                    "%s != maxcpus (%u)",
                    topo_msg, maxcpus);
-        return;
+        return false;
     }
 
     if (maxcpus < cpus) {
@@ -885,7 +885,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
                    "maxcpus must be equal to or greater than smp: "
                    "%s == maxcpus (%u) < smp_cpus (%u)",
                    topo_msg, maxcpus, cpus);
-        return;
+        return false;
     }
 
     if (ms->smp.cpus < mc->min_cpus) {
@@ -893,7 +893,7 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
                    "supported by machine '%s' is %d",
                    ms->smp.cpus,
                    mc->name, mc->min_cpus);
-        return;
+        return false;
     }
 
     if (ms->smp.max_cpus > mc->max_cpus) {
@@ -901,8 +901,10 @@ static void smp_parse(MachineState *ms, SMPConfiguration *config, Error **errp)
                    "supported by machine '%s' is %d",
                    ms->smp.max_cpus,
                    mc->name, mc->max_cpus);
-        return;
+        return false;
     }
+
+    return true;
 }
 
 static void machine_get_smp(Object *obj, Visitor *v, const char *name,
@@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
         return;
     }
 
-    smp_parse(ms, config, errp);
-    if (*errp) {
+    if (!smp_parse(ms, config, errp)) {
         qapi_free_SMPConfiguration(config);
     }
 }
-- 
2.19.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
@ 2021-09-29  8:27   ` Philippe Mathieu-Daudé
  2021-09-29  8:28   ` Daniel P. Berrangé
                     ` (2 subsequent siblings)
  3 siblings, 0 replies; 33+ messages in thread
From: Philippe Mathieu-Daudé @ 2021-09-29  8:27 UTC (permalink / raw)
  To: Yanan Wang, Eduardo Habkost, Paolo Bonzini,
	Daniel P . Berrangé,
	Andrew Jones, Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, Cornelia Huck,
	qemu-devel, qemu-s390x, qemu-arm, Michael S . Tsirkin,
	wanghaibin.wang, qemu-ppc, David Gibson

On 9/29/21 04:58, Yanan Wang wrote:
> Quoting one of the Rules described in include/qapi/error.h:
> "
> Whenever practical, also return a value that indicates success /
> failure.  This can make the error checking more concise, and can
> avoid useless error object creation and destruction.  Note that
> we still have many functions returning void.  We recommend
> • bool-valued functions return true on success / false on failure,
> • pointer-valued functions return non-null / null pointer, and
> • integer-valued functions return non-negative / negative.
> "
> 
> So make smp_parse() return true on success and false on failure,
> so that we can more laconically check whether the parsing has
> succeeded without touching the errp.
> 
> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
> ---
>  hw/core/machine.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)

Thank you!

Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com>



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
  2021-09-29  8:27   ` Philippe Mathieu-Daudé
@ 2021-09-29  8:28   ` Daniel P. Berrangé
  2021-09-29 11:22   ` Markus Armbruster
  2021-10-01 17:08   ` Paolo Bonzini
  3 siblings, 0 replies; 33+ messages in thread
From: Daniel P. Berrangé @ 2021-09-29  8:28 UTC (permalink / raw)
  To: Yanan Wang
  Cc: Peter Maydell, Andrew Jones, Cornelia Huck, Eduardo Habkost,
	Pierre Morel, Michael S . Tsirkin, Pankaj Gupta,
	Markus Armbruster, qemu-devel, qemu-s390x, qemu-arm, qemu-ppc,
	wanghaibin.wang, Paolo Bonzini, Philippe Mathieu-Daudé,
	David Gibson

On Wed, Sep 29, 2021 at 10:58:16AM +0800, Yanan Wang wrote:
> Quoting one of the Rules described in include/qapi/error.h:
> "
> Whenever practical, also return a value that indicates success /
> failure.  This can make the error checking more concise, and can
> avoid useless error object creation and destruction.  Note that
> we still have many functions returning void.  We recommend
> • bool-valued functions return true on success / false on failure,
> • pointer-valued functions return non-null / null pointer, and
> • integer-valued functions return non-negative / negative.
> "
> 
> So make smp_parse() return true on success and false on failure,
> so that we can more laconically check whether the parsing has
> succeeded without touching the errp.
> 
> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
> ---
>  hw/core/machine.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)

Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>


Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
  2021-09-29  8:27   ` Philippe Mathieu-Daudé
  2021-09-29  8:28   ` Daniel P. Berrangé
@ 2021-09-29 11:22   ` Markus Armbruster
  2021-10-01 17:08   ` Paolo Bonzini
  3 siblings, 0 replies; 33+ messages in thread
From: Markus Armbruster @ 2021-09-29 11:22 UTC (permalink / raw)
  To: Yanan Wang
  Cc: Peter Maydell, Andrew Jones, Cornelia Huck,
	Daniel P . Berrangé,
	Eduardo Habkost, Pierre Morel, Michael S . Tsirkin, Pankaj Gupta,
	qemu-devel, qemu-s390x, qemu-arm, qemu-ppc, wanghaibin.wang,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	David Gibson

Yanan Wang <wangyanan55@huawei.com> writes:

> Quoting one of the Rules described in include/qapi/error.h:
> "
> Whenever practical, also return a value that indicates success /
> failure.  This can make the error checking more concise, and can
> avoid useless error object creation and destruction.  Note that
> we still have many functions returning void.  We recommend
> • bool-valued functions return true on success / false on failure,
> • pointer-valued functions return non-null / null pointer, and
> • integer-valued functions return non-negative / negative.
> "
>
> So make smp_parse() return true on success and false on failure,
> so that we can more laconically check whether the parsing has
> succeeded without touching the errp.
>
> Suggested-by: Philippe Mathieu-Daudé <philmd@redhat.com>
> Signed-off-by: Yanan Wang <wangyanan55@huawei.com>
> ---
>  hw/core/machine.c | 17 +++++++++--------
>  1 file changed, 9 insertions(+), 8 deletions(-)
>
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 4dc936732e..3e3a2707af 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c

[...]

> @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
   {
       MachineState *ms = MACHINE(obj);
       SMPConfiguration *config;
       ERRP_GUARD();

I believe ERRP_GUARD() is now redundant and should be dropped.

       if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
>          return;
>      }
>  
> -    smp_parse(ms, config, errp);
> -    if (*errp) {
> +    if (!smp_parse(ms, config, errp)) {
>          qapi_free_SMPConfiguration(config);
>      }
>  }



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 00/16] machine: smp parsing fixes and improvement
  2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
                   ` (15 preceding siblings ...)
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
@ 2021-09-29 12:39 ` Paolo Bonzini
  2021-09-29 14:46   ` Markus Armbruster
  16 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2021-09-29 12:39 UTC (permalink / raw)
  To: Yanan Wang, Eduardo Habkost, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, qemu-ppc,
	Cornelia Huck, qemu-devel, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, David Gibson

On 29/09/21 04:58, Yanan Wang wrote:
> Hi,
> 
> This is a new version (v12) with minor update suggested by Daniel
> and Philippe. Two new commits (#1 and #16) are added. Thanks!

Queued, thanks!

Paolo

> Summary of v12:
> 1) Specifying a CPU topology parameter as zero was implicitly allowed
> but undocumented before, while now it's explicitly deprecated.
> 
> 2) Refactor/fixes of the smp parsers.
> 
> 3) For consistency, maxcpus is now uniformly used to calculate the
> omitted topology members.
> 
> 4) Improve the error reporting of the parsers.
> 
> 5) It's also suggested that we should start to prefer cores over sockets
> over threads on the newer machine types, which will make the computed
> virtual topology more reflective of the real hardware. Related discussion
> can be found in [1].
> [1] https://lore.kernel.org/qemu-devel/YNIgInK00yNNI4Dy@redhat.com/
> 
> 6) In order to reduce code duplication and ease the code maintenance,
> smp_parse() is converted into a generic enough parser for all arches,
> so that the arch-specific ones (e.g. pc_smp_parse) can be removed.
> It's also convenient to introduce more topology members to the generic
> parser in the future. Related discussions can be found in [2] and [3].
> [2] https://lore.kernel.org/qemu-devel/20210630115602.txmvmfe2jrzu7o67@gator.home/
> [3] https://lore.kernel.org/qemu-devel/YPFN83pKBt7F97kW@redhat.com/
> 
> Changelogs:
> 
> v11->v12:
> - add an extra commit 16/16 to make smp_parse() return a boolean (Philippe)
> - split the machine.json Doc fix out into a separate patch 01/16 (Daniel)
> - add R-bs for the series from Daniel and Philippe, thanks!
> - v11: https://lore.kernel.org/qemu-devel/20210928035755.11684-1-wangyanan55@huawei.com/
> 
> v10->v11:
> - only update patch 11/14
>    use GString APIs to build the cpu topology hierarchy string (Daniel)
>    refine the comments of smp_parse()
> - v10: https://lore.kernel.org/qemu-devel/20210926084541.17352-1-wangyanan55@huawei.com/
> 
> v9->v10:
> - rebased on latest upstream commit 11a1199846.
>    there is no change of the patches in v10, except minor update
>    in 08/14 to resolve merge conflict with master.
> - To make this series more acceptable, drop the last two patches
>    about SMP unit test, since the scalability of the test is not
>    optimally designed after rethinking of it. So I will resend the
>    test related patches separately after refining them.
> - v9: https://lore.kernel.org/qemu-devel/20210910073025.16480-1-wangyanan55@huawei.com/
> 
> Yanan Wang (16):
>    qapi/machine: Fix an incorrect comment of SMPConfiguration
>    machine: Deprecate "parameter=0" SMP configurations
>    machine: Minor refactor/fix for the smp parsers
>    machine: Uniformly use maxcpus to calculate the omitted parameters
>    machine: Set the value of cpus to match maxcpus if it's omitted
>    machine: Improve the error reporting of smp parsing
>    qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg
>    qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split
>    machine: Prefer cores over sockets in smp parsing since 6.2
>    machine: Use ms instead of global current_machine in sanity-check
>    machine: Tweak the order of topology members in struct CpuTopology
>    machine: Make smp_parse generic enough for all arches
>    machine: Remove smp_parse callback from MachineClass
>    machine: Move smp_prefer_sockets to struct SMPCompatProps
>    machine: Put all sanity-check in the generic SMP parser
>    machine: Make smp_parse return a boolean
> 
>   docs/about/deprecated.rst  |  15 +++
>   hw/arm/virt.c              |   1 +
>   hw/core/machine.c          | 206 ++++++++++++++++++++++++++-----------
>   hw/i386/pc.c               |  63 +-----------
>   hw/i386/pc_piix.c          |   1 +
>   hw/i386/pc_q35.c           |   1 +
>   hw/ppc/spapr.c             |   1 +
>   hw/s390x/s390-virtio-ccw.c |   1 +
>   include/hw/boards.h        |  23 +++--
>   qapi/machine.json          |   2 +-
>   qemu-options.hx            |  24 +++--
>   tests/qtest/numa-test.c    |   6 +-
>   12 files changed, 201 insertions(+), 143 deletions(-)
> 
> --
> 2.19.1
> 
> 



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 00/16] machine: smp parsing fixes and improvement
  2021-09-29 12:39 ` [PATCH v12 00/16] machine: smp parsing fixes and improvement Paolo Bonzini
@ 2021-09-29 14:46   ` Markus Armbruster
  2021-09-29 14:57     ` Paolo Bonzini
  0 siblings, 1 reply; 33+ messages in thread
From: Markus Armbruster @ 2021-09-29 14:46 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, Andrew Jones, Daniel P . Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, qemu-ppc,
	Cornelia Huck, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 29/09/21 04:58, Yanan Wang wrote:
>> Hi,
>> This is a new version (v12) with minor update suggested by Daniel
>> and Philippe. Two new commits (#1 and #16) are added. Thanks!
>
> Queued, thanks!

Could you amend PATCH 16 to drop ERRP_GUARD() in machine_set_smp()?



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 00/16] machine: smp parsing fixes and improvement
  2021-09-29 14:46   ` Markus Armbruster
@ 2021-09-29 14:57     ` Paolo Bonzini
  2021-09-30  1:02       ` wangyanan (Y)
  0 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2021-09-29 14:57 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Peter Maydell, Andrew Jones, Daniel P . Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	qemu-ppc, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

On 29/09/21 16:46, Markus Armbruster wrote:
> Paolo Bonzini <pbonzini@redhat.com> writes:
> 
>> On 29/09/21 04:58, Yanan Wang wrote:
>>> Hi,
>>> This is a new version (v12) with minor update suggested by Daniel
>>> and Philippe. Two new commits (#1 and #16) are added. Thanks!
>>
>> Queued, thanks!
> 
> Could you amend PATCH 16 to drop ERRP_GUARD() in machine_set_smp()?
> 
> 

Sure.

Paolo



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 00/16] machine: smp parsing fixes and improvement
  2021-09-29 14:57     ` Paolo Bonzini
@ 2021-09-30  1:02       ` wangyanan (Y)
  0 siblings, 0 replies; 33+ messages in thread
From: wangyanan (Y) @ 2021-09-30  1:02 UTC (permalink / raw)
  To: Paolo Bonzini, Markus Armbruster
  Cc: Peter Maydell, Andrew Jones, Daniel P . Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, qemu-s390x, qemu-arm, qemu-ppc,
	wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson


On 2021/9/29 22:57, Paolo Bonzini wrote:
> On 29/09/21 16:46, Markus Armbruster wrote:
>> Paolo Bonzini <pbonzini@redhat.com> writes:
>>
>>> On 29/09/21 04:58, Yanan Wang wrote:
>>>> Hi,
>>>> This is a new version (v12) with minor update suggested by Daniel
>>>> and Philippe. Two new commits (#1 and #16) are added. Thanks!
>>>
>>> Queued, thanks!
>>
>> Could you amend PATCH 16 to drop ERRP_GUARD() in machine_set_smp()?
>>
>>
>
> Sure.
>
>
Ah, sorry, I missed that one line. Thank you for fixing it locally.

Yanan
.



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
                     ` (2 preceding siblings ...)
  2021-09-29 11:22   ` Markus Armbruster
@ 2021-10-01 17:08   ` Paolo Bonzini
  2021-10-01 17:15     ` Daniel P. Berrangé
  3 siblings, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2021-10-01 17:08 UTC (permalink / raw)
  To: Yanan Wang, Eduardo Habkost, Daniel P . Berrangé,
	Andrew Jones, Philippe Mathieu-Daudé,
	Markus Armbruster
  Cc: Peter Maydell, Pierre Morel, Pankaj Gupta, qemu-ppc,
	Cornelia Huck, qemu-devel, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, David Gibson

On 29/09/21 04:58, Yanan Wang wrote:
> @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>           return;
>       }
>   
> -    smp_parse(ms, config, errp);
> -    if (*errp) {
> +    if (!smp_parse(ms, config, errp)) {
>           qapi_free_SMPConfiguration(config);
>       }
>   }
> 

This is actually a leak, so I'm replacing this patch with

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 54f04a5ac6..d49ebc24e2 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -897,7 +897,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
  {
      MachineClass *mc = MACHINE_GET_CLASS(obj);
      MachineState *ms = MACHINE(obj);
-    SMPConfiguration *config;
+    g_autoptr(SMPConfiguration) config = NULL;
      ERRP_GUARD();
  
      if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
@@ -920,7 +920,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
  
      smp_parse(ms, config, errp);
      if (*errp) {
-        goto out_free;
+        return;
      }
  
      /* sanity-check smp_cpus and max_cpus against mc */
@@ -935,9 +935,6 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
                     ms->smp.max_cpus,
                     mc->name, mc->max_cpus);
      }
-
-out_free:
-    qapi_free_SMPConfiguration(config);
  }
  
  static void machine_class_init(ObjectClass *oc, void *data)

which removes the need.

Paolo



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-01 17:08   ` Paolo Bonzini
@ 2021-10-01 17:15     ` Daniel P. Berrangé
  2021-10-02  5:26       ` Markus Armbruster
  2021-10-02  6:40       ` Paolo Bonzini
  0 siblings, 2 replies; 33+ messages in thread
From: Daniel P. Berrangé @ 2021-10-01 17:15 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, Andrew Jones, Eduardo Habkost, Pierre Morel,
	Pankaj Gupta, qemu-ppc, Cornelia Huck, Markus Armbruster,
	qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	Michael S . Tsirkin, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

On Fri, Oct 01, 2021 at 07:08:51PM +0200, Paolo Bonzini wrote:
> On 29/09/21 04:58, Yanan Wang wrote:
> > @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
> >           return;
> >       }
> > -    smp_parse(ms, config, errp);
> > -    if (*errp) {
> > +    if (!smp_parse(ms, config, errp)) {
> >           qapi_free_SMPConfiguration(config);
> >       }
> >   }
> > 
> 
> This is actually a leak, so I'm replacing this patch with

This patch isn't adding a leak, as there's no change in
control flow / exit paths.  AFAICT, the leak was introduced
in patch 15 instead, so the code below shoudl be squashed
into that, and this patch left as-is.

> 
> diff --git a/hw/core/machine.c b/hw/core/machine.c
> index 54f04a5ac6..d49ebc24e2 100644
> --- a/hw/core/machine.c
> +++ b/hw/core/machine.c
> @@ -897,7 +897,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>  {
>      MachineClass *mc = MACHINE_GET_CLASS(obj);
>      MachineState *ms = MACHINE(obj);
> -    SMPConfiguration *config;
> +    g_autoptr(SMPConfiguration) config = NULL;
>      ERRP_GUARD();
>      if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
> @@ -920,7 +920,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>      smp_parse(ms, config, errp);
>      if (*errp) {
> -        goto out_free;
> +        return;
>      }
>      /* sanity-check smp_cpus and max_cpus against mc */
> @@ -935,9 +935,6 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>                     ms->smp.max_cpus,
>                     mc->name, mc->max_cpus);
>      }
> -
> -out_free:
> -    qapi_free_SMPConfiguration(config);
>  }
>  static void machine_class_init(ObjectClass *oc, void *data)
> 
> which removes the need.

Regards,
Daniel
-- 
|: https://berrange.com      -o-    https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org         -o-            https://fstop138.berrange.com :|
|: https://entangle-photo.org    -o-    https://www.instagram.com/dberrange :|



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-01 17:15     ` Daniel P. Berrangé
@ 2021-10-02  5:26       ` Markus Armbruster
  2021-10-02  6:40       ` Paolo Bonzini
  1 sibling, 0 replies; 33+ messages in thread
From: Markus Armbruster @ 2021-10-02  5:26 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Peter Maydell, Andrew Jones, Eduardo Habkost, Pierre Morel,
	Pankaj Gupta, qemu-ppc, Cornelia Huck, qemu-devel, Yanan Wang,
	qemu-s390x, qemu-arm, Michael S . Tsirkin, wanghaibin.wang,
	Paolo Bonzini, Philippe Mathieu-Daudé,
	David Gibson

Daniel P. Berrangé <berrange@redhat.com> writes:

> On Fri, Oct 01, 2021 at 07:08:51PM +0200, Paolo Bonzini wrote:
>> On 29/09/21 04:58, Yanan Wang wrote:
>> > @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>> >           return;
>> >       }
>> > -    smp_parse(ms, config, errp);
>> > -    if (*errp) {
>> > +    if (!smp_parse(ms, config, errp)) {
>> >           qapi_free_SMPConfiguration(config);
>> >       }
>> >   }
>> > 
>> 
>> This is actually a leak, so I'm replacing this patch with
>
> This patch isn't adding a leak, as there's no change in
> control flow / exit paths.  AFAICT, the leak was introduced
> in patch 15 instead, so the code below shoudl be squashed
> into that, and this patch left as-is.

Concur.



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-01 17:15     ` Daniel P. Berrangé
  2021-10-02  5:26       ` Markus Armbruster
@ 2021-10-02  6:40       ` Paolo Bonzini
  2021-10-02 11:27         ` Markus Armbruster
  1 sibling, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2021-10-02  6:40 UTC (permalink / raw)
  To: Daniel P. Berrangé
  Cc: Peter Maydell, Andrew Jones, Eduardo Habkost, Pierre Morel,
	Pankaj Gupta, Michael S . Tsirkin, Cornelia Huck,
	Markus Armbruster, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	qemu-ppc, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

On 01/10/21 19:15, Daniel P. Berrangé wrote:
> On Fri, Oct 01, 2021 at 07:08:51PM +0200, Paolo Bonzini wrote:
>> On 29/09/21 04:58, Yanan Wang wrote:
>>> @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>>>            return;
>>>        }
>>> -    smp_parse(ms, config, errp);
>>> -    if (*errp) {
>>> +    if (!smp_parse(ms, config, errp)) {
>>>            qapi_free_SMPConfiguration(config);
>>>        }
>>>    }
>>>
>>
>> This is actually a leak, so I'm replacing this patch with
> 
> This patch isn't adding a leak, as there's no change in
> control flow / exit paths.  AFAICT, the leak was introduced
> in patch 15 instead, so the code below shoudl be squashed
> into that, and this patch left as-is.

Yes, even better make it a separate patch and fix the conflict in patch
15.  But I'm still not sure of the wisdom of this patch.

At this point smp_parse has exactly one caller and it doesn't care about
the return value.  The "return a boolean" rule adds some complexity (and
a possibility for things to be wrong/inconsistent) to the function for
the benefit of the callers.  If there is only one caller, as is the case
here or for virtual functions, the benefit can well be zero (this case)
or negative (virtual functions).

Paolo

---------------- 8< ----------------
 From e7f944bb94a375e8ee7469ffa535ea6e11ce59e1 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Fri, 1 Oct 2021 19:04:03 +0200
Subject: [PATCH] machine: Use g_autoptr in machine_set_smp

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
  hw/core/machine.c | 7 ++-----
  1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/hw/core/machine.c b/hw/core/machine.c
index 54f04a5ac6..d49ebc24e2 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -897,7 +897,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
  {
      MachineClass *mc = MACHINE_GET_CLASS(obj);
      MachineState *ms = MACHINE(obj);
-    SMPConfiguration *config;
+    g_autoptr(SMPConfiguration) config = NULL;
      ERRP_GUARD();
  
      if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
@@ -920,7 +920,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
  
      smp_parse(ms, config, errp);
      if (*errp) {
-        goto out_free;
+        return;
      }
  
      /* sanity-check smp_cpus and max_cpus against mc */
@@ -935,9 +935,6 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
                     ms->smp.max_cpus,
                     mc->name, mc->max_cpus);
      }
-
-out_free:
-    qapi_free_SMPConfiguration(config);
  }
  
  static void machine_class_init(ObjectClass *oc, void *data)
-- 
2.31.1



^ permalink raw reply related	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-02  6:40       ` Paolo Bonzini
@ 2021-10-02 11:27         ` Markus Armbruster
  2021-10-07  3:44           ` wangyanan (Y)
  2021-10-07  8:29           ` Paolo Bonzini
  0 siblings, 2 replies; 33+ messages in thread
From: Markus Armbruster @ 2021-10-02 11:27 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, Andrew Jones, Daniel P. Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	qemu-ppc, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 01/10/21 19:15, Daniel P. Berrangé wrote:
>> On Fri, Oct 01, 2021 at 07:08:51PM +0200, Paolo Bonzini wrote:
>>> On 29/09/21 04:58, Yanan Wang wrote:
>>>> @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>>>>            return;
>>>>        }
>>>> -    smp_parse(ms, config, errp);
>>>> -    if (*errp) {
>>>> +    if (!smp_parse(ms, config, errp)) {
>>>>            qapi_free_SMPConfiguration(config);
>>>>        }
>>>>    }
>>>>
>>>
>>> This is actually a leak, so I'm replacing this patch with
>> 
>> This patch isn't adding a leak, as there's no change in
>> control flow / exit paths.  AFAICT, the leak was introduced
>> in patch 15 instead, so the code below shoudl be squashed
>> into that, and this patch left as-is.
>
> Yes, even better make it a separate patch and fix the conflict in patch
> 15.  But I'm still not sure of the wisdom of this patch.
>
> At this point smp_parse has exactly one caller and it doesn't care about
> the return value.  The "return a boolean" rule adds some complexity (and
> a possibility for things to be wrong/inconsistent) to the function for
> the benefit of the callers.

Yes, but returning something is only a minor burden.  It also makes
success vs. failure obvious at a glance.

I'm not worrying about inconsistency anymore.  In a way, void functions
are an exception.  Many non-void functions return a distinct error value
on failure, like NULL.  The only kind of inconsistency I can remember
seeing in these functions is forgetting to set an error.  Can be screwed
up in a void function just as easily.

>                              If there is only one caller, as is the case
> here or for virtual functions, the benefit can well be zero (this case)
> or negative (virtual functions).

Two small benefits here:

1. No need for ERRP_GUARD().

2. Conforms to the rules.  Rules are not laws, but let's stick to them
when it's as easy as it is here.

For what it's worth, GLib always advised users of GError to return a
value.  We chose to deviate for our Error, then spent nine years
learning how that leads to cumbersome code, leading us to:

commit e3fe3988d7851cac30abffae06d2f555ff7bee62
Author: Markus Armbruster <armbru@redhat.com>
Date:   Tue Jul 7 18:05:31 2020 +0200

    error: Document Error API usage rules
    
    This merely codifies existing practice, with one exception: the rule
    advising against returning void, where existing practice is mixed.
    
    When the Error API was created, we adopted the (unwritten) rule to
    return void when the function returns no useful value on success,
    unlike GError, which recommends to return true on success and false on
    error then.
    
    When a function returns a distinct error value, say false, a checked
    call that passes the error up looks like
    
        if (!frobnicate(..., errp)) {
            handle the error...
        }
    
    When it returns void, we need
    
        Error *err = NULL;
    
        frobnicate(..., &err);
        if (err) {
            handle the error...
            error_propagate(errp, err);
        }
    
    Not only is this more verbose, it also creates an Error object even
    when @errp is null, &error_abort or &error_fatal.
    
    People got tired of the additional boilerplate, and started to ignore
    the unwritten rule.  The result is confusion among developers about
    the preferred usage.
    
    Make the rule advising against returning void official by putting it
    in writing.  This will hopefully reduce confusion.
    
    Update the examples accordingly.
    
    The remainder of this series will update a substantial amount of code
    to honor the rule.
    
    Signed-off-by: Markus Armbruster <armbru@redhat.com>
    Reviewed-by: Eric Blake <eblake@redhat.com>
    Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
    Reviewed-by: Greg Kurz <groug@kaod.org>
    Message-Id: <20200707160613.848843-4-armbru@redhat.com>
    [Tweak prose as per advice from Eric]



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-02 11:27         ` Markus Armbruster
@ 2021-10-07  3:44           ` wangyanan (Y)
  2021-10-07  8:30             ` Paolo Bonzini
  2021-10-07  8:29           ` Paolo Bonzini
  1 sibling, 1 reply; 33+ messages in thread
From: wangyanan (Y) @ 2021-10-07  3:44 UTC (permalink / raw)
  To: Markus Armbruster, Paolo Bonzini
  Cc: Peter Maydell, Andrew Jones, Daniel P. Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, qemu-s390x, qemu-arm, qemu-ppc,
	wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson


On 2021/10/2 19:27, Markus Armbruster wrote:
> Paolo Bonzini <pbonzini@redhat.com> writes:
>
>> On 01/10/21 19:15, Daniel P. Berrangé wrote:
>>> On Fri, Oct 01, 2021 at 07:08:51PM +0200, Paolo Bonzini wrote:
>>>> On 29/09/21 04:58, Yanan Wang wrote:
>>>>> @@ -933,8 +935,7 @@ static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>>>>>             return;
>>>>>         }
>>>>> -    smp_parse(ms, config, errp);
>>>>> -    if (*errp) {
>>>>> +    if (!smp_parse(ms, config, errp)) {
>>>>>             qapi_free_SMPConfiguration(config);
>>>>>         }
>>>>>     }
>>>>>
>>>> This is actually a leak, so I'm replacing this patch with
>>> This patch isn't adding a leak, as there's no change in
>>> control flow / exit paths.  AFAICT, the leak was introduced
>>> in patch 15 instead, so the code below shoudl be squashed
>>> into that, and this patch left as-is.
>> Yes, even better make it a separate patch and fix the conflict in patch
>> 15.  But I'm still not sure of the wisdom of this patch.
>>
>> At this point smp_parse has exactly one caller and it doesn't care about
>> the return value.  The "return a boolean" rule adds some complexity (and
>> a possibility for things to be wrong/inconsistent) to the function for
>> the benefit of the callers.
> Yes, but returning something is only a minor burden.  It also makes
> success vs. failure obvious at a glance.
>
> I'm not worrying about inconsistency anymore.  In a way, void functions
> are an exception.  Many non-void functions return a distinct error value
> on failure, like NULL.  The only kind of inconsistency I can remember
> seeing in these functions is forgetting to set an error.  Can be screwed
> up in a void function just as easily.
>
>>                               If there is only one caller, as is the case
>> here or for virtual functions, the benefit can well be zero (this case)
>> or negative (virtual functions).
> Two small benefits here:
>
> 1. No need for ERRP_GUARD().
>
> 2. Conforms to the rules.  Rules are not laws, but let's stick to them
> when it's as easy as it is here.
>
> For what it's worth, GLib always advised users of GError to return a
> value.  We chose to deviate for our Error, then spent nine years
> learning how that leads to cumbersome code, leading us to:
>
> commit e3fe3988d7851cac30abffae06d2f555ff7bee62
> Author: Markus Armbruster <armbru@redhat.com>
> Date:   Tue Jul 7 18:05:31 2020 +0200
>
>      error: Document Error API usage rules
>      
>      This merely codifies existing practice, with one exception: the rule
>      advising against returning void, where existing practice is mixed.
>      
>      When the Error API was created, we adopted the (unwritten) rule to
>      return void when the function returns no useful value on success,
>      unlike GError, which recommends to return true on success and false on
>      error then.
>      
>      When a function returns a distinct error value, say false, a checked
>      call that passes the error up looks like
>      
>          if (!frobnicate(..., errp)) {
>              handle the error...
>          }
>      
>      When it returns void, we need
>      
>          Error *err = NULL;
>      
>          frobnicate(..., &err);
>          if (err) {
>              handle the error...
>              error_propagate(errp, err);
>          }
>      
>      Not only is this more verbose, it also creates an Error object even
>      when @errp is null, &error_abort or &error_fatal.
>      
>      People got tired of the additional boilerplate, and started to ignore
>      the unwritten rule.  The result is confusion among developers about
>      the preferred usage.
>      
>      Make the rule advising against returning void official by putting it
>      in writing.  This will hopefully reduce confusion.
>      
>      Update the examples accordingly.
>      
>      The remainder of this series will update a substantial amount of code
>      to honor the rule.
>      
>      Signed-off-by: Markus Armbruster <armbru@redhat.com>
>      Reviewed-by: Eric Blake <eblake@redhat.com>
>      Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
>      Reviewed-by: Greg Kurz <groug@kaod.org>
>      Message-Id: <20200707160613.848843-4-armbru@redhat.com>
>      [Tweak prose as per advice from Eric]
>
Hi,

Thanks for the fix, Paolo!

I notice that with Paolo's fix applied first and then Patch15 removing
the sanity checks out, machine_set_smp() at last simply becomes:

static void machine_set_smp(Object *obj, Visitor *v, const char *name,
                             void *opaque, Error **errp)
{
     MachineState *ms = MACHINE(obj);
     g_autoptr(SMPConfiguration) config = NULL;

     if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
return;
}

     smp_parse(ms, config, errp);
}

It looks good currently, neither the returned boolean nor the errp needs to
be checked here now, and smp_parse is only called here. So in this case,
we may avoid the boolean until we need to use it and honor the rule. :)

Thanks,
Yanan



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-02 11:27         ` Markus Armbruster
  2021-10-07  3:44           ` wangyanan (Y)
@ 2021-10-07  8:29           ` Paolo Bonzini
  2021-10-07 12:03             ` Markus Armbruster
  1 sibling, 1 reply; 33+ messages in thread
From: Paolo Bonzini @ 2021-10-07  8:29 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Peter Maydell, Andrew Jones, Daniel P. Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	qemu-ppc, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

On 02/10/21 13:27, Markus Armbruster wrote:
>> The "return a boolean" rule adds some complexity (and
>> a possibility for things to be wrong/inconsistent) to the function for
>> the benefit of the callers.
> Yes, but returning something is only a minor burden.  It also makes
> success vs. failure obvious at a glance.

Fair enough; I'd still prefer to have an exception to the rule for 
virtual functions.  In that case, I really find the benefit to be negative.

Paolo



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-07  3:44           ` wangyanan (Y)
@ 2021-10-07  8:30             ` Paolo Bonzini
  0 siblings, 0 replies; 33+ messages in thread
From: Paolo Bonzini @ 2021-10-07  8:30 UTC (permalink / raw)
  To: wangyanan (Y), Markus Armbruster
  Cc: Peter Maydell, Andrew Jones, Daniel P. Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, qemu-s390x, qemu-arm, qemu-ppc,
	wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

On 07/10/21 05:44, wangyanan (Y) wrote:
> 
> I notice that with Paolo's fix applied first and then Patch15 removing
> the sanity checks out, machine_set_smp() at last simply becomes:
> 
> static void machine_set_smp(Object *obj, Visitor *v, const char *name,
>                              void *opaque, Error **errp)
> {
>      MachineState *ms = MACHINE(obj);
>      g_autoptr(SMPConfiguration) config = NULL;
> 
>      if (!visit_type_SMPConfiguration(v, name, &config, errp)) {
> return;
> }
> 
>      smp_parse(ms, config, errp);
> }
> 
> It looks good currently, neither the returned boolean nor the errp needs to
> be checked here now, and smp_parse is only called here. So in this case,
> we may avoid the boolean until we need to use it and honor the rule. :)

Even inlining smp_parse is a possibility now.

Paolo



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v12 16/16] machine: Make smp_parse return a boolean
  2021-10-07  8:29           ` Paolo Bonzini
@ 2021-10-07 12:03             ` Markus Armbruster
  0 siblings, 0 replies; 33+ messages in thread
From: Markus Armbruster @ 2021-10-07 12:03 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Peter Maydell, Andrew Jones, Daniel P. Berrangé,
	Eduardo Habkost, Pierre Morel, Pankaj Gupta, Michael S . Tsirkin,
	Cornelia Huck, qemu-devel, Yanan Wang, qemu-s390x, qemu-arm,
	qemu-ppc, wanghaibin.wang, Philippe Mathieu-Daudé,
	David Gibson

Paolo Bonzini <pbonzini@redhat.com> writes:

> On 02/10/21 13:27, Markus Armbruster wrote:
>>> The "return a boolean" rule adds some complexity (and
>>> a possibility for things to be wrong/inconsistent) to the function for
>>> the benefit of the callers.
>>
>> Yes, but returning something is only a minor burden.  It also makes
>> success vs. failure obvious at a glance.
>
> Fair enough; I'd still prefer to have an exception to the rule for
> virtual functions.  In that case, I really find the benefit to be
> negative.

No rule without exceptions :)



^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2021-10-07 12:04 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-09-29  2:58 [PATCH v12 00/16] machine: smp parsing fixes and improvement Yanan Wang
2021-09-29  2:58 ` [PATCH v12 01/16] qapi/machine: Fix an incorrect comment of SMPConfiguration Yanan Wang
2021-09-29  2:58 ` [PATCH v12 02/16] machine: Deprecate "parameter=0" SMP configurations Yanan Wang
2021-09-29  2:58 ` [PATCH v12 03/16] machine: Minor refactor/fix for the smp parsers Yanan Wang
2021-09-29  2:58 ` [PATCH v12 04/16] machine: Uniformly use maxcpus to calculate the omitted parameters Yanan Wang
2021-09-29  2:58 ` [PATCH v12 05/16] machine: Set the value of cpus to match maxcpus if it's omitted Yanan Wang
2021-09-29  2:58 ` [PATCH v12 06/16] machine: Improve the error reporting of smp parsing Yanan Wang
2021-09-29  2:58 ` [PATCH v12 07/16] qtest/numa-test: Use detailed -smp CLIs in pc_dynamic_cpu_cfg Yanan Wang
2021-09-29  2:58 ` [PATCH v12 08/16] qtest/numa-test: Use detailed -smp CLIs in test_def_cpu_split Yanan Wang
2021-09-29  2:58 ` [PATCH v12 09/16] machine: Prefer cores over sockets in smp parsing since 6.2 Yanan Wang
2021-09-29  2:58 ` [PATCH v12 10/16] machine: Use ms instead of global current_machine in sanity-check Yanan Wang
2021-09-29  2:58 ` [PATCH v12 11/16] machine: Tweak the order of topology members in struct CpuTopology Yanan Wang
2021-09-29  2:58 ` [PATCH v12 12/16] machine: Make smp_parse generic enough for all arches Yanan Wang
2021-09-29  2:58 ` [PATCH v12 13/16] machine: Remove smp_parse callback from MachineClass Yanan Wang
2021-09-29  2:58 ` [PATCH v12 14/16] machine: Move smp_prefer_sockets to struct SMPCompatProps Yanan Wang
2021-09-29  2:58 ` [PATCH v12 15/16] machine: Put all sanity-check in the generic SMP parser Yanan Wang
2021-09-29  2:58 ` [PATCH v12 16/16] machine: Make smp_parse return a boolean Yanan Wang
2021-09-29  8:27   ` Philippe Mathieu-Daudé
2021-09-29  8:28   ` Daniel P. Berrangé
2021-09-29 11:22   ` Markus Armbruster
2021-10-01 17:08   ` Paolo Bonzini
2021-10-01 17:15     ` Daniel P. Berrangé
2021-10-02  5:26       ` Markus Armbruster
2021-10-02  6:40       ` Paolo Bonzini
2021-10-02 11:27         ` Markus Armbruster
2021-10-07  3:44           ` wangyanan (Y)
2021-10-07  8:30             ` Paolo Bonzini
2021-10-07  8:29           ` Paolo Bonzini
2021-10-07 12:03             ` Markus Armbruster
2021-09-29 12:39 ` [PATCH v12 00/16] machine: smp parsing fixes and improvement Paolo Bonzini
2021-09-29 14:46   ` Markus Armbruster
2021-09-29 14:57     ` Paolo Bonzini
2021-09-30  1:02       ` wangyanan (Y)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).