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