[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL v6 37/42] i386: Make unversioned CPU models be aliase
From: |
Eduardo Habkost |
Subject: |
[Qemu-devel] [PULL v6 37/42] i386: Make unversioned CPU models be aliases |
Date: |
Fri, 5 Jul 2019 19:14:59 -0300 |
This will make unversioned CPU models behavior depend on the
machine type:
* "pc-*-4.0" and older will not report them as aliases.
This is done to keep compatibility with older QEMU versions
after management software starts translating aliases.
* "pc-*-4.1" will translate unversioned CPU models to -v1.
This is done to keep compatibility with existing management
software, that still relies on CPU model runnability promises.
* "none" will translate unversioned CPU models to their latest
version. This is planned become the default in future machine
types (probably in pc-*-4.3).
Signed-off-by: Eduardo Habkost <address@hidden>
Message-Id: <address@hidden>
Reviewed-by: Daniel P. Berrangé <address@hidden>
Signed-off-by: Eduardo Habkost <address@hidden>
---
include/hw/i386/pc.h | 3 +
target/i386/cpu.h | 12 ++
hw/i386/pc.c | 3 +
hw/i386/pc_piix.c | 4 +
hw/i386/pc_q35.c | 4 +
target/i386/cpu.c | 52 ++++++++-
tests/acceptance/x86_cpu_model_versions.py | 126 +++++++++++++++++++++
7 files changed, 203 insertions(+), 1 deletion(-)
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 0fa3e3beeb..859b64c51d 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -109,6 +109,9 @@ typedef struct PCMachineClass {
/* Compat options: */
+ /* Default CPU model version. See x86_cpu_set_default_version(). */
+ int default_cpu_version;
+
/* ACPI compat: */
bool has_acpi_build;
bool rsdp_in_ram;
diff --git a/target/i386/cpu.h b/target/i386/cpu.h
index 12bc3cd4a8..05393cf9d1 100644
--- a/target/i386/cpu.h
+++ b/target/i386/cpu.h
@@ -1934,11 +1934,23 @@ void x86_cpu_change_kvm_default(const char *prop, const
char *value);
/* Resolve to latest CPU version */
#define CPU_VERSION_LATEST -1
+/*
+ * Resolve to version defined by current machine type.
+ * See x86_cpu_set_default_version()
+ */
+#define CPU_VERSION_AUTO -2
+
/* Don't resolve to any versioned CPU models, like old QEMU versions */
#define CPU_VERSION_LEGACY 0
typedef int X86CPUVersion;
+/*
+ * Set default CPU model version for CPU models having
+ * version == CPU_VERSION_AUTO.
+ */
+void x86_cpu_set_default_version(X86CPUVersion version);
+
/* Return name of 32-bit register, from a R_* constant */
const char *get_register_name_32(unsigned int reg);
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index b9c55301a2..c33ce47578 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1645,6 +1645,9 @@ void pc_cpus_init(PCMachineState *pcms)
const CPUArchIdList *possible_cpus;
MachineState *ms = MACHINE(pcms);
MachineClass *mc = MACHINE_GET_CLASS(pcms);
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(mc);
+
+ x86_cpu_set_default_version(pcmc->default_cpu_version);
/* Calculates the limit to CPU APIC ID values
*
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index f29de58636..581b3c2baa 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -429,9 +429,11 @@ static void pc_i440fx_machine_options(MachineClass *m)
static void pc_i440fx_4_1_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = 1;
+ pcmc->default_cpu_version = 1;
}
DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
@@ -439,9 +441,11 @@ DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
static void pc_i440fx_4_0_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_i440fx_4_1_machine_options(m);
m->alias = NULL;
m->is_default = 0;
+ pcmc->default_cpu_version = CPU_VERSION_LEGACY;
compat_props_add(m->compat_props, hw_compat_4_0, hw_compat_4_0_len);
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 57232aed6b..397e1fdd2f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -367,8 +367,10 @@ static void pc_q35_machine_options(MachineClass *m)
static void pc_q35_4_1_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_machine_options(m);
m->alias = "q35";
+ pcmc->default_cpu_version = 1;
}
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
@@ -376,8 +378,10 @@ DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
static void pc_q35_4_0_1_machine_options(MachineClass *m)
{
+ PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
pc_q35_4_1_machine_options(m);
m->alias = NULL;
+ pcmc->default_cpu_version = CPU_VERSION_LEGACY;
/*
* This is the default machine for the 4.0-stable branch. It is basically
* a 4.0 that doesn't use split irqchip by default. It MUST hence apply the
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index f41917649d..0cf8e545c6 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -1470,6 +1470,11 @@ struct X86CPUModel {
X86CPUDefinition *cpudef;
/* CPU model version */
X86CPUVersion version;
+ /*
+ * If true, this is an alias CPU model.
+ * This matters only for "-cpu help" and query-cpu-definitions
+ */
+ bool is_alias;
};
/* Get full model name for CPU version */
@@ -2835,6 +2840,15 @@ static PropValue tcg_default_props[] = {
};
+X86CPUVersion default_cpu_version = CPU_VERSION_LATEST;
+
+void x86_cpu_set_default_version(X86CPUVersion version)
+{
+ /* Translating CPU_VERSION_AUTO to CPU_VERSION_AUTO doesn't make sense */
+ assert(version != CPU_VERSION_AUTO);
+ default_cpu_version = version;
+}
+
static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model)
{
int v = 0;
@@ -2851,6 +2865,9 @@ static X86CPUVersion x86_cpu_model_last_version(const
X86CPUModel *model)
static X86CPUVersion x86_cpu_model_resolve_version(const X86CPUModel *model)
{
X86CPUVersion v = model->version;
+ if (v == CPU_VERSION_AUTO) {
+ v = default_cpu_version;
+ }
if (v == CPU_VERSION_LATEST) {
return x86_cpu_model_last_version(model);
}
@@ -3589,13 +3606,35 @@ static char *x86_cpu_class_get_model_id(X86CPUClass *xc)
return r;
}
+static char *x86_cpu_class_get_alias_of(X86CPUClass *cc)
+{
+ X86CPUVersion version;
+
+ if (!cc->model || !cc->model->is_alias) {
+ return NULL;
+ }
+ version = x86_cpu_model_resolve_version(cc->model);
+ if (version <= 0) {
+ return NULL;
+ }
+ return x86_cpu_versioned_model_name(cc->model->cpudef, version);
+}
+
static void x86_cpu_list_entry(gpointer data, gpointer user_data)
{
ObjectClass *oc = data;
X86CPUClass *cc = X86_CPU_CLASS(oc);
char *name = x86_cpu_class_get_model_name(cc);
char *desc = g_strdup(cc->model_description);
+ char *alias_of = x86_cpu_class_get_alias_of(cc);
+ if (!desc && alias_of) {
+ if (cc->model && cc->model->version == CPU_VERSION_AUTO) {
+ desc = g_strdup("(alias configured by machine type)");
+ } else {
+ desc = g_strdup_printf("(alias of %s)", alias_of);
+ }
+ }
if (!desc) {
desc = x86_cpu_class_get_model_id(cc);
}
@@ -3603,6 +3642,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer
user_data)
qemu_printf("x86 %-20s %-48s\n", name, desc);
g_free(name);
g_free(desc);
+ g_free(alias_of);
}
/* list available CPU models and flags */
@@ -3651,6 +3691,14 @@ static void x86_cpu_definition_entry(gpointer data,
gpointer user_data)
info->migration_safe = cc->migration_safe;
info->has_migration_safe = true;
info->q_static = cc->static_model;
+ /*
+ * Old machine types won't report aliases, so that alias translation
+ * doesn't break compatibility with previous QEMU versions.
+ */
+ if (default_cpu_version != CPU_VERSION_LEGACY) {
+ info->alias_of = x86_cpu_class_get_alias_of(cc);
+ info->has_alias_of = !!info->alias_of;
+ }
entry = g_malloc0(sizeof(*entry));
entry->value = info;
@@ -4070,7 +4118,8 @@ static void x86_register_cpudef_types(X86CPUDefinition
*def)
/* Unversioned model: */
m = g_new0(X86CPUModel, 1);
m->cpudef = def;
- m->version = CPU_VERSION_LEGACY;
+ m->version = CPU_VERSION_AUTO;
+ m->is_alias = true;
x86_register_cpu_model_type(def->name, m);
/* Versioned models: */
@@ -4087,6 +4136,7 @@ static void x86_register_cpudef_types(X86CPUDefinition
*def)
X86CPUModel *am = g_new0(X86CPUModel, 1);
am->cpudef = def;
am->version = vdef->version;
+ am->is_alias = true;
x86_register_cpu_model_type(vdef->alias, am);
}
}
diff --git a/tests/acceptance/x86_cpu_model_versions.py
b/tests/acceptance/x86_cpu_model_versions.py
index b85d6f8604..165c0c7601 100644
--- a/tests/acceptance/x86_cpu_model_versions.py
+++ b/tests/acceptance/x86_cpu_model_versions.py
@@ -103,3 +103,129 @@ class X86CPUModelAliases(avocado_qemu.Test):
# On pc-*-4.0, no CPU model should be reported as an alias:
for name,c in cpus.items():
self.assertNotIn('alias-of', c, "%s shouldn't be an alias" %
(name))
+
+ def test_4_1_alias(self):
+ """Check if unversioned CPU model is an alias pointing to right
version"""
+ self.vm.add_args('-S')
+ self.vm.set_machine('pc-i440fx-4.1')
+ self.vm.launch()
+
+ cpus = dict((m['name'], m) for m in
self.vm.command('query-cpu-definitions'))
+
+ self.assertFalse(cpus['Cascadelake-Server']['static'],
+ 'unversioned Cascadelake-Server CPU model must not be
static')
+ self.assertEquals(cpus['Cascadelake-Server'].get('alias-of'),
'Cascadelake-Server-v1',
+ 'Cascadelake-Server must be an alias of
Cascadelake-Server-v1')
+ self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
+ 'Cascadelake-Server-v1 must not be an alias')
+
+ self.assertFalse(cpus['qemu64']['static'],
+ 'unversioned qemu64 CPU model must not be static')
+ self.assertEquals(cpus['qemu64'].get('alias-of'), 'qemu64-v1',
+ 'qemu64 must be an alias of qemu64-v1')
+ self.assertNotIn('alias-of', cpus['qemu64-v1'],
+ 'qemu64-v1 must not be an alias')
+
+ self.validate_variant_aliases(cpus)
+
+ # On pc-*-4.1, -noTSX and -IBRS models should be aliases:
+ self.assertEquals(cpus["Haswell"].get('alias-of'),
+ "Haswell-v1",
+ "Haswell must be an alias")
+ self.assertEquals(cpus["Haswell-noTSX"].get('alias-of'),
+ "Haswell-v2",
+ "Haswell-noTSX must be an alias")
+ self.assertEquals(cpus["Haswell-IBRS"].get('alias-of'),
+ "Haswell-v3",
+ "Haswell-IBRS must be an alias")
+ self.assertEquals(cpus["Haswell-noTSX-IBRS"].get('alias-of'),
+ "Haswell-v4",
+ "Haswell-noTSX-IBRS must be an alias")
+
+ self.assertEquals(cpus["Broadwell"].get('alias-of'),
+ "Broadwell-v1",
+ "Broadwell must be an alias")
+ self.assertEquals(cpus["Broadwell-noTSX"].get('alias-of'),
+ "Broadwell-v2",
+ "Broadwell-noTSX must be an alias")
+ self.assertEquals(cpus["Broadwell-IBRS"].get('alias-of'),
+ "Broadwell-v3",
+ "Broadwell-IBRS must be an alias")
+ self.assertEquals(cpus["Broadwell-noTSX-IBRS"].get('alias-of'),
+ "Broadwell-v4",
+ "Broadwell-noTSX-IBRS must be an alias")
+
+ self.assertEquals(cpus["Nehalem"].get('alias-of'),
+ "Nehalem-v1",
+ "Nehalem must be an alias")
+ self.assertEquals(cpus["Nehalem-IBRS"].get('alias-of'),
+ "Nehalem-v2",
+ "Nehalem-IBRS must be an alias")
+
+ self.assertEquals(cpus["Westmere"].get('alias-of'),
+ "Westmere-v1",
+ "Westmere must be an alias")
+ self.assertEquals(cpus["Westmere-IBRS"].get('alias-of'),
+ "Westmere-v2",
+ "Westmere-IBRS must be an alias")
+
+ self.assertEquals(cpus["SandyBridge"].get('alias-of'),
+ "SandyBridge-v1",
+ "SandyBridge must be an alias")
+ self.assertEquals(cpus["SandyBridge-IBRS"].get('alias-of'),
+ "SandyBridge-v2",
+ "SandyBridge-IBRS must be an alias")
+
+ self.assertEquals(cpus["IvyBridge"].get('alias-of'),
+ "IvyBridge-v1",
+ "IvyBridge must be an alias")
+ self.assertEquals(cpus["IvyBridge-IBRS"].get('alias-of'),
+ "IvyBridge-v2",
+ "IvyBridge-IBRS must be an alias")
+
+ self.assertEquals(cpus["Skylake-Client"].get('alias-of'),
+ "Skylake-Client-v1",
+ "Skylake-Client must be an alias")
+ self.assertEquals(cpus["Skylake-Client-IBRS"].get('alias-of'),
+ "Skylake-Client-v2",
+ "Skylake-Client-IBRS must be an alias")
+
+ self.assertEquals(cpus["Skylake-Server"].get('alias-of'),
+ "Skylake-Server-v1",
+ "Skylake-Server must be an alias")
+ self.assertEquals(cpus["Skylake-Server-IBRS"].get('alias-of'),
+ "Skylake-Server-v2",
+ "Skylake-Server-IBRS must be an alias")
+
+ self.assertEquals(cpus["EPYC"].get('alias-of'),
+ "EPYC-v1",
+ "EPYC must be an alias")
+ self.assertEquals(cpus["EPYC-IBPB"].get('alias-of'),
+ "EPYC-v2",
+ "EPYC-IBPB must be an alias")
+
+ self.validate_aliases(cpus)
+
+ def test_none_alias(self):
+ """Check if unversioned CPU model is an alias pointing to some
version"""
+ self.vm.add_args('-S')
+ self.vm.set_machine('none')
+ self.vm.launch()
+
+ cpus = dict((m['name'], m) for m in
self.vm.command('query-cpu-definitions'))
+
+ self.assertFalse(cpus['Cascadelake-Server']['static'],
+ 'unversioned Cascadelake-Server CPU model must not be
static')
+ self.assertTrue(re.match('Cascadelake-Server-v[0-9]+',
cpus['Cascadelake-Server']['alias-of']),
+ 'Cascadelake-Server must be an alias of versioned CPU
model')
+ self.assertNotIn('alias-of', cpus['Cascadelake-Server-v1'],
+ 'Cascadelake-Server-v1 must not be an alias')
+
+ self.assertFalse(cpus['qemu64']['static'],
+ 'unversioned qemu64 CPU model must not be static')
+ self.assertTrue(re.match('qemu64-v[0-9]+', cpus['qemu64']['alias-of']),
+ 'qemu64 must be an alias of versioned CPU model')
+ self.assertNotIn('alias-of', cpus['qemu64-v1'],
+ 'qemu64-v1 must not be an alias')
+
+ self.validate_aliases(cpus)
--
2.18.0.rc1.1.g3f1ff2140
- [Qemu-devel] [PULL v6 34/42] i386: Register versioned CPU models, (continued)
- [Qemu-devel] [PULL v6 34/42] i386: Register versioned CPU models, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 42/42] tests: use -numa memdev option in tests instead of legacy 'mem' option, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 32/42] i386: Add x-force-features option for testing, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 33/42] i386: Get model-id from CPU object on "-cpu help", Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 39/42] i386: Add Cascadelake-Server-v2 CPU model, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 40/42] numa: Make deprecation warnings conditional on !qtest_enabled(), Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 38/42] docs: Deprecate CPU model runnability guarantees, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 36/42] i386: Replace -noTSX, -IBRS, -IBPB CPU models with aliases, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 35/42] i386: Define -IBRS, -noTSX, -IBRS versions of CPU models, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 41/42] numa: allow memory-less nodes when using memdev as backend, Eduardo Habkost, 2019/07/05
- [Qemu-devel] [PULL v6 37/42] i386: Make unversioned CPU models be aliases,
Eduardo Habkost <=
- Re: [Qemu-devel] [PULL v6 00/42] Machine and x86 queue, 2019-07-05, no-reply, 2019/07/06
- Re: [Qemu-devel] [PULL v6 00/42] Machine and x86 queue, 2019-07-05, Peter Maydell, 2019/07/08