[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v3 1/2] Introduce (x86) CPU model deprecation API
From: |
Eduardo Habkost |
Subject: |
Re: [PATCH v3 1/2] Introduce (x86) CPU model deprecation API |
Date: |
Fri, 18 Sep 2020 12:42:37 -0400 |
On Fri, Sep 18, 2020 at 01:48:18PM +0800, Robert Hoo wrote:
> On Thu, 2020-09-17 at 14:18 -0400, Eduardo Habkost wrote:
> > I think the patch looks better now, thanks!
> >
> > Just a few minor questions and suggestions:
> >
> > On Wed, Sep 16, 2020 at 04:37:13PM +0800, Robert Hoo wrote:
> > > Complement versioned CPU model framework with the ability of
> > > marking some
> > > versions deprecated. When that CPU model is chosen, get some
> > > warning. The
> > > warning message is customized, e.g. telling in which future QEMU
> > > version will
> > > it be obsoleted.
> > > The deprecation message will also appear by x86_cpu_list_entry(),
> > > e.g. '-cpu
> > > help'.
> > > QMP 'query-cpu-definitions' will also return a bool value
> > > indicating the
> > > deprecation status.
> > >
> > > Signed-off-by: Robert Hoo <robert.hu@linux.intel.com>
> > > ---
> > > Changelog
> > > v3:
> > > Make the deprecation implementation CPUClass generic.
> > >
> > > v2:
> > > Move deprecation check from parse_cpu_option() to
> > > machine_run_board_init(), so
> > > that it can cover implicit cpu_type assignment cases.
> >
> > What do you mean by implicit cpu_type assignment cases?
>
> Means the case that user doesn't explicitly assign '-cpu xxx' but
> implicitly inherits machine's default cpu type.
> vl.c
> /* parse features once if machine provides default cpu_type */
> current_machine->cpu_type = machine_class->default_cpu_type;
> if (cpu_option) {
> current_machine->cpu_type = parse_cpu_option(cpu_option);
> }
We probably would never deprecate CPU models that are still used
by default, so this is not an issue.
> >
> > Doing it inside parse_cpu_option() like you did in v1 will make
> > the deprecation warnings appear for *-user too (which is a good
> > thing).
> >
> So you changed your mind;-)
Sorry, I don't remember suggesting this. I couldn't find any
reply from myself in v1, and v2 already had the code moved to
machine_run_board_init().
Note that doing the check in machine_run_board_init() is not
necessarily a problem, I'm just trying to understand why the code
was moved from parse_cpu_option() to machine_run_board_init()
between v1 and v2.
>
> Could you shed more details? I don't get this point. What do you mean
> "*-user"?
I mean QEMU user mode emulator, bsd-user and linux-user (e.g. the
qemu-x86_64 binary). They call parse_cpu_option() as well.
>
> > > Add qapi new member documentation. Thanks Eric for comment and
> > > guidance on qapi.
> > >
> > > hw/core/machine.c | 12 ++++++++++--
> > > include/hw/core/cpu.h | 6 ++++++
> > > qapi/machine-target.json | 7 ++++++-
> > > target/i386/cpu.c | 29 +++++++++++++++++++++++------
> > > 4 files changed, 45 insertions(+), 9 deletions(-)
> > >
> > > diff --git a/hw/core/machine.c b/hw/core/machine.c
> > > index ea26d61..b41f88d 100644
> > > --- a/hw/core/machine.c
> > > +++ b/hw/core/machine.c
> > > @@ -1095,6 +1095,8 @@ MemoryRegion
> > > *machine_consume_memdev(MachineState *machine,
> > > void machine_run_board_init(MachineState *machine)
> > > {
> > > MachineClass *machine_class = MACHINE_GET_CLASS(machine);
> > > + ObjectClass *oc = object_class_by_name(machine->cpu_type);
> > > + CPUClass *cc;
> > >
> > > if (machine->ram_memdev_id) {
> > > Object *o;
> > > @@ -1114,11 +1116,10 @@ void machine_run_board_init(MachineState
> > > *machine)
> > > * specified a CPU with -cpu check here that the user CPU is
> > > supported.
> > > */
> > > if (machine_class->valid_cpu_types && machine->cpu_type) {
> > > - ObjectClass *class = object_class_by_name(machine-
> > > >cpu_type);
> > > int i;
> > >
> > > for (i = 0; machine_class->valid_cpu_types[i]; i++) {
> > > - if (object_class_dynamic_cast(class,
> > > + if (object_class_dynamic_cast(oc,
> > > machine_class-
> > > >valid_cpu_types[i])) {
> > > /* The user specificed CPU is in the valid field,
> > > we are
> > > * good to go.
> > > @@ -1141,6 +1142,13 @@ void machine_run_board_init(MachineState
> > > *machine)
> > > }
> > > }
> > >
> > > + /* Check if CPU type is deprecated and warn if so */
> > > + cc = CPU_CLASS(oc);
> > > + if (cc->deprecated) {
> > > + warn_report("CPU model %s is deprecated -- %s", machine-
> > > >cpu_type,
> > > + cc->deprecation_note);
> > > + }
> > > +
> > > machine_class->init(machine);
> > > }
> > >
> > > diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> > > index 99dc33f..c4b17c8 100644
> > > --- a/include/hw/core/cpu.h
> > > +++ b/include/hw/core/cpu.h
> > > @@ -155,6 +155,10 @@ struct TranslationBlock;
> > > * @disas_set_info: Setup architecture specific components of
> > > disassembly info
> > > * @adjust_watchpoint_address: Perform a target-specific
> > > adjustment to an
> > > * address before attempting to match it against watchpoints.
> > > + * @deprecated: True if this CPU model is deprecated (going to be
> > > removed in
> > > + * near future).
> > > + * @deprecation_note: Message about the deprecation. e.g. Since
> > > which version
> > > + * will it be obsoleted.
> >
> > We don't need two separate fields if (deprecation_note != NULL)
> > means the CPU model is deprecated. This is how it was
> > implemented in MachineClass (see MachineClass::deprecation_reason).
> >
>
> Agree.
> I think such applies to X86CPUModel::deprecated and X86CPUModel::note
> as well; and rename X86CPUModel::note --> deprecation_note. How do you
> like this?
Sound good!
>
> > > *
> > > * Represents a CPU family or model.
> > > */
> > > @@ -221,6 +225,8 @@ struct CPUClass {
> > > vaddr (*adjust_watchpoint_address)(CPUState *cpu, vaddr addr,
> > > int len);
> > > void (*tcg_initialize)(void);
> > >
> > > + bool deprecated;
> > > + const char *deprecation_note;
> > > /* Keep non-pointer data at the end to minimize holes. */
> > > int gdb_num_core_regs;
> > > bool gdb_stop_before_watchpoint;
> > > diff --git a/qapi/machine-target.json b/qapi/machine-target.json
> > > index 698850c..fec3bb8 100644
> > > --- a/qapi/machine-target.json
> > > +++ b/qapi/machine-target.json
> > > @@ -286,6 +286,10 @@
> > > # in the VM configuration, because aliases may stop
> > > being
> > > # migration-safe in the future (since 4.1)
> > > #
> > > +# @deprecated: If true, this CPU model is deprecated and may be
> > > removed in
> > > +# in some future version of QEMU according to the
> > > QEMU deprecation
> > > +# policy. (since 5.2)
> > > +#
> > > # @unavailable-features is a list of QOM property names that
> > > # represent CPU model attributes that prevent the CPU from
> > > running.
> > > # If the QOM property is read-only, that means there's no known
> > > @@ -310,7 +314,8 @@
> > > 'static': 'bool',
> > > '*unavailable-features': [ 'str' ],
> > > 'typename': 'str',
> > > - '*alias-of' : 'str' },
> > > + '*alias-of' : 'str',
> > > + 'deprecated' : 'bool' },
> > > 'if': 'defined(TARGET_PPC) || defined(TARGET_ARM) ||
> > > defined(TARGET_I386) || defined(TARGET_S390X) ||
> > > defined(TARGET_MIPS)' }
> > >
> > > ##
> > > diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> > > index 49d8958..9cb82b7 100644
> > > --- a/target/i386/cpu.c
> > > +++ b/target/i386/cpu.c
> > > @@ -1716,6 +1716,7 @@ typedef struct X86CPUVersionDefinition {
> > > const char *alias;
> > > const char *note;
> > > PropValue *props;
> > > + bool deprecated;
> > > } X86CPUVersionDefinition;
> > >
> > > /* Base definition for a CPU model */
> > > @@ -1751,6 +1752,11 @@ struct X86CPUModel {
> > > * This matters only for "-cpu help" and query-cpu-definitions
> > > */
> > > bool is_alias;
> > > + /*
> > > + * If true, this model is deprecated, and may be removed in
> > > the future.
> > > + * Trying to use it now will cause a warning.
> > > + */
> > > + bool deprecated;
> > > };
> > >
> > > /* Get full model name for CPU version */
> > > @@ -5096,6 +5102,7 @@ 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;
> > > + info->deprecated = cc->model ? cc->model->deprecated : false;
> > > /*
> > > * Old machine types won't report aliases, so that alias
> > > translation
> > > * doesn't break compatibility with previous QEMU versions.
> > > @@ -5486,9 +5493,12 @@ static void
> > > x86_cpu_cpudef_class_init(ObjectClass *oc, void *data)
> > > {
> > > X86CPUModel *model = data;
> > > X86CPUClass *xcc = X86_CPU_CLASS(oc);
> > > + CPUClass *cc = CPU_CLASS(oc);
> > >
> > > xcc->model = model;
> > > xcc->migration_safe = true;
> > > + cc->deprecated = model->deprecated;
> > > + cc->deprecation_note = g_strdup(model->note);
> >
> > The meaning of cc->deprecation_note and model->note is a bit
> > ambiguous here. model->note is not necessarily a deprecation
> > note, but its contents are being copied unconditionally to
> > cc->deprecation_note.
> >
> > What about setting cc->deprecation_note only if and only if the
> > model is deprecated?
> >
> Agree. Since X86CPUModel::note is actually unused by anything now,
> going to rename it to deprecation_note as aforementioned.
.note is used by all the CPU models that set .note. See for
example:
x86 Cascadelake-Server-v1 Intel Xeon Processor (Cascadelake)
x86 Cascadelake-Server-v2 Intel Xeon Processor (Cascadelake)
[ARCH_CAPABILITIES]
x86 Cascadelake-Server-v3 Intel Xeon Processor (Cascadelake)
[ARCH_CAPABILITIES, no TSX]
x86 Cascadelake-Server-v4 Intel Xeon Processor (Cascadelake)
[ARCH_CAPABILITIES, no TSX]
>
> A side concern,
> cc->deprecation_note = g_strdup(model->note);
>
> I don's see where free the cc object. Assuming the dup'ed string, as
> well as object, will last through QEMU process life time, freed
> implicitly as this process gone. Is my understanding right?
We never free QOM class structs (like CPUClass), so that's OK.
> >
> > > }
> > >
> > > static void x86_register_cpu_model_type(const char *name,
> > > X86CPUModel *model)
> > > @@ -5524,21 +5534,28 @@ static void
> > > x86_register_cpudef_types(X86CPUDefinition *def)
> > > x86_register_cpu_model_type(def->name, m);
> > >
> > > /* Versioned models: */
> > > -
> > > for (vdef = x86_cpu_def_get_versions(def); vdef->version;
> > > vdef++) {
> > > - X86CPUModel *m = g_new0(X86CPUModel, 1);
> > > + X86CPUModel *vm = g_new0(X86CPUModel, 1);
> > > g_autofree char *name =
> > > x86_cpu_versioned_model_name(def, vdef->version);
> > > - m->cpudef = def;
> > > - m->version = vdef->version;
> > > - m->note = vdef->note;
> > > - x86_register_cpu_model_type(name, m);
> > > + vm->cpudef = def;
> > > + vm->version = vdef->version;
> > > + vm->note = vdef->note;
> > > + vm->deprecated = vdef->deprecated;
> > > + /* If Model-v1 is deprecated, Model is deprecated. */
> > > + if (vdef->version == 1 && vdef->deprecated == true) {
> > > + m->deprecated = true;
> > > + m->note = vdef->note;
> >
> > I'm not sure this rule will always apply. If we deprecate
> > "Model-v1" but not "Model-v2", we probably don't want "Model" to
> > be deprecated too.
>
> Agree
> >
> > Considering that we don't have cases where specific versions are
> > being deprecated, what about making it as simple as possible and
> > just add a new X86CPUDefinition::deprecation_note field? No need
> > for any new fields in X86CPUModel (model->cpudef->deprecation_note
> > can be used directly), no need for two new fields in CPUClass
> > (just deprecation_note).
>
> How about eliminating the unversioned CPU model? Then we can still have
> deprecation_note in X86CPUModel, which looks more natural to me than in
> X86CPUDefition.
> For anyway, the unversioned CPU model will eventually be instantiated
> to its some versioned CPU model. It's like a virtual class.
What do you mean by eliminating the unversioned CPU model? Keep
in mind that we need "-cpu Model" to keep working, because of
compatibility and also because "-cpu Model" is more convenient.
There are ways the representation of CPU models + aliases +
versions can be improved, but I assume you wouldn't want a large
refactor of the CPU model/version table to get in the way of a
simple feature.
>
> >
> > If one day we decide to deprecate just some versions of a CPU
> > model, we can extend X86CPUVersionDefinition in the future.
> >
> > > + }
> > > + x86_register_cpu_model_type(name, vm);
> > >
> > > if (vdef->alias) {
> > > X86CPUModel *am = g_new0(X86CPUModel, 1);
> > > am->cpudef = def;
> > > am->version = vdef->version;
> > > am->is_alias = true;
> > > + am->note = vdef->note;
> > > + am->deprecated = vdef->deprecated;
> > > x86_register_cpu_model_type(vdef->alias, am);
> > > }
> > > }
> > > --
> > > 1.8.3.1
> > >
> >
> >
>
--
Eduardo
Re: [PATCH v3 1/2] Introduce (x86) CPU model deprecation API, Eduardo Habkost, 2020/09/17