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" 30*1df4f540SDaniel Henrique Barboza #include "qapi/qmp/qerror.h" 31*1df4f540SDaniel Henrique Barboza #include "qapi/qobject-input-visitor.h" 32*1df4f540SDaniel Henrique Barboza #include "qapi/visitor.h" 33aeb2bc59SDaniel Henrique Barboza #include "qom/qom-qobject.h" 34c0177f91SDaniel Henrique Barboza #include "cpu-qom.h" 35aeb2bc59SDaniel Henrique Barboza #include "cpu.h" 36c0177f91SDaniel Henrique Barboza 37c0177f91SDaniel Henrique Barboza static void riscv_cpu_add_definition(gpointer data, gpointer user_data) 38c0177f91SDaniel Henrique Barboza { 39c0177f91SDaniel Henrique Barboza ObjectClass *oc = data; 40c0177f91SDaniel Henrique Barboza CpuDefinitionInfoList **cpu_list = user_data; 41c0177f91SDaniel Henrique Barboza CpuDefinitionInfo *info = g_malloc0(sizeof(*info)); 42c0177f91SDaniel Henrique Barboza const char *typename = object_class_get_name(oc); 439e1a30d3SDaniel Henrique Barboza ObjectClass *dyn_class; 44c0177f91SDaniel Henrique Barboza 45c0177f91SDaniel Henrique Barboza info->name = g_strndup(typename, 46c0177f91SDaniel Henrique Barboza strlen(typename) - strlen("-" TYPE_RISCV_CPU)); 47c0177f91SDaniel Henrique Barboza info->q_typename = g_strdup(typename); 48c0177f91SDaniel Henrique Barboza 499e1a30d3SDaniel Henrique Barboza dyn_class = object_class_dynamic_cast(oc, TYPE_RISCV_DYNAMIC_CPU); 509e1a30d3SDaniel Henrique Barboza info->q_static = dyn_class == NULL; 519e1a30d3SDaniel Henrique Barboza 52c0177f91SDaniel Henrique Barboza QAPI_LIST_PREPEND(*cpu_list, info); 53c0177f91SDaniel Henrique Barboza } 54c0177f91SDaniel Henrique Barboza 55c0177f91SDaniel Henrique Barboza CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp) 56c0177f91SDaniel Henrique Barboza { 57c0177f91SDaniel Henrique Barboza CpuDefinitionInfoList *cpu_list = NULL; 58c0177f91SDaniel Henrique Barboza GSList *list = object_class_get_list(TYPE_RISCV_CPU, false); 59c0177f91SDaniel Henrique Barboza 60c0177f91SDaniel Henrique Barboza g_slist_foreach(list, riscv_cpu_add_definition, &cpu_list); 61c0177f91SDaniel Henrique Barboza g_slist_free(list); 62c0177f91SDaniel Henrique Barboza 63c0177f91SDaniel Henrique Barboza return cpu_list; 64c0177f91SDaniel Henrique Barboza } 65aeb2bc59SDaniel Henrique Barboza 66aeb2bc59SDaniel Henrique Barboza static void riscv_obj_add_qdict_prop(Object *obj, QDict *qdict_out, 67aeb2bc59SDaniel Henrique Barboza const char *name) 68aeb2bc59SDaniel Henrique Barboza { 69aeb2bc59SDaniel Henrique Barboza ObjectProperty *prop = object_property_find(obj, name); 70aeb2bc59SDaniel Henrique Barboza 71aeb2bc59SDaniel Henrique Barboza if (prop) { 72aeb2bc59SDaniel Henrique Barboza QObject *value; 73aeb2bc59SDaniel Henrique Barboza 74aeb2bc59SDaniel Henrique Barboza assert(prop->get); 75aeb2bc59SDaniel Henrique Barboza value = object_property_get_qobject(obj, name, &error_abort); 76aeb2bc59SDaniel Henrique Barboza 77aeb2bc59SDaniel Henrique Barboza qdict_put_obj(qdict_out, name, value); 78aeb2bc59SDaniel Henrique Barboza } 79aeb2bc59SDaniel Henrique Barboza } 80aeb2bc59SDaniel Henrique Barboza 81aeb2bc59SDaniel Henrique Barboza static void riscv_obj_add_multiext_props(Object *obj, QDict *qdict_out, 82aeb2bc59SDaniel Henrique Barboza const RISCVCPUMultiExtConfig *arr) 83aeb2bc59SDaniel Henrique Barboza { 84aeb2bc59SDaniel Henrique Barboza for (int i = 0; arr[i].name != NULL; i++) { 85aeb2bc59SDaniel Henrique Barboza riscv_obj_add_qdict_prop(obj, qdict_out, arr[i].name); 86aeb2bc59SDaniel Henrique Barboza } 87aeb2bc59SDaniel Henrique Barboza } 88aeb2bc59SDaniel Henrique Barboza 89*1df4f540SDaniel Henrique Barboza static void riscv_cpuobj_validate_qdict_in(Object *obj, QObject *props, 90*1df4f540SDaniel Henrique Barboza const QDict *qdict_in, 91*1df4f540SDaniel Henrique Barboza Error **errp) 92*1df4f540SDaniel Henrique Barboza { 93*1df4f540SDaniel Henrique Barboza const QDictEntry *qe; 94*1df4f540SDaniel Henrique Barboza Visitor *visitor; 95*1df4f540SDaniel Henrique Barboza Error *local_err = NULL; 96*1df4f540SDaniel Henrique Barboza 97*1df4f540SDaniel Henrique Barboza visitor = qobject_input_visitor_new(props); 98*1df4f540SDaniel Henrique Barboza if (!visit_start_struct(visitor, NULL, NULL, 0, &local_err)) { 99*1df4f540SDaniel Henrique Barboza goto err; 100*1df4f540SDaniel Henrique Barboza } 101*1df4f540SDaniel Henrique Barboza 102*1df4f540SDaniel Henrique Barboza for (qe = qdict_first(qdict_in); qe; qe = qdict_next(qdict_in, qe)) { 103*1df4f540SDaniel Henrique Barboza object_property_find_err(obj, qe->key, &local_err); 104*1df4f540SDaniel Henrique Barboza if (local_err) { 105*1df4f540SDaniel Henrique Barboza goto err; 106*1df4f540SDaniel Henrique Barboza } 107*1df4f540SDaniel Henrique Barboza 108*1df4f540SDaniel Henrique Barboza object_property_set(obj, qe->key, visitor, &local_err); 109*1df4f540SDaniel Henrique Barboza if (local_err) { 110*1df4f540SDaniel Henrique Barboza goto err; 111*1df4f540SDaniel Henrique Barboza } 112*1df4f540SDaniel Henrique Barboza } 113*1df4f540SDaniel Henrique Barboza 114*1df4f540SDaniel Henrique Barboza visit_check_struct(visitor, &local_err); 115*1df4f540SDaniel Henrique Barboza if (local_err) { 116*1df4f540SDaniel Henrique Barboza goto err; 117*1df4f540SDaniel Henrique Barboza } 118*1df4f540SDaniel Henrique Barboza 119*1df4f540SDaniel Henrique Barboza riscv_cpu_finalize_features(RISCV_CPU(obj), &local_err); 120*1df4f540SDaniel Henrique Barboza if (local_err) { 121*1df4f540SDaniel Henrique Barboza goto err; 122*1df4f540SDaniel Henrique Barboza } 123*1df4f540SDaniel Henrique Barboza 124*1df4f540SDaniel Henrique Barboza visit_end_struct(visitor, NULL); 125*1df4f540SDaniel Henrique Barboza 126*1df4f540SDaniel Henrique Barboza err: 127*1df4f540SDaniel Henrique Barboza error_propagate(errp, local_err); 128*1df4f540SDaniel Henrique Barboza visit_free(visitor); 129*1df4f540SDaniel Henrique Barboza } 130*1df4f540SDaniel Henrique Barboza 131aeb2bc59SDaniel Henrique Barboza CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type, 132aeb2bc59SDaniel Henrique Barboza CpuModelInfo *model, 133aeb2bc59SDaniel Henrique Barboza Error **errp) 134aeb2bc59SDaniel Henrique Barboza { 135aeb2bc59SDaniel Henrique Barboza CpuModelExpansionInfo *expansion_info; 136*1df4f540SDaniel Henrique Barboza const QDict *qdict_in = NULL; 137aeb2bc59SDaniel Henrique Barboza QDict *qdict_out; 138aeb2bc59SDaniel Henrique Barboza ObjectClass *oc; 139aeb2bc59SDaniel Henrique Barboza Object *obj; 140*1df4f540SDaniel Henrique Barboza Error *local_err = NULL; 141aeb2bc59SDaniel Henrique Barboza 142aeb2bc59SDaniel Henrique Barboza if (type != CPU_MODEL_EXPANSION_TYPE_FULL) { 143aeb2bc59SDaniel Henrique Barboza error_setg(errp, "The requested expansion type is not supported"); 144aeb2bc59SDaniel Henrique Barboza return NULL; 145aeb2bc59SDaniel Henrique Barboza } 146aeb2bc59SDaniel Henrique Barboza 147aeb2bc59SDaniel Henrique Barboza oc = cpu_class_by_name(TYPE_RISCV_CPU, model->name); 148aeb2bc59SDaniel Henrique Barboza if (!oc) { 149aeb2bc59SDaniel Henrique Barboza error_setg(errp, "The CPU type '%s' is not a known RISC-V CPU type", 150aeb2bc59SDaniel Henrique Barboza model->name); 151aeb2bc59SDaniel Henrique Barboza return NULL; 152aeb2bc59SDaniel Henrique Barboza } 153aeb2bc59SDaniel Henrique Barboza 154*1df4f540SDaniel Henrique Barboza if (model->props) { 155*1df4f540SDaniel Henrique Barboza qdict_in = qobject_to(QDict, model->props); 156*1df4f540SDaniel Henrique Barboza if (!qdict_in) { 157*1df4f540SDaniel Henrique Barboza error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); 158*1df4f540SDaniel Henrique Barboza return NULL; 159*1df4f540SDaniel Henrique Barboza } 160*1df4f540SDaniel Henrique Barboza } 161*1df4f540SDaniel Henrique Barboza 162aeb2bc59SDaniel Henrique Barboza obj = object_new(object_class_get_name(oc)); 163aeb2bc59SDaniel Henrique Barboza 164*1df4f540SDaniel Henrique Barboza if (qdict_in) { 165*1df4f540SDaniel Henrique Barboza riscv_cpuobj_validate_qdict_in(obj, model->props, qdict_in, 166*1df4f540SDaniel Henrique Barboza &local_err); 167*1df4f540SDaniel Henrique Barboza if (local_err) { 168*1df4f540SDaniel Henrique Barboza error_propagate(errp, local_err); 169*1df4f540SDaniel Henrique Barboza object_unref(obj); 170*1df4f540SDaniel Henrique Barboza return NULL; 171*1df4f540SDaniel Henrique Barboza } 172*1df4f540SDaniel Henrique Barboza } 173*1df4f540SDaniel Henrique Barboza 174aeb2bc59SDaniel Henrique Barboza expansion_info = g_new0(CpuModelExpansionInfo, 1); 175aeb2bc59SDaniel Henrique Barboza expansion_info->model = g_malloc0(sizeof(*expansion_info->model)); 176aeb2bc59SDaniel Henrique Barboza expansion_info->model->name = g_strdup(model->name); 177aeb2bc59SDaniel Henrique Barboza 178aeb2bc59SDaniel Henrique Barboza qdict_out = qdict_new(); 179aeb2bc59SDaniel Henrique Barboza 180aeb2bc59SDaniel Henrique Barboza riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_extensions); 181aeb2bc59SDaniel Henrique Barboza riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_experimental_exts); 182aeb2bc59SDaniel Henrique Barboza riscv_obj_add_multiext_props(obj, qdict_out, riscv_cpu_vendor_exts); 183aeb2bc59SDaniel Henrique Barboza 184aeb2bc59SDaniel Henrique Barboza /* Add our CPU boolean options too */ 185aeb2bc59SDaniel Henrique Barboza riscv_obj_add_qdict_prop(obj, qdict_out, "mmu"); 186aeb2bc59SDaniel Henrique Barboza riscv_obj_add_qdict_prop(obj, qdict_out, "pmp"); 187aeb2bc59SDaniel Henrique Barboza 188aeb2bc59SDaniel Henrique Barboza if (!qdict_size(qdict_out)) { 189aeb2bc59SDaniel Henrique Barboza qobject_unref(qdict_out); 190aeb2bc59SDaniel Henrique Barboza } else { 191aeb2bc59SDaniel Henrique Barboza expansion_info->model->props = QOBJECT(qdict_out); 192aeb2bc59SDaniel Henrique Barboza } 193aeb2bc59SDaniel Henrique Barboza 194aeb2bc59SDaniel Henrique Barboza object_unref(obj); 195aeb2bc59SDaniel Henrique Barboza 196aeb2bc59SDaniel Henrique Barboza return expansion_info; 197aeb2bc59SDaniel Henrique Barboza } 198