Message ID | 20250123115613.1537173-1-anisinha@redhat.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | [v5] hw/i386/cpu: remove default_cpu_version and simplify | expand |
> hw/i386/microvm.c | 3 +- > hw/i386/pc.c | 14 +++++++++ > hw/i386/pc_piix.c | 6 ++-- > hw/i386/pc_q35.c | 6 ++-- > hw/i386/x86-common.c | 4 +-- > include/hw/i386/pc.h | 7 +++-- > include/hw/i386/x86.h | 2 +- > target/i386/cpu.c | 69 ++++++++++++++++++++++--------------------- > target/i386/cpu.h | 21 +++---------- > 9 files changed, 67 insertions(+), 65 deletions(-) > > changelog: > v2: explain in commit log why use of CPU_VERSION_LATEST for machines > is problematic. > v3: fix a bug that broke the pipeline > https://gitlab.com/mstredhat/qemu/-/pipelines/1626171267 > when cpu versions are explicitly specified in the command line, > respect that and do not enforce legacy (unversioned) cpu logic. > The pipeline is green now with the fix: > https://gitlab.com/anisinha/qemu/-/pipelines/1626783632 > v4: made changes as per Zhao's suggestions. > Pipeline passes https://gitlab.com/anisinha/qemu/-/pipelines/1635829877 > v5: adjustment of pc_init_cpus() declaration as per Zhao's suggestion. This > simplifies things and also passes compilation. > CI still passes https://gitlab.com/anisinha/qemu/-/pipelines/1637657451 v5 is fine for me, so Reviewed-by: Zhao Liu <zhao1.liu@intel.com> Let's see if anyone else has comments.
On Thu, 23 Jan 2025 17:26:12 +0530 Ani Sinha <anisinha@redhat.com> wrote: > commit 0788a56bd1ae3 ("i386: Make unversioned CPU models be aliases") > introduced 'default_cpu_version' for PCMachineClass. This created three > categories of CPU models: > - Most unversioned CPU models would use version 1 by default. > - For machines 4.0.1 and older that do not support cpu model aliases, a > special default_cpu_version value of CPU_VERSION_LEGACY is used. Testing current master: ==== ./qemu-system-x86_64 -M pc-i440fx-4.0 -cpu Haswell-v4 -monitor stdio ... (qemu) info hotpluggable-cpus Hotpluggable CPUs: type: "Haswell-v4-x86_64-cpu" we can run versioned on old machine types. with caveat not being able to migrate to old qemu that doesn't have it ==== ./qemu-system-x86_64 -M pc-i440fx-4.0 -cpu Haswell -monitor stdio ... (qemu) info hotpluggable-cpus Hotpluggable CPUs: type: "Haswell-x86_64-cpu" ==== ./qemu-system-x86_64 -M pc-i440fx-5.0 -cpu Haswell -monitor stdio ... (qemu) info hotpluggable-cpus Hotpluggable CPUs: type: "Haswell-x86_64-cpu" non-versioned model resolves to the same type regardless of legacy Do we really have to keep CPU_VERSION_LEGACY code around? Lets assume we drop all CPU_VERSION_LEGACY code, what would change? > - It was thought that future machines would use the latest value of cpu > versions corresponding to default_cpu_version value of > CPU_VERSION_LATEST [1]. > > All pc machines still use the default cpu version of 1 for > unversioned cpu models. CPU_VERSION_LATEST is a moving target and > changes with time. Therefore, if machines use CPU_VERSION_LATEST, it would > mean that over a period of time, for the same machine type, the cpu version > would be different depending on what is latest at that time. This would > break guests even when they use a constant machine type. Therefore, for ^^^^^^^^^^^^^^^^^^ s/.../versioned .../ > pc machines, use of CPU_VERSION_LATEST is not possible. Currently, only > microvms use CPU_VERSION_LATEST. > > This change cleans up the complicated logic around default_cpu_version > including getting rid of default_cpu_version property itself. A couple of new > flags are introduced, one for the legacy model for machines 4.0.1 and older > and other for microvms. For older machines, a new pc machine property is > introduced that separates pc machine versions 4.0.1 and older from the newer > machines. 4.0.1 and older machines are scheduled to be deleted towards > end of 2025 since they would be 6 years old by then. At that time, we can > remove all logic around legacy cpus. Microvms are the only machines that > continue to use the latest cpu version. If this changes later, we can > remove all logic around x86_cpu_model_last_version(). Default cpu version > for unversioned cpu models is hardcoded to the value 1 and applies > unconditionally for all pc machine types of version 4.1 and above. > > This change also removes all complications around CPU_VERSION_AUTO > including removal of the value itself. > > 1) See commit dcafd1ef0af227 ("i386: Register versioned CPU models") > > CC: imammedo@redhat.com > Signed-off-by: Ani Sinha <anisinha@redhat.com> > --- > hw/i386/microvm.c | 3 +- > hw/i386/pc.c | 14 +++++++++ > hw/i386/pc_piix.c | 6 ++-- > hw/i386/pc_q35.c | 6 ++-- > hw/i386/x86-common.c | 4 +-- > include/hw/i386/pc.h | 7 +++-- > include/hw/i386/x86.h | 2 +- > target/i386/cpu.c | 69 ++++++++++++++++++++++--------------------- > target/i386/cpu.h | 21 +++---------- > 9 files changed, 67 insertions(+), 65 deletions(-) > > changelog: > v2: explain in commit log why use of CPU_VERSION_LATEST for machines > is problematic. > v3: fix a bug that broke the pipeline > https://gitlab.com/mstredhat/qemu/-/pipelines/1626171267 > when cpu versions are explicitly specified in the command line, > respect that and do not enforce legacy (unversioned) cpu logic. > The pipeline is green now with the fix: > https://gitlab.com/anisinha/qemu/-/pipelines/1626783632 > v4: made changes as per Zhao's suggestions. > Pipeline passes https://gitlab.com/anisinha/qemu/-/pipelines/1635829877 > v5: adjustment of pc_init_cpus() declaration as per Zhao's suggestion. This > simplifies things and also passes compilation. > CI still passes https://gitlab.com/anisinha/qemu/-/pipelines/1637657451 > > diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c > index a8d354aabe..ffb1b37fe5 100644 > --- a/hw/i386/microvm.c > +++ b/hw/i386/microvm.c > @@ -458,7 +458,8 @@ static void microvm_machine_state_init(MachineState *machine) > > microvm_memory_init(mms); > > - x86_cpus_init(x86ms, CPU_VERSION_LATEST); > + x86_cpu_uses_lastest_version(); > + x86_cpus_init(x86ms); > > microvm_devices_init(mms); > } > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > index b46975c8a4..f97a519573 100644 > --- a/hw/i386/pc.c > +++ b/hw/i386/pc.c > @@ -30,6 +30,7 @@ > #include "hw/hyperv/hv-balloon.h" > #include "hw/i386/fw_cfg.h" > #include "hw/i386/vmport.h" > +#include "target/i386/cpu.h" > #include "system/cpus.h" > #include "hw/ide/ide-bus.h" > #include "hw/timer/hpet.h" > @@ -615,6 +616,19 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) > } > } > > +void pc_init_cpus(MachineState *ms) > +{ > + X86MachineState *x86ms = X86_MACHINE(ms); > + PCMachineState *pcms = PC_MACHINE(ms); > + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); > + > + if (pcmc->no_versioned_cpu_model) { > + /* use legacy cpu as it does not support versions */ > + x86_cpu_set_legacy_version(); > + } > + x86_cpus_init(x86ms); > +} > + > static > void pc_machine_done(Notifier *notifier, void *data) > { > diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c > index 04d2957adc..dc684cb011 100644 > --- a/hw/i386/pc_piix.c > +++ b/hw/i386/pc_piix.c > @@ -181,7 +181,8 @@ static void pc_init1(MachineState *machine, const char *pci_type) > } > > pc_machine_init_sgx_epc(pcms); > - x86_cpus_init(x86ms, pcmc->default_cpu_version); > + > + pc_init_cpus(machine); > > if (kvm_enabled()) { > kvmclock_create(pcmc->kvmclock_create_always); > @@ -457,7 +458,6 @@ static void pc_i440fx_machine_options(MachineClass *m) > ObjectClass *oc = OBJECT_CLASS(m); > pcmc->default_south_bridge = TYPE_PIIX3_DEVICE; > pcmc->pci_root_uid = 0; > - pcmc->default_cpu_version = 1; > > m->family = "pc_piix"; > m->desc = "Standard PC (i440FX + PIIX, 1996)"; > @@ -669,7 +669,7 @@ static void pc_i440fx_machine_4_0_options(MachineClass *m) > { > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > pc_i440fx_machine_4_1_options(m); > - pcmc->default_cpu_version = CPU_VERSION_LEGACY; > + pcmc->no_versioned_cpu_model = true; > 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 77536dd697..045b05da64 100644 > --- a/hw/i386/pc_q35.c > +++ b/hw/i386/pc_q35.c > @@ -187,7 +187,8 @@ static void pc_q35_init(MachineState *machine) > } > > pc_machine_init_sgx_epc(pcms); > - x86_cpus_init(x86ms, pcmc->default_cpu_version); > + > + pc_init_cpus(machine); > > if (kvm_enabled()) { > kvmclock_create(pcmc->kvmclock_create_always); > @@ -339,7 +340,6 @@ static void pc_q35_machine_options(MachineClass *m) > { > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > pcmc->pci_root_uid = 0; > - pcmc->default_cpu_version = 1; > > m->family = "pc_q35"; > m->desc = "Standard PC (Q35 + ICH9, 2009)"; > @@ -547,7 +547,7 @@ static void pc_q35_machine_4_0_1_options(MachineClass *m) > { > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > pc_q35_machine_4_1_options(m); > - pcmc->default_cpu_version = CPU_VERSION_LEGACY; > + pcmc->no_versioned_cpu_model = true; > /* > * 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/hw/i386/x86-common.c b/hw/i386/x86-common.c > index 008496b5b8..1ed5bc6010 100644 > --- a/hw/i386/x86-common.c > +++ b/hw/i386/x86-common.c > @@ -66,15 +66,13 @@ out: > object_unref(cpu); > } > > -void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) > +void x86_cpus_init(X86MachineState *x86ms) > { > int i; > const CPUArchIdList *possible_cpus; > MachineState *ms = MACHINE(x86ms); > MachineClass *mc = MACHINE_GET_CLASS(x86ms); > > - x86_cpu_set_default_version(default_cpu_version); > - > /* > * Calculates the limit to CPU APIC ID values > * > diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h > index a558705cb9..563f765d7f 100644 > --- a/include/hw/i386/pc.h > +++ b/include/hw/i386/pc.h > @@ -92,9 +92,6 @@ struct PCMachineClass { > > /* Compat options: */ > > - /* Default CPU model version. See x86_cpu_set_default_version(). */ > - int default_cpu_version; > - > /* ACPI compat: */ > bool has_acpi_build; > int pci_root_uid; > @@ -125,6 +122,9 @@ struct PCMachineClass { > * check for memory. > */ > bool broken_32bit_mem_addr_check; > + > + /* whether the machine supports versioned cpu models */ > + bool no_versioned_cpu_model; > }; > > #define TYPE_PC_MACHINE "generic-pc-machine" > @@ -136,6 +136,7 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); > > /* pc.c */ > > +void pc_init_cpus(MachineState *ms); > void pc_acpi_smi_interrupt(void *opaque, int irq, int level); > > #define PCI_HOST_PROP_RAM_MEM "ram-mem" > diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h > index d43cb3908e..2d2b987fa1 100644 > --- a/include/hw/i386/x86.h > +++ b/include/hw/i386/x86.h > @@ -114,7 +114,7 @@ void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms); > uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, > unsigned int cpu_index); > > -void x86_cpus_init(X86MachineState *pcms, int default_cpu_version); > +void x86_cpus_init(X86MachineState *pcms); > void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count); > void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, > DeviceState *dev, Error **errp); > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > index 1b9c11022c..c1f868c4dd 100644 > --- a/target/i386/cpu.c > +++ b/target/i386/cpu.c > @@ -192,6 +192,9 @@ struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = { > */ > #define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF > > +/* default cpu version to use */ > +#define DEFAULT_CPU_VERSION 1 > + > /* > * Return a CPUID 2 cache descriptor for a given cache. > * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE > @@ -5343,20 +5346,16 @@ static const X86CPUDefinition builtin_x86_defs[] = { > }, > }; > > -/* > - * We resolve CPU model aliases using -v1 when using "-machine > - * none", but this is just for compatibility while libvirt isn't > - * adapted to resolve CPU model versions before creating VMs. > - * See "Runnability guarantee of CPU models" at > - * docs/about/deprecated.rst. > - */ > -X86CPUVersion default_cpu_version = 1; > +static bool use_legacy_cpu; > +void x86_cpu_set_legacy_version(void) > +{ > + use_legacy_cpu = true; > +} > > -void x86_cpu_set_default_version(X86CPUVersion version) > +static bool use_latest_cpu; > +void x86_cpu_uses_lastest_version(void) > { > - /* Translating CPU_VERSION_AUTO to CPU_VERSION_AUTO doesn't make sense */ > - assert(version != CPU_VERSION_AUTO); > - default_cpu_version = version; > + use_latest_cpu = true; > } > > static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) > @@ -5374,14 +5373,11 @@ static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) > /* Return the actual version being used for a specific CPU 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) { > + if (use_latest_cpu) { > return x86_cpu_model_last_version(model); > } > - return v; > + > + return model->version; > } > > static const Property max_x86_cpu_properties[] = { > @@ -5985,10 +5981,15 @@ static char *x86_cpu_class_get_alias_of(X86CPUClass *cc) > if (!cc->model || !cc->model->is_alias) { > return NULL; > } > - version = x86_cpu_model_resolve_version(cc->model); > - if (version <= 0) { > + > + if (use_legacy_cpu) { > + /* legacy cpu models do not support cpu aliases */ > return NULL; > } > + > + version = x86_cpu_model_resolve_version(cc->model); > + assert(version); > + > return x86_cpu_versioned_model_name(cc->model->cpudef, version); > } > > @@ -6002,11 +6003,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) > g_autofree char *model_id = x86_cpu_class_get_model_id(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 && cc->model && cc->model->note) { > desc = g_strdup_printf("%s [%s]", model_id, cc->model->note); > @@ -6109,13 +6106,8 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) > } else { > info->deprecated = false; > } > - /* > - * 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->alias_of = x86_cpu_class_get_alias_of(cc); > > QAPI_LIST_PREPEND(*cpu_list, info); > } > @@ -6287,7 +6279,12 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) > const X86CPUVersionDefinition *vdef; > X86CPUVersion version = x86_cpu_model_resolve_version(model); > > - if (version == CPU_VERSION_LEGACY) { > + /* > + * if the machine uses legacy cpus, use legacy cpus with no versions > + * when no explict CPU versions are specified in the CPU definition > + * passed from the command line. > + */ > + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { > return; > } > > @@ -6317,7 +6314,11 @@ static const CPUCaches *x86_cpu_get_versioned_cache_info(X86CPU *cpu, > X86CPUVersion version = x86_cpu_model_resolve_version(model); > const CPUCaches *cache_info = model->cpudef->cache_info; > > - if (version == CPU_VERSION_LEGACY) { > + /* > + * If machine supports legacy cpus and no explicit cpu versions are > + * specified, use the cache from the unversioned cpu definition. > + */ > + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { > return cache_info; > } > > @@ -6452,7 +6453,7 @@ static void x86_register_cpudef_types(const X86CPUDefinition *def) > /* Unversioned model: */ > m = g_new0(X86CPUModel, 1); > m->cpudef = def; > - m->version = CPU_VERSION_AUTO; > + m->version = DEFAULT_CPU_VERSION; > m->is_alias = true; > x86_register_cpu_model_type(def->name, m); > > diff --git a/target/i386/cpu.h b/target/i386/cpu.h > index b26e25ba15..bdbe54b26f 100644 > --- a/target/i386/cpu.h > +++ b/target/i386/cpu.h > @@ -2679,27 +2679,14 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); > void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, > TPRAccess access); > > -/* Special values for X86CPUVersion: */ > - > -/* 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. > + * Set CPU model version to the lastest version. > + * Currently, this is only used by microvm. > */ > -void x86_cpu_set_default_version(X86CPUVersion version); > +void x86_cpu_uses_lastest_version(void); > +void x86_cpu_set_legacy_version(void); > > #ifndef CONFIG_USER_ONLY >
On Thu, Jan 23, 2025 at 7:52 PM Igor Mammedov <imammedo@redhat.com> wrote: > > On Thu, 23 Jan 2025 17:26:12 +0530 > Ani Sinha <anisinha@redhat.com> wrote: > > > commit 0788a56bd1ae3 ("i386: Make unversioned CPU models be aliases") > > introduced 'default_cpu_version' for PCMachineClass. This created three > > categories of CPU models: > > - Most unversioned CPU models would use version 1 by default. > > - For machines 4.0.1 and older that do not support cpu model aliases, a > > special default_cpu_version value of CPU_VERSION_LEGACY is used. > > > Testing current master: > ==== > ./qemu-system-x86_64 -M pc-i440fx-4.0 -cpu Haswell-v4 -monitor stdio > ... > (qemu) info hotpluggable-cpus > Hotpluggable CPUs: > type: "Haswell-v4-x86_64-cpu" > > we can run versioned on old machine types. with caveat > not being able to migrate to old qemu that doesn't have it > > ==== > ./qemu-system-x86_64 -M pc-i440fx-4.0 -cpu Haswell -monitor stdio > ... > (qemu) info hotpluggable-cpus > Hotpluggable CPUs: > type: "Haswell-x86_64-cpu" > > ==== > ./qemu-system-x86_64 -M pc-i440fx-5.0 -cpu Haswell -monitor stdio > ... > (qemu) info hotpluggable-cpus > Hotpluggable CPUs: > type: "Haswell-x86_64-cpu" > > non-versioned model resolves to the same type regardless of legacy > > Do we really have to keep CPU_VERSION_LEGACY code around? > > Lets assume we drop all CPU_VERSION_LEGACY code, what would change? From code, x86_cpu_class_get_alias_of() always returns NULL for legacy. Maybe somewhere the descriptions are different? To be safe, I would just wait for another 10 months to drop all legacy stuff. > > > - It was thought that future machines would use the latest value of cpu > > versions corresponding to default_cpu_version value of > > CPU_VERSION_LATEST [1]. > > > > All pc machines still use the default cpu version of 1 for > > unversioned cpu models. CPU_VERSION_LATEST is a moving target and > > changes with time. Therefore, if machines use CPU_VERSION_LATEST, it would > > mean that over a period of time, for the same machine type, the cpu version > > would be different depending on what is latest at that time. This would > > break guests even when they use a constant machine type. Therefore, for > ^^^^^^^^^^^^^^^^^^ > s/.../versioned .../ > > > pc machines, use of CPU_VERSION_LATEST is not possible. Currently, only > > microvms use CPU_VERSION_LATEST. > > > > This change cleans up the complicated logic around default_cpu_version > > including getting rid of default_cpu_version property itself. A couple of new > > flags are introduced, one for the legacy model for machines 4.0.1 and older > > and other for microvms. For older machines, a new pc machine property is > > introduced that separates pc machine versions 4.0.1 and older from the newer > > machines. 4.0.1 and older machines are scheduled to be deleted towards > > end of 2025 since they would be 6 years old by then. At that time, we can > > remove all logic around legacy cpus. Microvms are the only machines that > > continue to use the latest cpu version. If this changes later, we can > > remove all logic around x86_cpu_model_last_version(). Default cpu version > > for unversioned cpu models is hardcoded to the value 1 and applies > > unconditionally for all pc machine types of version 4.1 and above. > > > > This change also removes all complications around CPU_VERSION_AUTO > > including removal of the value itself. > > > > 1) See commit dcafd1ef0af227 ("i386: Register versioned CPU models") > > > > CC: imammedo@redhat.com > > Signed-off-by: Ani Sinha <anisinha@redhat.com> > > --- > > hw/i386/microvm.c | 3 +- > > hw/i386/pc.c | 14 +++++++++ > > hw/i386/pc_piix.c | 6 ++-- > > hw/i386/pc_q35.c | 6 ++-- > > hw/i386/x86-common.c | 4 +-- > > include/hw/i386/pc.h | 7 +++-- > > include/hw/i386/x86.h | 2 +- > > target/i386/cpu.c | 69 ++++++++++++++++++++++--------------------- > > target/i386/cpu.h | 21 +++---------- > > 9 files changed, 67 insertions(+), 65 deletions(-) > > > > changelog: > > v2: explain in commit log why use of CPU_VERSION_LATEST for machines > > is problematic. > > v3: fix a bug that broke the pipeline > > https://gitlab.com/mstredhat/qemu/-/pipelines/1626171267 > > when cpu versions are explicitly specified in the command line, > > respect that and do not enforce legacy (unversioned) cpu logic. > > The pipeline is green now with the fix: > > https://gitlab.com/anisinha/qemu/-/pipelines/1626783632 > > v4: made changes as per Zhao's suggestions. > > Pipeline passes https://gitlab.com/anisinha/qemu/-/pipelines/1635829877 > > v5: adjustment of pc_init_cpus() declaration as per Zhao's suggestion. This > > simplifies things and also passes compilation. > > CI still passes https://gitlab.com/anisinha/qemu/-/pipelines/1637657451 > > > > diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c > > index a8d354aabe..ffb1b37fe5 100644 > > --- a/hw/i386/microvm.c > > +++ b/hw/i386/microvm.c > > @@ -458,7 +458,8 @@ static void microvm_machine_state_init(MachineState *machine) > > > > microvm_memory_init(mms); > > > > - x86_cpus_init(x86ms, CPU_VERSION_LATEST); > > + x86_cpu_uses_lastest_version(); > > + x86_cpus_init(x86ms); > > > > microvm_devices_init(mms); > > } > > diff --git a/hw/i386/pc.c b/hw/i386/pc.c > > index b46975c8a4..f97a519573 100644 > > --- a/hw/i386/pc.c > > +++ b/hw/i386/pc.c > > @@ -30,6 +30,7 @@ > > #include "hw/hyperv/hv-balloon.h" > > #include "hw/i386/fw_cfg.h" > > #include "hw/i386/vmport.h" > > +#include "target/i386/cpu.h" > > #include "system/cpus.h" > > #include "hw/ide/ide-bus.h" > > #include "hw/timer/hpet.h" > > @@ -615,6 +616,19 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) > > } > > } > > > > +void pc_init_cpus(MachineState *ms) > > +{ > > + X86MachineState *x86ms = X86_MACHINE(ms); > > + PCMachineState *pcms = PC_MACHINE(ms); > > + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); > > + > > + if (pcmc->no_versioned_cpu_model) { > > + /* use legacy cpu as it does not support versions */ > > + x86_cpu_set_legacy_version(); > > + } > > + x86_cpus_init(x86ms); > > +} > > + > > static > > void pc_machine_done(Notifier *notifier, void *data) > > { > > diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c > > index 04d2957adc..dc684cb011 100644 > > --- a/hw/i386/pc_piix.c > > +++ b/hw/i386/pc_piix.c > > @@ -181,7 +181,8 @@ static void pc_init1(MachineState *machine, const char *pci_type) > > } > > > > pc_machine_init_sgx_epc(pcms); > > - x86_cpus_init(x86ms, pcmc->default_cpu_version); > > + > > + pc_init_cpus(machine); > > > > if (kvm_enabled()) { > > kvmclock_create(pcmc->kvmclock_create_always); > > @@ -457,7 +458,6 @@ static void pc_i440fx_machine_options(MachineClass *m) > > ObjectClass *oc = OBJECT_CLASS(m); > > pcmc->default_south_bridge = TYPE_PIIX3_DEVICE; > > pcmc->pci_root_uid = 0; > > - pcmc->default_cpu_version = 1; > > > > m->family = "pc_piix"; > > m->desc = "Standard PC (i440FX + PIIX, 1996)"; > > @@ -669,7 +669,7 @@ static void pc_i440fx_machine_4_0_options(MachineClass *m) > > { > > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > > pc_i440fx_machine_4_1_options(m); > > - pcmc->default_cpu_version = CPU_VERSION_LEGACY; > > + pcmc->no_versioned_cpu_model = true; > > 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 77536dd697..045b05da64 100644 > > --- a/hw/i386/pc_q35.c > > +++ b/hw/i386/pc_q35.c > > @@ -187,7 +187,8 @@ static void pc_q35_init(MachineState *machine) > > } > > > > pc_machine_init_sgx_epc(pcms); > > - x86_cpus_init(x86ms, pcmc->default_cpu_version); > > + > > + pc_init_cpus(machine); > > > > if (kvm_enabled()) { > > kvmclock_create(pcmc->kvmclock_create_always); > > @@ -339,7 +340,6 @@ static void pc_q35_machine_options(MachineClass *m) > > { > > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > > pcmc->pci_root_uid = 0; > > - pcmc->default_cpu_version = 1; > > > > m->family = "pc_q35"; > > m->desc = "Standard PC (Q35 + ICH9, 2009)"; > > @@ -547,7 +547,7 @@ static void pc_q35_machine_4_0_1_options(MachineClass *m) > > { > > PCMachineClass *pcmc = PC_MACHINE_CLASS(m); > > pc_q35_machine_4_1_options(m); > > - pcmc->default_cpu_version = CPU_VERSION_LEGACY; > > + pcmc->no_versioned_cpu_model = true; > > /* > > * 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/hw/i386/x86-common.c b/hw/i386/x86-common.c > > index 008496b5b8..1ed5bc6010 100644 > > --- a/hw/i386/x86-common.c > > +++ b/hw/i386/x86-common.c > > @@ -66,15 +66,13 @@ out: > > object_unref(cpu); > > } > > > > -void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) > > +void x86_cpus_init(X86MachineState *x86ms) > > { > > int i; > > const CPUArchIdList *possible_cpus; > > MachineState *ms = MACHINE(x86ms); > > MachineClass *mc = MACHINE_GET_CLASS(x86ms); > > > > - x86_cpu_set_default_version(default_cpu_version); > > - > > /* > > * Calculates the limit to CPU APIC ID values > > * > > diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h > > index a558705cb9..563f765d7f 100644 > > --- a/include/hw/i386/pc.h > > +++ b/include/hw/i386/pc.h > > @@ -92,9 +92,6 @@ struct PCMachineClass { > > > > /* Compat options: */ > > > > - /* Default CPU model version. See x86_cpu_set_default_version(). */ > > - int default_cpu_version; > > - > > /* ACPI compat: */ > > bool has_acpi_build; > > int pci_root_uid; > > @@ -125,6 +122,9 @@ struct PCMachineClass { > > * check for memory. > > */ > > bool broken_32bit_mem_addr_check; > > + > > + /* whether the machine supports versioned cpu models */ > > + bool no_versioned_cpu_model; > > }; > > > > #define TYPE_PC_MACHINE "generic-pc-machine" > > @@ -136,6 +136,7 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); > > > > /* pc.c */ > > > > +void pc_init_cpus(MachineState *ms); > > void pc_acpi_smi_interrupt(void *opaque, int irq, int level); > > > > #define PCI_HOST_PROP_RAM_MEM "ram-mem" > > diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h > > index d43cb3908e..2d2b987fa1 100644 > > --- a/include/hw/i386/x86.h > > +++ b/include/hw/i386/x86.h > > @@ -114,7 +114,7 @@ void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms); > > uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, > > unsigned int cpu_index); > > > > -void x86_cpus_init(X86MachineState *pcms, int default_cpu_version); > > +void x86_cpus_init(X86MachineState *pcms); > > void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count); > > void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, > > DeviceState *dev, Error **errp); > > diff --git a/target/i386/cpu.c b/target/i386/cpu.c > > index 1b9c11022c..c1f868c4dd 100644 > > --- a/target/i386/cpu.c > > +++ b/target/i386/cpu.c > > @@ -192,6 +192,9 @@ struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = { > > */ > > #define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF > > > > +/* default cpu version to use */ > > +#define DEFAULT_CPU_VERSION 1 > > + > > /* > > * Return a CPUID 2 cache descriptor for a given cache. > > * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE > > @@ -5343,20 +5346,16 @@ static const X86CPUDefinition builtin_x86_defs[] = { > > }, > > }; > > > > -/* > > - * We resolve CPU model aliases using -v1 when using "-machine > > - * none", but this is just for compatibility while libvirt isn't > > - * adapted to resolve CPU model versions before creating VMs. > > - * See "Runnability guarantee of CPU models" at > > - * docs/about/deprecated.rst. > > - */ > > -X86CPUVersion default_cpu_version = 1; > > +static bool use_legacy_cpu; > > +void x86_cpu_set_legacy_version(void) > > +{ > > + use_legacy_cpu = true; > > +} > > > > -void x86_cpu_set_default_version(X86CPUVersion version) > > +static bool use_latest_cpu; > > +void x86_cpu_uses_lastest_version(void) > > { > > - /* Translating CPU_VERSION_AUTO to CPU_VERSION_AUTO doesn't make sense */ > > - assert(version != CPU_VERSION_AUTO); > > - default_cpu_version = version; > > + use_latest_cpu = true; > > } > > > > static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) > > @@ -5374,14 +5373,11 @@ static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) > > /* Return the actual version being used for a specific CPU 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) { > > + if (use_latest_cpu) { > > return x86_cpu_model_last_version(model); > > } > > - return v; > > + > > + return model->version; > > } > > > > static const Property max_x86_cpu_properties[] = { > > @@ -5985,10 +5981,15 @@ static char *x86_cpu_class_get_alias_of(X86CPUClass *cc) > > if (!cc->model || !cc->model->is_alias) { > > return NULL; > > } > > - version = x86_cpu_model_resolve_version(cc->model); > > - if (version <= 0) { > > + > > + if (use_legacy_cpu) { > > + /* legacy cpu models do not support cpu aliases */ > > return NULL; > > } > > + > > + version = x86_cpu_model_resolve_version(cc->model); > > + assert(version); > > + > > return x86_cpu_versioned_model_name(cc->model->cpudef, version); > > } > > > > @@ -6002,11 +6003,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) > > g_autofree char *model_id = x86_cpu_class_get_model_id(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 && cc->model && cc->model->note) { > > desc = g_strdup_printf("%s [%s]", model_id, cc->model->note); > > @@ -6109,13 +6106,8 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) > > } else { > > info->deprecated = false; > > } > > - /* > > - * 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->alias_of = x86_cpu_class_get_alias_of(cc); > > > > QAPI_LIST_PREPEND(*cpu_list, info); > > } > > @@ -6287,7 +6279,12 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) > > const X86CPUVersionDefinition *vdef; > > X86CPUVersion version = x86_cpu_model_resolve_version(model); > > > > - if (version == CPU_VERSION_LEGACY) { > > + /* > > + * if the machine uses legacy cpus, use legacy cpus with no versions > > + * when no explict CPU versions are specified in the CPU definition > > + * passed from the command line. > > + */ > > + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { > > return; > > } > > > > @@ -6317,7 +6314,11 @@ static const CPUCaches *x86_cpu_get_versioned_cache_info(X86CPU *cpu, > > X86CPUVersion version = x86_cpu_model_resolve_version(model); > > const CPUCaches *cache_info = model->cpudef->cache_info; > > > > - if (version == CPU_VERSION_LEGACY) { > > + /* > > + * If machine supports legacy cpus and no explicit cpu versions are > > + * specified, use the cache from the unversioned cpu definition. > > + */ > > + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { > > return cache_info; > > } > > > > @@ -6452,7 +6453,7 @@ static void x86_register_cpudef_types(const X86CPUDefinition *def) > > /* Unversioned model: */ > > m = g_new0(X86CPUModel, 1); > > m->cpudef = def; > > - m->version = CPU_VERSION_AUTO; > > + m->version = DEFAULT_CPU_VERSION; > > m->is_alias = true; > > x86_register_cpu_model_type(def->name, m); > > > > diff --git a/target/i386/cpu.h b/target/i386/cpu.h > > index b26e25ba15..bdbe54b26f 100644 > > --- a/target/i386/cpu.h > > +++ b/target/i386/cpu.h > > @@ -2679,27 +2679,14 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); > > void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, > > TPRAccess access); > > > > -/* Special values for X86CPUVersion: */ > > - > > -/* 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. > > + * Set CPU model version to the lastest version. > > + * Currently, this is only used by microvm. > > */ > > -void x86_cpu_set_default_version(X86CPUVersion version); > > +void x86_cpu_uses_lastest_version(void); > > +void x86_cpu_set_legacy_version(void); > > > > #ifndef CONFIG_USER_ONLY > > >
diff --git a/hw/i386/microvm.c b/hw/i386/microvm.c index a8d354aabe..ffb1b37fe5 100644 --- a/hw/i386/microvm.c +++ b/hw/i386/microvm.c @@ -458,7 +458,8 @@ static void microvm_machine_state_init(MachineState *machine) microvm_memory_init(mms); - x86_cpus_init(x86ms, CPU_VERSION_LATEST); + x86_cpu_uses_lastest_version(); + x86_cpus_init(x86ms); microvm_devices_init(mms); } diff --git a/hw/i386/pc.c b/hw/i386/pc.c index b46975c8a4..f97a519573 100644 --- a/hw/i386/pc.c +++ b/hw/i386/pc.c @@ -30,6 +30,7 @@ #include "hw/hyperv/hv-balloon.h" #include "hw/i386/fw_cfg.h" #include "hw/i386/vmport.h" +#include "target/i386/cpu.h" #include "system/cpus.h" #include "hw/ide/ide-bus.h" #include "hw/timer/hpet.h" @@ -615,6 +616,19 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level) } } +void pc_init_cpus(MachineState *ms) +{ + X86MachineState *x86ms = X86_MACHINE(ms); + PCMachineState *pcms = PC_MACHINE(ms); + PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms); + + if (pcmc->no_versioned_cpu_model) { + /* use legacy cpu as it does not support versions */ + x86_cpu_set_legacy_version(); + } + x86_cpus_init(x86ms); +} + static void pc_machine_done(Notifier *notifier, void *data) { diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c index 04d2957adc..dc684cb011 100644 --- a/hw/i386/pc_piix.c +++ b/hw/i386/pc_piix.c @@ -181,7 +181,8 @@ static void pc_init1(MachineState *machine, const char *pci_type) } pc_machine_init_sgx_epc(pcms); - x86_cpus_init(x86ms, pcmc->default_cpu_version); + + pc_init_cpus(machine); if (kvm_enabled()) { kvmclock_create(pcmc->kvmclock_create_always); @@ -457,7 +458,6 @@ static void pc_i440fx_machine_options(MachineClass *m) ObjectClass *oc = OBJECT_CLASS(m); pcmc->default_south_bridge = TYPE_PIIX3_DEVICE; pcmc->pci_root_uid = 0; - pcmc->default_cpu_version = 1; m->family = "pc_piix"; m->desc = "Standard PC (i440FX + PIIX, 1996)"; @@ -669,7 +669,7 @@ static void pc_i440fx_machine_4_0_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_i440fx_machine_4_1_options(m); - pcmc->default_cpu_version = CPU_VERSION_LEGACY; + pcmc->no_versioned_cpu_model = true; 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 77536dd697..045b05da64 100644 --- a/hw/i386/pc_q35.c +++ b/hw/i386/pc_q35.c @@ -187,7 +187,8 @@ static void pc_q35_init(MachineState *machine) } pc_machine_init_sgx_epc(pcms); - x86_cpus_init(x86ms, pcmc->default_cpu_version); + + pc_init_cpus(machine); if (kvm_enabled()) { kvmclock_create(pcmc->kvmclock_create_always); @@ -339,7 +340,6 @@ static void pc_q35_machine_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pcmc->pci_root_uid = 0; - pcmc->default_cpu_version = 1; m->family = "pc_q35"; m->desc = "Standard PC (Q35 + ICH9, 2009)"; @@ -547,7 +547,7 @@ static void pc_q35_machine_4_0_1_options(MachineClass *m) { PCMachineClass *pcmc = PC_MACHINE_CLASS(m); pc_q35_machine_4_1_options(m); - pcmc->default_cpu_version = CPU_VERSION_LEGACY; + pcmc->no_versioned_cpu_model = true; /* * 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/hw/i386/x86-common.c b/hw/i386/x86-common.c index 008496b5b8..1ed5bc6010 100644 --- a/hw/i386/x86-common.c +++ b/hw/i386/x86-common.c @@ -66,15 +66,13 @@ out: object_unref(cpu); } -void x86_cpus_init(X86MachineState *x86ms, int default_cpu_version) +void x86_cpus_init(X86MachineState *x86ms) { int i; const CPUArchIdList *possible_cpus; MachineState *ms = MACHINE(x86ms); MachineClass *mc = MACHINE_GET_CLASS(x86ms); - x86_cpu_set_default_version(default_cpu_version); - /* * Calculates the limit to CPU APIC ID values * diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h index a558705cb9..563f765d7f 100644 --- a/include/hw/i386/pc.h +++ b/include/hw/i386/pc.h @@ -92,9 +92,6 @@ struct PCMachineClass { /* Compat options: */ - /* Default CPU model version. See x86_cpu_set_default_version(). */ - int default_cpu_version; - /* ACPI compat: */ bool has_acpi_build; int pci_root_uid; @@ -125,6 +122,9 @@ struct PCMachineClass { * check for memory. */ bool broken_32bit_mem_addr_check; + + /* whether the machine supports versioned cpu models */ + bool no_versioned_cpu_model; }; #define TYPE_PC_MACHINE "generic-pc-machine" @@ -136,6 +136,7 @@ GSIState *pc_gsi_create(qemu_irq **irqs, bool pci_enabled); /* pc.c */ +void pc_init_cpus(MachineState *ms); void pc_acpi_smi_interrupt(void *opaque, int irq, int level); #define PCI_HOST_PROP_RAM_MEM "ram-mem" diff --git a/include/hw/i386/x86.h b/include/hw/i386/x86.h index d43cb3908e..2d2b987fa1 100644 --- a/include/hw/i386/x86.h +++ b/include/hw/i386/x86.h @@ -114,7 +114,7 @@ void init_topo_info(X86CPUTopoInfo *topo_info, const X86MachineState *x86ms); uint32_t x86_cpu_apic_id_from_index(X86MachineState *x86ms, unsigned int cpu_index); -void x86_cpus_init(X86MachineState *pcms, int default_cpu_version); +void x86_cpus_init(X86MachineState *pcms); void x86_rtc_set_cpus_count(ISADevice *rtc, uint16_t cpus_count); void x86_cpu_pre_plug(HotplugHandler *hotplug_dev, DeviceState *dev, Error **errp); diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 1b9c11022c..c1f868c4dd 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -192,6 +192,9 @@ struct CPUID2CacheDescriptorInfo cpuid2_cache_descriptors[] = { */ #define CACHE_DESCRIPTOR_UNAVAILABLE 0xFF +/* default cpu version to use */ +#define DEFAULT_CPU_VERSION 1 + /* * Return a CPUID 2 cache descriptor for a given cache. * If no known descriptor is found, return CACHE_DESCRIPTOR_UNAVAILABLE @@ -5343,20 +5346,16 @@ static const X86CPUDefinition builtin_x86_defs[] = { }, }; -/* - * We resolve CPU model aliases using -v1 when using "-machine - * none", but this is just for compatibility while libvirt isn't - * adapted to resolve CPU model versions before creating VMs. - * See "Runnability guarantee of CPU models" at - * docs/about/deprecated.rst. - */ -X86CPUVersion default_cpu_version = 1; +static bool use_legacy_cpu; +void x86_cpu_set_legacy_version(void) +{ + use_legacy_cpu = true; +} -void x86_cpu_set_default_version(X86CPUVersion version) +static bool use_latest_cpu; +void x86_cpu_uses_lastest_version(void) { - /* Translating CPU_VERSION_AUTO to CPU_VERSION_AUTO doesn't make sense */ - assert(version != CPU_VERSION_AUTO); - default_cpu_version = version; + use_latest_cpu = true; } static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) @@ -5374,14 +5373,11 @@ static X86CPUVersion x86_cpu_model_last_version(const X86CPUModel *model) /* Return the actual version being used for a specific CPU 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) { + if (use_latest_cpu) { return x86_cpu_model_last_version(model); } - return v; + + return model->version; } static const Property max_x86_cpu_properties[] = { @@ -5985,10 +5981,15 @@ static char *x86_cpu_class_get_alias_of(X86CPUClass *cc) if (!cc->model || !cc->model->is_alias) { return NULL; } - version = x86_cpu_model_resolve_version(cc->model); - if (version <= 0) { + + if (use_legacy_cpu) { + /* legacy cpu models do not support cpu aliases */ return NULL; } + + version = x86_cpu_model_resolve_version(cc->model); + assert(version); + return x86_cpu_versioned_model_name(cc->model->cpudef, version); } @@ -6002,11 +6003,7 @@ static void x86_cpu_list_entry(gpointer data, gpointer user_data) g_autofree char *model_id = x86_cpu_class_get_model_id(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 && cc->model && cc->model->note) { desc = g_strdup_printf("%s [%s]", model_id, cc->model->note); @@ -6109,13 +6106,8 @@ static void x86_cpu_definition_entry(gpointer data, gpointer user_data) } else { info->deprecated = false; } - /* - * 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->alias_of = x86_cpu_class_get_alias_of(cc); QAPI_LIST_PREPEND(*cpu_list, info); } @@ -6287,7 +6279,12 @@ static void x86_cpu_apply_version_props(X86CPU *cpu, X86CPUModel *model) const X86CPUVersionDefinition *vdef; X86CPUVersion version = x86_cpu_model_resolve_version(model); - if (version == CPU_VERSION_LEGACY) { + /* + * if the machine uses legacy cpus, use legacy cpus with no versions + * when no explict CPU versions are specified in the CPU definition + * passed from the command line. + */ + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { return; } @@ -6317,7 +6314,11 @@ static const CPUCaches *x86_cpu_get_versioned_cache_info(X86CPU *cpu, X86CPUVersion version = x86_cpu_model_resolve_version(model); const CPUCaches *cache_info = model->cpudef->cache_info; - if (version == CPU_VERSION_LEGACY) { + /* + * If machine supports legacy cpus and no explicit cpu versions are + * specified, use the cache from the unversioned cpu definition. + */ + if (version == DEFAULT_CPU_VERSION && use_legacy_cpu) { return cache_info; } @@ -6452,7 +6453,7 @@ static void x86_register_cpudef_types(const X86CPUDefinition *def) /* Unversioned model: */ m = g_new0(X86CPUModel, 1); m->cpudef = def; - m->version = CPU_VERSION_AUTO; + m->version = DEFAULT_CPU_VERSION; m->is_alias = true; x86_register_cpu_model_type(def->name, m); diff --git a/target/i386/cpu.h b/target/i386/cpu.h index b26e25ba15..bdbe54b26f 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2679,27 +2679,14 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access); void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip, TPRAccess access); -/* Special values for X86CPUVersion: */ - -/* 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. + * Set CPU model version to the lastest version. + * Currently, this is only used by microvm. */ -void x86_cpu_set_default_version(X86CPUVersion version); +void x86_cpu_uses_lastest_version(void); +void x86_cpu_set_legacy_version(void); #ifndef CONFIG_USER_ONLY
commit 0788a56bd1ae3 ("i386: Make unversioned CPU models be aliases") introduced 'default_cpu_version' for PCMachineClass. This created three categories of CPU models: - Most unversioned CPU models would use version 1 by default. - For machines 4.0.1 and older that do not support cpu model aliases, a special default_cpu_version value of CPU_VERSION_LEGACY is used. - It was thought that future machines would use the latest value of cpu versions corresponding to default_cpu_version value of CPU_VERSION_LATEST [1]. All pc machines still use the default cpu version of 1 for unversioned cpu models. CPU_VERSION_LATEST is a moving target and changes with time. Therefore, if machines use CPU_VERSION_LATEST, it would mean that over a period of time, for the same machine type, the cpu version would be different depending on what is latest at that time. This would break guests even when they use a constant machine type. Therefore, for pc machines, use of CPU_VERSION_LATEST is not possible. Currently, only microvms use CPU_VERSION_LATEST. This change cleans up the complicated logic around default_cpu_version including getting rid of default_cpu_version property itself. A couple of new flags are introduced, one for the legacy model for machines 4.0.1 and older and other for microvms. For older machines, a new pc machine property is introduced that separates pc machine versions 4.0.1 and older from the newer machines. 4.0.1 and older machines are scheduled to be deleted towards end of 2025 since they would be 6 years old by then. At that time, we can remove all logic around legacy cpus. Microvms are the only machines that continue to use the latest cpu version. If this changes later, we can remove all logic around x86_cpu_model_last_version(). Default cpu version for unversioned cpu models is hardcoded to the value 1 and applies unconditionally for all pc machine types of version 4.1 and above. This change also removes all complications around CPU_VERSION_AUTO including removal of the value itself. 1) See commit dcafd1ef0af227 ("i386: Register versioned CPU models") CC: imammedo@redhat.com Signed-off-by: Ani Sinha <anisinha@redhat.com> --- hw/i386/microvm.c | 3 +- hw/i386/pc.c | 14 +++++++++ hw/i386/pc_piix.c | 6 ++-- hw/i386/pc_q35.c | 6 ++-- hw/i386/x86-common.c | 4 +-- include/hw/i386/pc.h | 7 +++-- include/hw/i386/x86.h | 2 +- target/i386/cpu.c | 69 ++++++++++++++++++++++--------------------- target/i386/cpu.h | 21 +++---------- 9 files changed, 67 insertions(+), 65 deletions(-) changelog: v2: explain in commit log why use of CPU_VERSION_LATEST for machines is problematic. v3: fix a bug that broke the pipeline https://gitlab.com/mstredhat/qemu/-/pipelines/1626171267 when cpu versions are explicitly specified in the command line, respect that and do not enforce legacy (unversioned) cpu logic. The pipeline is green now with the fix: https://gitlab.com/anisinha/qemu/-/pipelines/1626783632 v4: made changes as per Zhao's suggestions. Pipeline passes https://gitlab.com/anisinha/qemu/-/pipelines/1635829877 v5: adjustment of pc_init_cpus() declaration as per Zhao's suggestion. This simplifies things and also passes compilation. CI still passes https://gitlab.com/anisinha/qemu/-/pipelines/1637657451