xref: /qemu/target/riscv/riscv-qmp-cmds.c (revision 4b26aa9f3a9a1f1e84f95e7462d1b3d893315b91)
1c0177f91SDaniel Henrique Barboza /*
2c0177f91SDaniel Henrique Barboza  * QEMU CPU QMP commands for RISC-V
3c0177f91SDaniel Henrique Barboza  *
4c0177f91SDaniel Henrique Barboza  * Copyright (c) 2023 Ventana Micro Systems Inc.
5c0177f91SDaniel Henrique Barboza  *
6c0177f91SDaniel Henrique Barboza  * Permission is hereby granted, free of charge, to any person obtaining a copy
7c0177f91SDaniel Henrique Barboza  * of this software and associated documentation files (the "Software"), to deal
8c0177f91SDaniel Henrique Barboza  * in the Software without restriction, including without limitation the rights
9c0177f91SDaniel Henrique Barboza  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10c0177f91SDaniel Henrique Barboza  * copies of the Software, and to permit persons to whom the Software is
11c0177f91SDaniel Henrique Barboza  * furnished to do so, subject to the following conditions:
12c0177f91SDaniel Henrique Barboza  *
13c0177f91SDaniel Henrique Barboza  * The above copyright notice and this permission notice shall be included in
14c0177f91SDaniel Henrique Barboza  * all copies or substantial portions of the Software.
15c0177f91SDaniel Henrique Barboza  *
16c0177f91SDaniel Henrique Barboza  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17c0177f91SDaniel Henrique Barboza  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18c0177f91SDaniel Henrique Barboza  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19c0177f91SDaniel Henrique Barboza  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20c0177f91SDaniel Henrique Barboza  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21c0177f91SDaniel Henrique Barboza  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22c0177f91SDaniel Henrique Barboza  * THE SOFTWARE.
23c0177f91SDaniel Henrique Barboza  */
24c0177f91SDaniel Henrique Barboza 
25c0177f91SDaniel Henrique Barboza #include "qemu/osdep.h"
26c0177f91SDaniel Henrique Barboza 
27aeb2bc59SDaniel Henrique Barboza #include "qapi/error.h"
28c0177f91SDaniel Henrique Barboza #include "qapi/qapi-commands-machine-target.h"
29aeb2bc59SDaniel Henrique Barboza #include "qapi/qmp/qdict.h"
301df4f540SDaniel Henrique Barboza #include "qapi/qmp/qerror.h"
311df4f540SDaniel Henrique Barboza #include "qapi/qobject-input-visitor.h"
321df4f540SDaniel Henrique Barboza #include "qapi/visitor.h"
33aeb2bc59SDaniel Henrique Barboza #include "qom/qom-qobject.h"
34a3abecbeSDaniel Henrique Barboza #include "sysemu/kvm.h"
35a3abecbeSDaniel Henrique Barboza #include "sysemu/tcg.h"
36c0177f91SDaniel Henrique Barboza #include "cpu-qom.h"
37aeb2bc59SDaniel Henrique Barboza #include "cpu.h"
38c0177f91SDaniel Henrique Barboza 
39c0177f91SDaniel Henrique Barboza static void riscv_cpu_add_definition(gpointer data, gpointer user_data)
40c0177f91SDaniel Henrique Barboza {
41c0177f91SDaniel Henrique Barboza     ObjectClass *oc = data;
42c0177f91SDaniel Henrique Barboza     CpuDefinitionInfoList **cpu_list = user_data;
43c0177f91SDaniel Henrique Barboza     CpuDefinitionInfo *info = g_malloc0(sizeof(*info));
44c0177f91SDaniel Henrique Barboza     const char *typename = object_class_get_name(oc);
459e1a30d3SDaniel Henrique Barboza     ObjectClass *dyn_class;
46c0177f91SDaniel Henrique Barboza 
47*4b26aa9fSGavin Shan     info->name = cpu_model_from_type(typename);
48c0177f91SDaniel Henrique Barboza     info->q_typename = g_strdup(typename);
49c0177f91SDaniel Henrique Barboza 
509e1a30d3SDaniel Henrique Barboza     dyn_class = object_class_dynamic_cast(oc, TYPE_RISCV_DYNAMIC_CPU);
519e1a30d3SDaniel Henrique Barboza     info->q_static = dyn_class == NULL;
529e1a30d3SDaniel Henrique Barboza 
53c0177f91SDaniel Henrique Barboza     QAPI_LIST_PREPEND(*cpu_list, info);
54c0177f91SDaniel Henrique Barboza }
55c0177f91SDaniel Henrique Barboza 
56c0177f91SDaniel Henrique Barboza CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
57c0177f91SDaniel Henrique Barboza {
58c0177f91SDaniel Henrique Barboza     CpuDefinitionInfoList *cpu_list = NULL;
59c0177f91SDaniel Henrique Barboza     GSList *list = object_class_get_list(TYPE_RISCV_CPU, false);
60c0177f91SDaniel Henrique Barboza 
61c0177f91SDaniel Henrique Barboza     g_slist_foreach(list, riscv_cpu_add_definition, &cpu_list);
62c0177f91SDaniel Henrique Barboza     g_slist_free(list);
63c0177f91SDaniel Henrique Barboza 
64c0177f91SDaniel Henrique Barboza     return cpu_list;
65c0177f91SDaniel Henrique Barboza }
66aeb2bc59SDaniel Henrique Barboza 
67a3abecbeSDaniel Henrique Barboza static void riscv_check_if_cpu_available(RISCVCPU *cpu, Error **errp)
68a3abecbeSDaniel Henrique Barboza {
69a3abecbeSDaniel Henrique Barboza     if (!riscv_cpu_accelerator_compatible(cpu)) {
70a3abecbeSDaniel Henrique Barboza         g_autofree char *name = riscv_cpu_get_name(cpu);
71a3abecbeSDaniel Henrique Barboza         const char *accel = kvm_enabled() ? "kvm" : "tcg";
72a3abecbeSDaniel Henrique Barboza 
73a3abecbeSDaniel Henrique Barboza         error_setg(errp, "'%s' CPU not available with %s", name, accel);
74a3abecbeSDaniel Henrique Barboza         return;
75a3abecbeSDaniel Henrique Barboza     }
76a3abecbeSDaniel Henrique Barboza }
77a3abecbeSDaniel Henrique Barboza 
78aeb2bc59SDaniel Henrique Barboza static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out,
79aeb2bc59SDaniel Henrique Barboza                                      const char *name)
80aeb2bc59SDaniel Henrique Barboza {
81aeb2bc59SDaniel Henrique Barboza     ObjectProperty *prop = object_property_find(obj, name);
82aeb2bc59SDaniel Henrique Barboza 
83aeb2bc59SDaniel Henrique Barboza     if (prop) {
84aeb2bc59SDaniel Henrique Barboza         QObject *value;
85aeb2bc59SDaniel Henrique Barboza 
86aeb2bc59SDaniel Henrique Barboza         assert(prop->get);
87aeb2bc59SDaniel Henrique Barboza         value = object_property_get_qobject(obj, name, &error_abort);
88aeb2bc59SDaniel Henrique Barboza 
89aeb2bc59SDaniel Henrique Barboza         qdict_put_obj(qdict_out, name, value);
90aeb2bc59SDaniel Henrique Barboza     }
91aeb2bc59SDaniel Henrique Barboza }
92aeb2bc59SDaniel Henrique Barboza 
93aeb2bc59SDaniel Henrique Barboza static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out,
94aeb2bc59SDaniel Henrique Barboza                                          const RISCVCPUMultiExtConfig *arr)
95aeb2bc59SDaniel Henrique Barboza {
96aeb2bc59SDaniel Henrique Barboza     for (int i = 0; arr[i].name != NULL; i++) {
97aeb2bc59SDaniel Henrique Barboza         riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name);
98aeb2bc59SDaniel Henrique Barboza     }
99aeb2bc59SDaniel Henrique Barboza }
100aeb2bc59SDaniel Henrique Barboza 
1011df4f540SDaniel Henrique Barboza static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props,
1021df4f540SDaniel Henrique Barboza                                            const QDict *qdict_in,
1031df4f540SDaniel Henrique Barboza                                            Error **errp)
1041df4f540SDaniel Henrique Barboza {
1051df4f540SDaniel Henrique Barboza     const QDictEntry *qe;
1061df4f540SDaniel Henrique Barboza     Visitor *visitor;
1071df4f540SDaniel Henrique Barboza     Error *local_err = NULL;
1081df4f540SDaniel Henrique Barboza 
1091df4f540SDaniel Henrique Barboza     visitor = qobject_input_visitor_new(props);
1101df4f540SDaniel Henrique Barboza     if (!visit_start_struct(visitor, NULL, NULL, 0, &local_err)) {
1111df4f540SDaniel Henrique Barboza         goto err;
1121df4f540SDaniel Henrique Barboza     }
1131df4f540SDaniel Henrique Barboza 
1141df4f540SDaniel Henrique Barboza     for (qe = qdict_first(qdict_in); qe; qe = qdict_next(qdict_in, qe)) {
1151df4f540SDaniel Henrique Barboza         object_property_find_err(obj, qe->key, &local_err);
1161df4f540SDaniel Henrique Barboza         if (local_err) {
1171df4f540SDaniel Henrique Barboza             goto err;
1181df4f540SDaniel Henrique Barboza         }
1191df4f540SDaniel Henrique Barboza 
1201df4f540SDaniel Henrique Barboza         object_property_set(obj, qe->key, visitor, &local_err);
1211df4f540SDaniel Henrique Barboza         if (local_err) {
1221df4f540SDaniel Henrique Barboza             goto err;
1231df4f540SDaniel Henrique Barboza         }
1241df4f540SDaniel Henrique Barboza     }
1251df4f540SDaniel Henrique Barboza 
1261df4f540SDaniel Henrique Barboza     visit_check_struct(visitor, &local_err);
1271df4f540SDaniel Henrique Barboza     if (local_err) {
1281df4f540SDaniel Henrique Barboza         goto err;
1291df4f540SDaniel Henrique Barboza     }
1301df4f540SDaniel Henrique Barboza 
1311df4f540SDaniel Henrique Barboza     riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err);
1321df4f540SDaniel Henrique Barboza     if (local_err) {
1331df4f540SDaniel Henrique Barboza         goto err;
1341df4f540SDaniel Henrique Barboza     }
1351df4f540SDaniel Henrique Barboza 
1361df4f540SDaniel Henrique Barboza     visit_end_struct(visitor, NULL);
1371df4f540SDaniel Henrique Barboza 
1381df4f540SDaniel Henrique Barboza err:
1391df4f540SDaniel Henrique Barboza     error_propagate(errp, local_err);
1401df4f540SDaniel Henrique Barboza     visit_free(visitor);
1411df4f540SDaniel Henrique Barboza }
1421df4f540SDaniel Henrique Barboza 
143aeb2bc59SDaniel Henrique Barboza CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
144aeb2bc59SDaniel Henrique Barboza                                                      CpuModelInfo *model,
145aeb2bc59SDaniel Henrique Barboza                                                      Error **errp)
146aeb2bc59SDaniel Henrique Barboza {
147aeb2bc59SDaniel Henrique Barboza     CpuModelExpansionInfo *expansion_info;
1481df4f540SDaniel Henrique Barboza     const QDict *qdict_in = NULL;
149aeb2bc59SDaniel Henrique Barboza     QDict *qdict_out;
150aeb2bc59SDaniel Henrique Barboza     ObjectClass *oc;
151aeb2bc59SDaniel Henrique Barboza     Object *obj;
1521df4f540SDaniel Henrique Barboza     Error *local_err = NULL;
153aeb2bc59SDaniel Henrique Barboza 
154aeb2bc59SDaniel Henrique Barboza     if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
155aeb2bc59SDaniel Henrique Barboza         error_setg(errp, "The requested expansion type is not supported");
156aeb2bc59SDaniel Henrique Barboza         return NULL;
157aeb2bc59SDaniel Henrique Barboza     }
158aeb2bc59SDaniel Henrique Barboza 
159aeb2bc59SDaniel Henrique Barboza     oc = cpu_class_by_name(TYPE_RISCV_CPU, model->name);
160aeb2bc59SDaniel Henrique Barboza     if (!oc) {
161aeb2bc59SDaniel Henrique Barboza         error_setg(errp, "The CPU type '%s' is not a known RISC-V CPU type",
162aeb2bc59SDaniel Henrique Barboza                    model->name);
163aeb2bc59SDaniel Henrique Barboza         return NULL;
164aeb2bc59SDaniel Henrique Barboza     }
165aeb2bc59SDaniel Henrique Barboza 
1661df4f540SDaniel Henrique Barboza     if (model->props) {
1671df4f540SDaniel Henrique Barboza         qdict_in = qobject_to(QDict, model->props);
1681df4f540SDaniel Henrique Barboza         if (!qdict_in) {
1691df4f540SDaniel Henrique Barboza             error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
1701df4f540SDaniel Henrique Barboza             return NULL;
1711df4f540SDaniel Henrique Barboza         }
1721df4f540SDaniel Henrique Barboza     }
1731df4f540SDaniel Henrique Barboza 
174aeb2bc59SDaniel Henrique Barboza     obj = object_new(object_class_get_name(oc));
175aeb2bc59SDaniel Henrique Barboza 
176a3abecbeSDaniel Henrique Barboza     riscv_check_if_cpu_available(RISCV_CPU(obj), &local_err);
177a3abecbeSDaniel Henrique Barboza     if (local_err != NULL) {
178a3abecbeSDaniel Henrique Barboza         error_propagate(errp, local_err);
179a3abecbeSDaniel Henrique Barboza         object_unref(obj);
180a3abecbeSDaniel Henrique Barboza         return NULL;
181a3abecbeSDaniel Henrique Barboza     }
182a3abecbeSDaniel Henrique Barboza 
1831df4f540SDaniel Henrique Barboza     if (qdict_in) {
1841df4f540SDaniel Henrique Barboza         riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in,
1851df4f540SDaniel Henrique Barboza                                        &local_err);
1861df4f540SDaniel Henrique Barboza         if (local_err) {
1871df4f540SDaniel Henrique Barboza             error_propagate(errp, local_err);
1881df4f540SDaniel Henrique Barboza             object_unref(obj);
1891df4f540SDaniel Henrique Barboza             return NULL;
1901df4f540SDaniel Henrique Barboza         }
1911df4f540SDaniel Henrique Barboza     }
1921df4f540SDaniel Henrique Barboza 
193aeb2bc59SDaniel Henrique Barboza     expansion_info = g_new0(CpuModelExpansionInfo, 1);
194aeb2bc59SDaniel Henrique Barboza     expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
195aeb2bc59SDaniel Henrique Barboza     expansion_info->model->name = g_strdup(model->name);
196aeb2bc59SDaniel Henrique Barboza 
197aeb2bc59SDaniel Henrique Barboza     qdict_out = qdict_new();
198aeb2bc59SDaniel Henrique Barboza 
199aeb2bc59SDaniel Henrique Barboza     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions);
200aeb2bc59SDaniel Henrique Barboza     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts);
201aeb2bc59SDaniel Henrique Barboza     riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts);
202aeb2bc59SDaniel Henrique Barboza 
203aeb2bc59SDaniel Henrique Barboza     /* Add our CPU boolean options too */
204aeb2bc59SDaniel Henrique Barboza     riscv_obj_add_qdict_prop(obj, qdict_out, "mmu");
205aeb2bc59SDaniel Henrique Barboza     riscv_obj_add_qdict_prop(obj, qdict_out, "pmp");
206aeb2bc59SDaniel Henrique Barboza 
207aeb2bc59SDaniel Henrique Barboza     if (!qdict_size(qdict_out)) {
208aeb2bc59SDaniel Henrique Barboza         qobject_unref(qdict_out);
209aeb2bc59SDaniel Henrique Barboza     } else {
210aeb2bc59SDaniel Henrique Barboza         expansion_info->model->props = QOBJECT(qdict_out);
211aeb2bc59SDaniel Henrique Barboza     }
212aeb2bc59SDaniel Henrique Barboza 
213aeb2bc59SDaniel Henrique Barboza     object_unref(obj);
214aeb2bc59SDaniel Henrique Barboza 
215aeb2bc59SDaniel Henrique Barboza     return expansion_info;
216aeb2bc59SDaniel Henrique Barboza }
217