1381b43f8SPhilippe Mathieu-Daudé /*
2381b43f8SPhilippe Mathieu-Daudé * QEMU LoongArch CPU (monitor definitions)
3381b43f8SPhilippe Mathieu-Daudé *
4381b43f8SPhilippe Mathieu-Daudé * SPDX-FileCopyrightText: 2021 Loongson Technology Corporation Limited
5381b43f8SPhilippe Mathieu-Daudé *
6381b43f8SPhilippe Mathieu-Daudé * SPDX-License-Identifier: GPL-2.0-or-later
7381b43f8SPhilippe Mathieu-Daudé */
8381b43f8SPhilippe Mathieu-Daudé
9381b43f8SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
1031f694b9SSong Gao #include "qapi/error.h"
11381b43f8SPhilippe Mathieu-Daudé #include "qapi/qapi-commands-machine-target.h"
12381b43f8SPhilippe Mathieu-Daudé #include "cpu.h"
1331f694b9SSong Gao #include "qapi/qmp/qdict.h"
1431f694b9SSong Gao #include "qapi/qobject-input-visitor.h"
1531f694b9SSong Gao #include "qom/qom-qobject.h"
16381b43f8SPhilippe Mathieu-Daudé
loongarch_cpu_add_definition(gpointer data,gpointer user_data)17381b43f8SPhilippe Mathieu-Daudé static void loongarch_cpu_add_definition(gpointer data, gpointer user_data)
18381b43f8SPhilippe Mathieu-Daudé {
19381b43f8SPhilippe Mathieu-Daudé ObjectClass *oc = data;
20381b43f8SPhilippe Mathieu-Daudé CpuDefinitionInfoList **cpu_list = user_data;
21381b43f8SPhilippe Mathieu-Daudé CpuDefinitionInfo *info = g_new0(CpuDefinitionInfo, 1);
22381b43f8SPhilippe Mathieu-Daudé const char *typename = object_class_get_name(oc);
23381b43f8SPhilippe Mathieu-Daudé
244b26aa9fSGavin Shan info->name = cpu_model_from_type(typename);
25381b43f8SPhilippe Mathieu-Daudé info->q_typename = g_strdup(typename);
26381b43f8SPhilippe Mathieu-Daudé
27381b43f8SPhilippe Mathieu-Daudé QAPI_LIST_PREPEND(*cpu_list, info);
28381b43f8SPhilippe Mathieu-Daudé }
29381b43f8SPhilippe Mathieu-Daudé
qmp_query_cpu_definitions(Error ** errp)30381b43f8SPhilippe Mathieu-Daudé CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
31381b43f8SPhilippe Mathieu-Daudé {
32381b43f8SPhilippe Mathieu-Daudé CpuDefinitionInfoList *cpu_list = NULL;
33381b43f8SPhilippe Mathieu-Daudé GSList *list;
34381b43f8SPhilippe Mathieu-Daudé
35381b43f8SPhilippe Mathieu-Daudé list = object_class_get_list(TYPE_LOONGARCH_CPU, false);
36381b43f8SPhilippe Mathieu-Daudé g_slist_foreach(list, loongarch_cpu_add_definition, &cpu_list);
37381b43f8SPhilippe Mathieu-Daudé g_slist_free(list);
38381b43f8SPhilippe Mathieu-Daudé
39381b43f8SPhilippe Mathieu-Daudé return cpu_list;
40381b43f8SPhilippe Mathieu-Daudé }
4131f694b9SSong Gao
4231f694b9SSong Gao static const char *cpu_model_advertised_features[] = {
43*6edd2a9bSBibo Mao "lsx", "lasx", "lbt", "pmu", NULL
4431f694b9SSong Gao };
4531f694b9SSong Gao
qmp_query_cpu_model_expansion(CpuModelExpansionType type,CpuModelInfo * model,Error ** errp)4631f694b9SSong Gao CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
4731f694b9SSong Gao CpuModelInfo *model,
4831f694b9SSong Gao Error **errp)
4931f694b9SSong Gao {
5028054406SMarkus Armbruster Visitor *visitor;
5128054406SMarkus Armbruster bool ok;
5231f694b9SSong Gao CpuModelExpansionInfo *expansion_info;
5331f694b9SSong Gao QDict *qdict_out;
5431f694b9SSong Gao ObjectClass *oc;
5531f694b9SSong Gao Object *obj;
5631f694b9SSong Gao const char *name;
5731f694b9SSong Gao int i;
5831f694b9SSong Gao
5931f694b9SSong Gao if (type != CPU_MODEL_EXPANSION_TYPE_STATIC) {
6031f694b9SSong Gao error_setg(errp, "The requested expansion type is not supported");
6131f694b9SSong Gao return NULL;
6231f694b9SSong Gao }
6331f694b9SSong Gao
6428054406SMarkus Armbruster if (model->props) {
6528054406SMarkus Armbruster visitor = qobject_input_visitor_new(model->props);
6628054406SMarkus Armbruster if (!visit_start_struct(visitor, "model.props", NULL, 0, errp)) {
6728054406SMarkus Armbruster visit_free(visitor);
6828054406SMarkus Armbruster return NULL;
6928054406SMarkus Armbruster }
7028054406SMarkus Armbruster
7128054406SMarkus Armbruster ok = visit_check_struct(visitor, errp);
7228054406SMarkus Armbruster visit_end_struct(visitor, NULL);
7328054406SMarkus Armbruster visit_free(visitor);
7428054406SMarkus Armbruster if (!ok) {
7528054406SMarkus Armbruster return NULL;
7628054406SMarkus Armbruster }
7728054406SMarkus Armbruster }
7828054406SMarkus Armbruster
7931f694b9SSong Gao oc = cpu_class_by_name(TYPE_LOONGARCH_CPU, model->name);
8031f694b9SSong Gao if (!oc) {
8131f694b9SSong Gao error_setg(errp, "The CPU type '%s' is not a recognized LoongArch CPU type",
8231f694b9SSong Gao model->name);
8331f694b9SSong Gao return NULL;
8431f694b9SSong Gao }
8531f694b9SSong Gao
8631f694b9SSong Gao obj = object_new(object_class_get_name(oc));
8731f694b9SSong Gao
8831f694b9SSong Gao expansion_info = g_new0(CpuModelExpansionInfo, 1);
8931f694b9SSong Gao expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
9031f694b9SSong Gao expansion_info->model->name = g_strdup(model->name);
9131f694b9SSong Gao
9231f694b9SSong Gao qdict_out = qdict_new();
9331f694b9SSong Gao
9431f694b9SSong Gao i = 0;
9531f694b9SSong Gao while ((name = cpu_model_advertised_features[i++]) != NULL) {
9631f694b9SSong Gao ObjectProperty *prop = object_property_find(obj, name);
9731f694b9SSong Gao if (prop) {
9831f694b9SSong Gao QObject *value;
9931f694b9SSong Gao
10031f694b9SSong Gao assert(prop->get);
10131f694b9SSong Gao value = object_property_get_qobject(obj, name, &error_abort);
10231f694b9SSong Gao
10331f694b9SSong Gao qdict_put_obj(qdict_out, name, value);
10431f694b9SSong Gao }
10531f694b9SSong Gao }
10631f694b9SSong Gao
10731f694b9SSong Gao if (!qdict_size(qdict_out)) {
10831f694b9SSong Gao qobject_unref(qdict_out);
10931f694b9SSong Gao } else {
11031f694b9SSong Gao expansion_info->model->props = QOBJECT(qdict_out);
11131f694b9SSong Gao }
11231f694b9SSong Gao
11331f694b9SSong Gao object_unref(obj);
11431f694b9SSong Gao
11531f694b9SSong Gao return expansion_info;
11631f694b9SSong Gao }
117