| 1 | /* |
| 2 | * HMP commands related to machines and CPUs |
| 3 | * |
| 4 | * Copyright IBM, Corp. 2011 |
| 5 | * |
| 6 | * Authors: |
| 7 | * Anthony Liguori <aliguori@us.ibm.com> |
| 8 | * |
| 9 | * This work is licensed under the terms of the GNU GPL, version 2. See |
| 10 | * the COPYING file in the top-level directory. |
| 11 | * |
| 12 | * Contributions after 2012-01-13 are licensed under the terms of the |
| 13 | * GNU GPL, version 2 or (at your option) any later version. |
| 14 | */ |
| 15 | |
| 16 | #include "qemu/osdep.h" |
| 17 | #include "monitor/hmp.h" |
| 18 | #include "qapi/error.h" |
| 19 | #include "qapi/qapi-builtin-visit.h" |
| 20 | #include "qapi/qapi-commands-accelerator.h" |
| 21 | #include "qapi/qapi-commands-machine.h" |
| 22 | #include "qobject/qdict.h" |
| 23 | #include "qapi/string-output-visitor.h" |
| 24 | #include "qemu/error-report.h" |
| 25 | #include "system/numa.h" |
| 26 | #include "hw/core/boards.h" |
| 27 | |
| 28 | void hmp_info_cpus(MonitorHMP *hmp, const QDict *qdict) |
| 29 | { |
| 30 | CpuInfoFastList *cpu_list, *cpu; |
| 31 | |
| 32 | cpu_list = qmp_query_cpus_fast(NULL); |
| 33 | |
| 34 | for (cpu = cpu_list; cpu; cpu = cpu->next) { |
| 35 | g_autofree char *cpu_model = cpu_model_from_type(cpu->value->qom_type); |
| 36 | int active = ' '; |
| 37 | |
| 38 | if (cpu->value->cpu_index == monitor_hmp_get_cpu_index(hmp)) { |
| 39 | active = '*'; |
| 40 | } |
| 41 | |
| 42 | monitor_hmp_printf(hmp, "%c CPU #%" PRId64 ":", active, |
| 43 | cpu->value->cpu_index); |
| 44 | monitor_hmp_printf(hmp, " thread_id=%" PRId64 " model=%s\n", |
| 45 | cpu->value->thread_id, cpu_model); |
| 46 | } |
| 47 | |
| 48 | qapi_free_CpuInfoFastList(cpu_list); |
| 49 | } |
| 50 | |
| 51 | void hmp_hotpluggable_cpus(MonitorHMP *hmp, const QDict *qdict) |
| 52 | { |
| 53 | Error *err = NULL; |
| 54 | HotpluggableCPUList *l = qmp_query_hotpluggable_cpus(&err); |
| 55 | HotpluggableCPUList *saved = l; |
| 56 | CpuInstanceProperties *c; |
| 57 | |
| 58 | if (hmp_handle_error(hmp, err)) { |
| 59 | return; |
| 60 | } |
| 61 | |
| 62 | monitor_hmp_printf(hmp, "Hotpluggable CPUs:\n"); |
| 63 | while (l) { |
| 64 | monitor_hmp_printf(hmp, " type: \"%s\"\n", l->value->type); |
| 65 | monitor_hmp_printf(hmp, " vcpus_count: \"%" PRIu64 "\"\n", |
| 66 | l->value->vcpus_count); |
| 67 | if (l->value->qom_path) { |
| 68 | monitor_hmp_printf(hmp, " qom_path: \"%s\"\n", l->value->qom_path); |
| 69 | } |
| 70 | |
| 71 | c = l->value->props; |
| 72 | monitor_hmp_printf(hmp, " CPUInstance Properties:\n"); |
| 73 | if (c->has_node_id) { |
| 74 | monitor_hmp_printf(hmp, " node-id: \"%" PRIu64 "\"\n", c->node_id); |
| 75 | } |
| 76 | if (c->has_drawer_id) { |
| 77 | monitor_hmp_printf(hmp, " drawer-id: \"%" PRIu64 "\"\n", c->drawer_id); |
| 78 | } |
| 79 | if (c->has_book_id) { |
| 80 | monitor_hmp_printf(hmp, " book-id: \"%" PRIu64 "\"\n", c->book_id); |
| 81 | } |
| 82 | if (c->has_socket_id) { |
| 83 | monitor_hmp_printf(hmp, " socket-id: \"%" PRIu64 "\"\n", c->socket_id); |
| 84 | } |
| 85 | if (c->has_die_id) { |
| 86 | monitor_hmp_printf(hmp, " die-id: \"%" PRIu64 "\"\n", c->die_id); |
| 87 | } |
| 88 | if (c->has_cluster_id) { |
| 89 | monitor_hmp_printf(hmp, " cluster-id: \"%" PRIu64 "\"\n", |
| 90 | c->cluster_id); |
| 91 | } |
| 92 | if (c->has_module_id) { |
| 93 | monitor_hmp_printf(hmp, " module-id: \"%" PRIu64 "\"\n", |
| 94 | c->module_id); |
| 95 | } |
| 96 | if (c->has_core_id) { |
| 97 | monitor_hmp_printf(hmp, " core-id: \"%" PRIu64 "\"\n", c->core_id); |
| 98 | } |
| 99 | if (c->has_thread_id) { |
| 100 | monitor_hmp_printf(hmp, " thread-id: \"%" PRIu64 "\"\n", c->thread_id); |
| 101 | } |
| 102 | |
| 103 | l = l->next; |
| 104 | } |
| 105 | |
| 106 | qapi_free_HotpluggableCPUList(saved); |
| 107 | } |
| 108 | |
| 109 | void hmp_info_memdev(MonitorHMP *hmp, const QDict *qdict) |
| 110 | { |
| 111 | Error *err = NULL; |
| 112 | MemdevList *memdev_list = qmp_query_memdev(&err); |
| 113 | MemdevList *m = memdev_list; |
| 114 | Visitor *v; |
| 115 | char *str; |
| 116 | |
| 117 | while (m) { |
| 118 | v = string_output_visitor_new(false, &str); |
| 119 | visit_type_uint16List(v, NULL, &m->value->host_nodes, &error_abort); |
| 120 | monitor_hmp_printf(hmp, "memory backend: %s\n", m->value->id); |
| 121 | monitor_hmp_printf(hmp, " size: %" PRId64 "\n", m->value->size); |
| 122 | monitor_hmp_printf(hmp, " merge: %s\n", |
| 123 | m->value->merge ? "true" : "false"); |
| 124 | monitor_hmp_printf(hmp, " dump: %s\n", |
| 125 | m->value->dump ? "true" : "false"); |
| 126 | monitor_hmp_printf(hmp, " prealloc: %s\n", |
| 127 | m->value->prealloc ? "true" : "false"); |
| 128 | monitor_hmp_printf(hmp, " share: %s\n", |
| 129 | m->value->share ? "true" : "false"); |
| 130 | if (m->value->has_reserve) { |
| 131 | monitor_hmp_printf(hmp, " reserve: %s\n", |
| 132 | m->value->reserve ? "true" : "false"); |
| 133 | } |
| 134 | monitor_hmp_printf(hmp, " policy: %s\n", |
| 135 | HostMemPolicy_str(m->value->policy)); |
| 136 | visit_complete(v, &str); |
| 137 | monitor_hmp_printf(hmp, " host nodes: %s\n", str); |
| 138 | |
| 139 | g_free(str); |
| 140 | visit_free(v); |
| 141 | m = m->next; |
| 142 | } |
| 143 | |
| 144 | monitor_hmp_printf(hmp, "\n"); |
| 145 | |
| 146 | qapi_free_MemdevList(memdev_list); |
| 147 | hmp_handle_error(hmp, err); |
| 148 | } |
| 149 | |
| 150 | void hmp_info_kvm(MonitorHMP *hmp, const QDict *qdict) |
| 151 | { |
| 152 | KvmInfo *info; |
| 153 | |
| 154 | info = qmp_query_kvm(NULL); |
| 155 | monitor_hmp_printf(hmp, "kvm support: "); |
| 156 | if (info->present) { |
| 157 | monitor_hmp_printf(hmp, "%s\n", info->enabled ? "enabled" : "disabled"); |
| 158 | } else { |
| 159 | monitor_hmp_printf(hmp, "not compiled\n"); |
| 160 | } |
| 161 | |
| 162 | qapi_free_KvmInfo(info); |
| 163 | } |
| 164 | |
| 165 | void hmp_info_accelerators(MonitorHMP *hmp, const QDict *qdict) |
| 166 | { |
| 167 | AcceleratorInfo *info; |
| 168 | AcceleratorList *accel; |
| 169 | |
| 170 | info = qmp_query_accelerators(NULL); |
| 171 | for (accel = info->present; accel; accel = accel->next) { |
| 172 | char trail = accel->next ? ' ' : '\n'; |
| 173 | if (info->enabled == accel->value) { |
| 174 | monitor_hmp_printf(hmp, "[%s]%c", Accelerator_str(accel->value), trail); |
| 175 | } else { |
| 176 | monitor_hmp_printf(hmp, "%s%c", Accelerator_str(accel->value), trail); |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | qapi_free_AcceleratorInfo(info); |
| 181 | } |
| 182 | |
| 183 | void hmp_info_uuid(MonitorHMP *hmp, const QDict *qdict) |
| 184 | { |
| 185 | UuidInfo *info; |
| 186 | |
| 187 | info = qmp_query_uuid(NULL); |
| 188 | monitor_hmp_printf(hmp, "%s\n", info->UUID); |
| 189 | qapi_free_UuidInfo(info); |
| 190 | } |
| 191 | |
| 192 | void hmp_info_balloon(MonitorHMP *hmp, const QDict *qdict) |
| 193 | { |
| 194 | BalloonInfo *info; |
| 195 | Error *err = NULL; |
| 196 | |
| 197 | info = qmp_query_balloon(&err); |
| 198 | if (hmp_handle_error(hmp, err)) { |
| 199 | return; |
| 200 | } |
| 201 | |
| 202 | monitor_hmp_printf(hmp, "balloon: actual=%" PRId64 "\n", info->actual >> 20); |
| 203 | |
| 204 | qapi_free_BalloonInfo(info); |
| 205 | } |
| 206 | |
| 207 | void hmp_system_reset(MonitorHMP *hmp, const QDict *qdict) |
| 208 | { |
| 209 | qmp_system_reset(NULL); |
| 210 | } |
| 211 | |
| 212 | void hmp_system_powerdown(MonitorHMP *hmp, const QDict *qdict) |
| 213 | { |
| 214 | qmp_system_powerdown(NULL); |
| 215 | } |
| 216 | |
| 217 | void hmp_memsave(MonitorHMP *hmp, const QDict *qdict) |
| 218 | { |
| 219 | uint32_t size = qdict_get_int(qdict, "size"); |
| 220 | const char *filename = qdict_get_str(qdict, "filename"); |
| 221 | uint64_t addr = qdict_get_int(qdict, "val"); |
| 222 | Error *err = NULL; |
| 223 | int cpu_index = monitor_hmp_get_cpu_index(hmp); |
| 224 | |
| 225 | if (cpu_index < 0) { |
| 226 | monitor_hmp_printf(hmp, "No CPU available\n"); |
| 227 | return; |
| 228 | } |
| 229 | |
| 230 | qmp_memsave(addr, size, filename, true, cpu_index, &err); |
| 231 | hmp_handle_error(hmp, err); |
| 232 | } |
| 233 | |
| 234 | void hmp_pmemsave(MonitorHMP *hmp, const QDict *qdict) |
| 235 | { |
| 236 | uint32_t size = qdict_get_int(qdict, "size"); |
| 237 | const char *filename = qdict_get_str(qdict, "filename"); |
| 238 | uint64_t addr = qdict_get_int(qdict, "val"); |
| 239 | Error *err = NULL; |
| 240 | |
| 241 | qmp_pmemsave(addr, size, filename, &err); |
| 242 | hmp_handle_error(hmp, err); |
| 243 | } |
| 244 | |
| 245 | void hmp_system_wakeup(MonitorHMP *hmp, const QDict *qdict) |
| 246 | { |
| 247 | Error *err = NULL; |
| 248 | |
| 249 | qmp_system_wakeup(&err); |
| 250 | hmp_handle_error(hmp, err); |
| 251 | } |
| 252 | |
| 253 | void hmp_nmi(MonitorHMP *hmp, const QDict *qdict) |
| 254 | { |
| 255 | Error *err = NULL; |
| 256 | |
| 257 | qmp_inject_nmi(&err); |
| 258 | hmp_handle_error(hmp, err); |
| 259 | } |
| 260 | |
| 261 | void hmp_balloon(MonitorHMP *hmp, const QDict *qdict) |
| 262 | { |
| 263 | int64_t value = qdict_get_int(qdict, "value"); |
| 264 | Error *err = NULL; |
| 265 | |
| 266 | qmp_balloon(value, &err); |
| 267 | hmp_handle_error(hmp, err); |
| 268 | } |
| 269 | |
| 270 | void hmp_info_memory_devices(MonitorHMP *hmp, const QDict *qdict) |
| 271 | { |
| 272 | Error *err = NULL; |
| 273 | MemoryDeviceInfoList *info_list = qmp_query_memory_devices(&err); |
| 274 | MemoryDeviceInfoList *info; |
| 275 | VirtioPMEMDeviceInfo *vpi; |
| 276 | VirtioMEMDeviceInfo *vmi; |
| 277 | MemoryDeviceInfo *value; |
| 278 | PCDIMMDeviceInfo *di; |
| 279 | SgxEPCDeviceInfo *se; |
| 280 | HvBalloonDeviceInfo *hi; |
| 281 | SpMemDeviceInfo *spmi; |
| 282 | |
| 283 | for (info = info_list; info; info = info->next) { |
| 284 | value = info->value; |
| 285 | |
| 286 | if (value) { |
| 287 | switch (value->type) { |
| 288 | case MEMORY_DEVICE_INFO_KIND_DIMM: |
| 289 | case MEMORY_DEVICE_INFO_KIND_NVDIMM: |
| 290 | di = value->type == MEMORY_DEVICE_INFO_KIND_DIMM ? |
| 291 | value->u.dimm.data : value->u.nvdimm.data; |
| 292 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 293 | MemoryDeviceInfoKind_str(value->type), |
| 294 | di->id ? di->id : ""); |
| 295 | monitor_hmp_printf(hmp, " addr: 0x%" PRIx64 "\n", di->addr); |
| 296 | monitor_hmp_printf(hmp, " slot: %" PRId64 "\n", di->slot); |
| 297 | monitor_hmp_printf(hmp, " node: %" PRId64 "\n", di->node); |
| 298 | monitor_hmp_printf(hmp, " size: %" PRIu64 "\n", di->size); |
| 299 | monitor_hmp_printf(hmp, " memdev: %s\n", di->memdev); |
| 300 | monitor_hmp_printf(hmp, " hotplugged: %s\n", |
| 301 | di->hotplugged ? "true" : "false"); |
| 302 | monitor_hmp_printf(hmp, " hotpluggable: %s\n", |
| 303 | di->hotpluggable ? "true" : "false"); |
| 304 | break; |
| 305 | case MEMORY_DEVICE_INFO_KIND_VIRTIO_PMEM: |
| 306 | vpi = value->u.virtio_pmem.data; |
| 307 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 308 | MemoryDeviceInfoKind_str(value->type), |
| 309 | vpi->id ? vpi->id : ""); |
| 310 | monitor_hmp_printf(hmp, " memaddr: 0x%" PRIx64 "\n", vpi->memaddr); |
| 311 | monitor_hmp_printf(hmp, " size: %" PRIu64 "\n", vpi->size); |
| 312 | monitor_hmp_printf(hmp, " memdev: %s\n", vpi->memdev); |
| 313 | break; |
| 314 | case MEMORY_DEVICE_INFO_KIND_VIRTIO_MEM: |
| 315 | vmi = value->u.virtio_mem.data; |
| 316 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 317 | MemoryDeviceInfoKind_str(value->type), |
| 318 | vmi->id ? vmi->id : ""); |
| 319 | monitor_hmp_printf(hmp, " memaddr: 0x%" PRIx64 "\n", vmi->memaddr); |
| 320 | monitor_hmp_printf(hmp, " node: %" PRId64 "\n", vmi->node); |
| 321 | monitor_hmp_printf(hmp, " requested-size: %" PRIu64 "\n", |
| 322 | vmi->requested_size); |
| 323 | monitor_hmp_printf(hmp, " size: %" PRIu64 "\n", vmi->size); |
| 324 | monitor_hmp_printf(hmp, " max-size: %" PRIu64 "\n", vmi->max_size); |
| 325 | monitor_hmp_printf(hmp, " block-size: %" PRIu64 "\n", |
| 326 | vmi->block_size); |
| 327 | monitor_hmp_printf(hmp, " memdev: %s\n", vmi->memdev); |
| 328 | break; |
| 329 | case MEMORY_DEVICE_INFO_KIND_SGX_EPC: |
| 330 | se = value->u.sgx_epc.data; |
| 331 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 332 | MemoryDeviceInfoKind_str(value->type), |
| 333 | se->id ? se->id : ""); |
| 334 | monitor_hmp_printf(hmp, " memaddr: 0x%" PRIx64 "\n", se->memaddr); |
| 335 | monitor_hmp_printf(hmp, " size: %" PRIu64 "\n", se->size); |
| 336 | monitor_hmp_printf(hmp, " node: %" PRId64 "\n", se->node); |
| 337 | monitor_hmp_printf(hmp, " memdev: %s\n", se->memdev); |
| 338 | break; |
| 339 | case MEMORY_DEVICE_INFO_KIND_HV_BALLOON: |
| 340 | hi = value->u.hv_balloon.data; |
| 341 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 342 | MemoryDeviceInfoKind_str(value->type), |
| 343 | hi->id ? hi->id : ""); |
| 344 | if (hi->has_memaddr) { |
| 345 | monitor_hmp_printf(hmp, " memaddr: 0x%" PRIx64 "\n", |
| 346 | hi->memaddr); |
| 347 | } |
| 348 | monitor_hmp_printf(hmp, " max-size: %" PRIu64 "\n", hi->max_size); |
| 349 | if (hi->memdev) { |
| 350 | monitor_hmp_printf(hmp, " memdev: %s\n", hi->memdev); |
| 351 | } |
| 352 | break; |
| 353 | case MEMORY_DEVICE_INFO_KIND_SP_MEM: |
| 354 | spmi = value->u.sp_mem.data; |
| 355 | monitor_hmp_printf(hmp, "Memory device [%s]: \"%s\"\n", |
| 356 | MemoryDeviceInfoKind_str(value->type), |
| 357 | spmi->id ? spmi->id : ""); |
| 358 | monitor_hmp_printf(hmp, " addr: 0x%" PRIx64 "\n", spmi->addr); |
| 359 | monitor_hmp_printf(hmp, " node: %" PRId64 "\n", spmi->node); |
| 360 | monitor_hmp_printf(hmp, " size: %" PRIu64 "\n", spmi->size); |
| 361 | monitor_hmp_printf(hmp, " memdev: %s\n", spmi->memdev); |
| 362 | break; |
| 363 | default: |
| 364 | g_assert_not_reached(); |
| 365 | } |
| 366 | } |
| 367 | } |
| 368 | |
| 369 | qapi_free_MemoryDeviceInfoList(info_list); |
| 370 | hmp_handle_error(hmp, err); |
| 371 | } |
| 372 | |
| 373 | void hmp_info_vm_generation_id(MonitorHMP *hmp, const QDict *qdict) |
| 374 | { |
| 375 | Error *err = NULL; |
| 376 | GuidInfo *info = qmp_query_vm_generation_id(&err); |
| 377 | if (info) { |
| 378 | monitor_hmp_printf(hmp, "%s\n", info->guid); |
| 379 | } |
| 380 | hmp_handle_error(hmp, err); |
| 381 | qapi_free_GuidInfo(info); |
| 382 | } |
| 383 | |
| 384 | void hmp_info_memory_size_summary(MonitorHMP *hmp, const QDict *qdict) |
| 385 | { |
| 386 | Error *err = NULL; |
| 387 | MemoryInfo *info = qmp_query_memory_size_summary(&err); |
| 388 | if (info) { |
| 389 | monitor_hmp_printf(hmp, "base memory: %" PRIu64 "\n", |
| 390 | info->base_memory); |
| 391 | |
| 392 | if (info->has_plugged_memory) { |
| 393 | monitor_hmp_printf(hmp, "plugged memory: %" PRIu64 "\n", |
| 394 | info->plugged_memory); |
| 395 | } |
| 396 | |
| 397 | qapi_free_MemoryInfo(info); |
| 398 | } |
| 399 | hmp_handle_error(hmp, err); |
| 400 | } |