summary refs log tree commit diff stats
path: root/monitor/qmp-cmds.c
diff options
context:
space:
mode:
Diffstat (limited to 'monitor/qmp-cmds.c')
-rw-r--r--monitor/qmp-cmds.c353
1 files changed, 37 insertions, 316 deletions
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index bf22a8c5a6..859012aef4 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -14,34 +14,23 @@
  */
 
 #include "qemu/osdep.h"
-#include "block/blockjob.h"
-#include "qemu/cutils.h"
-#include "qemu/option.h"
-#include "monitor/monitor.h"
+#include "monitor-internal.h"
+#include "monitor/qdev.h"
 #include "monitor/qmp-helpers.h"
 #include "sysemu/sysemu.h"
-#include "qemu/config-file.h"
-#include "qemu/uuid.h"
-#include "chardev/char.h"
 #include "sysemu/kvm.h"
 #include "sysemu/runstate.h"
 #include "sysemu/runstate-action.h"
-#include "sysemu/blockdev.h"
 #include "sysemu/block-backend.h"
 #include "qapi/error.h"
-#include "qapi/qapi-commands-acpi.h"
-#include "qapi/qapi-commands-block.h"
+#include "qapi/qapi-init-commands.h"
 #include "qapi/qapi-commands-control.h"
-#include "qapi/qapi-commands-machine.h"
 #include "qapi/qapi-commands-misc.h"
-#include "qapi/qapi-commands-stats.h"
+#include "qapi/qmp/qerror.h"
 #include "qapi/type-helpers.h"
-#include "exec/ramlist.h"
 #include "hw/mem/memory-device.h"
-#include "hw/acpi/acpi_dev_interface.h"
 #include "hw/intc/intc.h"
 #include "hw/rdma/rdma.h"
-#include "monitor/stats.h"
 
 NameInfo *qmp_query_name(Error **errp)
 {
@@ -51,24 +40,6 @@ NameInfo *qmp_query_name(Error **errp)
     return info;
 }
 
-KvmInfo *qmp_query_kvm(Error **errp)
-{
-    KvmInfo *info = g_malloc0(sizeof(*info));
-
-    info->enabled = kvm_enabled();
-    info->present = accel_find("kvm");
-
-    return info;
-}
-
-UuidInfo *qmp_query_uuid(Error **errp)
-{
-    UuidInfo *info = g_malloc0(sizeof(*info));
-
-    info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid);
-    return info;
-}
-
 void qmp_quit(Error **errp)
 {
     shutdown_action = SHUTDOWN_ACTION_POWEROFF;
@@ -91,16 +62,6 @@ void qmp_stop(Error **errp)
     }
 }
 
-void qmp_system_reset(Error **errp)
-{
-    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET);
-}
-
-void qmp_system_powerdown(Error **errp)
-{
-    qemu_system_powerdown_request();
-}
-
 void qmp_cont(Error **errp)
 {
     BlockBackend *blk;
@@ -154,17 +115,6 @@ void qmp_cont(Error **errp)
     }
 }
 
-void qmp_system_wakeup(Error **errp)
-{
-    if (!qemu_wakeup_suspend_enabled()) {
-        error_setg(errp,
-                   "wake-up from suspend is not supported by this guest");
-        return;
-    }
-
-    qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp);
-}
-
 void qmp_add_client(const char *protocol, const char *fdname,
                     bool has_skipauth, bool skipauth, bool has_tls, bool tls,
                     Error **errp)
@@ -182,7 +132,6 @@ void qmp_add_client(const char *protocol, const char *fdname,
         { "@dbus-display", qmp_add_client_dbus_display },
 #endif
     };
-    Chardev *s;
     int fd, i;
 
     fd = monitor_get_fd(monitor_cur(), fdname, errp);
@@ -200,284 +149,56 @@ void qmp_add_client(const char *protocol, const char *fdname,
         }
     }
 
-    s = qemu_chr_find(protocol);
-    if (!s) {
-        error_setg(errp, "protocol '%s' is invalid", protocol);
-        close(fd);
-        return;
-    }
-    if (qemu_chr_add_client(s, fd) < 0) {
-        error_setg(errp, "failed to add client");
+    if (!qmp_add_client_char(fd, has_skipauth, skipauth, has_tls, tls,
+                             protocol, errp)) {
         close(fd);
-        return;
-    }
-}
-
-MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp)
-{
-    return qmp_memory_device_list();
-}
-
-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;
-}
-
-MemoryInfo *qmp_query_memory_size_summary(Error **errp)
-{
-    MemoryInfo *mem_info = g_new0(MemoryInfo, 1);
-    MachineState *ms = MACHINE(qdev_get_machine());
-
-    mem_info->base_memory = ms->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;
-}
-
-static int qmp_x_query_rdma_foreach(Object *obj, void *opaque)
-{
-    RdmaProvider *rdma;
-    RdmaProviderClass *k;
-    GString *buf = opaque;
-
-    if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
-        rdma = RDMA_PROVIDER(obj);
-        k = RDMA_PROVIDER_GET_CLASS(obj);
-        if (k->format_statistics) {
-            k->format_statistics(rdma, buf);
-        } else {
-            g_string_append_printf(buf,
-                                   "RDMA statistics not available for %s.\n",
-                                   object_get_typename(obj));
-        }
-    }
-
-    return 0;
-}
-
-HumanReadableText *qmp_x_query_rdma(Error **errp)
-{
-    g_autoptr(GString) buf = g_string_new("");
-
-    object_child_foreach_recursive(object_get_root(),
-                                   qmp_x_query_rdma_foreach, buf);
-
-    return human_readable_text_from_str(buf);
-}
-
-HumanReadableText *qmp_x_query_ramblock(Error **errp)
-{
-    g_autoptr(GString) buf = ram_block_format();
-
-    return human_readable_text_from_str(buf);
-}
-
-static int qmp_x_query_irq_foreach(Object *obj, void *opaque)
-{
-    InterruptStatsProvider *intc;
-    InterruptStatsProviderClass *k;
-    GString *buf = opaque;
-
-    if (object_dynamic_cast(obj, TYPE_INTERRUPT_STATS_PROVIDER)) {
-        intc = INTERRUPT_STATS_PROVIDER(obj);
-        k = INTERRUPT_STATS_PROVIDER_GET_CLASS(obj);
-        uint64_t *irq_counts;
-        unsigned int nb_irqs, i;
-        if (k->get_statistics &&
-            k->get_statistics(intc, &irq_counts, &nb_irqs)) {
-            if (nb_irqs > 0) {
-                g_string_append_printf(buf, "IRQ statistics for %s:\n",
-                                       object_get_typename(obj));
-                for (i = 0; i < nb_irqs; i++) {
-                    if (irq_counts[i] > 0) {
-                        g_string_append_printf(buf, "%2d: %" PRId64 "\n", i,
-                                               irq_counts[i]);
-                    }
-                }
-            }
-        } else {
-            g_string_append_printf(buf,
-                                   "IRQ statistics not available for %s.\n",
-                                   object_get_typename(obj));
-        }
     }
-
-    return 0;
 }
 
-HumanReadableText *qmp_x_query_irq(Error **errp)
+char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
+                                int64_t cpu_index, Error **errp)
 {
-    g_autoptr(GString) buf = g_string_new("");
-
-    object_child_foreach_recursive(object_get_root(),
-                                   qmp_x_query_irq_foreach, buf);
-
-    return human_readable_text_from_str(buf);
-}
-
-typedef struct StatsCallbacks {
-    StatsProvider provider;
-    StatRetrieveFunc *stats_cb;
-    SchemaRetrieveFunc *schemas_cb;
-    QTAILQ_ENTRY(StatsCallbacks) next;
-} StatsCallbacks;
-
-static QTAILQ_HEAD(, StatsCallbacks) stats_callbacks =
-    QTAILQ_HEAD_INITIALIZER(stats_callbacks);
-
-void add_stats_callbacks(StatsProvider provider,
-                         StatRetrieveFunc *stats_fn,
-                         SchemaRetrieveFunc *schemas_fn)
-{
-    StatsCallbacks *entry = g_new(StatsCallbacks, 1);
-    entry->provider = provider;
-    entry->stats_cb = stats_fn;
-    entry->schemas_cb = schemas_fn;
-
-    QTAILQ_INSERT_TAIL(&stats_callbacks, entry, next);
-}
-
-static bool invoke_stats_cb(StatsCallbacks *entry,
-                            StatsResultList **stats_results,
-                            StatsFilter *filter, StatsRequest *request,
-                            Error **errp)
-{
-    ERRP_GUARD();
-    strList *targets = NULL;
-    strList *names = NULL;
-
-    if (request) {
-        if (request->provider != entry->provider) {
-            return true;
-        }
-        if (request->has_names && !request->names) {
-            return true;
-        }
-        names = request->has_names ? request->names : NULL;
-    }
-
-    switch (filter->target) {
-    case STATS_TARGET_VM:
-        break;
-    case STATS_TARGET_VCPU:
-        if (filter->u.vcpu.has_vcpus) {
-            if (!filter->u.vcpu.vcpus) {
-                /* No targets allowed?  Return no statistics.  */
-                return true;
-            }
-            targets = filter->u.vcpu.vcpus;
-        }
-        break;
-    default:
-        abort();
-    }
-
-    entry->stats_cb(stats_results, filter->target, names, targets, errp);
-    if (*errp) {
-        qapi_free_StatsResultList(*stats_results);
-        *stats_results = NULL;
-        return false;
-    }
-    return true;
-}
+    char *output = NULL;
+    MonitorHMP hmp = {};
 
-StatsResultList *qmp_query_stats(StatsFilter *filter, Error **errp)
-{
-    StatsResultList *stats_results = NULL;
-    StatsCallbacks *entry;
-    StatsRequestList *request;
+    monitor_data_init(&hmp.common, false, true, false);
 
-    QTAILQ_FOREACH(entry, &stats_callbacks, next) {
-        if (filter->has_providers) {
-            for (request = filter->providers; request; request = request->next) {
-                if (!invoke_stats_cb(entry, &stats_results, filter,
-                                     request->value, errp)) {
-                    break;
-                }
-            }
-        } else {
-            if (!invoke_stats_cb(entry, &stats_results, filter, NULL, errp)) {
-                break;
-            }
+    if (has_cpu_index) {
+        int ret = monitor_set_cpu(&hmp.common, cpu_index);
+        if (ret < 0) {
+            error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "cpu-index",
+                       "a CPU number");
+            goto out;
         }
     }
 
-    return stats_results;
-}
+    handle_hmp_command(&hmp, command_line);
 
-StatsSchemaList *qmp_query_stats_schemas(bool has_provider,
-                                         StatsProvider provider,
-                                         Error **errp)
-{
-    ERRP_GUARD();
-    StatsSchemaList *stats_results = NULL;
-    StatsCallbacks *entry;
-
-    QTAILQ_FOREACH(entry, &stats_callbacks, next) {
-        if (!has_provider || provider == entry->provider) {
-            entry->schemas_cb(&stats_results, errp);
-            if (*errp) {
-                qapi_free_StatsSchemaList(stats_results);
-                return NULL;
-            }
-        }
+    WITH_QEMU_LOCK_GUARD(&hmp.common.mon_lock) {
+        output = g_strdup(hmp.common.outbuf->str);
     }
 
-    return stats_results;
+out:
+    monitor_data_destroy(&hmp.common);
+    return output;
 }
 
-void add_stats_entry(StatsResultList **stats_results, StatsProvider provider,
-                     const char *qom_path, StatsList *stats_list)
+static void __attribute__((__constructor__)) monitor_init_qmp_commands(void)
 {
-    StatsResult *entry = g_new0(StatsResult, 1);
+    /*
+     * Two command lists:
+     * - qmp_commands contains all QMP commands
+     * - qmp_cap_negotiation_commands contains just
+     *   "qmp_capabilities", to enforce capability negotiation
+     */
 
-    entry->provider = provider;
-    entry->qom_path = g_strdup(qom_path);
-    entry->stats = stats_list;
+    qmp_init_marshal(&qmp_commands);
 
-    QAPI_LIST_PREPEND(*stats_results, entry);
-}
+    qmp_register_command(&qmp_commands, "device_add",
+                         qmp_device_add, 0, 0);
 
-void add_stats_schema(StatsSchemaList **schema_results,
-                      StatsProvider provider, StatsTarget target,
-                      StatsSchemaValueList *stats_list)
-{
-    StatsSchema *entry = g_new0(StatsSchema, 1);
-
-    entry->provider = provider;
-    entry->target = target;
-    entry->stats = stats_list;
-    QAPI_LIST_PREPEND(*schema_results, entry);
-}
-
-bool apply_str_list_filter(const char *string, strList *list)
-{
-    strList *str_list = NULL;
-
-    if (!list) {
-        return true;
-    }
-    for (str_list = list; str_list; str_list = str_list->next) {
-        if (g_str_equal(string, str_list->value)) {
-            return true;
-        }
-    }
-    return false;
+    QTAILQ_INIT(&qmp_cap_negotiation_commands);
+    qmp_register_command(&qmp_cap_negotiation_commands, "qmp_capabilities",
+                         qmp_marshal_qmp_capabilities,
+                         QCO_ALLOW_PRECONFIG, 0);
 }