aboutsummaryrefslogtreecommitdiff
path: root/target/riscv
diff options
context:
space:
mode:
authorDaniel Henrique Barboza <dbarboza@ventanamicro.com>2023-10-18 16:56:36 -0300
committerAlistair Francis <alistair.francis@wdc.com>2023-11-07 11:06:02 +1000
commit1df4f540d6352131cefa7ca48b637ccb774ce9e0 (patch)
tree2dfba94a978a4b8951deed6899dfb5fde5a5894d /target/riscv
parenta13a6082c7488d4393453d383676ae423b38b4d8 (diff)
downloadqemu-1df4f540d6352131cefa7ca48b637ccb774ce9e0.zip
qemu-1df4f540d6352131cefa7ca48b637ccb774ce9e0.tar.gz
qemu-1df4f540d6352131cefa7ca48b637ccb774ce9e0.tar.bz2
target/riscv: handle custom props in qmp_query_cpu_model_expansion
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 <dbarboza@ventanamicro.com> Reviewed-by: Alistair Francis <alistair.francis@wdc.com> Message-ID: <20231018195638.211151-5-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
Diffstat (limited to 'target/riscv')
-rw-r--r--target/riscv/riscv-qmp-cmds.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c
index 2170562..5b2d186 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);