*/
#include <dirent.h>
#include "hw/hw.h"
-#include "hw/qdev.h"
+#include "monitor/qdev.h"
#include "hw/usb.h"
#include "hw/pcmcia.h"
-#include "hw/pc.h"
+#include "hw/i386/pc.h"
#include "hw/pci/pci.h"
-#include "hw/watchdog.h"
+#include "sysemu/watchdog.h"
#include "hw/loader.h"
#include "exec/gdbstub.h"
#include "net/net.h"
#include "net/slirp.h"
-#include "qemu-char.h"
+#include "sysemu/char.h"
#include "ui/qemu-spice.h"
-#include "sysemu.h"
+#include "sysemu/sysemu.h"
#include "monitor/monitor.h"
#include "monitor/readline.h"
#include "ui/console.h"
-#include "blockdev.h"
+#include "sysemu/blockdev.h"
#include "audio/audio.h"
#include "disas/disas.h"
-#include "balloon.h"
-#include "qemu-timer.h"
+#include "sysemu/balloon.h"
+#include "qemu/timer.h"
#include "migration/migration.h"
-#include "kvm.h"
-#include "acl.h"
+#include "sysemu/kvm.h"
+#include "qemu/acl.h"
+#include "sysemu/tpm.h"
#include "qapi/qmp/qint.h"
#include "qapi/qmp/qfloat.h"
#include "qapi/qmp/qlist.h"
#include "qapi/qmp/qjson.h"
#include "qapi/qmp/json-streamer.h"
#include "qapi/qmp/json-parser.h"
-#include "osdep.h"
+#include "qemu/osdep.h"
#include "cpu.h"
#include "trace.h"
#include "trace/control.h"
#ifdef CONFIG_TRACE_SIMPLE
#include "trace/simple.h"
#endif
-#include "ui/qemu-spice.h"
#include "exec/memory.h"
#include "qmp-commands.h"
#include "hmp.h"
-#include "qemu-thread.h"
+#include "qemu/thread.h"
/* for pic/irq_info */
#if defined(TARGET_SPARC)
-#include "hw/sun4m.h"
+#include "hw/sparc/sun4m.h"
#endif
-#include "hw/lm32_pic.h"
+#include "hw/lm32/lm32_pic.h"
//#define DEBUG
//#define DEBUG_COMPLETION
* 'F' filename
* 'B' block device name
* 's' string (accept optional quote)
+ * 'S' it just appends the rest of the string (accept optional quote)
* 'O' option string of the form NAME=VALUE,...
* parsed according to QemuOptsList given by its name
* Example: 'device:O' uses qemu_device_opts.
* 'M' Non-negative target long (32 or 64 bit), in user mode the
* value is multiplied by 2^20 (think Mebibyte)
* 'o' octets (aka bytes)
- * user mode accepts an optional T, t, G, g, M, m, K, k
- * suffix, which multiplies the value by 2^40 for
- * suffixes T and t, 2^30 for suffixes G and g, 2^20 for
- * M and m, 2^10 for K and k
+ * user mode accepts an optional E, e, P, p, T, t, G, g, M, m,
+ * K, k suffix, which multiplies the value by 2^60 for suffixes E
+ * and e, 2^50 for suffixes P and p, 2^40 for suffixes T and t,
+ * 2^30 for suffixes G and g, 2^20 for M and m, 2^10 for K and k
* 'T' double
* user mode accepts an optional ms, us, ns suffix,
* which divides the value by 1e3, 1e6, 1e9, respectively
const char *help;
void (*user_print)(Monitor *mon, const QObject *data);
union {
- void (*info)(Monitor *mon);
void (*cmd)(Monitor *mon, const QDict *qdict);
int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data);
int (*cmd_async)(Monitor *mon, const QDict *params,
MonitorCompletion *cb, void *opaque);
} mhandler;
int flags;
+ /* @sub_table is a list of 2nd level of commands. If it do not exist,
+ * mhandler should be used. If it exist, sub_table[?].mhandler should be
+ * used, and mhandler of 1st level plays the role of help function.
+ */
+ struct mon_cmd_t *sub_table;
} mon_cmd_t;
/* file descriptors passed via SCM_RIGHTS */
int reset_seen;
int flags;
int suspend_cnt;
- uint8_t outbuf[1024];
- int outbuf_index;
+ bool skip_flush;
+ QString *outbuf;
+ guint watch;
ReadLineState *rs;
MonitorControl *mc;
- CPUArchState *mon_cpu;
+ CPUState *mon_cpu;
BlockDriverCompletionFunc *password_completion_cb;
void *password_opaque;
+ mon_cmd_t *cmd_table;
QError *error;
QLIST_HEAD(,mon_fd_t) fds;
QLIST_ENTRY(Monitor) entry;
}
}
+static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
+ void *opaque)
+{
+ Monitor *mon = opaque;
+
+ mon->watch = 0;
+ monitor_flush(mon);
+ return FALSE;
+}
+
void monitor_flush(Monitor *mon)
{
- if (mon && mon->outbuf_index != 0 && !mon->mux_out) {
- qemu_chr_fe_write(mon->chr, mon->outbuf, mon->outbuf_index);
- mon->outbuf_index = 0;
+ int rc;
+ size_t len;
+ const char *buf;
+
+ if (mon->skip_flush) {
+ return;
+ }
+
+ buf = qstring_get_str(mon->outbuf);
+ len = qstring_get_length(mon->outbuf);
+
+ if (len && !mon->mux_out) {
+ rc = qemu_chr_fe_write(mon->chr, (const uint8_t *) buf, len);
+ if (rc == len) {
+ /* all flushed */
+ QDECREF(mon->outbuf);
+ mon->outbuf = qstring_new();
+ return;
+ }
+ if (rc > 0) {
+ /* partinal write */
+ QString *tmp = qstring_from_str(buf + rc);
+ QDECREF(mon->outbuf);
+ mon->outbuf = tmp;
+ }
+ if (mon->watch == 0) {
+ mon->watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT,
+ monitor_unblocked, mon);
+ }
}
}
-/* flush at every end of line or if the buffer is full */
+/* flush at every end of line */
static void monitor_puts(Monitor *mon, const char *str)
{
char c;
c = *str++;
if (c == '\0')
break;
- if (c == '\n')
- mon->outbuf[mon->outbuf_index++] = '\r';
- mon->outbuf[mon->outbuf_index++] = c;
- if (mon->outbuf_index >= (sizeof(mon->outbuf) - 1)
- || c == '\n')
+ if (c == '\n') {
+ qstring_append_chr(mon->outbuf, '\r');
+ }
+ qstring_append_chr(mon->outbuf, c);
+ if (c == '\n') {
monitor_flush(mon);
+ }
}
}
void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
{
- char buf[4096];
+ char *buf;
if (!mon)
return;
return;
}
- vsnprintf(buf, sizeof(buf), fmt, ap);
+ buf = g_strdup_vprintf(fmt, ap);
monitor_puts(mon, buf);
+ g_free(buf);
}
void monitor_printf(Monitor *mon, const char *fmt, ...)
[QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
[QEVENT_BLOCK_JOB_ERROR] = "BLOCK_JOB_ERROR",
[QEVENT_BLOCK_JOB_READY] = "BLOCK_JOB_READY",
+ [QEVENT_DEVICE_DELETED] = "DEVICE_DELETED",
[QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
+ [QEVENT_NIC_RX_FILTER_CHANGED] = "NIC_RX_FILTER_CHANGED",
[QEVENT_SUSPEND] = "SUSPEND",
[QEVENT_SUSPEND_DISK] = "SUSPEND_DISK",
[QEVENT_WAKEUP] = "WAKEUP",
[QEVENT_BALLOON_CHANGE] = "BALLOON_CHANGE",
[QEVENT_SPICE_MIGRATE_COMPLETED] = "SPICE_MIGRATE_COMPLETED",
+ [QEVENT_GUEST_PANICKED] = "GUEST_PANICKED",
+ [QEVENT_BLOCK_IMAGE_CORRUPTED] = "BLOCK_IMAGE_CORRUPTED",
};
QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
QObject *data)
{
MonitorEventState *evstate;
- int64_t now = qemu_get_clock_ns(rt_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
assert(event < QEVENT_MAX);
qemu_mutex_lock(&monitor_event_state_lock);
qobject_decref(evstate->data);
} else {
int64_t then = evstate->last + evstate->rate;
- qemu_mod_timer_ns(evstate->timer, then);
+ timer_mod_ns(evstate->timer, then);
}
evstate->data = data;
qobject_incref(evstate->data);
static void monitor_protocol_event_handler(void *opaque)
{
MonitorEventState *evstate = opaque;
- int64_t now = qemu_get_clock_ns(rt_clock);
+ int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
qemu_mutex_lock(&monitor_event_state_lock);
trace_monitor_protocol_event_throttle(event, rate);
evstate->event = event;
evstate->rate = rate * SCALE_MS;
- evstate->timer = qemu_new_timer(rt_clock,
+ evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
SCALE_MS,
monitor_protocol_event_handler,
evstate);
static void handle_user_command(Monitor *mon, const char *cmdline);
+static void monitor_data_init(Monitor *mon)
+{
+ memset(mon, 0, sizeof(Monitor));
+ mon->outbuf = qstring_new();
+ /* Use *mon_cmds by default. */
+ mon->cmd_table = mon_cmds;
+}
+
+static void monitor_data_destroy(Monitor *mon)
+{
+ QDECREF(mon->outbuf);
+}
+
char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
int64_t cpu_index, Error **errp)
{
char *output = NULL;
Monitor *old_mon, hmp;
- CharDriverState mchar;
- memset(&hmp, 0, sizeof(hmp));
- qemu_chr_init_mem(&mchar);
- hmp.chr = &mchar;
+ monitor_data_init(&hmp);
+ hmp.skip_flush = true;
old_mon = cur_mon;
cur_mon = &hmp;
handle_user_command(&hmp, command_line);
cur_mon = old_mon;
- if (qemu_chr_mem_osize(hmp.chr) > 0) {
- QString *str = qemu_chr_mem_to_qs(hmp.chr);
- output = g_strdup(qstring_get_str(str));
- QDECREF(str);
+ if (qstring_get_length(hmp.outbuf) > 0) {
+ output = g_strdup(qstring_get_str(hmp.outbuf));
} else {
output = g_strdup("");
}
out:
- qemu_chr_close_mem(hmp.chr);
+ monitor_data_destroy(&hmp);
return output;
}
return 0;
}
+static int get_str(char *buf, int buf_size, const char **pp)
+{
+ const char *p;
+ char *q;
+ int c;
+
+ q = buf;
+ p = *pp;
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (*p == '\0') {
+ fail:
+ *q = '\0';
+ *pp = p;
+ return -1;
+ }
+ if (*p == '\"') {
+ p++;
+ while (*p != '\0' && *p != '\"') {
+ if (*p == '\\') {
+ p++;
+ c = *p++;
+ switch (c) {
+ case 'n':
+ c = '\n';
+ break;
+ case 'r':
+ c = '\r';
+ break;
+ case '\\':
+ case '\'':
+ case '\"':
+ break;
+ default:
+ qemu_printf("unsupported escape code: '\\%c'\n", c);
+ goto fail;
+ }
+ if ((q - buf) < buf_size - 1) {
+ *q++ = c;
+ }
+ } else {
+ if ((q - buf) < buf_size - 1) {
+ *q++ = *p;
+ }
+ p++;
+ }
+ }
+ if (*p != '\"') {
+ qemu_printf("unterminated string\n");
+ goto fail;
+ }
+ p++;
+ } else {
+ while (*p != '\0' && !qemu_isspace(*p)) {
+ if ((q - buf) < buf_size - 1) {
+ *q++ = *p;
+ }
+ p++;
+ }
+ }
+ *q = '\0';
+ *pp = p;
+ return 0;
+}
+
+#define MAX_ARGS 16
+
+static void free_cmdline_args(char **args, int nb_args)
+{
+ int i;
+
+ assert(nb_args <= MAX_ARGS);
+
+ for (i = 0; i < nb_args; i++) {
+ g_free(args[i]);
+ }
+
+}
+
+/*
+ * Parse the command line to get valid args.
+ * @cmdline: command line to be parsed.
+ * @pnb_args: location to store the number of args, must NOT be NULL.
+ * @args: location to store the args, which should be freed by caller, must
+ * NOT be NULL.
+ *
+ * Returns 0 on success, negative on failure.
+ *
+ * NOTE: this parser is an approximate form of the real command parser. Number
+ * of args have a limit of MAX_ARGS. If cmdline contains more, it will
+ * return with failure.
+ */
+static int parse_cmdline(const char *cmdline,
+ int *pnb_args, char **args)
+{
+ const char *p;
+ int nb_args, ret;
+ char buf[1024];
+
+ p = cmdline;
+ nb_args = 0;
+ for (;;) {
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (*p == '\0') {
+ break;
+ }
+ if (nb_args >= MAX_ARGS) {
+ goto fail;
+ }
+ ret = get_str(buf, sizeof(buf), &p);
+ if (ret < 0) {
+ goto fail;
+ }
+ args[nb_args] = g_strdup(buf);
+ nb_args++;
+ }
+ *pnb_args = nb_args;
+ return 0;
+
+ fail:
+ free_cmdline_args(args, nb_args);
+ return -1;
+}
+
+static void help_cmd_dump_one(Monitor *mon,
+ const mon_cmd_t *cmd,
+ char **prefix_args,
+ int prefix_args_nb)
+{
+ int i;
+
+ for (i = 0; i < prefix_args_nb; i++) {
+ monitor_printf(mon, "%s ", prefix_args[i]);
+ }
+ monitor_printf(mon, "%s %s -- %s\n", cmd->name, cmd->params, cmd->help);
+}
+
+/* @args[@arg_index] is the valid command need to find in @cmds */
static void help_cmd_dump(Monitor *mon, const mon_cmd_t *cmds,
- const char *prefix, const char *name)
+ char **args, int nb_args, int arg_index)
{
const mon_cmd_t *cmd;
- for(cmd = cmds; cmd->name != NULL; cmd++) {
- if (!name || !strcmp(name, cmd->name))
- monitor_printf(mon, "%s%s %s -- %s\n", prefix, cmd->name,
- cmd->params, cmd->help);
+ /* No valid arg need to compare with, dump all in *cmds */
+ if (arg_index >= nb_args) {
+ for (cmd = cmds; cmd->name != NULL; cmd++) {
+ help_cmd_dump_one(mon, cmd, args, arg_index);
+ }
+ return;
+ }
+
+ /* Find one entry to dump */
+ for (cmd = cmds; cmd->name != NULL; cmd++) {
+ if (compare_cmd(args[arg_index], cmd->name)) {
+ if (cmd->sub_table) {
+ /* continue with next arg */
+ help_cmd_dump(mon, cmd->sub_table,
+ args, nb_args, arg_index + 1);
+ } else {
+ help_cmd_dump_one(mon, cmd, args, arg_index);
+ }
+ break;
+ }
}
}
static void help_cmd(Monitor *mon, const char *name)
{
- if (name && !strcmp(name, "info")) {
- help_cmd_dump(mon, info_cmds, "info ", NULL);
- } else {
- help_cmd_dump(mon, mon_cmds, "", name);
- if (name && !strcmp(name, "log")) {
- const CPULogItem *item;
+ char *args[MAX_ARGS];
+ int nb_args = 0;
+
+ /* 1. parse user input */
+ if (name) {
+ /* special case for log, directly dump and return */
+ if (!strcmp(name, "log")) {
+ const QEMULogItem *item;
monitor_printf(mon, "Log items (comma separated):\n");
monitor_printf(mon, "%-10s %s\n", "none", "remove all logs");
- for(item = cpu_log_items; item->mask != 0; item++) {
+ for (item = qemu_log_items; item->mask != 0; item++) {
monitor_printf(mon, "%-10s %s\n", item->name, item->help);
}
+ return;
+ }
+
+ if (parse_cmdline(name, &nb_args, args) < 0) {
+ return;
}
}
+
+ /* 2. dump the contents according to parsed args */
+ help_cmd_dump(mon, mon->cmd_table, args, nb_args, 0);
+
+ free_cmdline_args(args, nb_args);
}
static void do_help_cmd(Monitor *mon, const QDict *qdict)
{
const char *tp_name = qdict_get_str(qdict, "name");
bool new_state = qdict_get_bool(qdict, "option");
- int ret = trace_event_set_state(tp_name, new_state);
- if (!ret) {
+ bool found = false;
+ TraceEvent *ev = NULL;
+ while ((ev = trace_event_pattern(tp_name, ev)) != NULL) {
+ found = true;
+ if (!trace_event_get_state_static(ev)) {
+ monitor_printf(mon, "event \"%s\" is not traceable\n", tp_name);
+ } else {
+ trace_event_set_state_dynamic(ev, new_state);
+ }
+ }
+ if (!trace_event_is_pattern(tp_name) && !found) {
monitor_printf(mon, "unknown event name \"%s\"\n", tp_name);
}
}
}
}
-static void do_info(Monitor *mon, const QDict *qdict)
+static void do_info_help(Monitor *mon, const QDict *qdict)
{
- const mon_cmd_t *cmd;
- const char *item = qdict_get_try_str(qdict, "item");
-
- if (!item) {
- goto help;
- }
-
- for (cmd = info_cmds; cmd->name != NULL; cmd++) {
- if (compare_cmd(item, cmd->name))
- break;
- }
-
- if (cmd->name == NULL) {
- goto help;
- }
-
- cmd->mhandler.info(mon);
- return;
-
-help:
help_cmd(mon, "info");
}
/* set the current CPU defined by the user */
int monitor_set_cpu(int cpu_index)
{
- CPUArchState *env;
+ CPUState *cpu;
- for(env = first_cpu; env != NULL; env = env->next_cpu) {
- if (env->cpu_index == cpu_index) {
- cur_mon->mon_cpu = env;
- return 0;
- }
+ cpu = qemu_get_cpu(cpu_index);
+ if (cpu == NULL) {
+ return -1;
}
- return -1;
+ cur_mon->mon_cpu = cpu;
+ return 0;
}
static CPUArchState *mon_get_cpu(void)
monitor_set_cpu(0);
}
cpu_synchronize_state(cur_mon->mon_cpu);
- return cur_mon->mon_cpu;
+ return cur_mon->mon_cpu->env_ptr;
}
int monitor_get_cpu_index(void)
{
- return mon_get_cpu()->cpu_index;
+ CPUState *cpu = ENV_GET_CPU(mon_get_cpu());
+ return cpu->cpu_index;
}
-static void do_info_registers(Monitor *mon)
+static void do_info_registers(Monitor *mon, const QDict *qdict)
{
+ CPUState *cpu;
CPUArchState *env;
env = mon_get_cpu();
- cpu_dump_state(env, (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU);
+ cpu = ENV_GET_CPU(env);
+ cpu_dump_state(cpu, (FILE *)mon, monitor_fprintf, CPU_DUMP_FPU);
}
-static void do_info_jit(Monitor *mon)
+static void do_info_jit(Monitor *mon, const QDict *qdict)
{
dump_exec_info((FILE *)mon, monitor_fprintf);
}
-static void do_info_history(Monitor *mon)
+static void do_info_history(Monitor *mon, const QDict *qdict)
{
int i;
const char *str;
}
}
-#if defined(TARGET_PPC)
-/* XXX: not implemented in other targets */
-static void do_info_cpu_stats(Monitor *mon)
+static void do_info_cpu_stats(Monitor *mon, const QDict *qdict)
{
+ CPUState *cpu;
CPUArchState *env;
env = mon_get_cpu();
- cpu_dump_statistics(env, (FILE *)mon, &monitor_fprintf, 0);
+ cpu = ENV_GET_CPU(env);
+ cpu_dump_statistics(cpu, (FILE *)mon, &monitor_fprintf, 0);
}
-#endif
-static void do_trace_print_events(Monitor *mon)
+static void do_trace_print_events(Monitor *mon, const QDict *qdict)
{
trace_print_events((FILE *)mon, &monitor_fprintf);
}
static void do_logfile(Monitor *mon, const QDict *qdict)
{
- cpu_set_log_filename(qdict_get_str(qdict, "filename"));
+ qemu_set_log_filename(qdict_get_str(qdict, "filename"));
}
static void do_log(Monitor *mon, const QDict *qdict)
if (!strcmp(items, "none")) {
mask = 0;
} else {
- mask = cpu_str_to_log_mask(items);
+ mask = qemu_str_to_log_mask(items);
if (!mask) {
help_cmd(mon, "log");
return;
}
}
- cpu_set_log(mask);
+ qemu_set_log(mask);
}
static void do_singlestep(Monitor *mon, const QDict *qdict)
cpu_physical_memory_read(addr, buf, l);
} else {
env = mon_get_cpu();
- if (cpu_memory_rw_debug(env, addr, buf, l, 0) < 0) {
+ if (cpu_memory_rw_debug(ENV_GET_CPU(env), addr, buf, l, 0) < 0) {
monitor_printf(mon, " Cannot access memory\n");
break;
}
}
#endif
-static void tlb_info(Monitor *mon)
+static void tlb_info(Monitor *mon, const QDict *qdict)
{
CPUArchState *env;
}
#endif
-static void mem_info(Monitor *mon)
+static void mem_info(Monitor *mon, const QDict *qdict)
{
CPUArchState *env;
tlb->d, tlb->wt);
}
-static void tlb_info(Monitor *mon)
+static void tlb_info(Monitor *mon, const QDict *qdict)
{
CPUArchState *env = mon_get_cpu();
int i;
#endif
#if defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_XTENSA)
-static void tlb_info(Monitor *mon)
+static void tlb_info(Monitor *mon, const QDict *qdict)
{
CPUArchState *env1 = mon_get_cpu();
}
#endif
-static void do_info_mtree(Monitor *mon)
+static void do_info_mtree(Monitor *mon, const QDict *qdict)
{
mtree_info((fprintf_function)monitor_printf, mon);
}
-static void do_info_numa(Monitor *mon)
+static void do_info_numa(Monitor *mon, const QDict *qdict)
{
int i;
- CPUArchState *env;
+ CPUState *cpu;
monitor_printf(mon, "%d nodes\n", nb_numa_nodes);
for (i = 0; i < nb_numa_nodes; i++) {
monitor_printf(mon, "node %d cpus:", i);
- for (env = first_cpu; env != NULL; env = env->next_cpu) {
- if (env->numa_node == i) {
- monitor_printf(mon, " %d", env->cpu_index);
+ CPU_FOREACH(cpu) {
+ if (cpu->numa_node == i) {
+ monitor_printf(mon, " %d", cpu->cpu_index);
}
}
monitor_printf(mon, "\n");
int64_t qemu_time;
int64_t dev_time;
-static void do_info_profile(Monitor *mon)
+static void do_info_profile(Monitor *mon, const QDict *qdict)
{
int64_t total;
total = qemu_time;
dev_time = 0;
}
#else
-static void do_info_profile(Monitor *mon)
+static void do_info_profile(Monitor *mon, const QDict *qdict)
{
monitor_printf(mon, "Internal profiler not compiled\n");
}
/* Capture support */
static QLIST_HEAD (capture_list_head, CaptureState) capture_head;
-static void do_info_capture(Monitor *mon)
+static void do_info_capture(Monitor *mon, const QDict *qdict)
{
int i;
CaptureState *s;
}
}
-#ifdef HAS_AUDIO
static void do_stop_capture(Monitor *mon, const QDict *qdict)
{
int i;
}
QLIST_INSERT_HEAD (&capture_head, s, entries);
}
-#endif
static qemu_acl *find_acl(Monitor *mon, const char *name)
{
static void do_inject_mce(Monitor *mon, const QDict *qdict)
{
X86CPU *cpu;
- CPUX86State *cenv;
+ CPUState *cs;
int cpu_index = qdict_get_int(qdict, "cpu_index");
int bank = qdict_get_int(qdict, "bank");
uint64_t status = qdict_get_int(qdict, "status");
if (qdict_get_try_bool(qdict, "broadcast", 0)) {
flags |= MCE_INJECT_BROADCAST;
}
- for (cenv = first_cpu; cenv != NULL; cenv = cenv->next_cpu) {
- cpu = x86_env_get_cpu(cenv);
- if (cenv->cpu_index == cpu_index) {
- cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
- flags);
- break;
- }
+ cs = qemu_get_cpu(cpu_index);
+ if (cs != NULL) {
+ cpu = X86_CPU(cs);
+ cpu_x86_inject_mce(mon, cpu, bank, status, mcg_status, addr, misc,
+ flags);
}
}
#endif
return fd;
}
-/* mon_cmds and info_cmds would be sorted at runtime */
-static mon_cmd_t mon_cmds[] = {
-#include "hmp-commands.h"
- { NULL, NULL, },
-};
-
/* Please update hmp-commands.hx when adding or changing commands */
static mon_cmd_t info_cmds[] = {
{
.args_type = "",
.params = "",
.help = "show the version of QEMU",
- .mhandler.info = hmp_info_version,
+ .mhandler.cmd = hmp_info_version,
},
{
.name = "network",
.args_type = "",
.params = "",
.help = "show the network state",
- .mhandler.info = do_info_network,
+ .mhandler.cmd = do_info_network,
},
{
.name = "chardev",
.args_type = "",
.params = "",
.help = "show the character devices",
- .mhandler.info = hmp_info_chardev,
+ .mhandler.cmd = hmp_info_chardev,
},
{
.name = "block",
- .args_type = "",
- .params = "",
- .help = "show the block devices",
- .mhandler.info = hmp_info_block,
+ .args_type = "verbose:-v,device:B?",
+ .params = "[-v] [device]",
+ .help = "show info of one block device or all block devices "
+ "(and details of images with -v option)",
+ .mhandler.cmd = hmp_info_block,
},
{
.name = "blockstats",
.args_type = "",
.params = "",
.help = "show block device statistics",
- .mhandler.info = hmp_info_blockstats,
+ .mhandler.cmd = hmp_info_blockstats,
},
{
.name = "block-jobs",
.args_type = "",
.params = "",
.help = "show progress of ongoing block device operations",
- .mhandler.info = hmp_info_block_jobs,
+ .mhandler.cmd = hmp_info_block_jobs,
},
{
.name = "registers",
.args_type = "",
.params = "",
.help = "show the cpu registers",
- .mhandler.info = do_info_registers,
+ .mhandler.cmd = do_info_registers,
},
{
.name = "cpus",
.args_type = "",
.params = "",
.help = "show infos for each CPU",
- .mhandler.info = hmp_info_cpus,
+ .mhandler.cmd = hmp_info_cpus,
},
{
.name = "history",
.args_type = "",
.params = "",
.help = "show the command line history",
- .mhandler.info = do_info_history,
+ .mhandler.cmd = do_info_history,
},
#if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_MIPS) || \
defined(TARGET_LM32) || (defined(TARGET_SPARC) && !defined(TARGET_SPARC64))
.params = "",
.help = "show the interrupts statistics (if available)",
#ifdef TARGET_SPARC
- .mhandler.info = sun4m_irq_info,
+ .mhandler.cmd = sun4m_irq_info,
#elif defined(TARGET_LM32)
- .mhandler.info = lm32_irq_info,
+ .mhandler.cmd = lm32_irq_info,
#else
- .mhandler.info = irq_info,
+ .mhandler.cmd = irq_info,
#endif
},
{
.params = "",
.help = "show i8259 (PIC) state",
#ifdef TARGET_SPARC
- .mhandler.info = sun4m_pic_info,
+ .mhandler.cmd = sun4m_pic_info,
#elif defined(TARGET_LM32)
- .mhandler.info = lm32_do_pic_info,
+ .mhandler.cmd = lm32_do_pic_info,
#else
- .mhandler.info = pic_info,
+ .mhandler.cmd = pic_info,
#endif
},
#endif
.args_type = "",
.params = "",
.help = "show PCI info",
- .mhandler.info = hmp_info_pci,
+ .mhandler.cmd = hmp_info_pci,
},
#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \
defined(TARGET_PPC) || defined(TARGET_XTENSA)
.args_type = "",
.params = "",
.help = "show virtual to physical memory mappings",
- .mhandler.info = tlb_info,
+ .mhandler.cmd = tlb_info,
},
#endif
#if defined(TARGET_I386)
.args_type = "",
.params = "",
.help = "show the active virtual memory mappings",
- .mhandler.info = mem_info,
+ .mhandler.cmd = mem_info,
},
#endif
{
.args_type = "",
.params = "",
.help = "show memory tree",
- .mhandler.info = do_info_mtree,
+ .mhandler.cmd = do_info_mtree,
},
{
.name = "jit",
.args_type = "",
.params = "",
.help = "show dynamic compiler info",
- .mhandler.info = do_info_jit,
+ .mhandler.cmd = do_info_jit,
},
{
.name = "kvm",
.args_type = "",
.params = "",
.help = "show KVM information",
- .mhandler.info = hmp_info_kvm,
+ .mhandler.cmd = hmp_info_kvm,
},
{
.name = "numa",
.args_type = "",
.params = "",
.help = "show NUMA information",
- .mhandler.info = do_info_numa,
+ .mhandler.cmd = do_info_numa,
},
{
.name = "usb",
.args_type = "",
.params = "",
.help = "show guest USB devices",
- .mhandler.info = usb_info,
+ .mhandler.cmd = usb_info,
},
{
.name = "usbhost",
.args_type = "",
.params = "",
.help = "show host USB devices",
- .mhandler.info = usb_host_info,
+ .mhandler.cmd = usb_host_info,
},
{
.name = "profile",
.args_type = "",
.params = "",
.help = "show profiling information",
- .mhandler.info = do_info_profile,
+ .mhandler.cmd = do_info_profile,
},
{
.name = "capture",
.args_type = "",
.params = "",
.help = "show capture information",
- .mhandler.info = do_info_capture,
+ .mhandler.cmd = do_info_capture,
},
{
.name = "snapshots",
.args_type = "",
.params = "",
.help = "show the currently saved VM snapshots",
- .mhandler.info = do_info_snapshots,
+ .mhandler.cmd = do_info_snapshots,
},
{
.name = "status",
.args_type = "",
.params = "",
.help = "show the current VM status (running|paused)",
- .mhandler.info = hmp_info_status,
+ .mhandler.cmd = hmp_info_status,
},
{
.name = "pcmcia",
.args_type = "",
.params = "",
.help = "show guest PCMCIA status",
- .mhandler.info = pcmcia_info,
+ .mhandler.cmd = pcmcia_info,
},
{
.name = "mice",
.args_type = "",
.params = "",
.help = "show which guest mouse is receiving events",
- .mhandler.info = hmp_info_mice,
+ .mhandler.cmd = hmp_info_mice,
},
{
.name = "vnc",
.args_type = "",
.params = "",
.help = "show the vnc server status",
- .mhandler.info = hmp_info_vnc,
+ .mhandler.cmd = hmp_info_vnc,
},
#if defined(CONFIG_SPICE)
{
.args_type = "",
.params = "",
.help = "show the spice server status",
- .mhandler.info = hmp_info_spice,
+ .mhandler.cmd = hmp_info_spice,
},
#endif
{
.args_type = "",
.params = "",
.help = "show the current VM name",
- .mhandler.info = hmp_info_name,
+ .mhandler.cmd = hmp_info_name,
},
{
.name = "uuid",
.args_type = "",
.params = "",
.help = "show the current VM UUID",
- .mhandler.info = hmp_info_uuid,
+ .mhandler.cmd = hmp_info_uuid,
},
-#if defined(TARGET_PPC)
{
.name = "cpustats",
.args_type = "",
.params = "",
.help = "show CPU statistics",
- .mhandler.info = do_info_cpu_stats,
+ .mhandler.cmd = do_info_cpu_stats,
},
-#endif
#if defined(CONFIG_SLIRP)
{
.name = "usernet",
.args_type = "",
.params = "",
.help = "show user network stack connection states",
- .mhandler.info = do_info_usernet,
+ .mhandler.cmd = do_info_usernet,
},
#endif
{
.args_type = "",
.params = "",
.help = "show migration status",
- .mhandler.info = hmp_info_migrate,
+ .mhandler.cmd = hmp_info_migrate,
},
{
.name = "migrate_capabilities",
.args_type = "",
.params = "",
.help = "show current migration capabilities",
- .mhandler.info = hmp_info_migrate_capabilities,
+ .mhandler.cmd = hmp_info_migrate_capabilities,
},
{
.name = "migrate_cache_size",
.args_type = "",
.params = "",
.help = "show current migration xbzrle cache size",
- .mhandler.info = hmp_info_migrate_cache_size,
+ .mhandler.cmd = hmp_info_migrate_cache_size,
},
{
.name = "balloon",
.args_type = "",
.params = "",
.help = "show balloon information",
- .mhandler.info = hmp_info_balloon,
+ .mhandler.cmd = hmp_info_balloon,
},
{
.name = "qtree",
.args_type = "",
.params = "",
.help = "show device tree",
- .mhandler.info = do_info_qtree,
+ .mhandler.cmd = do_info_qtree,
},
{
.name = "qdm",
.args_type = "",
.params = "",
.help = "show qdev device model list",
- .mhandler.info = do_info_qdm,
+ .mhandler.cmd = do_info_qdm,
},
{
.name = "roms",
.args_type = "",
.params = "",
.help = "show roms",
- .mhandler.info = do_info_roms,
+ .mhandler.cmd = do_info_roms,
},
{
.name = "trace-events",
.args_type = "",
.params = "",
.help = "show available trace-events & their state",
- .mhandler.info = do_trace_print_events,
+ .mhandler.cmd = do_trace_print_events,
+ },
+ {
+ .name = "tpm",
+ .args_type = "",
+ .params = "",
+ .help = "show the TPM device",
+ .mhandler.cmd = hmp_info_tpm,
},
{
.name = NULL,
},
};
+/* mon_cmds and info_cmds would be sorted at runtime */
+static mon_cmd_t mon_cmds[] = {
+#include "hmp-commands.h"
+ { NULL, NULL, },
+};
+
static const mon_cmd_t qmp_cmds[] = {
#include "qmp-commands-old.h"
{ /* NULL */ },
/*******************************************************************/
static const char *pch;
-static jmp_buf expr_env;
+static sigjmp_buf expr_env;
#define MD_TLONG 0
#define MD_I32 1
{ "xer", 0, &monitor_get_xer, },
{ "tbu", 0, &monitor_get_tbu, },
{ "tbl", 0, &monitor_get_tbl, },
-#if defined(TARGET_PPC64)
- /* Address space register */
- { "asr", offsetof(CPUPPCState, asr) },
-#endif
/* Segment registers */
{ "sdr1", offsetof(CPUPPCState, spr[SPR_SDR1]) },
{ "sr0", offsetof(CPUPPCState, sr[0]) },
{ NULL },
};
-static void expr_error(Monitor *mon, const char *msg)
+static void GCC_FMT_ATTR(2, 3) QEMU_NORETURN
+expr_error(Monitor *mon, const char *fmt, ...)
{
- monitor_printf(mon, "%s\n", msg);
- longjmp(expr_env, 1);
+ va_list ap;
+ va_start(ap, fmt);
+ monitor_vprintf(mon, fmt, ap);
+ monitor_printf(mon, "\n");
+ va_end(ap);
+ siglongjmp(expr_env, 1);
}
/* return 0 if OK, -1 if not found */
expr_error(mon, "number too large");
}
if (pch == p) {
- expr_error(mon, "invalid char in expression");
+ expr_error(mon, "invalid char '%c' in expression", *p);
}
pch = p;
while (qemu_isspace(*pch))
static int get_expr(Monitor *mon, int64_t *pval, const char **pp)
{
pch = *pp;
- if (setjmp(expr_env)) {
+ if (sigsetjmp(expr_env, 0)) {
*pp = pch;
return -1;
}
return 0;
}
-static int get_str(char *buf, int buf_size, const char **pp)
-{
- const char *p;
- char *q;
- int c;
-
- q = buf;
- p = *pp;
- while (qemu_isspace(*p))
- p++;
- if (*p == '\0') {
- fail:
- *q = '\0';
- *pp = p;
- return -1;
- }
- if (*p == '\"') {
- p++;
- while (*p != '\0' && *p != '\"') {
- if (*p == '\\') {
- p++;
- c = *p++;
- switch(c) {
- case 'n':
- c = '\n';
- break;
- case 'r':
- c = '\r';
- break;
- case '\\':
- case '\'':
- case '\"':
- break;
- default:
- qemu_printf("unsupported escape code: '\\%c'\n", c);
- goto fail;
- }
- if ((q - buf) < buf_size - 1) {
- *q++ = c;
- }
- } else {
- if ((q - buf) < buf_size - 1) {
- *q++ = *p;
- }
- p++;
- }
- }
- if (*p != '\"') {
- qemu_printf("unterminated string\n");
- goto fail;
- }
- p++;
- } else {
- while (*p != '\0' && !qemu_isspace(*p)) {
- if ((q - buf) < buf_size - 1) {
- *q++ = *p;
- }
- p++;
- }
- }
- *q = '\0';
- *pp = p;
- return 0;
-}
-
/*
* Store the command-name in cmdname, and return a pointer to
* the remaining of the command string.
static int default_fmt_format = 'x';
static int default_fmt_size = 4;
-#define MAX_ARGS 16
-
static int is_valid_option(const char *c, const char *typestr)
{
char option[3];
return NULL;
}
-static const mon_cmd_t *monitor_find_command(const char *cmdname)
-{
- return search_dispatch_table(mon_cmds, cmdname);
-}
-
static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
{
return search_dispatch_table(qmp_cmds, cmdname);
}
+/*
+ * Parse @cmdline according to command table @table.
+ * If @cmdline is blank, return NULL.
+ * If it can't be parsed, report to @mon, and return NULL.
+ * Else, insert command arguments into @qdict, and return the command.
+ * If a sub-command table exists, and if @cmdline contains an additional string
+ * for a sub-command, this function will try to search the sub-command table.
+ * If no additional string for a sub-command is present, this function will
+ * return the command found in @table.
+ * Do not assume the returned command points into @table! It doesn't
+ * when the command is a sub-command.
+ */
static const mon_cmd_t *monitor_parse_command(Monitor *mon,
const char *cmdline,
+ int start,
+ mon_cmd_t *table,
QDict *qdict)
{
const char *p, *typestr;
char *key;
#ifdef DEBUG
- monitor_printf(mon, "command='%s'\n", cmdline);
+ monitor_printf(mon, "command='%s', start='%d'\n", cmdline, start);
#endif
/* extract the command name */
- p = get_command_name(cmdline, cmdname, sizeof(cmdname));
+ p = get_command_name(cmdline + start, cmdname, sizeof(cmdname));
if (!p)
return NULL;
- cmd = monitor_find_command(cmdname);
+ cmd = search_dispatch_table(table, cmdname);
if (!cmd) {
- monitor_printf(mon, "unknown command: '%s'\n", cmdname);
+ monitor_printf(mon, "unknown command: '%.*s'\n",
+ (int)(p - cmdline), cmdline);
return NULL;
}
+ /* filter out following useless space */
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ /* search sub command */
+ if (cmd->sub_table != NULL) {
+ /* check if user set additional command */
+ if (*p == '\0') {
+ return cmd;
+ }
+ return monitor_parse_command(mon, cmdline, p - cmdline,
+ cmd->sub_table, qdict);
+ }
+
/* parse the parameters */
typestr = cmd->args_type;
for(;;) {
}
}
break;
+ case 'S':
+ {
+ /* package all remaining string */
+ int len;
+
+ while (qemu_isspace(*p)) {
+ p++;
+ }
+ if (*typestr == '?') {
+ typestr++;
+ if (*p == '\0') {
+ /* no remaining string: NULL argument */
+ break;
+ }
+ }
+ len = strlen(p);
+ if (len <= 0) {
+ monitor_printf(mon, "%s: string expected\n",
+ cmdname);
+ break;
+ }
+ qdict_put(qdict, key, qstring_from_str(p));
+ p += len;
+ }
+ break;
default:
bad_type:
monitor_printf(mon, "%s: unknown type '%c'\n", cmdname, c);
qdict = qdict_new();
- cmd = monitor_parse_command(mon, cmdline, qdict);
+ cmd = monitor_parse_command(mon, cmdline, 0, mon->cmd_table, qdict);
if (!cmd)
goto out;
QDECREF(qdict);
}
-static void cmd_completion(const char *name, const char *list)
+static void cmd_completion(Monitor *mon, const char *name, const char *list)
{
const char *p, *pstart;
char cmd[128];
memcpy(cmd, pstart, len);
cmd[len] = '\0';
if (name[0] == '\0' || !strncmp(name, cmd, strlen(name))) {
- readline_add_completion(cur_mon->rs, cmd);
+ readline_add_completion(mon->rs, cmd);
}
if (*p == '\0')
break;
}
}
-static void file_completion(const char *input)
+static void file_completion(Monitor *mon, const char *input)
{
DIR *ffs;
struct dirent *d;
pstrcpy(file_prefix, sizeof(file_prefix), p + 1);
}
#ifdef DEBUG_COMPLETION
- monitor_printf(cur_mon, "input='%s' path='%s' prefix='%s'\n",
+ monitor_printf(mon, "input='%s' path='%s' prefix='%s'\n",
input, path, file_prefix);
#endif
ffs = opendir(path);
if (stat(file, &sb) == 0 && S_ISDIR(sb.st_mode)) {
pstrcat(file, sizeof(file), "/");
}
- readline_add_completion(cur_mon->rs, file);
+ readline_add_completion(mon->rs, file);
}
}
closedir(ffs);
}
+typedef struct MonitorBlockComplete {
+ Monitor *mon;
+ const char *input;
+} MonitorBlockComplete;
+
static void block_completion_it(void *opaque, BlockDriverState *bs)
{
const char *name = bdrv_get_device_name(bs);
- const char *input = opaque;
+ MonitorBlockComplete *mbc = opaque;
+ Monitor *mon = mbc->mon;
+ const char *input = mbc->input;
if (input[0] == '\0' ||
!strncmp(name, (char *)input, strlen(input))) {
- readline_add_completion(cur_mon->rs, name);
+ readline_add_completion(mon->rs, name);
}
}
-/* NOTE: this parser is an approximate form of the real command parser */
-static void parse_cmdline(const char *cmdline,
- int *pnb_args, char **args)
-{
- const char *p;
- int nb_args, ret;
- char buf[1024];
-
- p = cmdline;
- nb_args = 0;
- for(;;) {
- while (qemu_isspace(*p))
- p++;
- if (*p == '\0')
- break;
- if (nb_args >= MAX_ARGS)
- break;
- ret = get_str(buf, sizeof(buf), &p);
- args[nb_args] = g_strdup(buf);
- nb_args++;
- if (ret < 0)
- break;
- }
- *pnb_args = nb_args;
-}
-
static const char *next_arg_type(const char *typestr)
{
const char *p = strchr(typestr, ':');
return (p != NULL ? ++p : typestr);
}
-static void monitor_find_completion(const char *cmdline)
+static void monitor_find_completion_by_table(Monitor *mon,
+ const mon_cmd_t *cmd_table,
+ char **args,
+ int nb_args)
{
const char *cmdname;
- char *args[MAX_ARGS];
- int nb_args, i, len;
+ int i;
const char *ptype, *str;
const mon_cmd_t *cmd;
+ MonitorBlockComplete mbs;
- parse_cmdline(cmdline, &nb_args, args);
-#ifdef DEBUG_COMPLETION
- for(i = 0; i < nb_args; i++) {
- monitor_printf(cur_mon, "arg%d = '%s'\n", i, (char *)args[i]);
- }
-#endif
-
- /* if the line ends with a space, it means we want to complete the
- next arg */
- len = strlen(cmdline);
- if (len > 0 && qemu_isspace(cmdline[len - 1])) {
- if (nb_args >= MAX_ARGS) {
- goto cleanup;
- }
- args[nb_args++] = g_strdup("");
- }
if (nb_args <= 1) {
/* command completion */
if (nb_args == 0)
cmdname = "";
else
cmdname = args[0];
- readline_set_completion_index(cur_mon->rs, strlen(cmdname));
- for(cmd = mon_cmds; cmd->name != NULL; cmd++) {
- cmd_completion(cmdname, cmd->name);
+ readline_set_completion_index(mon->rs, strlen(cmdname));
+ for (cmd = cmd_table; cmd->name != NULL; cmd++) {
+ cmd_completion(mon, cmdname, cmd->name);
}
} else {
/* find the command */
- for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
+ for (cmd = cmd_table; cmd->name != NULL; cmd++) {
if (compare_cmd(args[0], cmd->name)) {
break;
}
}
if (!cmd->name) {
- goto cleanup;
+ return;
+ }
+
+ if (cmd->sub_table) {
+ /* do the job again */
+ return monitor_find_completion_by_table(mon, cmd->sub_table,
+ &args[1], nb_args - 1);
}
ptype = next_arg_type(cmd->args_type);
switch(*ptype) {
case 'F':
/* file completion */
- readline_set_completion_index(cur_mon->rs, strlen(str));
- file_completion(str);
+ readline_set_completion_index(mon->rs, strlen(str));
+ file_completion(mon, str);
break;
case 'B':
/* block device name completion */
- readline_set_completion_index(cur_mon->rs, strlen(str));
- bdrv_iterate(block_completion_it, (void *)str);
+ mbs.mon = mon;
+ mbs.input = str;
+ readline_set_completion_index(mon->rs, strlen(str));
+ bdrv_iterate(block_completion_it, &mbs);
break;
case 's':
- /* XXX: more generic ? */
- if (!strcmp(cmd->name, "info")) {
- readline_set_completion_index(cur_mon->rs, strlen(str));
- for(cmd = info_cmds; cmd->name != NULL; cmd++) {
- cmd_completion(str, cmd->name);
- }
- } else if (!strcmp(cmd->name, "sendkey")) {
+ case 'S':
+ if (!strcmp(cmd->name, "sendkey")) {
char *sep = strrchr(str, '-');
if (sep)
str = sep + 1;
- readline_set_completion_index(cur_mon->rs, strlen(str));
+ readline_set_completion_index(mon->rs, strlen(str));
for (i = 0; i < Q_KEY_CODE_MAX; i++) {
- cmd_completion(str, QKeyCode_lookup[i]);
+ cmd_completion(mon, str, QKeyCode_lookup[i]);
}
} else if (!strcmp(cmd->name, "help|?")) {
- readline_set_completion_index(cur_mon->rs, strlen(str));
- for (cmd = mon_cmds; cmd->name != NULL; cmd++) {
- cmd_completion(str, cmd->name);
- }
+ monitor_find_completion_by_table(mon, cmd_table,
+ &args[1], nb_args - 1);
}
break;
default:
break;
}
}
+}
-cleanup:
+static void monitor_find_completion(Monitor *mon,
+ const char *cmdline)
+{
+ char *args[MAX_ARGS];
+ int nb_args, len;
+
+ /* 1. parse the cmdline */
+ if (parse_cmdline(cmdline, &nb_args, args) < 0) {
+ return;
+ }
+#ifdef DEBUG_COMPLETION
for (i = 0; i < nb_args; i++) {
- g_free(args[i]);
+ monitor_printf(mon, "arg%d = '%s'\n", i, args[i]);
}
+#endif
+
+ /* if the line ends with a space, it means we want to complete the
+ next arg */
+ len = strlen(cmdline);
+ if (len > 0 && qemu_isspace(cmdline[len - 1])) {
+ if (nb_args >= MAX_ARGS) {
+ goto cleanup;
+ }
+ args[nb_args++] = g_strdup("");
+ }
+
+ /* 2. auto complete according to args */
+ monitor_find_completion_by_table(mon, mon->cmd_table, args, nb_args);
+
+cleanup:
+ free_cmdline_args(args, nb_args);
}
static int monitor_can_read(void *opaque)
if (is_first_init) {
monitor_protocol_event_init();
+ sortcmdlist();
is_first_init = 0;
}
- mon = g_malloc0(sizeof(*mon));
+ mon = g_malloc(sizeof(*mon));
+ monitor_data_init(mon);
mon->chr = chr;
mon->flags = flags;
QLIST_INSERT_HEAD(&mon_list, mon, entry);
if (!default_mon || (flags & MONITOR_IS_DEFAULT))
default_mon = mon;
-
- sortcmdlist();
}
static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque)
return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
}
+
+QemuOptsList qemu_mon_opts = {
+ .name = "mon",
+ .implied_opt_name = "chardev",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_mon_opts.head),
+ .desc = {
+ {
+ .name = "mode",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "chardev",
+ .type = QEMU_OPT_STRING,
+ },{
+ .name = "default",
+ .type = QEMU_OPT_BOOL,
+ },{
+ .name = "pretty",
+ .type = QEMU_OPT_BOOL,
+ },
+ { /* end of list */ }
+ },
+};