diff options
-rw-r--r-- | cpus.c | 45 | ||||
-rw-r--r-- | hmp.c | 39 | ||||
-rw-r--r-- | hmp.h | 1 | ||||
-rw-r--r-- | monitor.c | 101 | ||||
-rw-r--r-- | qapi-schema.json | 46 | ||||
-rw-r--r-- | qmp-commands.hx | 6 |
6 files changed, 138 insertions, 100 deletions
@@ -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; +} @@ -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); @@ -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); @@ -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 e4cf6da..a1bf90d 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 dcca53c..434ce6c 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 --------- |