diff mbox series

[v2,7/7] cpu: Add `machine` parameter to query-cpu-definitions

Message ID 20201013230457.150630-8-ehabkost@redhat.com
State New
Headers show
Series i386: Add `machine` parameter to query-cpu-definitions | expand

Commit Message

Eduardo Habkost Oct. 13, 2020, 11:04 p.m. UTC
The new parameter can be used by management software to query for
CPU model alias information for multiple machines without
restarting QEMU.

Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
---
Changes v1 -> v2:
* Rewrite documentation, with suggestions from Markus
---
 qapi/machine-target.json                   | 14 ++++++-
 target/arm/helper.c                        |  4 +-
 target/i386/cpu.c                          | 24 ++++++++++-
 target/mips/helper.c                       |  4 +-
 target/s390x/cpu_models.c                  |  4 +-
 target/ppc/translate_init.c.inc            |  4 +-
 tests/acceptance/x86_cpu_model_versions.py | 48 ++++++++++++++++++++++
 7 files changed, 95 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/qapi/machine-target.json b/qapi/machine-target.json
index 698850cc78..211cb2d7c9 100644
--- a/qapi/machine-target.json
+++ b/qapi/machine-target.json
@@ -282,6 +282,10 @@ 
 #
 # @alias-of: Name of CPU model this model is an alias for.  The target of the
 #            CPU model alias may change depending on the machine type.
+#            If the @machine argument was provided to query-cpu-definitions,
+#            alias information for that machine type will be returned.
+#            If @machine is not provided, alias information for
+#            the current machine will be returned.
 #            Management software is supposed to translate CPU model aliases
 #            in the VM configuration, because aliases may stop being
 #            migration-safe in the future (since 4.1)
@@ -318,9 +322,17 @@ 
 #
 # Return a list of supported virtual CPU definitions
 #
+# @machine: Name of machine type.  The value of the @alias-of field
+#           is machine-specific.  This overrides the machine type
+#           used to look up that information.  This can be used
+#           to query machine-specific CPU model aliases without
+#           restarting QEMU (since 5.2)
+#
 # Returns: a list of CpuDefInfo
 #
 # Since: 1.2.0
 ##
-{ 'command': 'query-cpu-definitions', 'returns': ['CpuDefinitionInfo'],
+{ 'command': 'query-cpu-definitions',
+  'data': { '*machine': 'str' },
+  'returns': ['CpuDefinitionInfo'],
   'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_I386) || defined(TARGET_S390X) || defined(TARGET_MIPS)' }
diff --git a/target/arm/helper.c b/target/arm/helper.c
index cd0779ff5f..fc339a19ba 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8276,7 +8276,9 @@  static void arm_cpu_add_definition(gpointer data, gpointer user_data)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(bool has_machine,
+                                                 const char *machine,
+                                                 Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 0807d12ffa..d78ff6a563 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -56,6 +56,7 @@ 
 #ifndef CONFIG_USER_ONLY
 #include "exec/address-spaces.h"
 #include "hw/i386/apic_internal.h"
+#include "hw/i386/pc.h"
 #include "hw/boards.h"
 #endif
 
@@ -4187,6 +4188,13 @@  static char *x86_cpu_model_resolve_alias(const X86CPUModel *model,
     }
     return x86_cpu_versioned_model_name(model->cpudef, version);
 }
+
+static X86CPUVersion default_cpu_version_for_machine(MachineClass *mc)
+{
+    PCMachineClass *pcmc =
+        (PCMachineClass *)object_class_dynamic_cast(OBJECT_CLASS(mc), TYPE_PC_MACHINE);
+    return pcmc ? pcmc->default_cpu_version : 1;
+}
 #endif
 
 void x86_cpu_change_kvm_default(const char *prop, const char *value)
@@ -5027,12 +5035,24 @@  static void x86_cpu_definition_entry(gpointer data, gpointer user_data)
     args->cpu_list = entry;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(bool has_machine,
+                                                 const char *machine,
+                                                 Error **errp)
 {
     X86CPUDefinitionArgs args = { .cpu_list = NULL };
     GSList *list = get_sorted_cpu_model_list();
 
-    args.default_version = default_cpu_version;
+    if (!has_machine) {
+        args.default_version = default_cpu_version;
+    } else {
+        MachineClass *mc = machine_find_class(machine);
+        if (!mc) {
+            error_setg(errp, "Machine type '%s' not found", machine);
+            return NULL;
+        }
+        args.default_version = default_cpu_version_for_machine(mc);
+    }
+
     g_slist_foreach(list, x86_cpu_definition_entry, &args);
     g_slist_free(list);
     return args.cpu_list;
diff --git a/target/mips/helper.c b/target/mips/helper.c
index afd78b1990..33351e9578 100644
--- a/target/mips/helper.c
+++ b/target/mips/helper.c
@@ -1518,7 +1518,9 @@  static void mips_cpu_add_definition(gpointer data, gpointer user_data)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(bool has_machine,
+                                                 const char *machine,
+                                                 Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
diff --git a/target/s390x/cpu_models.c b/target/s390x/cpu_models.c
index ca484bfda7..19ccbd50ea 100644
--- a/target/s390x/cpu_models.c
+++ b/target/s390x/cpu_models.c
@@ -456,7 +456,9 @@  static void create_cpu_model_list(ObjectClass *klass, void *opaque)
     *cpu_list = entry;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(bool has_machine,
+                                                 const char *machine,
+                                                 Error **errp)
 {
     struct CpuDefinitionInfoListData list_data = {
         .list = NULL,
diff --git a/target/ppc/translate_init.c.inc b/target/ppc/translate_init.c.inc
index bb66526280..0d31da0c7f 100644
--- a/target/ppc/translate_init.c.inc
+++ b/target/ppc/translate_init.c.inc
@@ -10635,7 +10635,9 @@  static void ppc_cpu_defs_entry(gpointer data, gpointer user_data)
     *first = entry;
 }
 
-CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
+CpuDefinitionInfoList *qmp_query_cpu_definitions(bool has_machine,
+                                                 const char *machine,
+                                                 Error **errp)
 {
     CpuDefinitionInfoList *cpu_list = NULL;
     GSList *list;
diff --git a/tests/acceptance/x86_cpu_model_versions.py b/tests/acceptance/x86_cpu_model_versions.py
index 01ff614ec2..7fb17d00ba 100644
--- a/tests/acceptance/x86_cpu_model_versions.py
+++ b/tests/acceptance/x86_cpu_model_versions.py
@@ -238,6 +238,54 @@  class X86CPUModelAliases(avocado_qemu.Test):
 
         self.validate_aliases(cpus)
 
+    def test_machine_arg_none(self):
+        """Check results using explicit machine=none argument"""
+        vm1 = self.get_vm()
+        vm1.add_args('-S')
+        vm1.set_machine('pc-i440fx-4.0')
+        vm1.launch()
+        cpus1 = dict((m['name'], m.get('alias-of'))
+                     for m in vm1.command('query-cpu-definitions',
+                                          machine='none'))
+        vm1.shutdown()
+
+        vm2 = self.get_vm()
+        vm2.add_args('-S')
+        vm2.set_machine('none')
+        vm2.launch()
+        cpus2 = dict((m['name'], m.get('alias-of'))
+                     for m in vm2.command('query-cpu-definitions'))
+        vm1.shutdown()
+
+        self.assertEquals(cpus1, cpus2)
+
+    def test_machine_arg_4_1(self):
+        """Check results using explicit machine=pc-i440fx-4.1 argument"""
+        vm1 = self.get_vm()
+        vm1.add_args('-S')
+        vm1.set_machine('pc-i440fx-4.0')
+        vm1.launch()
+        cpus1 = dict((m['name'], m.get('alias-of'))
+                     for m in vm1.command('query-cpu-definitions',
+                                          machine='pc-i440fx-4.1'))
+        vm1.shutdown()
+
+        vm2 = self.get_vm()
+        vm2.add_args('-S')
+        vm2.set_machine('pc-i440fx-4.1')
+        vm2.launch()
+        cpus2 = dict((m['name'], m.get('alias-of'))
+                     for m in vm2.command('query-cpu-definitions'))
+        vm1.shutdown()
+
+        self.assertEquals(cpus1, cpus2)
+
+    def test_invalid_machine(self):
+        self.vm.add_args('-S')
+        self.vm.launch()
+        r = self.vm.qmp('query-cpu-definitions', machine='invalid-machine-123')
+        self.assertIn('error', r)
+
 
 class CascadelakeArchCapabilities(avocado_qemu.Test):
     """