summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cpus.c45
-rw-r--r--hmp.c39
-rw-r--r--hmp.h1
-rw-r--r--monitor.c101
-rw-r--r--qapi-schema.json46
-rw-r--r--qmp-commands.hx6
6 files changed, 138 insertions, 100 deletions
diff --git a/cpus.c b/cpus.c
index 79a76560cb..f768683ad6 100644
--- a/cpus.c
+++ b/cpus.c
@@ -30,6 +30,7 @@
#include "gdbstub.h"
#include "dma.h"
#include "kvm.h"
+#include "qmp-commands.h"
#include "qemu-thread.h"
#include "cpus.h"
@@ -1094,3 +1095,47 @@ void list_cpus(FILE *f, fprintf_function cpu_fprintf, const char *optarg)
cpu_list(f, cpu_fprintf); /* deprecated */
#endif
}
+
+CpuInfoList *qmp_query_cpus(Error **errp)
+{
+ CpuInfoList *head = NULL, *cur_item = NULL;
+ CPUState *env;
+
+ for(env = first_cpu; env != NULL; env = env->next_cpu) {
+ CpuInfoList *info;
+
+ cpu_synchronize_state(env);
+
+ info = g_malloc0(sizeof(*info));
+ info->value = g_malloc0(sizeof(*info->value));
+ info->value->CPU = env->cpu_index;
+ info->value->current = (env == first_cpu);
+ info->value->halted = env->halted;
+ info->value->thread_id = env->thread_id;
+#if defined(TARGET_I386)
+ info->value->has_pc = true;
+ info->value->pc = env->eip + env->segs[R_CS].base;
+#elif defined(TARGET_PPC)
+ info->value->has_nip = true;
+ info->value->nip = env->nip;
+#elif defined(TARGET_SPARC)
+ info->value->has_pc = true;
+ info->value->pc = env->pc;
+ info->value->has_npc = true;
+ info->value->npc = env->npc;
+#elif defined(TARGET_MIPS)
+ info->value->has_PC = true;
+ info->value->PC = env->active_tc.PC;
+#endif
+
+ /* XXX: waiting for the qapi to support GSList */
+ if (!cur_item) {
+ head = cur_item = info;
+ } else {
+ cur_item->next = info;
+ cur_item = info;
+ }
+ }
+
+ return head;
+}
diff --git a/hmp.c b/hmp.c
index 35b0ca0bea..172fe9cc4b 100644
--- a/hmp.c
+++ b/hmp.c
@@ -145,6 +145,45 @@ void hmp_info_migrate(Monitor *mon)
qapi_free_MigrationInfo(info);
}
+void hmp_info_cpus(Monitor *mon)
+{
+ CpuInfoList *cpu_list, *cpu;
+
+ cpu_list = qmp_query_cpus(NULL);
+
+ for (cpu = cpu_list; cpu; cpu = cpu->next) {
+ int active = ' ';
+
+ if (cpu->value->CPU == monitor_get_cpu_index()) {
+ active = '*';
+ }
+
+ monitor_printf(mon, "%c CPU #%" PRId64 ": ", active, cpu->value->CPU);
+
+ if (cpu->value->has_pc) {
+ monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc);
+ }
+ if (cpu->value->has_nip) {
+ monitor_printf(mon, "nip=0x%016" PRIx64, cpu->value->nip);
+ }
+ if (cpu->value->has_npc) {
+ monitor_printf(mon, "pc=0x%016" PRIx64, cpu->value->pc);
+ monitor_printf(mon, "npc=0x%016" PRIx64, cpu->value->npc);
+ }
+ if (cpu->value->has_PC) {
+ monitor_printf(mon, "PC=0x%016" PRIx64, cpu->value->PC);
+ }
+
+ if (cpu->value->halted) {
+ monitor_printf(mon, " (halted)");
+ }
+
+ monitor_printf(mon, " thread_id=%" PRId64 "\n", cpu->value->thread_id);
+ }
+
+ qapi_free_CpuInfoList(cpu_list);
+}
+
void hmp_quit(Monitor *mon, const QDict *qdict)
{
monitor_suspend(mon);
diff --git a/hmp.h b/hmp.h
index 9322b7f7f3..d9a83eb160 100644
--- a/hmp.h
+++ b/hmp.h
@@ -25,6 +25,7 @@ void hmp_info_uuid(Monitor *mon);
void hmp_info_chardev(Monitor *mon);
void hmp_info_mice(Monitor *mon);
void hmp_info_migrate(Monitor *mon);
+void hmp_info_cpus(Monitor *mon);
void hmp_quit(Monitor *mon, const QDict *qdict);
void hmp_stop(Monitor *mon, const QDict *qdict);
void hmp_system_reset(Monitor *mon, const QDict *qdict);
diff --git a/monitor.c b/monitor.c
index 1edb646b95..2f49c74793 100644
--- a/monitor.c
+++ b/monitor.c
@@ -812,96 +812,6 @@ static void do_info_registers(Monitor *mon)
#endif
}
-static void print_cpu_iter(QObject *obj, void *opaque)
-{
- QDict *cpu;
- int active = ' ';
- Monitor *mon = opaque;
-
- assert(qobject_type(obj) == QTYPE_QDICT);
- cpu = qobject_to_qdict(obj);
-
- if (qdict_get_bool(cpu, "current")) {
- active = '*';
- }
-
- monitor_printf(mon, "%c CPU #%d: ", active, (int)qdict_get_int(cpu, "CPU"));
-
-#if defined(TARGET_I386)
- monitor_printf(mon, "pc=0x" TARGET_FMT_lx,
- (target_ulong) qdict_get_int(cpu, "pc"));
-#elif defined(TARGET_PPC)
- monitor_printf(mon, "nip=0x" TARGET_FMT_lx,
- (target_long) qdict_get_int(cpu, "nip"));
-#elif defined(TARGET_SPARC)
- monitor_printf(mon, "pc=0x" TARGET_FMT_lx,
- (target_long) qdict_get_int(cpu, "pc"));
- monitor_printf(mon, "npc=0x" TARGET_FMT_lx,
- (target_long) qdict_get_int(cpu, "npc"));
-#elif defined(TARGET_MIPS)
- monitor_printf(mon, "PC=0x" TARGET_FMT_lx,
- (target_long) qdict_get_int(cpu, "PC"));
-#endif
-
- if (qdict_get_bool(cpu, "halted")) {
- monitor_printf(mon, " (halted)");
- }
-
- monitor_printf(mon, " thread_id=%" PRId64 " ",
- qdict_get_int(cpu, "thread_id"));
-
- monitor_printf(mon, "\n");
-}
-
-static void monitor_print_cpus(Monitor *mon, const QObject *data)
-{
- QList *cpu_list;
-
- assert(qobject_type(data) == QTYPE_QLIST);
- cpu_list = qobject_to_qlist(data);
- qlist_iter(cpu_list, print_cpu_iter, mon);
-}
-
-static void do_info_cpus(Monitor *mon, QObject **ret_data)
-{
- CPUState *env;
- QList *cpu_list;
-
- cpu_list = qlist_new();
-
- /* just to set the default cpu if not already done */
- mon_get_cpu();
-
- for(env = first_cpu; env != NULL; env = env->next_cpu) {
- QDict *cpu;
- QObject *obj;
-
- cpu_synchronize_state(env);
-
- obj = qobject_from_jsonf("{ 'CPU': %d, 'current': %i, 'halted': %i }",
- env->cpu_index, env == mon->mon_cpu,
- env->halted);
-
- cpu = qobject_to_qdict(obj);
-
-#if defined(TARGET_I386)
- qdict_put(cpu, "pc", qint_from_int(env->eip + env->segs[R_CS].base));
-#elif defined(TARGET_PPC)
- qdict_put(cpu, "nip", qint_from_int(env->nip));
-#elif defined(TARGET_SPARC)
- qdict_put(cpu, "pc", qint_from_int(env->pc));
- qdict_put(cpu, "npc", qint_from_int(env->npc));
-#elif defined(TARGET_MIPS)
- qdict_put(cpu, "PC", qint_from_int(env->active_tc.PC));
-#endif
- qdict_put(cpu, "thread_id", qint_from_int(env->thread_id));
-
- qlist_append(cpu_list, cpu);
- }
-
- *ret_data = QOBJECT(cpu_list);
-}
-
static void do_info_jit(Monitor *mon)
{
dump_exec_info((FILE *)mon, monitor_fprintf);
@@ -2787,8 +2697,7 @@ static const mon_cmd_t info_cmds[] = {
.args_type = "",
.params = "",
.help = "show infos for each CPU",
- .user_print = monitor_print_cpus,
- .mhandler.info_new = do_info_cpus,
+ .mhandler.info = hmp_info_cpus,
},
{
.name = "history",
@@ -3068,14 +2977,6 @@ static const mon_cmd_t qmp_query_cmds[] = {
.mhandler.info_new = bdrv_info_stats,
},
{
- .name = "cpus",
- .args_type = "",
- .params = "",
- .help = "show infos for each CPU",
- .user_print = monitor_print_cpus,
- .mhandler.info_new = do_info_cpus,
- },
- {
.name = "pci",
.args_type = "",
.params = "",
diff --git a/qapi-schema.json b/qapi-schema.json
index e4cf6da4fb..a1bf90deea 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -306,6 +306,52 @@
{ 'command': 'query-mice', 'returns': ['MouseInfo'] }
##
+# @CpuInfo:
+#
+# Information about a virtual CPU
+#
+# @CPU: the index of the virtual CPU
+#
+# @current: this only exists for backwards compatible and should be ignored
+#
+# @halted: true if the virtual CPU is in the halt state. Halt usually refers
+# to a processor specific low power mode.
+#
+# @pc: #optional If the target is i386 or x86_64, this is the 64-bit instruction
+# pointer.
+# If the target is Sparc, this is the PC component of the
+# instruction pointer.
+#
+# @nip: #optional If the target is PPC, the instruction pointer
+#
+# @npc: #optional If the target is Sparc, the NPC component of the instruction
+# pointer
+#
+# @PC: #optional If the target is MIPS, the instruction pointer
+#
+# @thread_id: ID of the underlying host thread
+#
+# Since: 0.14.0
+#
+# Notes: @halted is a transient state that changes frequently. By the time the
+# data is sent to the client, the guest may no longer be halted.
+##
+{ 'type': 'CpuInfo',
+ 'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int',
+ '*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} }
+
+##
+# @query-cpus:
+#
+# Returns a list of information about each virtual CPU.
+#
+# Returns: a list of @CpuInfo for each virtual CPU
+#
+# Since: 0.14.0
+##
+{ 'command': 'query-cpus', 'returns': ['CpuInfo'] }
+
+##
# @quit:
#
# This command will cause the QEMU process to exit gracefully. While every
diff --git a/qmp-commands.hx b/qmp-commands.hx
index dcca53cb5a..434ce6cba6 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1347,6 +1347,12 @@ Example:
EQMP
+ {
+ .name = "query-cpus",
+ .args_type = "",
+ .mhandler.cmd_new = qmp_marshal_input_query_cpus,
+ },
+
SQMP
query-pci
---------