qmp.c 19.5 KB
Newer Older
A
Anthony Liguori 已提交
1 2 3 4 5 6 7 8 9 10 11
/*
 * QEMU Management Protocol
 *
 * Copyright IBM, Corp. 2011
 *
 * Authors:
 *  Anthony Liguori   <aliguori@us.ibm.com>
 *
 * This work is licensed under the terms of the GNU GPL, version 2.  See
 * the COPYING file in the top-level directory.
 *
12 13
 * Contributions after 2012-01-13 are licensed under the terms of the
 * GNU GPL, version 2 or (at your option) any later version.
A
Anthony Liguori 已提交
14 15
 */

P
Peter Maydell 已提交
16
#include "qemu/osdep.h"
17
#include "qemu-version.h"
18
#include "qemu/cutils.h"
19
#include "monitor/monitor.h"
20
#include "sysemu/sysemu.h"
M
Marc-André Lureau 已提交
21
#include "qemu/config-file.h"
F
Fam Zheng 已提交
22
#include "qemu/uuid.h"
A
Anthony Liguori 已提交
23
#include "qmp-commands.h"
24
#include "chardev/char.h"
L
Luiz Capitulino 已提交
25 26
#include "ui/qemu-spice.h"
#include "ui/vnc.h"
27 28
#include "sysemu/kvm.h"
#include "sysemu/arch_init.h"
A
Anthony Liguori 已提交
29
#include "hw/qdev.h"
30
#include "sysemu/blockdev.h"
31
#include "sysemu/block-backend.h"
32
#include "qom/qom-qobject.h"
33
#include "qapi/error.h"
34
#include "qapi/qmp/qdict.h"
35
#include "qapi/qmp/qerror.h"
36
#include "qapi/qobject-input-visitor.h"
I
Igor Mammedov 已提交
37
#include "hw/boards.h"
38
#include "qom/object_interfaces.h"
39
#include "hw/mem/pc-dimm.h"
40
#include "hw/acpi/acpi_dev_interface.h"
A
Anthony Liguori 已提交
41 42 43 44 45 46 47 48 49 50 51 52

NameInfo *qmp_query_name(Error **errp)
{
    NameInfo *info = g_malloc0(sizeof(*info));

    if (qemu_name) {
        info->has_name = true;
        info->name = g_strdup(qemu_name);
    }

    return info;
}
L
Luiz Capitulino 已提交
53

54
VersionInfo *qmp_query_version(Error **errp)
L
Luiz Capitulino 已提交
55
{
56
    VersionInfo *info = g_new0(VersionInfo, 1);
L
Luiz Capitulino 已提交
57

58
    info->qemu = g_new0(VersionTriple, 1);
59 60 61
    info->qemu->major = QEMU_VERSION_MAJOR;
    info->qemu->minor = QEMU_VERSION_MINOR;
    info->qemu->micro = QEMU_VERSION_MICRO;
L
Luiz Capitulino 已提交
62 63 64 65
    info->package = g_strdup(QEMU_PKGVERSION);

    return info;
}
L
Luiz Capitulino 已提交
66 67 68 69 70 71 72 73 74 75 76

KvmInfo *qmp_query_kvm(Error **errp)
{
    KvmInfo *info = g_malloc0(sizeof(*info));

    info->enabled = kvm_enabled();
    info->present = kvm_available();

    return info;
}

L
Luiz Capitulino 已提交
77 78 79 80
UuidInfo *qmp_query_uuid(Error **errp)
{
    UuidInfo *info = g_malloc0(sizeof(*info));

F
Fam Zheng 已提交
81
    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
L
Luiz Capitulino 已提交
82 83 84
    return info;
}

85
void qmp_quit(Error **errp)
L
Luiz Capitulino 已提交
86 87
{
    no_shutdown = 0;
88
    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP);
L
Luiz Capitulino 已提交
89 90
}

L
Luiz Capitulino 已提交
91 92
void qmp_stop(Error **errp)
{
93 94 95 96 97 98 99
    /* if there is a dump in background, we should wait until the dump
     * finished */
    if (dump_in_progress()) {
        error_setg(errp, "There is a dump in process, please wait.");
        return;
    }

100 101 102 103 104
    if (runstate_check(RUN_STATE_INMIGRATE)) {
        autostart = 0;
    } else {
        vm_stop(RUN_STATE_PAUSED);
    }
L
Luiz Capitulino 已提交
105 106
}

L
Luiz Capitulino 已提交
107 108
void qmp_system_reset(Error **errp)
{
109
    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP);
L
Luiz Capitulino 已提交
110
}
L
Luiz Capitulino 已提交
111 112 113 114 115

void qmp_system_powerdown(Error **erp)
{
    qemu_system_powerdown_request();
}
L
Luiz Capitulino 已提交
116

I
Igor Mammedov 已提交
117 118
void qmp_cpu_add(int64_t id, Error **errp)
{
119 120 121
    MachineClass *mc;

    mc = MACHINE_GET_CLASS(current_machine);
122 123
    if (mc->hot_add_cpu) {
        mc->hot_add_cpu(id, errp);
I
Igor Mammedov 已提交
124 125 126 127 128
    } else {
        error_setg(errp, "Not supported");
    }
}

L
Luiz Capitulino 已提交
129 130 131 132 133
#ifndef CONFIG_VNC
/* If VNC support is enabled, the "true" query-vnc command is
   defined in the VNC subsystem */
VncInfo *qmp_query_vnc(Error **errp)
{
134
    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
L
Luiz Capitulino 已提交
135 136
    return NULL;
};
137 138 139

VncInfo2List *qmp_query_vnc_servers(Error **errp)
{
140
    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
141 142
    return NULL;
};
L
Luiz Capitulino 已提交
143
#endif
L
Luiz Capitulino 已提交
144 145

#ifndef CONFIG_SPICE
146 147 148 149 150
/*
 * qmp-commands.hx ensures that QMP command query-spice exists only
 * #ifdef CONFIG_SPICE.  Necessary for an accurate query-commands
 * result.  However, the QAPI schema is blissfully unaware of that,
 * and the QAPI code generator happily generates a dead
151 152 153
 * qmp_marshal_query_spice() that calls qmp_query_spice().  Provide it
 * one, or else linking fails.  FIXME Educate the QAPI schema on
 * CONFIG_SPICE.
154
 */
L
Luiz Capitulino 已提交
155 156
SpiceInfo *qmp_query_spice(Error **errp)
{
157
    abort();
L
Luiz Capitulino 已提交
158 159
};
#endif
L
Luiz Capitulino 已提交
160 161 162

void qmp_cont(Error **errp)
{
163
    BlockBackend *blk;
164
    Error *local_err = NULL;
L
Luiz Capitulino 已提交
165

166 167 168 169 170 171 172
    /* if there is a dump in background, we should wait until the dump
     * finished */
    if (dump_in_progress()) {
        error_setg(errp, "There is a dump in process, please wait.");
        return;
    }

173
    if (runstate_needs_reset()) {
174
        error_setg(errp, "Resetting the Virtual Machine is required");
L
Luiz Capitulino 已提交
175
        return;
176 177
    } else if (runstate_check(RUN_STATE_SUSPENDED)) {
        return;
L
Luiz Capitulino 已提交
178 179
    }

180 181
    for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
        blk_iostatus_reset(blk);
182
    }
K
Kevin Wolf 已提交
183

184
    /* Continuing after completed migration. Images have been inactivated to
185 186 187 188 189 190 191 192 193
     * allow the destination to take control. Need to get control back now.
     *
     * If there are no inactive block nodes (e.g. because the VM was just
     * paused rather than completing a migration), bdrv_inactivate_all() simply
     * doesn't do anything. */
    bdrv_invalidate_cache_all(&local_err);
    if (local_err) {
        error_propagate(errp, local_err);
        return;
194 195
    }

196 197 198 199 200
    if (runstate_check(RUN_STATE_INMIGRATE)) {
        autostart = 1;
    } else {
        vm_start();
    }
L
Luiz Capitulino 已提交
201
}
A
Anthony Liguori 已提交
202

203 204 205 206 207
void qmp_system_wakeup(Error **errp)
{
    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER);
}

208
ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp)
A
Anthony Liguori 已提交
209
{
210
    Object *obj;
A
Anthony Liguori 已提交
211
    bool ambiguous = false;
212 213
    ObjectPropertyInfoList *props = NULL;
    ObjectProperty *prop;
214
    ObjectPropertyIterator iter;
A
Anthony Liguori 已提交
215

216 217
    obj = object_resolve_path(path, &ambiguous);
    if (obj == NULL) {
218 219 220
        if (ambiguous) {
            error_setg(errp, "Path '%s' is ambiguous", path);
        } else {
221 222
            error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                      "Device '%s' not found", path);
223
        }
A
Anthony Liguori 已提交
224 225 226
        return NULL;
    }

227 228
    object_property_iter_init(&iter, obj);
    while ((prop = object_property_iter_next(&iter))) {
229
        ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry));
A
Anthony Liguori 已提交
230

231
        entry->value = g_malloc0(sizeof(ObjectPropertyInfo));
A
Anthony Liguori 已提交
232 233 234 235 236 237 238 239 240
        entry->next = props;
        props = entry;

        entry->value->name = g_strdup(prop->name);
        entry->value->type = g_strdup(prop->type);
    }

    return props;
}
241

242 243
void qmp_qom_set(const char *path, const char *property, QObject *value,
                 Error **errp)
244
{
245
    Object *obj;
246

247 248
    obj = object_resolve_path(path, NULL);
    if (!obj) {
249
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
250
                  "Device '%s' not found", path);
251
        return;
252 253
    }

254
    object_property_set_qobject(obj, value, property, errp);
255 256
}

257
QObject *qmp_qom_get(const char *path, const char *property, Error **errp)
258
{
259
    Object *obj;
260

261 262
    obj = object_resolve_path(path, NULL);
    if (!obj) {
263
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
264
                  "Device '%s' not found", path);
265
        return NULL;
266 267
    }

268
    return object_property_get_qobject(obj, property, errp);
269
}
L
Luiz Capitulino 已提交
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285

void qmp_set_password(const char *protocol, const char *password,
                      bool has_connected, const char *connected, Error **errp)
{
    int disconnect_if_connected = 0;
    int fail_if_connected = 0;
    int rc;

    if (has_connected) {
        if (strcmp(connected, "fail") == 0) {
            fail_if_connected = 1;
        } else if (strcmp(connected, "disconnect") == 0) {
            disconnect_if_connected = 1;
        } else if (strcmp(connected, "keep") == 0) {
            /* nothing */
        } else {
286
            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
L
Luiz Capitulino 已提交
287 288 289 290 291
            return;
        }
    }

    if (strcmp(protocol, "spice") == 0) {
292
        if (!qemu_using_spice(errp)) {
L
Luiz Capitulino 已提交
293 294 295 296 297
            return;
        }
        rc = qemu_spice_set_passwd(password, fail_if_connected,
                                   disconnect_if_connected);
        if (rc != 0) {
298
            error_setg(errp, QERR_SET_PASSWD_FAILED);
L
Luiz Capitulino 已提交
299 300 301 302 303 304 305
        }
        return;
    }

    if (strcmp(protocol, "vnc") == 0) {
        if (fail_if_connected || disconnect_if_connected) {
            /* vnc supports "connected=keep" only */
306
            error_setg(errp, QERR_INVALID_PARAMETER, "connected");
L
Luiz Capitulino 已提交
307 308 309 310 311 312
            return;
        }
        /* Note that setting an empty password will not disable login through
         * this interface. */
        rc = vnc_display_password(NULL, password);
        if (rc < 0) {
313
            error_setg(errp, QERR_SET_PASSWD_FAILED);
L
Luiz Capitulino 已提交
314 315 316 317
        }
        return;
    }

318
    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
L
Luiz Capitulino 已提交
319
}
L
Luiz Capitulino 已提交
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

void qmp_expire_password(const char *protocol, const char *whenstr,
                         Error **errp)
{
    time_t when;
    int rc;

    if (strcmp(whenstr, "now") == 0) {
        when = 0;
    } else if (strcmp(whenstr, "never") == 0) {
        when = TIME_MAX;
    } else if (whenstr[0] == '+') {
        when = time(NULL) + strtoull(whenstr+1, NULL, 10);
    } else {
        when = strtoull(whenstr, NULL, 10);
    }

    if (strcmp(protocol, "spice") == 0) {
338
        if (!qemu_using_spice(errp)) {
L
Luiz Capitulino 已提交
339 340 341 342
            return;
        }
        rc = qemu_spice_set_pw_expire(when);
        if (rc != 0) {
343
            error_setg(errp, QERR_SET_PASSWD_FAILED);
L
Luiz Capitulino 已提交
344 345 346 347 348 349 350
        }
        return;
    }

    if (strcmp(protocol, "vnc") == 0) {
        rc = vnc_display_pw_expire(NULL, when);
        if (rc != 0) {
351
            error_setg(errp, QERR_SET_PASSWD_FAILED);
L
Luiz Capitulino 已提交
352 353 354 355
        }
        return;
    }

356
    error_setg(errp, QERR_INVALID_PARAMETER, "protocol");
L
Luiz Capitulino 已提交
357
}
358

L
Luiz Capitulino 已提交
359
#ifdef CONFIG_VNC
360 361 362
void qmp_change_vnc_password(const char *password, Error **errp)
{
    if (vnc_display_password(NULL, password) < 0) {
363
        error_setg(errp, QERR_SET_PASSWD_FAILED);
364 365
    }
}
L
Luiz Capitulino 已提交
366

367
static void qmp_change_vnc_listen(const char *target, Error **errp)
L
Luiz Capitulino 已提交
368
{
369 370 371 372 373 374 375 376 377 378 379 380
    QemuOptsList *olist = qemu_find_opts("vnc");
    QemuOpts *opts;

    if (strstr(target, "id=")) {
        error_setg(errp, "id not supported");
        return;
    }

    opts = qemu_opts_find(olist, "default");
    if (opts) {
        qemu_opts_del(opts);
    }
381
    opts = vnc_parse(target, errp);
382 383 384 385
    if (!opts) {
        return;
    }

386
    vnc_display_open("default", errp);
L
Luiz Capitulino 已提交
387 388 389 390 391 392 393
}

static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
                           Error **errp)
{
    if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) {
        if (!has_arg) {
394
            error_setg(errp, QERR_MISSING_PARAMETER, "password");
L
Luiz Capitulino 已提交
395 396 397 398 399 400 401 402 403 404
        } else {
            qmp_change_vnc_password(arg, errp);
        }
    } else {
        qmp_change_vnc_listen(target, errp);
    }
}
#else
void qmp_change_vnc_password(const char *password, Error **errp)
{
405
    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
L
Luiz Capitulino 已提交
406 407 408 409
}
static void qmp_change_vnc(const char *target, bool has_arg, const char *arg,
                           Error **errp)
{
410
    error_setg(errp, QERR_FEATURE_DISABLED, "vnc");
L
Luiz Capitulino 已提交
411 412 413 414
}
#endif /* !CONFIG_VNC */

void qmp_change(const char *device, const char *target,
415
                bool has_arg, const char *arg, Error **errp)
L
Luiz Capitulino 已提交
416 417
{
    if (strcmp(device, "vnc") == 0) {
418
        qmp_change_vnc(target, has_arg, arg, errp);
L
Luiz Capitulino 已提交
419
    } else {
420 421
        qmp_blockdev_change_medium(true, device, false, NULL, target,
                                   has_arg, arg, false, 0, errp);
L
Luiz Capitulino 已提交
422 423
    }
}
424 425 426 427 428

static void qom_list_types_tramp(ObjectClass *klass, void *data)
{
    ObjectTypeInfoList *e, **pret = data;
    ObjectTypeInfo *info;
429
    ObjectClass *parent = object_class_get_parent(klass);
430 431 432

    info = g_malloc0(sizeof(*info));
    info->name = g_strdup(object_class_get_name(klass));
433
    info->has_abstract = info->abstract = object_class_is_abstract(klass);
434 435 436 437
    if (parent) {
        info->has_parent = true;
        info->parent = g_strdup(object_class_get_name(parent));
    }
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456

    e = g_malloc0(sizeof(*e));
    e->value = info;
    e->next = *pret;
    *pret = e;
}

ObjectTypeInfoList *qmp_qom_list_types(bool has_implements,
                                       const char *implements,
                                       bool has_abstract,
                                       bool abstract,
                                       Error **errp)
{
    ObjectTypeInfoList *ret = NULL;

    object_class_foreach(qom_list_types_tramp, implements, abstract, &ret);

    return ret;
}
457

458 459 460 461 462 463 464 465 466
/* Return a DevicePropertyInfo for a qdev property.
 *
 * If a qdev property with the given name does not exist, use the given default
 * type.  If the qdev property info should not be shown, return NULL.
 *
 * The caller must free the return value.
 */
static DevicePropertyInfo *make_device_property_info(ObjectClass *klass,
                                                     const char *name,
467 468
                                                     const char *default_type,
                                                     const char *description)
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484
{
    DevicePropertyInfo *info;
    Property *prop;

    do {
        for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) {
            if (strcmp(name, prop->name) != 0) {
                continue;
            }

            /*
             * TODO Properties without a parser are just for dirty hacks.
             * qdev_prop_ptr is the only such PropertyInfo.  It's marked
             * for removal.  This conditional should be removed along with
             * it.
             */
F
Fam Zheng 已提交
485
            if (!prop->info->set && !prop->info->create) {
486 487 488 489 490
                return NULL;           /* no way to set it, don't show */
            }

            info = g_malloc0(sizeof(*info));
            info->name = g_strdup(prop->name);
491 492
            info->type = default_type ? g_strdup(default_type)
                                      : g_strdup(prop->info->name);
493 494
            info->has_description = !!prop->info->description;
            info->description = g_strdup(prop->info->description);
495 496 497 498 499 500 501 502 503
            return info;
        }
        klass = object_class_get_parent(klass);
    } while (klass != object_class_by_name(TYPE_DEVICE));

    /* Not a qdev property, use the default type */
    info = g_malloc0(sizeof(*info));
    info->name = g_strdup(name);
    info->type = g_strdup(default_type);
504 505 506
    info->has_description = !!description;
    info->description = g_strdup(description);

507 508 509
    return info;
}

510 511 512 513
DevicePropertyInfoList *qmp_device_list_properties(const char *typename,
                                                   Error **errp)
{
    ObjectClass *klass;
514 515
    Object *obj;
    ObjectProperty *prop;
516
    ObjectPropertyIterator iter;
517 518 519 520
    DevicePropertyInfoList *prop_list = NULL;

    klass = object_class_by_name(typename);
    if (klass == NULL) {
521 522
        error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND,
                  "Device '%s' not found", typename);
523 524 525 526 527
        return NULL;
    }

    klass = object_class_dynamic_cast(klass, TYPE_DEVICE);
    if (klass == NULL) {
528
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE);
529 530 531
        return NULL;
    }

532
    if (object_class_is_abstract(klass)) {
533
        error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename",
534 535 536 537
                   "non-abstract device type");
        return NULL;
    }

538
    obj = object_new(typename);
539

540 541
    object_property_iter_init(&iter, obj);
    while ((prop = object_property_iter_next(&iter))) {
542 543 544 545 546 547 548
        DevicePropertyInfo *info;
        DevicePropertyInfoList *entry;

        /* Skip Object and DeviceState properties */
        if (strcmp(prop->name, "type") == 0 ||
            strcmp(prop->name, "realized") == 0 ||
            strcmp(prop->name, "hotpluggable") == 0 ||
549
            strcmp(prop->name, "hotplugged") == 0 ||
550 551 552
            strcmp(prop->name, "parent_bus") == 0) {
            continue;
        }
553

554 555 556 557 558 559
        /* Skip legacy properties since they are just string versions of
         * properties that we already list.
         */
        if (strstart(prop->name, "legacy-", NULL)) {
            continue;
        }
560

561 562
        info = make_device_property_info(klass, prop->name, prop->type,
                                         prop->description);
563 564
        if (!info) {
            continue;
565
        }
566 567 568 569 570 571 572 573

        entry = g_malloc0(sizeof(*entry));
        entry->value = info;
        entry->next = prop_list;
        prop_list = entry;
    }

    object_unref(obj);
574 575 576

    return prop_list;
}
577

578 579 580 581 582
CpuDefinitionInfoList *qmp_query_cpu_definitions(Error **errp)
{
    return arch_query_cpu_definitions(errp);
}

583 584 585 586 587 588 589
CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
                                                     CpuModelInfo *model,
                                                     Error **errp)
{
    return arch_query_cpu_model_expansion(type, model, errp);
}

590 591 592 593 594 595 596
CpuModelCompareInfo *qmp_query_cpu_model_comparison(CpuModelInfo *modela,
                                                    CpuModelInfo *modelb,
                                                    Error **errp)
{
    return arch_query_cpu_model_comparison(modela, modelb, errp);
}

597 598 599 600 601 602 603
CpuModelBaselineInfo *qmp_query_cpu_model_baseline(CpuModelInfo *modela,
                                                   CpuModelInfo *modelb,
                                                   Error **errp)
{
    return arch_query_cpu_model_baseline(modela, modelb, errp);
}

L
Luiz Capitulino 已提交
604 605 606 607
void qmp_add_client(const char *protocol, const char *fdname,
                    bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                    Error **errp)
{
608
    Chardev *s;
L
Luiz Capitulino 已提交
609 610 611 612 613 614 615 616
    int fd;

    fd = monitor_get_fd(cur_mon, fdname, errp);
    if (fd < 0) {
        return;
    }

    if (strcmp(protocol, "spice") == 0) {
617
        if (!qemu_using_spice(errp)) {
L
Luiz Capitulino 已提交
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645
            close(fd);
            return;
        }
        skipauth = has_skipauth ? skipauth : false;
        tls = has_tls ? tls : false;
        if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) {
            error_setg(errp, "spice failed to add client");
            close(fd);
        }
        return;
#ifdef CONFIG_VNC
    } else if (strcmp(protocol, "vnc") == 0) {
        skipauth = has_skipauth ? skipauth : false;
        vnc_display_add_client(NULL, fd, skipauth);
        return;
#endif
    } else if ((s = qemu_chr_find(protocol)) != NULL) {
        if (qemu_chr_add_client(s, fd) < 0) {
            error_setg(errp, "failed to add client");
            close(fd);
            return;
        }
        return;
    }

    error_setg(errp, "protocol '%s' is invalid", protocol);
    close(fd);
}
646

647

648 649
void qmp_object_add(const char *type, const char *id,
                    bool has_props, QObject *props, Error **errp)
650
{
651
    QDict *pdict;
652
    Visitor *v;
653
    Object *obj;
654 655 656 657

    if (props) {
        pdict = qobject_to_qdict(props);
        if (!pdict) {
658 659
            error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict");
            return;
660
        }
661 662 663
        QINCREF(pdict);
    } else {
        pdict = qdict_new();
664 665
    }

666
    v = qobject_input_visitor_new(QOBJECT(pdict));
667 668
    obj = user_creatable_add_type(type, id, pdict, v, errp);
    visit_free(v);
669 670 671
    if (obj) {
        object_unref(obj);
    }
672
    QDECREF(pdict);
673 674
}

675 676
void qmp_object_del(const char *id, Error **errp)
{
677
    user_creatable_del(id, errp);
678
}
679 680 681 682 683 684 685 686 687 688

MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
{
    MemoryDeviceInfoList *head = NULL;
    MemoryDeviceInfoList **prev = &head;

    qmp_pc_dimm_device_list(qdev_get_machine(), &prev);

    return head;
}
689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707

ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp)
{
    bool ambig;
    ACPIOSTInfoList *head = NULL;
    ACPIOSTInfoList **prev = &head;
    Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig);

    if (obj) {
        AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj);
        AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj);

        adevc->ospm_status(adev, &prev);
    } else {
        error_setg(errp, "command is not supported, missing ACPI device");
    }

    return head;
}
708 709 710 711 712 713 714 715 716 717 718 719 720

MemoryInfo *qmp_query_memory_size_summary(Error **errp)
{
    MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo));

    mem_info->base_memory = ram_size;

    mem_info->plugged_memory = get_plugged_memory_size();
    mem_info->has_plugged_memory =
        mem_info->plugged_memory != (uint64_t)-1;

    return mem_info;
}