1 /* 2 * QEMU Management Protocol commands 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 "qemu/cutils.h" 18 #include "qemu/option.h" 19 #include "monitor/monitor.h" 20 #include "sysemu/sysemu.h" 21 #include "qemu/config-file.h" 22 #include "qemu/uuid.h" 23 #include "chardev/char.h" 24 #include "ui/qemu-spice.h" 25 #include "ui/console.h" 26 #include "ui/dbus-display.h" 27 #include "sysemu/kvm.h" 28 #include "sysemu/runstate.h" 29 #include "sysemu/runstate-action.h" 30 #include "sysemu/blockdev.h" 31 #include "sysemu/block-backend.h" 32 #include "qapi/error.h" 33 #include "qapi/qapi-commands-acpi.h" 34 #include "qapi/qapi-commands-block.h" 35 #include "qapi/qapi-commands-control.h" 36 #include "qapi/qapi-commands-machine.h" 37 #include "qapi/qapi-commands-misc.h" 38 #include "qapi/qapi-commands-stats.h" 39 #include "qapi/type-helpers.h" 40 #include "exec/ramlist.h" 41 #include "hw/mem/memory-device.h" 42 #include "hw/acpi/acpi_dev_interface.h" 43 #include "hw/intc/intc.h" 44 #include "hw/rdma/rdma.h" 45 #include "monitor/stats.h" 46 47 NameInfo *qmp_query_name(Error **errp) 48 { 49 NameInfo *info = g_malloc0(sizeof(*info)); 50 51 info->name = g_strdup(qemu_name); 52 return info; 53 } 54 55 KvmInfo *qmp_query_kvm(Error **errp) 56 { 57 KvmInfo *info = g_malloc0(sizeof(*info)); 58 59 info->enabled = kvm_enabled(); 60 info->present = accel_find("kvm"); 61 62 return info; 63 } 64 65 UuidInfo *qmp_query_uuid(Error **errp) 66 { 67 UuidInfo *info = g_malloc0(sizeof(*info)); 68 69 info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 70 return info; 71 } 72 73 void qmp_quit(Error **errp) 74 { 75 shutdown_action = SHUTDOWN_ACTION_POWEROFF; 76 qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); 77 } 78 79 void qmp_stop(Error **errp) 80 { 81 /* if there is a dump in background, we should wait until the dump 82 * finished */ 83 if (qemu_system_dump_in_progress()) { 84 error_setg(errp, "There is a dump in process, please wait."); 85 return; 86 } 87 88 if (runstate_check(RUN_STATE_INMIGRATE)) { 89 autostart = 0; 90 } else { 91 vm_stop(RUN_STATE_PAUSED); 92 } 93 } 94 95 void qmp_system_reset(Error **errp) 96 { 97 qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 98 } 99 100 void qmp_system_powerdown(Error **errp) 101 { 102 qemu_system_powerdown_request(); 103 } 104 105 void qmp_cont(Error **errp) 106 { 107 BlockBackend *blk; 108 BlockJob *job; 109 Error *local_err = NULL; 110 111 /* if there is a dump in background, we should wait until the dump 112 * finished */ 113 if (qemu_system_dump_in_progress()) { 114 error_setg(errp, "There is a dump in process, please wait."); 115 return; 116 } 117 118 if (runstate_needs_reset()) { 119 error_setg(errp, "Resetting the Virtual Machine is required"); 120 return; 121 } else if (runstate_check(RUN_STATE_SUSPENDED)) { 122 return; 123 } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { 124 error_setg(errp, "Migration is not finalized yet"); 125 return; 126 } 127 128 for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { 129 blk_iostatus_reset(blk); 130 } 131 132 WITH_JOB_LOCK_GUARD() { 133 for (job = block_job_next_locked(NULL); job; 134 job = block_job_next_locked(job)) { 135 block_job_iostatus_reset_locked(job); 136 } 137 } 138 139 /* Continuing after completed migration. Images have been inactivated to 140 * allow the destination to take control. Need to get control back now. 141 * 142 * If there are no inactive block nodes (e.g. because the VM was just 143 * paused rather than completing a migration), bdrv_inactivate_all() simply 144 * doesn't do anything. */ 145 bdrv_activate_all(&local_err); 146 if (local_err) { 147 error_propagate(errp, local_err); 148 return; 149 } 150 151 if (runstate_check(RUN_STATE_INMIGRATE)) { 152 autostart = 1; 153 } else { 154 vm_start(); 155 } 156 } 157 158 void qmp_system_wakeup(Error **errp) 159 { 160 if (!qemu_wakeup_suspend_enabled()) { 161 error_setg(errp, 162 "wake-up from suspend is not supported by this guest"); 163 return; 164 } 165 166 qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 167 } 168 169 void qmp_add_client(const char *protocol, const char *fdname, 170 bool has_skipauth, bool skipauth, bool has_tls, bool tls, 171 Error **errp) 172 { 173 Chardev *s; 174 int fd; 175 176 fd = monitor_get_fd(monitor_cur(), fdname, errp); 177 if (fd < 0) { 178 return; 179 } 180 181 if (strcmp(protocol, "spice") == 0) { 182 if (!qemu_using_spice(errp)) { 183 close(fd); 184 return; 185 } 186 skipauth = has_skipauth ? skipauth : false; 187 tls = has_tls ? tls : false; 188 if (qemu_spice.display_add_client(fd, skipauth, tls) < 0) { 189 error_setg(errp, "spice failed to add client"); 190 close(fd); 191 } 192 #ifdef CONFIG_VNC 193 } else if (strcmp(protocol, "vnc") == 0) { 194 skipauth = has_skipauth ? skipauth : false; 195 vnc_display_add_client(NULL, fd, skipauth); 196 #endif 197 #ifdef CONFIG_DBUS_DISPLAY 198 } else if (strcmp(protocol, "@dbus-display") == 0) { 199 if (!qemu_using_dbus_display(errp)) { 200 close(fd); 201 return; 202 } 203 if (!qemu_dbus_display.add_client(fd, errp)) { 204 close(fd); 205 return; 206 } 207 #endif 208 } else { 209 s = qemu_chr_find(protocol); 210 if (!s) { 211 error_setg(errp, "protocol '%s' is invalid", protocol); 212 close(fd); 213 return; 214 } 215 if (qemu_chr_add_client(s, fd) < 0) { 216 error_setg(errp, "failed to add client"); 217 close(fd); 218 return; 219 } 220 } 221 } 222 223 MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 224 { 225 return qmp_memory_device_list(); 226 } 227 228 ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) 229 { 230 bool ambig; 231 ACPIOSTInfoList *head = NULL; 232 ACPIOSTInfoList **prev = &head; 233 Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig); 234 235 if (obj) { 236 AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); 237 AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj); 238 239 adevc->ospm_status(adev, &prev); 240 } else { 241 error_setg(errp, "command is not supported, missing ACPI device"); 242 } 243 244 return head; 245 } 246 247 MemoryInfo *qmp_query_memory_size_summary(Error **errp) 248 { 249 MemoryInfo *mem_info = g_new0(MemoryInfo, 1); 250 MachineState *ms = MACHINE(qdev_get_machine()); 251 252 mem_info->base_memory = ms->ram_size; 253 254 mem_info->plugged_memory = get_plugged_memory_size(); 255 mem_info->has_plugged_memory = 256 mem_info->plugged_memory != (uint64_t)-1; 257 258 return mem_info; 259 } 260 261 static int qmp_x_query_rdma_foreach(Object *obj, void *opaque) 262 { 263 RdmaProvider *rdma; 264 RdmaProviderClass *k; 265 GString *buf = opaque; 266 267 if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) { 268 rdma = RDMA_PROVIDER(obj); 269 k = RDMA_PROVIDER_GET_CLASS(obj); 270 if (k->format_statistics) { 271 k->format_statistics(rdma, buf); 272 } else { 273 g_string_append_printf(buf, 274 "RDMA statistics not available for %s.\n", 275 object_get_typename(obj)); 276 } 277 } 278 279 return 0; 280 } 281 282 HumanReadableText *qmp_x_query_rdma(Error **errp) 283 { 284 g_autoptr(GString) buf = g_string_new(""); 285 286 object_child_foreach_recursive(object_get_root(), 287 qmp_x_query_rdma_foreach, buf); 288 289 return human_readable_text_from_str(buf); 290 } 291 292 HumanReadableText *qmp_x_query_ramblock(Error **errp) 293 { 294 g_autoptr(GString) buf = ram_block_format(); 295 296 return human_readable_text_from_str(buf); 297 } 298 299 static int qmp_x_query_irq_foreach(Object *obj, void *opaque) 300 { 301 InterruptStatsProvider *intc; 302 InterruptStatsProviderClass *k; 303 GString *buf = opaque; 304 305 if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) { 306 intc = INTERRUPT_STATS_PROVIDER(obj); 307 k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj); 308 uint64_t *irq_counts; 309 unsigned int nb_irqs, i; 310 if (k->get_statistics && 311 k->get_statistics(intc, &irq_counts, &nb_irqs)) { 312 if (nb_irqs > 0) { 313 g_string_append_printf(buf, "IRQ statistics for %s:\n", 314 object_get_typename(obj)); 315 for (i = 0; i < nb_irqs; i++) { 316 if (irq_counts[i] > 0) { 317 g_string_append_printf(buf, "%2d: %" PRId64 "\n", i, 318 irq_counts[i]); 319 } 320 } 321 } 322 } else { 323 g_string_append_printf(buf, 324 "IRQ statistics not available for %s.\n", 325 object_get_typename(obj)); 326 } 327 } 328 329 return 0; 330 } 331 332 HumanReadableText *qmp_x_query_irq(Error **errp) 333 { 334 g_autoptr(GString) buf = g_string_new(""); 335 336 object_child_foreach_recursive(object_get_root(), 337 qmp_x_query_irq_foreach, buf); 338 339 return human_readable_text_from_str(buf); 340 } 341 342 typedef struct StatsCallbacks { 343 StatsProvider provider; 344 StatRetrieveFunc *stats_cb; 345 SchemaRetrieveFunc *schemas_cb; 346 QTAILQ_ENTRY(StatsCallbacks) next; 347 } StatsCallbacks; 348 349 static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks = 350 QTAILQ_HEAD_INITIALIZER(stats_callbacks); 351 352 void add_stats_callbacks(StatsProvider provider, 353 StatRetrieveFunc *stats_fn, 354 SchemaRetrieveFunc *schemas_fn) 355 { 356 StatsCallbacks *entry = g_new(StatsCallbacks, 1); 357 entry->provider = provider; 358 entry->stats_cb = stats_fn; 359 entry->schemas_cb = schemas_fn; 360 361 QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next); 362 } 363 364 static bool invoke_stats_cb(StatsCallbacks *entry, 365 StatsResultList **stats_results, 366 StatsFilter *filter, StatsRequest *request, 367 Error **errp) 368 { 369 ERRP_GUARD(); 370 strList *targets = NULL; 371 strList *names = NULL; 372 373 if (request) { 374 if (request->provider != entry->provider) { 375 return true; 376 } 377 if (request->has_names && !request->names) { 378 return true; 379 } 380 names = request->has_names ? request->names : NULL; 381 } 382 383 switch (filter->target) { 384 case STATS_TARGET_VM: 385 break; 386 case STATS_TARGET_VCPU: 387 if (filter->u.vcpu.has_vcpus) { 388 if (!filter->u.vcpu.vcpus) { 389 /* No targets allowed? Return no statistics. */ 390 return true; 391 } 392 targets = filter->u.vcpu.vcpus; 393 } 394 break; 395 default: 396 abort(); 397 } 398 399 entry->stats_cb(stats_results, filter->target, names, targets, errp); 400 if (*errp) { 401 qapi_free_StatsResultList(*stats_results); 402 *stats_results = NULL; 403 return false; 404 } 405 return true; 406 } 407 408 StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp) 409 { 410 StatsResultList *stats_results = NULL; 411 StatsCallbacks *entry; 412 StatsRequestList *request; 413 414 QTAILQ_FOREACH(entry, &stats_callbacks, next) { 415 if (filter->has_providers) { 416 for (request = filter->providers; request; request = request->next) { 417 if (!invoke_stats_cb(entry, &stats_results, filter, 418 request->value, errp)) { 419 break; 420 } 421 } 422 } else { 423 if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) { 424 break; 425 } 426 } 427 } 428 429 return stats_results; 430 } 431 432 StatsSchemaList *qmp_query_stats_schemas(bool has_provider, 433 StatsProvider provider, 434 Error **errp) 435 { 436 ERRP_GUARD(); 437 StatsSchemaList *stats_results = NULL; 438 StatsCallbacks *entry; 439 440 QTAILQ_FOREACH(entry, &stats_callbacks, next) { 441 if (!has_provider || provider == entry->provider) { 442 entry->schemas_cb(&stats_results, errp); 443 if (*errp) { 444 qapi_free_StatsSchemaList(stats_results); 445 return NULL; 446 } 447 } 448 } 449 450 return stats_results; 451 } 452 453 void add_stats_entry(StatsResultList **stats_results, StatsProvider provider, 454 const char *qom_path, StatsList *stats_list) 455 { 456 StatsResult *entry = g_new0(StatsResult, 1); 457 458 entry->provider = provider; 459 entry->qom_path = g_strdup(qom_path); 460 entry->stats = stats_list; 461 462 QAPI_LIST_PREPEND(*stats_results, entry); 463 } 464 465 void add_stats_schema(StatsSchemaList **schema_results, 466 StatsProvider provider, StatsTarget target, 467 StatsSchemaValueList *stats_list) 468 { 469 StatsSchema *entry = g_new0(StatsSchema, 1); 470 471 entry->provider = provider; 472 entry->target = target; 473 entry->stats = stats_list; 474 QAPI_LIST_PREPEND(*schema_results, entry); 475 } 476 477 bool apply_str_list_filter(const char *string, strList *list) 478 { 479 strList *str_list = NULL; 480 481 if (!list) { 482 return true; 483 } 484 for (str_list = list; str_list; str_list = str_list->next) { 485 if (g_str_equal(string, str_list->value)) { 486 return true; 487 } 488 } 489 return false; 490 } 491