]> git.ipfire.org Git - thirdparty/qemu.git/blame - target/arm/monitor.c
target/arm/cpu64: max cpu: Introduce sve<N> properties
[thirdparty/qemu.git] / target / arm / monitor.c
CommitLineData
ae50a770
PX
1/*
2 * QEMU monitor.c for ARM.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
112ed241 22
ae50a770 23#include "qemu/osdep.h"
e19afd56 24#include "hw/boards.h"
db31e49a 25#include "kvm_arm.h"
e19afd56
AJ
26#include "qapi/error.h"
27#include "qapi/visitor.h"
28#include "qapi/qobject-input-visitor.h"
29#include "qapi/qapi-commands-machine-target.h"
b0227cdb 30#include "qapi/qapi-commands-misc-target.h"
e19afd56
AJ
31#include "qapi/qmp/qerror.h"
32#include "qapi/qmp/qdict.h"
33#include "qom/qom-qobject.h"
db31e49a
PX
34
35static GICCapability *gic_cap_new(int version)
36{
37 GICCapability *cap = g_new0(GICCapability, 1);
38 cap->version = version;
39 /* by default, support none */
40 cap->emulated = false;
41 cap->kernel = false;
42 return cap;
43}
44
45static GICCapabilityList *gic_cap_list_add(GICCapabilityList *head,
46 GICCapability *cap)
47{
48 GICCapabilityList *item = g_new0(GICCapabilityList, 1);
49 item->value = cap;
50 item->next = head;
51 return item;
52}
53
54static inline void gic_cap_kvm_probe(GICCapability *v2, GICCapability *v3)
55{
56#ifdef CONFIG_KVM
57 int fdarray[3];
58
59 if (!kvm_arm_create_scratch_host_vcpu(NULL, fdarray, NULL)) {
60 return;
61 }
62
63 /* Test KVM GICv2 */
64 if (kvm_device_supported(fdarray[1], KVM_DEV_TYPE_ARM_VGIC_V2)) {
65 v2->kernel = true;
66 }
67
68 /* Test KVM GICv3 */
69 if (kvm_device_supported(fdarray[1], KVM_DEV_TYPE_ARM_VGIC_V3)) {
70 v3->kernel = true;
71 }
72
73 kvm_arm_destroy_scratch_host_vcpu(fdarray);
74#endif
75}
ae50a770
PX
76
77GICCapabilityList *qmp_query_gic_capabilities(Error **errp)
78{
db31e49a
PX
79 GICCapabilityList *head = NULL;
80 GICCapability *v2 = gic_cap_new(2), *v3 = gic_cap_new(3);
81
82 v2->emulated = true;
3b1a2225 83 v3->emulated = true;
db31e49a
PX
84
85 gic_cap_kvm_probe(v2, v3);
86
87 head = gic_cap_list_add(head, v2);
88 head = gic_cap_list_add(head, v3);
89
90 return head;
ae50a770 91}
e19afd56 92
0df9142d
AJ
93QEMU_BUILD_BUG_ON(ARM_MAX_VQ > 16);
94
e19afd56
AJ
95/*
96 * These are cpu model features we want to advertise. The order here
97 * matters as this is the order in which qmp_query_cpu_model_expansion
98 * will attempt to set them. If there are dependencies between features,
99 * then the order that considers those dependencies must be used.
100 */
101static const char *cpu_model_advertised_features[] = {
73234775 102 "aarch64", "pmu", "sve",
0df9142d
AJ
103 "sve128", "sve256", "sve384", "sve512",
104 "sve640", "sve768", "sve896", "sve1024", "sve1152", "sve1280",
105 "sve1408", "sve1536", "sve1664", "sve1792", "sve1920", "sve2048",
e19afd56
AJ
106 NULL
107};
108
109CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
110 CpuModelInfo *model,
111 Error **errp)
112{
113 CpuModelExpansionInfo *expansion_info;
114 const QDict *qdict_in = NULL;
115 QDict *qdict_out;
116 ObjectClass *oc;
117 Object *obj;
118 const char *name;
119 int i;
120
121 if (type != CPU_MODEL_EXPANSION_TYPE_FULL) {
122 error_setg(errp, "The requested expansion type is not supported");
123 return NULL;
124 }
125
126 if (!kvm_enabled() && !strcmp(model->name, "host")) {
127 error_setg(errp, "The CPU type '%s' requires KVM", model->name);
128 return NULL;
129 }
130
131 oc = cpu_class_by_name(TYPE_ARM_CPU, model->name);
132 if (!oc) {
133 error_setg(errp, "The CPU type '%s' is not a recognized ARM CPU type",
134 model->name);
135 return NULL;
136 }
137
138 if (kvm_enabled()) {
139 const char *cpu_type = current_machine->cpu_type;
140 int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
141 bool supported = false;
142
143 if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
144 /* These are kvmarm's recommended cpu types */
145 supported = true;
146 } else if (strlen(model->name) == len &&
147 !strncmp(model->name, cpu_type, len)) {
148 /* KVM is enabled and we're using this type, so it works. */
149 supported = true;
150 }
151 if (!supported) {
152 error_setg(errp, "We cannot guarantee the CPU type '%s' works "
153 "with KVM on this host", model->name);
154 return NULL;
155 }
156 }
157
158 if (model->props) {
159 qdict_in = qobject_to(QDict, model->props);
160 if (!qdict_in) {
161 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
162 return NULL;
163 }
164 }
165
166 obj = object_new(object_class_get_name(oc));
167
168 if (qdict_in) {
169 Visitor *visitor;
170 Error *err = NULL;
171
172 visitor = qobject_input_visitor_new(model->props);
173 visit_start_struct(visitor, NULL, NULL, 0, &err);
174 if (err) {
175 visit_free(visitor);
176 object_unref(obj);
177 error_propagate(errp, err);
178 return NULL;
179 }
180
181 i = 0;
182 while ((name = cpu_model_advertised_features[i++]) != NULL) {
183 if (qdict_get(qdict_in, name)) {
184 object_property_set(obj, visitor, name, &err);
185 if (err) {
186 break;
187 }
188 }
189 }
190
191 if (!err) {
192 visit_check_struct(visitor, &err);
193 }
0df9142d
AJ
194 if (!err) {
195 arm_cpu_finalize_features(ARM_CPU(obj), &err);
196 }
e19afd56
AJ
197 visit_end_struct(visitor, NULL);
198 visit_free(visitor);
199 if (err) {
200 object_unref(obj);
201 error_propagate(errp, err);
202 return NULL;
203 }
0df9142d
AJ
204 } else {
205 Error *err = NULL;
206 arm_cpu_finalize_features(ARM_CPU(obj), &err);
207 assert(err == NULL);
e19afd56
AJ
208 }
209
210 expansion_info = g_new0(CpuModelExpansionInfo, 1);
211 expansion_info->model = g_malloc0(sizeof(*expansion_info->model));
212 expansion_info->model->name = g_strdup(model->name);
213
214 qdict_out = qdict_new();
215
216 i = 0;
217 while ((name = cpu_model_advertised_features[i++]) != NULL) {
218 ObjectProperty *prop = object_property_find(obj, name, NULL);
219 if (prop) {
220 Error *err = NULL;
221 QObject *value;
222
223 assert(prop->get);
224 value = object_property_get_qobject(obj, name, &err);
225 assert(!err);
226
227 qdict_put_obj(qdict_out, name, value);
228 }
229 }
230
231 if (!qdict_size(qdict_out)) {
232 qobject_unref(qdict_out);
233 } else {
234 expansion_info->model->props = QOBJECT(qdict_out);
235 expansion_info->model->has_props = true;
236 }
237
238 object_unref(obj);
239
240 return expansion_info;
241}