summaryrefslogtreecommitdiffstats
path: root/monitor
diff options
context:
space:
mode:
Diffstat (limited to 'monitor')
-rw-r--r--monitor/hmp-cmds.c101
-rw-r--r--monitor/hmp.c32
-rw-r--r--monitor/misc.c46
-rw-r--r--monitor/monitor-internal.h7
-rw-r--r--monitor/qmp-cmds.c116
5 files changed, 182 insertions, 120 deletions
diff --git a/monitor/hmp-cmds.c b/monitor/hmp-cmds.c
index bcaa41350e..9c91bf93e9 100644
--- a/monitor/hmp-cmds.c
+++ b/monitor/hmp-cmds.c
@@ -52,9 +52,7 @@
#include "ui/console.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
-#include "exec/ramlist.h"
#include "hw/intc/intc.h"
-#include "hw/rdma/rdma.h"
#include "migration/snapshot.h"
#include "migration/misc.h"
@@ -62,11 +60,13 @@
#include <spice/enums.h>
#endif
-void hmp_handle_error(Monitor *mon, Error *err)
+bool hmp_handle_error(Monitor *mon, Error *err)
{
if (err) {
error_reportf_err(err, "Error: ");
+ return true;
}
+ return false;
}
/*
@@ -577,8 +577,7 @@ void hmp_info_vnc(Monitor *mon, const QDict *qdict)
info2l = qmp_query_vnc_servers(&err);
info2l_head = info2l;
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
if (!info2l) {
@@ -693,8 +692,7 @@ void hmp_info_balloon(Monitor *mon, const QDict *qdict)
Error *err = NULL;
info = qmp_query_balloon(&err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -786,44 +784,6 @@ static void hmp_info_pci_device(Monitor *mon, const PciDeviceInfo *dev)
}
}
-static int hmp_info_irq_foreach(Object *obj, void *opaque)
-{
- InterruptStatsProvider *intc;
- InterruptStatsProviderClass *k;
- Monitor *mon = 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) {
- monitor_printf(mon, "IRQ statistics for %s:\n",
- object_get_typename(obj));
- for (i = 0; i < nb_irqs; i++) {
- if (irq_counts[i] > 0) {
- monitor_printf(mon, "%2d: %" PRId64 "\n", i,
- irq_counts[i]);
- }
- }
- }
- } else {
- monitor_printf(mon, "IRQ statistics not available for %s.\n",
- object_get_typename(obj));
- }
- }
-
- return 0;
-}
-
-void hmp_info_irq(Monitor *mon, const QDict *qdict)
-{
- object_child_foreach_recursive(object_get_root(),
- hmp_info_irq_foreach, mon);
-}
-
static int hmp_info_pic_foreach(Object *obj, void *opaque)
{
InterruptStatsProvider *intc;
@@ -850,32 +810,6 @@ void hmp_info_pic(Monitor *mon, const QDict *qdict)
hmp_info_pic_foreach, mon);
}
-static int hmp_info_rdma_foreach(Object *obj, void *opaque)
-{
- RdmaProvider *rdma;
- RdmaProviderClass *k;
- Monitor *mon = opaque;
-
- if (object_dynamic_cast(obj, INTERFACE_RDMA_PROVIDER)) {
- rdma = RDMA_PROVIDER(obj);
- k = RDMA_PROVIDER_GET_CLASS(obj);
- if (k->print_statistics) {
- k->print_statistics(mon, rdma);
- } else {
- monitor_printf(mon, "RDMA statistics not available for %s.\n",
- object_get_typename(obj));
- }
- }
-
- return 0;
-}
-
-void hmp_info_rdma(Monitor *mon, const QDict *qdict)
-{
- object_child_foreach_recursive(object_get_root(),
- hmp_info_rdma_foreach, mon);
-}
-
void hmp_info_pci(Monitor *mon, const QDict *qdict)
{
PciInfoList *info_list, *info;
@@ -1065,8 +999,7 @@ void hmp_ringbuf_read(Monitor *mon, const QDict *qdict)
int i;
data = qmp_ringbuf_read(chardev, size, false, 0, &err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1582,8 +1515,7 @@ void hmp_migrate(Monitor *mon, const QDict *qdict)
qmp_migrate(uri, !!blk, blk, !!inc, inc,
false, false, true, resume, &err);
- if (err) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1917,8 +1849,7 @@ void hmp_rocker(Monitor *mon, const QDict *qdict)
Error *err = NULL;
rocker = qmp_query_rocker(name, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1936,8 +1867,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_ports(name, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -1945,7 +1875,7 @@ void hmp_rocker_ports(Monitor *mon, const QDict *qdict)
monitor_printf(mon, " port link duplex neg?\n");
for (port = list; port; port = port->next) {
- monitor_printf(mon, "%10s %-4s %-3s %2s %-3s\n",
+ monitor_printf(mon, "%10s %-4s %-3s %2s %s\n",
port->value->name,
port->value->enabled ? port->value->link_up ?
"up" : "down" : "!ena",
@@ -1965,8 +1895,7 @@ void hmp_rocker_of_dpa_flows(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_of_dpa_flows(name, tbl_id != -1, tbl_id, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -2115,8 +2044,7 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
Error *err = NULL;
list = qmp_query_rocker_of_dpa_groups(name, type != 9, type, &err);
- if (err != NULL) {
- hmp_handle_error(mon, err);
+ if (hmp_handle_error(mon, err)) {
return;
}
@@ -2209,11 +2137,6 @@ void hmp_rocker_of_dpa_groups(Monitor *mon, const QDict *qdict)
qapi_free_RockerOfDpaGroupList(list);
}
-void hmp_info_ramblock(Monitor *mon, const QDict *qdict)
-{
- ram_block_dump(mon);
-}
-
void hmp_info_vm_generation_id(Monitor *mon, const QDict *qdict)
{
Error *err = NULL;
diff --git a/monitor/hmp.c b/monitor/hmp.c
index d50c3124e1..b20737e63c 100644
--- a/monitor/hmp.c
+++ b/monitor/hmp.c
@@ -26,6 +26,7 @@
#include <dirent.h>
#include "hw/qdev-core.h"
#include "monitor-internal.h"
+#include "monitor/hmp.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qmp/qnum.h"
@@ -1061,6 +1062,31 @@ fail:
return NULL;
}
+static void hmp_info_human_readable_text(Monitor *mon,
+ HumanReadableText *(*handler)(Error **))
+{
+ Error *err = NULL;
+ g_autoptr(HumanReadableText) info = handler(&err);
+
+ if (hmp_handle_error(mon, err)) {
+ return;
+ }
+
+ monitor_printf(mon, "%s", info->human_readable_text);
+}
+
+static void handle_hmp_command_exec(Monitor *mon,
+ const HMPCommand *cmd,
+ QDict *qdict)
+{
+ if (cmd->cmd_info_hrt) {
+ hmp_info_human_readable_text(mon,
+ cmd->cmd_info_hrt);
+ } else {
+ cmd->cmd(mon, qdict);
+ }
+}
+
typedef struct HandleHmpCommandCo {
Monitor *mon;
const HMPCommand *cmd;
@@ -1071,7 +1097,7 @@ typedef struct HandleHmpCommandCo {
static void handle_hmp_command_co(void *opaque)
{
HandleHmpCommandCo *data = opaque;
- data->cmd->cmd(data->mon, data->qdict);
+ handle_hmp_command_exec(data->mon, data->cmd, data->qdict);
monitor_set_cur(qemu_coroutine_self(), NULL);
data->done = true;
}
@@ -1089,7 +1115,7 @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
return;
}
- if (!cmd->cmd) {
+ if (!cmd->cmd && !cmd->cmd_info_hrt) {
/* FIXME: is it useful to try autoload modules here ??? */
monitor_printf(&mon->common, "Command \"%.*s\" is not available.\n",
(int)(cmdline - cmd_start), cmd_start);
@@ -1109,7 +1135,7 @@ void handle_hmp_command(MonitorHMP *mon, const char *cmdline)
if (!cmd->coroutine) {
/* old_mon is non-NULL when called from qmp_human_monitor_command() */
Monitor *old_mon = monitor_set_cur(qemu_coroutine_self(), &mon->common);
- cmd->cmd(&mon->common, qdict);
+ handle_hmp_command_exec(&mon->common, cmd, qdict);
monitor_set_cur(qemu_coroutine_self(), old_mon);
} else {
HandleHmpCommandCo data = {
diff --git a/monitor/misc.c b/monitor/misc.c
index 1759d1e7f1..a3a6e47844 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -72,6 +72,7 @@
#include "qapi/qapi-commands-qom.h"
#include "qapi/qapi-commands-run-state.h"
#include "qapi/qapi-commands-trace.h"
+#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-init-commands.h"
#include "qapi/error.h"
#include "qapi/qmp-event.h"
@@ -939,33 +940,6 @@ static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
mtree_info(flatview, dispatch_tree, owner, disabled);
}
-#ifdef CONFIG_PROFILER
-
-int64_t dev_time;
-
-static void hmp_info_profile(Monitor *mon, const QDict *qdict)
-{
- static int64_t last_cpu_exec_time;
- int64_t cpu_exec_time;
- int64_t delta;
-
- cpu_exec_time = tcg_cpu_exec_time();
- delta = cpu_exec_time - last_cpu_exec_time;
-
- monitor_printf(mon, "async time %" PRId64 " (%0.3f)\n",
- dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
- monitor_printf(mon, "qemu time %" PRId64 " (%0.3f)\n",
- delta, delta / (double)NANOSECONDS_PER_SECOND);
- last_cpu_exec_time = cpu_exec_time;
- dev_time = 0;
-}
-#else
-static void hmp_info_profile(Monitor *mon, const QDict *qdict)
-{
- monitor_printf(mon, "Internal profiler not compiled\n");
-}
-#endif
-
/* Capture support */
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
@@ -1973,7 +1947,7 @@ void monitor_register_hmp(const char *name, bool info,
while (table->name != NULL) {
if (strcmp(table->name, name) == 0) {
- g_assert(table->cmd == NULL);
+ g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
table->cmd = cmd;
return;
}
@@ -1982,6 +1956,22 @@ void monitor_register_hmp(const char *name, bool info,
g_assert_not_reached();
}
+void monitor_register_hmp_info_hrt(const char *name,
+ HumanReadableText *(*handler)(Error **errp))
+{
+ HMPCommand *table = hmp_info_cmds;
+
+ while (table->name != NULL) {
+ if (strcmp(table->name, name) == 0) {
+ g_assert(table->cmd == NULL && table->cmd_info_hrt == NULL);
+ table->cmd_info_hrt = handler;
+ return;
+ }
+ table++;
+ }
+ g_assert_not_reached();
+}
+
void monitor_init_globals(void)
{
monitor_init_globals_core();
diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h
index 9c3a09cb01..3da3f86c6a 100644
--- a/monitor/monitor-internal.h
+++ b/monitor/monitor-internal.h
@@ -74,6 +74,13 @@ typedef struct HMPCommand {
const char *help;
const char *flags; /* p=preconfig */
void (*cmd)(Monitor *mon, const QDict *qdict);
+ /*
+ * If implementing a command that takes no arguments and simply
+ * prints formatted data, then leave @cmd NULL, and then set
+ * @cmd_info_hrt to the corresponding QMP handler that returns
+ * the formatted text.
+ */
+ HumanReadableText *(*cmd_info_hrt)(Error **errp);
bool coroutine;
/*
* @sub_table is a list of 2nd level of commands. If it does not exist,
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 5c0d5e116b..343353e27a 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -36,9 +36,13 @@
#include "qapi/qapi-commands-machine.h"
#include "qapi/qapi-commands-misc.h"
#include "qapi/qapi-commands-ui.h"
+#include "qapi/type-helpers.h"
#include "qapi/qmp/qerror.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"
NameInfo *qmp_query_name(Error **errp)
{
@@ -350,3 +354,115 @@ void qmp_display_reload(DisplayReloadOptions *arg, Error **errp)
abort();
}
}
+
+#ifdef CONFIG_PROFILER
+
+int64_t dev_time;
+
+HumanReadableText *qmp_x_query_profile(Error **errp)
+{
+ g_autoptr(GString) buf = g_string_new("");
+ static int64_t last_cpu_exec_time;
+ int64_t cpu_exec_time;
+ int64_t delta;
+
+ cpu_exec_time = tcg_cpu_exec_time();
+ delta = cpu_exec_time - last_cpu_exec_time;
+
+ g_string_append_printf(buf, "async time %" PRId64 " (%0.3f)\n",
+ dev_time, dev_time / (double)NANOSECONDS_PER_SECOND);
+ g_string_append_printf(buf, "qemu time %" PRId64 " (%0.3f)\n",
+ delta, delta / (double)NANOSECONDS_PER_SECOND);
+ last_cpu_exec_time = cpu_exec_time;
+ dev_time = 0;
+
+ return human_readable_text_from_str(buf);
+}
+#else
+HumanReadableText *qmp_x_query_profile(Error **errp)
+{
+ error_setg(errp, "Internal profiler not compiled");
+ return NULL;
+}
+#endif
+
+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)
+{
+ 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);
+}