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/boards.h" 13 #include "hw/intc/intc.h" 14 #include "hw/mem/memory-device.h" 15 #include "hw/rdma/rdma.h" 16 #include "qapi/error.h" 17 #include "qapi/qapi-builtin-visit.h" 18 #include "qapi/qapi-commands-machine.h" 19 #include "qapi/qmp/qobject.h" 20 #include "qapi/qobject-input-visitor.h" 21 #include "qapi/type-helpers.h" 22 #include "qemu/main-loop.h" 23 #include "qemu/uuid.h" 24 #include "qom/qom-qobject.h" 25 #include "sysemu/hostmem.h" 26 #include "sysemu/hw_accel.h" 27 #include "sysemu/numa.h" 28 #include "sysemu/runstate.h" 29 #include "sysemu/sysemu.h" 30 31 /* 32 * fast means: we NEVER interrupt vCPU threads to retrieve 33 * information from KVM. 34 */ 35 CpuInfoFastList *qmp_query_cpus_fast(Error **errp) 36 { 37 MachineState *ms = MACHINE(qdev_get_machine()); 38 MachineClass *mc = MACHINE_GET_CLASS(ms); 39 CpuInfoFastList *head = NULL, **tail = &head; 40 SysEmuTarget target = qapi_enum_parse(&SysEmuTarget_lookup, target_name(), 41 -1, &error_abort); 42 CPUState *cpu; 43 44 CPU_FOREACH(cpu) { 45 CpuInfoFast *value = g_malloc0(sizeof(*value)); 46 47 value->cpu_index = cpu->cpu_index; 48 value->qom_path = object_get_canonical_path(OBJECT(cpu)); 49 value->thread_id = cpu->thread_id; 50 51 if (mc->cpu_index_to_instance_props) { 52 CpuInstanceProperties *props; 53 props = g_malloc0(sizeof(*props)); 54 *props = mc->cpu_index_to_instance_props(ms, cpu->cpu_index); 55 value->props = props; 56 } 57 58 value->target = target; 59 if (cpu->cc->query_cpu_fast) { 60 cpu->cc->query_cpu_fast(cpu, value); 61 } 62 63 QAPI_LIST_APPEND(tail, value); 64 } 65 66 return head; 67 } 68 69 MachineInfoList *qmp_query_machines(Error **errp) 70 { 71 GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false); 72 MachineInfoList *mach_list = NULL; 73 74 for (el = machines; el; el = el->next) { 75 MachineClass *mc = el->data; 76 MachineInfo *info; 77 78 info = g_malloc0(sizeof(*info)); 79 if (mc->is_default) { 80 info->has_is_default = true; 81 info->is_default = true; 82 } 83 84 if (mc->alias) { 85 info->alias = g_strdup(mc->alias); 86 } 87 88 info->name = g_strdup(mc->name); 89 info->cpu_max = !mc->max_cpus ? 1 : mc->max_cpus; 90 info->hotpluggable_cpus = mc->has_hotpluggable_cpus; 91 info->numa_mem_supported = mc->numa_mem_supported; 92 info->deprecated = !!mc->deprecation_reason; 93 info->acpi = !!object_class_property_find(OBJECT_CLASS(mc), "acpi"); 94 if (mc->default_cpu_type) { 95 info->default_cpu_type = g_strdup(mc->default_cpu_type); 96 } 97 if (mc->default_ram_id) { 98 info->default_ram_id = g_strdup(mc->default_ram_id); 99 } 100 101 QAPI_LIST_PREPEND(mach_list, info); 102 } 103 104 g_slist_free(machines); 105 return mach_list; 106 } 107 108 CurrentMachineParams *qmp_query_current_machine(Error **errp) 109 { 110 CurrentMachineParams *params = g_malloc0(sizeof(*params)); 111 params->wakeup_suspend_support = qemu_wakeup_suspend_enabled(); 112 113 return params; 114 } 115 116 TargetInfo *qmp_query_target(Error **errp) 117 { 118 TargetInfo *info = g_malloc0(sizeof(*info)); 119 120 info->arch = qapi_enum_parse(&SysEmuTarget_lookup, target_name(), -1, 121 &error_abort); 122 123 return info; 124 } 125 126 HotpluggableCPUList *qmp_query_hotpluggable_cpus(Error **errp) 127 { 128 MachineState *ms = MACHINE(qdev_get_machine()); 129 MachineClass *mc = MACHINE_GET_CLASS(ms); 130 131 if (!mc->has_hotpluggable_cpus) { 132 error_setg(errp, "machine does not support hot-plugging CPUs"); 133 return NULL; 134 } 135 136 return machine_query_hotpluggable_cpus(ms); 137 } 138 139 void qmp_set_numa_node(NumaOptions *cmd, Error **errp) 140 { 141 if (phase_check(PHASE_MACHINE_INITIALIZED)) { 142 error_setg(errp, "The command is permitted only before the machine has been created"); 143 return; 144 } 145 146 set_numa_options(MACHINE(qdev_get_machine()), cmd, errp); 147 } 148 149 static int query_memdev(Object *obj, void *opaque) 150 { 151 Error *err = NULL; 152 MemdevList **list = opaque; 153 Memdev *m; 154 QObject *host_nodes; 155 Visitor *v; 156 157 if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) { 158 m = g_malloc0(sizeof(*m)); 159 160 m->id = g_strdup(object_get_canonical_path_component(obj)); 161 162 m->size = object_property_get_uint(obj, "size", &error_abort); 163 m->merge = object_property_get_bool(obj, "merge", &error_abort); 164 m->dump = object_property_get_bool(obj, "dump", &error_abort); 165 m->prealloc = object_property_get_bool(obj, "prealloc", &error_abort); 166 m->share = object_property_get_bool(obj, "share", &error_abort); 167 m->reserve = object_property_get_bool(obj, "reserve", &err); 168 if (err) { 169 error_free_or_abort(&err); 170 } else { 171 m->has_reserve = true; 172 } 173 m->policy = object_property_get_enum(obj, "policy", "HostMemPolicy", 174 &error_abort); 175 host_nodes = object_property_get_qobject(obj, 176 "host-nodes", 177 &error_abort); 178 v = qobject_input_visitor_new(host_nodes); 179 visit_type_uint16List(v, NULL, &m->host_nodes, &error_abort); 180 visit_free(v); 181 qobject_unref(host_nodes); 182 183 QAPI_LIST_PREPEND(*list, m); 184 } 185 186 return 0; 187 } 188 189 MemdevList *qmp_query_memdev(Error **errp) 190 { 191 Object *obj = object_get_objects_root(); 192 MemdevList *list = NULL; 193 194 object_child_foreach(obj, query_memdev, &list); 195 return list; 196 } 197 198 HumanReadableText *qmp_x_query_numa(Error **errp) 199 { 200 g_autoptr(GString) buf = g_string_new(""); 201 int i, nb_numa_nodes; 202 NumaNodeMem *node_mem; 203 CpuInfoFastList *cpu_list, *cpu; 204 MachineState *ms = MACHINE(qdev_get_machine()); 205 206 nb_numa_nodes = ms->numa_state ? ms->numa_state->num_nodes : 0; 207 g_string_append_printf(buf, "%d nodes\n", nb_numa_nodes); 208 if (!nb_numa_nodes) { 209 goto done; 210 } 211 212 cpu_list = qmp_query_cpus_fast(&error_abort); 213 node_mem = g_new0(NumaNodeMem, nb_numa_nodes); 214 215 query_numa_node_mem(node_mem, ms); 216 for (i = 0; i < nb_numa_nodes; i++) { 217 g_string_append_printf(buf, "node %d cpus:", i); 218 for (cpu = cpu_list; cpu; cpu = cpu->next) { 219 if (cpu->value->props && cpu->value->props->has_node_id && 220 cpu->value->props->node_id == i) { 221 g_string_append_printf(buf, " %" PRIi64, cpu->value->cpu_index); 222 } 223 } 224 g_string_append_printf(buf, "\n"); 225 g_string_append_printf(buf, "node %d size: %" PRId64 " MB\n", i, 226 node_mem[i].node_mem >> 20); 227 g_string_append_printf(buf, "node %d plugged: %" PRId64 " MB\n", i, 228 node_mem[i].node_plugged_mem >> 20); 229 } 230 qapi_free_CpuInfoFastList(cpu_list); 231 g_free(node_mem); 232 233 done: 234 return human_readable_text_from_str(buf); 235 } 236 237 KvmInfo *qmp_query_kvm(Error **errp) 238 { 239 KvmInfo *info = g_malloc0(sizeof(*info)); 240 241 info->enabled = kvm_enabled(); 242 info->present = accel_find("kvm"); 243 244 return info; 245 } 246 247 UuidInfo *qmp_query_uuid(Error **errp) 248 { 249 UuidInfo *info = g_malloc0(sizeof(*info)); 250 251 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 252 return info; 253 } 254 255 void qmp_system_reset(Error **errp) 256 { 257 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 258 } 259 260 void qmp_system_powerdown(Error **errp) 261 { 262 qemu_system_powerdown_request(); 263 } 264 265 void qmp_system_wakeup(Error **errp) 266 { 267 if (!qemu_wakeup_suspend_enabled()) { 268 error_setg(errp, 269 "wake-up from suspend is not supported by this guest"); 270 return; 271 } 272 273 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 274 } 275 276 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 277 { 278 return qmp_memory_device_list(); 279 } 280 281 MemoryInfo *qmp_query_memory_size_summary(Error **errp) 282 { 283 MemoryInfo *mem_info = g_new0(MemoryInfo, 1); 284 MachineState *ms = MACHINE(qdev_get_machine()); 285 286 mem_info->base_memory = ms->ram_size; 287 288 mem_info->plugged_memory = get_plugged_memory_size(); 289 mem_info->has_plugged_memory = 290 mem_info->plugged_memory != (uint64_t)-1; 291 292 return mem_info; 293 } 294 295 static int qmp_x_query_rdma_foreach(Object *obj, void *opaque) 296 { 297 RdmaProvider *rdma; 298 RdmaProviderClass *k; 299 GString *buf = opaque; 300 301 if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) { 302 rdma = RDMA_PROVIDER(obj); 303 k = RDMA_PROVIDER_GET_CLASS(obj); 304 if (k->format_statistics) { 305 k->format_statistics(rdma, buf); 306 } else { 307 g_string_append_printf(buf, 308 "RDMA statistics not available for %s.\n", 309 object_get_typename(obj)); 310 } 311 } 312 313 return 0; 314 } 315 316 HumanReadableText *qmp_x_query_rdma(Error **errp) 317 { 318 g_autoptr(GString) buf = g_string_new(""); 319 320 object_child_foreach_recursive(object_get_root(), 321 qmp_x_query_rdma_foreach, buf); 322 323 return human_readable_text_from_str(buf); 324 } 325 326 HumanReadableText *qmp_x_query_ramblock(Error **errp) 327 { 328 g_autoptr(GString) buf = ram_block_format(); 329 330 return human_readable_text_from_str(buf); 331 } 332 333 static int qmp_x_query_irq_foreach(Object *obj, void *opaque) 334 { 335 InterruptStatsProvider *intc; 336 InterruptStatsProviderClass *k; 337 GString *buf = opaque; 338 339 if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { 340 intc = INTERRUPT_STATS_PROVIDER(obj); 341 k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); 342 uint64_t *irq_counts; 343 unsigned int nb_irqs, i; 344 if (k->get_statistics && 345 k->get_statistics(intc, &irq_counts, &nb_irqs)) { 346 if (nb_irqs > 0) { 347 g_string_append_printf(buf, "IRQ statistics for %s:\n", 348 object_get_typename(obj)); 349 for (i = 0; i < nb_irqs; i++) { 350 if (irq_counts[i] > 0) { 351 g_string_append_printf(buf, "%2d: %" PRId64 "\n", i, 352 irq_counts[i]); 353 } 354 } 355 } 356 } else { 357 g_string_append_printf(buf, 358 "IRQ statistics not available for %s.\n", 359 object_get_typename(obj)); 360 } 361 } 362 363 return 0; 364 } 365 366 HumanReadableText *qmp_x_query_irq(Error **errp) 367 { 368 g_autoptr(GString) buf = g_string_new(""); 369 370 object_child_foreach_recursive(object_get_root(), 371 qmp_x_query_irq_foreach, buf); 372 373 return human_readable_text_from_str(buf); 374 } 375 376 GuidInfo *qmp_query_vm_generation_id(Error **errp) 377 { 378 GuidInfo *info; 379 VmGenIdState *vms; 380 Object *obj = find_vmgenid_dev(); 381 382 if (!obj) { 383 error_setg(errp, "VM Generation ID device not found"); 384 return NULL; 385 } 386 vms = VMGENID(obj); 387 388 info = g_malloc0(sizeof(*info)); 389 info->guid = qemu_uuid_unparse_strdup(&vms->guid); 390 return info; 391 } 392