mirror of https://github.com/xemu-project/xemu.git
i386: Make unversioned CPU models be aliases
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 <ehabkost@redhat.com> Message-Id: <20190628002844.24894-8-ehabkost@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
This commit is contained in:
parent
53db89d93b
commit
0788a56bd1
|
@ -1645,6 +1645,9 @@ void pc_cpus_init(PCMachineState *pcms)
|
||||||
const CPUArchIdList *possible_cpus;
|
const CPUArchIdList *possible_cpus;
|
||||||
MachineState *ms = MACHINE(pcms);
|
MachineState *ms = MACHINE(pcms);
|
||||||
MachineClass *mc = MACHINE_GET_CLASS(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
|
/* Calculates the limit to CPU APIC ID values
|
||||||
*
|
*
|
||||||
|
|
|
@ -429,9 +429,11 @@ static void pc_i440fx_machine_options(MachineClass *m)
|
||||||
|
|
||||||
static void pc_i440fx_4_1_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);
|
pc_i440fx_machine_options(m);
|
||||||
m->alias = "pc";
|
m->alias = "pc";
|
||||||
m->is_default = 1;
|
m->is_default = 1;
|
||||||
|
pcmc->default_cpu_version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_I440FX_MACHINE(v4_1, "pc-i440fx-4.1", NULL,
|
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)
|
static void pc_i440fx_4_0_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
|
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||||
pc_i440fx_4_1_machine_options(m);
|
pc_i440fx_4_1_machine_options(m);
|
||||||
m->alias = NULL;
|
m->alias = NULL;
|
||||||
m->is_default = 0;
|
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, hw_compat_4_0, hw_compat_4_0_len);
|
||||||
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
compat_props_add(m->compat_props, pc_compat_4_0, pc_compat_4_0_len);
|
||||||
}
|
}
|
||||||
|
|
|
@ -367,8 +367,10 @@ static void pc_q35_machine_options(MachineClass *m)
|
||||||
|
|
||||||
static void pc_q35_4_1_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);
|
pc_q35_machine_options(m);
|
||||||
m->alias = "q35";
|
m->alias = "q35";
|
||||||
|
pcmc->default_cpu_version = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFINE_Q35_MACHINE(v4_1, "pc-q35-4.1", NULL,
|
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)
|
static void pc_q35_4_0_1_machine_options(MachineClass *m)
|
||||||
{
|
{
|
||||||
|
PCMachineClass *pcmc = PC_MACHINE_CLASS(m);
|
||||||
pc_q35_4_1_machine_options(m);
|
pc_q35_4_1_machine_options(m);
|
||||||
m->alias = NULL;
|
m->alias = NULL;
|
||||||
|
pcmc->default_cpu_version = CPU_VERSION_LEGACY;
|
||||||
/*
|
/*
|
||||||
* This is the default machine for the 4.0-stable branch. It is basically
|
* 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
|
* a 4.0 that doesn't use split irqchip by default. It MUST hence apply the
|
||||||
|
|
|
@ -109,6 +109,9 @@ typedef struct PCMachineClass {
|
||||||
|
|
||||||
/* Compat options: */
|
/* Compat options: */
|
||||||
|
|
||||||
|
/* Default CPU model version. See x86_cpu_set_default_version(). */
|
||||||
|
int default_cpu_version;
|
||||||
|
|
||||||
/* ACPI compat: */
|
/* ACPI compat: */
|
||||||
bool has_acpi_build;
|
bool has_acpi_build;
|
||||||
bool rsdp_in_ram;
|
bool rsdp_in_ram;
|
||||||
|
|
|
@ -1470,6 +1470,11 @@ struct X86CPUModel {
|
||||||
X86CPUDefinition *cpudef;
|
X86CPUDefinition *cpudef;
|
||||||
/* CPU model version */
|
/* CPU model version */
|
||||||
X86CPUVersion 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 */
|
/* 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)
|
static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model)
|
||||||
{
|
{
|
||||||
int v = 0;
|
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)
|
static X86CPUVersion x86_cpu_model_resolve_version(const X86CPUModel *model)
|
||||||
{
|
{
|
||||||
X86CPUVersion v = model->version;
|
X86CPUVersion v = model->version;
|
||||||
|
if (v == CPU_VERSION_AUTO) {
|
||||||
|
v = default_cpu_version;
|
||||||
|
}
|
||||||
if (v == CPU_VERSION_LATEST) {
|
if (v == CPU_VERSION_LATEST) {
|
||||||
return x86_cpu_model_last_version(model);
|
return x86_cpu_model_last_version(model);
|
||||||
}
|
}
|
||||||
|
@ -3589,13 +3606,35 @@ static char *x86_cpu_class_get_model_id(X86CPUClass *xc)
|
||||||
return r;
|
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)
|
static void x86_cpu_list_entry(gpointer data, gpointer user_data)
|
||||||
{
|
{
|
||||||
ObjectClass *oc = data;
|
ObjectClass *oc = data;
|
||||||
X86CPUClass *cc = X86_CPU_CLASS(oc);
|
X86CPUClass *cc = X86_CPU_CLASS(oc);
|
||||||
char *name = x86_cpu_class_get_model_name(cc);
|
char *name = x86_cpu_class_get_model_name(cc);
|
||||||
char *desc = g_strdup(cc->model_description);
|
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) {
|
if (!desc) {
|
||||||
desc = x86_cpu_class_get_model_id(cc);
|
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);
|
qemu_printf("x86 %-20s %-48s\n", name, desc);
|
||||||
g_free(name);
|
g_free(name);
|
||||||
g_free(desc);
|
g_free(desc);
|
||||||
|
g_free(alias_of);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* list available CPU models and flags */
|
/* 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->migration_safe = cc->migration_safe;
|
||||||
info->has_migration_safe = true;
|
info->has_migration_safe = true;
|
||||||
info->q_static = cc->static_model;
|
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 = g_malloc0(sizeof(*entry));
|
||||||
entry->value = info;
|
entry->value = info;
|
||||||
|
@ -4070,7 +4118,8 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
|
||||||
/* Unversioned model: */
|
/* Unversioned model: */
|
||||||
m = g_new0(X86CPUModel, 1);
|
m = g_new0(X86CPUModel, 1);
|
||||||
m->cpudef = def;
|
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);
|
x86_register_cpu_model_type(def->name, m);
|
||||||
|
|
||||||
/* Versioned models: */
|
/* Versioned models: */
|
||||||
|
@ -4087,6 +4136,7 @@ static void x86_register_cpudef_types(X86CPUDefinition *def)
|
||||||
X86CPUModel *am = g_new0(X86CPUModel, 1);
|
X86CPUModel *am = g_new0(X86CPUModel, 1);
|
||||||
am->cpudef = def;
|
am->cpudef = def;
|
||||||
am->version = vdef->version;
|
am->version = vdef->version;
|
||||||
|
am->is_alias = true;
|
||||||
x86_register_cpu_model_type(vdef->alias, am);
|
x86_register_cpu_model_type(vdef->alias, am);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1934,11 +1934,23 @@ void x86_cpu_change_kvm_default(const char *prop, const char *value);
|
||||||
/* Resolve to latest CPU version */
|
/* Resolve to latest CPU version */
|
||||||
#define CPU_VERSION_LATEST -1
|
#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 */
|
/* Don't resolve to any versioned CPU models, like old QEMU versions */
|
||||||
#define CPU_VERSION_LEGACY 0
|
#define CPU_VERSION_LEGACY 0
|
||||||
|
|
||||||
typedef int X86CPUVersion;
|
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 */
|
/* Return name of 32-bit register, from a R_* constant */
|
||||||
const char *get_register_name_32(unsigned int reg);
|
const char *get_register_name_32(unsigned int reg);
|
||||||
|
|
||||||
|
|
|
@ -103,3 +103,129 @@ class X86CPUModelAliases(avocado_qemu.Test):
|
||||||
# On pc-*-4.0, no CPU model should be reported as an alias:
|
# On pc-*-4.0, no CPU model should be reported as an alias:
|
||||||
for name,c in cpus.items():
|
for name,c in cpus.items():
|
||||||
self.assertNotIn('alias-of', c, "%s shouldn't be an alias" % (name))
|
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)
|
||||||
|
|
Loading…
Reference in New Issue