master
c 456 lines 13.2 KB
Raw
1 /*
2 * QMP commands related to machines and CPUs
3 *
4 * Copyright (C) 2014 Red Hat Inc
5 *
6 * This work is licensed under the terms of the GNU GPL, version 2 or later.
7 * See the COPYING file in the top-level directory.
8 */
9
10 #include "qemu/osdep.h"
11 #include "hw/acpi/vmgenid.h"
12 #include "hw/core/boards.h"
13 #include "hw/core/nmi.h"
14 #include "hw/intc/intc.h"
15 #include "hw/mem/memory-device.h"
16 #include "qapi/error.h"
17 #include "qapi/qapi-builtin-visit.h"
18 #include "qapi/qapi-commands-accelerator.h"
19 #include "qapi/qapi-commands-machine.h"
20 #include "qobject/qobject.h"
21 #include "qapi/qobject-input-visitor.h"
22 #include "qapi/type-helpers.h"
23 #include "qemu/uuid.h"
24 #include "qemu/target-info.h"
25 #include "qemu/target-info-qapi.h"
26 #include "qom/qom-qobject.h"
27 #include "system/hostmem.h"
28 #include "system/hw_accel.h"
29 #include "system/numa.h"
30 #include "system/ramlist.h"
31 #include "system/runstate.h"
32 #include "system/system.h"
33 #include "hw/s390x/storage-keys.h"
34
35 /*
36 * QMP query for enabled and present accelerators
37 */
38 AcceleratorInfo *qmp_query_accelerators(Error **errp)
39 {
40 AcceleratorInfo *info = g_malloc0(sizeof(*info));
41 AccelClass *current_class = ACCEL_GET_CLASS(current_accel());
42 int i;
43
44 for (i = ACCELERATOR__MAX; i-- > 0; ) {
45 const char *s = Accelerator_str(i);
46 AccelClass *this_class = accel_find(s);
47
48 if (this_class) {
49 QAPI_LIST_PREPEND(info->present, i);
50 if (this_class == current_class) {
51 info->enabled = i;
52 }
53 }
54 }
55 return info;
56 }
57
58 /*
59 * fast means: we NEVER interrupt vCPU threads to retrieve
60 * information from KVM.
61 */
62 CpuInfoFastList *qmp_query_cpus_fast(Error **errp)
63 {
64 MachineState *ms = MACHINE(qdev_get_machine());
65 MachineClass *mc = MACHINE_GET_CLASS(ms);
66 CpuInfoFastList *head = NULL, **tail = &head;
67 SysEmuTarget target = target_arch();
68 CPUState *cpu;
69
70 CPU_FOREACH(cpu) {
71 CpuInfoFast *value = g_malloc0(sizeof(*value));
72
73 value->cpu_index = cpu->cpu_index;
74 value->qom_path = object_get_canonical_path(OBJECT(cpu));
75 value->thread_id = cpu->thread_id;
76 value->qom_type = g_strdup(object_get_typename(OBJECT(cpu)));
77
78 if (mc->cpu_index_to_instance_props) {
79 CpuInstanceProperties *props;
80 props = g_malloc0(sizeof(*props));
81 *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index);
82 value->props = props;
83 }
84
85 value->target = target;
86 if (cpu->cc->query_cpu_fast) {
87 cpu->cc->query_cpu_fast(cpu, value);
88 }
89
90 QAPI_LIST_APPEND(tail, value);
91 }
92
93 return head;
94 }
95
96 MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
97 Error **errp)
98 {
99 GSList *el, *machines;
100 MachineInfoList *mach_list = NULL;
101
102 machines = object_class_get_list(target_machine_typename(), false);
103 for (el = machines; el; el = el->next) {
104 MachineClass *mc = el->data;
105 const char *default_cpu_type = machine_class_default_cpu_type(mc);
106 MachineInfo *info;
107
108 info = g_malloc0(sizeof(*info));
109 if (mc->is_default) {
110 info->has_is_default = true;
111 info->is_default = true;
112 }
113
114 if (mc->alias) {
115 info->alias = g_strdup(mc->alias);
116 }
117
118 info->name = g_strdup(mc->name);
119 info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus;
120 info->hotpluggable_cpus = mc->has_hotpluggable_cpus;
121 info->numa_mem_supported = mc->numa_mem_supported;
122 info->deprecated = !!mc->deprecation_reason;
123 info->acpi = !!object_class_property_find(OBJECT_CLASS(mc), "acpi");
124 if (default_cpu_type) {
125 info->default_cpu_type = g_strdup(default_cpu_type);
126 }
127 if (mc->default_ram_id) {
128 info->default_ram_id = g_strdup(mc->default_ram_id);
129 }
130
131 if (compat_props && mc->compat_props) {
132 int i;
133 info->compat_props = NULL;
134 CompatPropertyList **tail = &(info->compat_props);
135 info->has_compat_props = true;
136
137 for (i = 0; i < mc->compat_props->len; i++) {
138 GlobalProperty *mt_prop = g_ptr_array_index(mc->compat_props,
139 i);
140 CompatProperty *prop;
141
142 prop = g_malloc0(sizeof(*prop));
143 prop->qom_type = g_strdup(mt_prop->driver);
144 prop->property = g_strdup(mt_prop->property);
145 prop->value = g_strdup(mt_prop->value);
146
147 QAPI_LIST_APPEND(tail, prop);
148 }
149 }
150
151 QAPI_LIST_PREPEND(mach_list, info);
152 }
153
154 g_slist_free(machines);
155 return mach_list;
156 }
157
158 CurrentMachineParams *qmp_query_current_machine(Error **errp)
159 {
160 CurrentMachineParams *params = g_malloc0(sizeof(*params));
161 params->wakeup_suspend_support = qemu_wakeup_suspend_enabled();
162
163 return params;
164 }
165
166 QemuTargetInfo *qmp_query_target(Error **errp)
167 {
168 QemuTargetInfo *info = g_malloc0(sizeof(*info));
169
170 info->arch = target_arch();
171
172 return info;
173 }
174
175 HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp)
176 {
177 MachineState *ms = MACHINE(qdev_get_machine());
178 MachineClass *mc = MACHINE_GET_CLASS(ms);
179
180 if (!mc->has_hotpluggable_cpus) {
181 error_setg(errp, "machine does not support hot-plugging CPUs");
182 return NULL;
183 }
184
185 return machine_query_hotpluggable_cpus(ms);
186 }
187
188 void qmp_set_numa_node(NumaOptions *cmd, Error **errp)
189 {
190 if (phase_check(PHASE_MACHINE_INITIALIZED)) {
191 error_setg(errp, "The command is permitted only before the machine has been created");
192 return;
193 }
194
195 set_numa_options(MACHINE(qdev_get_machine()), cmd, errp);
196 }
197
198 static int query_memdev(Object *obj, void *opaque)
199 {
200 Error *err = NULL;
201 MemdevList **list = opaque;
202 Memdev *m;
203 QObject *host_nodes;
204 Visitor *v;
205
206 if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
207 m = g_malloc0(sizeof(*m));
208
209 m->id = g_strdup(object_get_canonical_path_component(obj));
210
211 m->size = object_property_get_uint(obj, "size", &error_abort);
212 m->merge = object_property_get_bool(obj, "merge", &error_abort);
213 m->dump = object_property_get_bool(obj, "dump", &error_abort);
214 m->prealloc = object_property_get_bool(obj, "prealloc", &error_abort);
215 m->share = object_property_get_bool(obj, "share", &error_abort);
216 m->reserve = object_property_get_bool(obj, "reserve", &err);
217 if (err) {
218 error_free_or_abort(&err);
219 } else {
220 m->has_reserve = true;
221 }
222 m->policy = object_property_get_enum(obj, "policy", "HostMemPolicy",
223 &error_abort);
224 host_nodes = object_property_get_qobject(obj,
225 "host-nodes",
226 &error_abort);
227 v = qobject_input_visitor_new(host_nodes);
228 visit_type_uint16List(v, NULL, &m->host_nodes, &error_abort);
229 visit_free(v);
230 qobject_unref(host_nodes);
231
232 QAPI_LIST_PREPEND(*list, m);
233 }
234
235 return 0;
236 }
237
238 MemdevList *qmp_query_memdev(Error **errp)
239 {
240 Object *obj = object_get_objects_root();
241 MemdevList *list = NULL;
242
243 object_child_foreach(obj, query_memdev, &list);
244 return list;
245 }
246
247 HumanReadableText *qmp_x_query_numa(Error **errp)
248 {
249 g_autoptr(GString) buf = g_string_new("");
250 int i, nb_numa_nodes;
251 NumaNodeMem *node_mem;
252 CpuInfoFastList *cpu_list, *cpu;
253 MachineState *ms = MACHINE(qdev_get_machine());
254
255 nb_numa_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0;
256 g_string_append_printf(buf, "%d nodes\n", nb_numa_nodes);
257 if (!nb_numa_nodes) {
258 goto done;
259 }
260
261 cpu_list = qmp_query_cpus_fast(&error_abort);
262 node_mem = g_new0(NumaNodeMem, nb_numa_nodes);
263
264 query_numa_node_mem(node_mem, ms);
265 for (i = 0; i < nb_numa_nodes; i++) {
266 g_string_append_printf(buf, "node %d cpus:", i);
267 for (cpu = cpu_list; cpu; cpu = cpu->next) {
268 if (cpu->value->props && cpu->value->props->has_node_id &&
269 cpu->value->props->node_id == i) {
270 g_string_append_printf(buf, " %" PRIi64, cpu->value->cpu_index);
271 }
272 }
273 g_string_append_printf(buf, "\n");
274 g_string_append_printf(buf, "node %d size: %" PRId64 " MB\n", i,
275 node_mem[i].node_mem >> 20);
276 g_string_append_printf(buf, "node %d plugged: %" PRId64 " MB\n", i,
277 node_mem[i].node_plugged_mem >> 20);
278 }
279 qapi_free_CpuInfoFastList(cpu_list);
280 g_free(node_mem);
281
282 done:
283 return human_readable_text_from_str(buf);
284 }
285
286 KvmInfo *qmp_query_kvm(Error **errp)
287 {
288 KvmInfo *info = g_malloc0(sizeof(*info));
289
290 info->enabled = kvm_enabled();
291 info->present = accel_find("kvm");
292
293 return info;
294 }
295
296 UuidInfo *qmp_query_uuid(Error **errp)
297 {
298 UuidInfo *info = g_malloc0(sizeof(*info));
299
300 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
301 return info;
302 }
303
304 void qmp_system_reset(Error **errp)
305 {
306 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
307 }
308
309 void qmp_system_powerdown(Error **errp)
310 {
311 qemu_system_powerdown_request();
312 }
313
314 void qmp_system_wakeup(Error **errp)
315 {
316 if (!qemu_wakeup_suspend_enabled()) {
317 error_setg(errp,
318 "wake-up from suspend is not supported by this guest");
319 return;
320 }
321
322 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
323 }
324
325 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
326 {
327 return qmp_memory_device_list();
328 }
329
330 MemoryInfo *qmp_query_memory_size_summary(Error **errp)
331 {
332 MemoryInfo *mem_info = g_new0(MemoryInfo, 1);
333 MachineState *ms = MACHINE(qdev_get_machine());
334
335 mem_info->base_memory = ms->ram_size;
336
337 mem_info->plugged_memory = get_plugged_memory_size();
338 mem_info->has_plugged_memory =
339 mem_info->plugged_memory != (uint64_t)-1;
340
341 return mem_info;
342 }
343
344 HumanReadableText *qmp_x_query_ramblock(Error **errp)
345 {
346 g_autoptr(GString) buf = ram_block_format();
347
348 return human_readable_text_from_str(buf);
349 }
350
351 static int qmp_x_query_irq_foreach(Object *obj, void *opaque)
352 {
353 InterruptStatsProvider *intc;
354 InterruptStatsProviderClass *k;
355 GString *buf = opaque;
356
357 if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
358 intc = INTERRUPT_STATS_PROVIDER(obj);
359 k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
360 uint64_t *irq_counts;
361 unsigned int nb_irqs, i;
362 if (k->get_statistics &&
363 k->get_statistics(intc, &irq_counts, &nb_irqs)) {
364 if (nb_irqs > 0) {
365 g_string_append_printf(buf, "IRQ statistics for %s:\n",
366 object_get_typename(obj));
367 for (i = 0; i < nb_irqs; i++) {
368 if (irq_counts[i] > 0) {
369 g_string_append_printf(buf, "%2d: %" PRId64 "\n", i,
370 irq_counts[i]);
371 }
372 }
373 }
374 } else {
375 g_string_append_printf(buf,
376 "IRQ statistics not available for %s.\n",
377 object_get_typename(obj));
378 }
379 }
380
381 return 0;
382 }
383
384 HumanReadableText *qmp_x_query_irq(Error **errp)
385 {
386 g_autoptr(GString) buf = g_string_new("");
387
388 object_child_foreach_recursive(object_get_root(),
389 qmp_x_query_irq_foreach, buf);
390
391 return human_readable_text_from_str(buf);
392 }
393
394 static int qmp_x_query_intc_foreach(Object *obj, void *opaque)
395 {
396 InterruptStatsProvider *intc;
397 InterruptStatsProviderClass *k;
398 GString *buf = opaque;
399
400 if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
401 intc = INTERRUPT_STATS_PROVIDER(obj);
402 k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
403 if (k->print_info) {
404 k->print_info(intc, buf);
405 } else {
406 g_string_append_printf(buf,
407 "Interrupt controller information not available for %s.\n",
408 object_get_typename(obj));
409 }
410 }
411
412 return 0;
413 }
414
415 HumanReadableText *qmp_x_query_interrupt_controllers(Error **errp)
416 {
417 g_autoptr(GString) buf = g_string_new("");
418 object_child_foreach_recursive(object_get_root(),
419 qmp_x_query_intc_foreach, buf);
420 return human_readable_text_from_str(buf);
421 }
422
423 GuidInfo *qmp_query_vm_generation_id(Error **errp)
424 {
425 GuidInfo *info;
426 VmGenIdState *vms;
427 Object *obj = find_vmgenid_dev();
428
429 if (!obj) {
430 error_setg(errp, "VM Generation ID device not found");
431 return NULL;
432 }
433 vms = VMGENID(obj);
434
435 info = g_malloc0(sizeof(*info));
436 info->guid = qemu_uuid_unparse_strdup(&vms->guid);
437 return info;
438 }
439
440 void qmp_dump_skeys(const char *filename, Error **errp)
441 {
442 ObjectClass *mc = object_get_class(qdev_get_machine());
443 ObjectClass *oc = object_class_dynamic_cast(mc, TYPE_DUMP_SKEYS_INTERFACE);
444
445 if (!oc) {
446 error_setg(errp, "Storage keys information not available"
447 " for this architecture");
448 return;
449 }
450 DUMP_SKEYS_INTERFACE_CLASS(oc)->qmp_dump_skeys(filename, errp);
451 }
452
453 void qmp_inject_nmi(Error **errp)
454 {
455 nmi_inject(errp);
456 }