On Wed, Sep 27, 2023 at 4:42 AM Daniel Henrique Barboza <dbarb...@ventanamicro.com> wrote: > > Callers can add 'props' when querying for a cpu model expansion to see > if a given CPU model supports a certain criteria, and what's the > resulting CPU object. > > If we have 'props' to handle, gather it in a QDict and use the new > riscv_cpuobj_validate_qdict_in() helper to validate it. This helper will > add the custom properties in the CPU object and validate it using > riscv_cpu_finalize_features(). Users will be aware of validation errors > if any occur, if not a CPU object with 'props' will be returned. > > Here's an example with the veyron-v1 vendor CPU. Disabling vendor CPU > extensions is allowed, assuming the final config is valid. Disabling > 'smstateen' is a valid expansion: > > (QEMU) query-cpu-model-expansion type=full > model={"name":"veyron-v1","props":{"smstateen":false}} > {"return": {"model": {"name": "veyron-v1", "props": {"zicond": false, ..., > "smstateen": false, ...} > > But enabling extensions isn't allowed for vendor CPUs. E.g. enabling 'V' > for the veyron-v1 CPU isn't allowed: > > (QEMU) query-cpu-model-expansion type=full > model={"name":"veyron-v1","props":{"v":true}} > {"error": {"class": "GenericError", "desc": "'veyron-v1' CPU does not allow > enabling extensions"}} > > Signed-off-by: Daniel Henrique Barboza <dbarb...@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.fran...@wdc.com> Alistair > --- > target/riscv/riscv-qmp-cmds.c | 65 +++++++++++++++++++++++++++++++++++ > 1 file changed, 65 insertions(+) > > diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c > index 2170562e3a..5b2d186c83 100644 > --- a/target/riscv/riscv-qmp-cmds.c > +++ b/target/riscv/riscv-qmp-cmds.c > @@ -27,6 +27,9 @@ > #include "qapi/error.h" > #include "qapi/qapi-commands-machine-target.h" > #include "qapi/qmp/qdict.h" > +#include "qapi/qmp/qerror.h" > +#include "qapi/qobject-input-visitor.h" > +#include "qapi/visitor.h" > #include "qom/qom-qobject.h" > #include "cpu-qom.h" > #include "cpu.h" > @@ -83,14 +86,58 @@ static void riscv_obj_add_multiext_props(Object *obj, > QDict *qdict_out, > } > } > > +static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, > + const QDict *qdict_in, > + Error **errp) > +{ > + const QDictEntry *qe; > + Visitor *visitor; > + Error *local_err = NULL; > + > + visitor = qobject_input_visitor_new(props); > + if (!visit_start_struct(visitor, NULL, NULL, 0, &local_err)) { > + goto err; > + } > + > + for (qe = qdict_first(qdict_in); qe; qe = qdict_next(qdict_in, qe)) { > + object_property_find_err(obj, qe->key, &local_err); > + if (local_err) { > + goto err; > + } > + > + object_property_set(obj, qe->key, visitor, &local_err); > + if (local_err) { > + goto err; > + } > + } > + > + visit_check_struct(visitor, &local_err); > + if (local_err) { > + goto err; > + } > + > + riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err); > + if (local_err) { > + goto err; > + } > + > + visit_end_struct(visitor, NULL); > + > +err: > + error_propagate(errp, local_err); > + visit_free(visitor); > +} > + > CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType > type, > CpuModelInfo *model, > Error **errp) > { > CpuModelExpansionInfo *expansion_info; > + const QDict *qdict_in = NULL; > QDict *qdict_out; > ObjectClass *oc; > Object *obj; > + Error *local_err = NULL; > > if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { > error_setg(errp, "The requested expansion type is not supported"); > @@ -104,8 +151,26 @@ CpuModelExpansionInfo > *qmp_query_cpu_model_expansion(CpuModelExpansionType type, > return NULL; > } > > + if (model->props) { > + qdict_in = qobject_to(QDict, model->props); > + if (!qdict_in) { > + error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); > + return NULL; > + } > + } > + > obj = object_new(object_class_get_name(oc)); > > + if (qdict_in) { > + riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in, > + &local_err); > + if (local_err) { > + error_propagate(errp, local_err); > + object_unref(obj); > + return NULL; > + } > + } > + > expansion_info = g_new0(CpuModelExpansionInfo, 1); > expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); > expansion_info->model->name = g_strdup(model->name); > -- > 2.41.0 > >