]> Git Repo - qemu.git/blobdiff - monitor.c
Merge remote-tracking branch 'remotes/kraxel/tags/pull-gtk-20141028-1' into staging
[qemu.git] / monitor.c
index 1266ba06fb032cb0e7c9dbaa1b6d22cd9047c6b4..1fc201ae820a164b49bcfc66c224c06c2e9de2ff 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -25,7 +25,6 @@
 #include "hw/hw.h"
 #include "monitor/qdev.h"
 #include "hw/usb.h"
-#include "hw/pcmcia.h"
 #include "hw/i386/pc.h"
 #include "hw/pci/pci.h"
 #include "sysemu/watchdog.h"
 #include "trace/simple.h"
 #endif
 #include "exec/memory.h"
+#include "exec/cpu_ldst.h"
 #include "qmp-commands.h"
 #include "hmp.h"
 #include "qemu/thread.h"
+#include "block/qapi.h"
+#include "qapi/qmp-event.h"
+#include "qapi-event.h"
 
 /* for pic/irq_info */
 #if defined(TARGET_SPARC)
@@ -177,27 +180,32 @@ typedef struct MonitorControl {
  * throttling is calculated globally, rather than per-Monitor
  * instance.
  */
-typedef struct MonitorEventState {
-    MonitorEvent event; /* Event being tracked */
-    int64_t rate;       /* Period over which to throttle. 0 to disable */
-    int64_t last;       /* Time at which event was last emitted */
+typedef struct MonitorQAPIEventState {
+    QAPIEvent event;    /* Event being tracked */
+    int64_t rate;       /* Minimum time (in ns) between two events */
+    int64_t last;       /* QEMU_CLOCK_REALTIME value at last emission */
     QEMUTimer *timer;   /* Timer for handling delayed events */
     QObject *data;      /* Event pending delayed dispatch */
-} MonitorEventState;
+} MonitorQAPIEventState;
 
 struct Monitor {
     CharDriverState *chr;
-    int mux_out;
     int reset_seen;
     int flags;
     int suspend_cnt;
     bool skip_flush;
+
+    QemuMutex out_lock;
     QString *outbuf;
-    guint watch;
+    guint out_watch;
+
+    /* Read under either BQL or out_lock, written with BQL+out_lock.  */
+    int mux_out;
+
     ReadLineState *rs;
     MonitorControl *mc;
     CPUState *mon_cpu;
-    BlockDriverCompletionFunc *password_completion_cb;
+    BlockCompletionFunc *password_completion_cb;
     void *password_opaque;
     mon_cmd_t *cmd_table;
     QError *error;
@@ -208,6 +216,9 @@ struct Monitor {
 /* QMP checker flags */
 #define QMP_ACCEPT_UNKNOWNS 1
 
+/* Protects mon_list, monitor_event_state.  */
+static QemuMutex monitor_lock;
+
 static QLIST_HEAD(mon_list, Monitor) mon_list;
 static QLIST_HEAD(mon_fdsets, MonFdset) mon_fdsets;
 static int mon_refcount;
@@ -266,17 +277,22 @@ int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
     }
 }
 
+static void monitor_flush_locked(Monitor *mon);
+
 static gboolean monitor_unblocked(GIOChannel *chan, GIOCondition cond,
                                   void *opaque)
 {
     Monitor *mon = opaque;
 
-    mon->watch = 0;
-    monitor_flush(mon);
+    qemu_mutex_lock(&mon->out_lock);
+    mon->out_watch = 0;
+    monitor_flush_locked(mon);
+    qemu_mutex_unlock(&mon->out_lock);
     return FALSE;
 }
 
-void monitor_flush(Monitor *mon)
+/* Called with mon->out_lock held.  */
+static void monitor_flush_locked(Monitor *mon)
 {
     int rc;
     size_t len;
@@ -303,18 +319,26 @@ void monitor_flush(Monitor *mon)
             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);
+        if (mon->out_watch == 0) {
+            mon->out_watch = qemu_chr_fe_add_watch(mon->chr, G_IO_OUT|G_IO_HUP,
+                                                   monitor_unblocked, mon);
         }
     }
 }
 
+void monitor_flush(Monitor *mon)
+{
+    qemu_mutex_lock(&mon->out_lock);
+    monitor_flush_locked(mon);
+    qemu_mutex_unlock(&mon->out_lock);
+}
+
 /* flush at every end of line */
 static void monitor_puts(Monitor *mon, const char *str)
 {
     char c;
 
+    qemu_mutex_lock(&mon->out_lock);
     for(;;) {
         c = *str++;
         if (c == '\0')
@@ -324,9 +348,10 @@ static void monitor_puts(Monitor *mon, const char *str)
         }
         qstring_append_chr(mon->outbuf, c);
         if (c == '\n') {
-            monitor_flush(mon);
+            monitor_flush_locked(mon);
         }
     }
+    qemu_mutex_unlock(&mon->out_lock);
 }
 
 void monitor_vprintf(Monitor *mon, const char *fmt, va_list ap)
@@ -437,65 +462,14 @@ static void monitor_protocol_emitter(Monitor *mon, QObject *data)
     QDECREF(qmp);
 }
 
-static void timestamp_put(QDict *qdict)
-{
-    int err;
-    QObject *obj;
-    qemu_timeval tv;
-
-    err = qemu_gettimeofday(&tv);
-    if (err < 0)
-        return;
-
-    obj = qobject_from_jsonf("{ 'seconds': %" PRId64 ", "
-                                "'microseconds': %" PRId64 " }",
-                                (int64_t) tv.tv_sec, (int64_t) tv.tv_usec);
-    qdict_put_obj(qdict, "timestamp", obj);
-}
-
-
-static const char *monitor_event_names[] = {
-    [QEVENT_SHUTDOWN] = "SHUTDOWN",
-    [QEVENT_RESET] = "RESET",
-    [QEVENT_POWERDOWN] = "POWERDOWN",
-    [QEVENT_STOP] = "STOP",
-    [QEVENT_RESUME] = "RESUME",
-    [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
-    [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
-    [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
-    [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
-    [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
-    [QEVENT_WATCHDOG] = "WATCHDOG",
-    [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
-    [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
-    [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
-    [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
-    [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",
-    [QEVENT_QUORUM_FAILURE] = "QUORUM_FAILURE",
-    [QEVENT_QUORUM_REPORT_BAD] = "QUORUM_REPORT_BAD",
-};
-QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
 
-MonitorEventState monitor_event_state[QEVENT_MAX];
+static MonitorQAPIEventState monitor_qapi_event_state[QAPI_EVENT_MAX];
 
 /*
- * Emits the event to every monitor instance
+ * Emits the event to every monitor instance, @event is only used for trace
+ * Called with monitor_lock held.
  */
-static void
-monitor_protocol_event_emit(MonitorEvent event,
-                            QObject *data)
+static void monitor_qapi_event_emit(QAPIEvent event, QObject *data)
 {
     Monitor *mon;
 
@@ -507,20 +481,18 @@ monitor_protocol_event_emit(MonitorEvent event,
     }
 }
 
-
 /*
  * Queue a new event for emission to Monitor instances,
  * applying any rate limiting if required.
  */
 static void
-monitor_protocol_event_queue(MonitorEvent event,
-                             QObject *data)
+monitor_qapi_event_queue(QAPIEvent event, QDict *data, Error **errp)
 {
-    MonitorEventState *evstate;
+    MonitorQAPIEventState *evstate;
+    assert(event < QAPI_EVENT_MAX);
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
-    assert(event < QEVENT_MAX);
 
-    evstate = &(monitor_event_state[event]);
+    evstate = &(monitor_qapi_event_state[event]);
     trace_monitor_protocol_event_queue(event,
                                        data,
                                        evstate->rate,
@@ -528,8 +500,9 @@ monitor_protocol_event_queue(MonitorEvent event,
                                        now);
 
     /* Rate limit of 0 indicates no throttling */
+    qemu_mutex_lock(&monitor_lock);
     if (!evstate->rate) {
-        monitor_protocol_event_emit(event, data);
+        monitor_qapi_event_emit(event, QOBJECT(data));
         evstate->last = now;
     } else {
         int64_t delta = now - evstate->last;
@@ -545,39 +518,39 @@ monitor_protocol_event_queue(MonitorEvent event,
                 int64_t then = evstate->last + evstate->rate;
                 timer_mod_ns(evstate->timer, then);
             }
-            evstate->data = data;
+            evstate->data = QOBJECT(data);
             qobject_incref(evstate->data);
         } else {
-            monitor_protocol_event_emit(event, data);
+            monitor_qapi_event_emit(event, QOBJECT(data));
             evstate->last = now;
         }
     }
+    qemu_mutex_unlock(&monitor_lock);
 }
 
-
 /*
  * The callback invoked by QemuTimer when a delayed
  * event is ready to be emitted
  */
-static void monitor_protocol_event_handler(void *opaque)
+static void monitor_qapi_event_handler(void *opaque)
 {
-    MonitorEventState *evstate = opaque;
+    MonitorQAPIEventState *evstate = opaque;
     int64_t now = qemu_clock_get_ns(QEMU_CLOCK_REALTIME);
 
-
     trace_monitor_protocol_event_handler(evstate->event,
                                          evstate->data,
                                          evstate->last,
                                          now);
+    qemu_mutex_lock(&monitor_lock);
     if (evstate->data) {
-        monitor_protocol_event_emit(evstate->event, evstate->data);
+        monitor_qapi_event_emit(evstate->event, evstate->data);
         qobject_decref(evstate->data);
         evstate->data = NULL;
     }
     evstate->last = now;
+    qemu_mutex_unlock(&monitor_lock);
 }
 
-
 /*
  * @event: the event ID to be limited
  * @rate: the rate limit in milliseconds
@@ -587,65 +560,36 @@ static void monitor_protocol_event_handler(void *opaque)
  * milliseconds
  */
 static void
-monitor_protocol_event_throttle(MonitorEvent event,
-                                int64_t rate)
+monitor_qapi_event_throttle(QAPIEvent event, int64_t rate)
 {
-    MonitorEventState *evstate;
-    assert(event < QEVENT_MAX);
+    MonitorQAPIEventState *evstate;
+    assert(event < QAPI_EVENT_MAX);
 
-    evstate = &(monitor_event_state[event]);
+    evstate = &(monitor_qapi_event_state[event]);
 
     trace_monitor_protocol_event_throttle(event, rate);
     evstate->event = event;
+    assert(rate * SCALE_MS <= INT64_MAX);
     evstate->rate = rate * SCALE_MS;
-    evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
-                                    SCALE_MS,
-                                    monitor_protocol_event_handler,
-                                    evstate);
     evstate->last = 0;
     evstate->data = NULL;
+    evstate->timer = timer_new(QEMU_CLOCK_REALTIME,
+                               SCALE_MS,
+                               monitor_qapi_event_handler,
+                               evstate);
 }
 
-
-/* Global, one-time initializer to configure the rate limiting
- * and initialize state */
-static void monitor_protocol_event_init(void)
-{
-    /* Limit RTC & BALLOON events to 1 per second */
-    monitor_protocol_event_throttle(QEVENT_RTC_CHANGE, 1000);
-    monitor_protocol_event_throttle(QEVENT_BALLOON_CHANGE, 1000);
-    monitor_protocol_event_throttle(QEVENT_WATCHDOG, 1000);
-    /* limit the rate of quorum events to avoid hammering the management */
-    monitor_protocol_event_throttle(QEVENT_QUORUM_REPORT_BAD, 1000);
-    monitor_protocol_event_throttle(QEVENT_QUORUM_FAILURE, 1000);
-}
-
-/**
- * monitor_protocol_event(): Generate a Monitor event
- *
- * Event-specific data can be emitted through the (optional) 'data' parameter.
- */
-void monitor_protocol_event(MonitorEvent event, QObject *data)
+static void monitor_qapi_event_init(void)
 {
-    QDict *qmp;
-    const char *event_name;
-
-    assert(event < QEVENT_MAX);
+    /* Limit guest-triggerable events to 1 per second */
+    monitor_qapi_event_throttle(QAPI_EVENT_RTC_CHANGE, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_WATCHDOG, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_BALLOON_CHANGE, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_REPORT_BAD, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_QUORUM_FAILURE, 1000);
+    monitor_qapi_event_throttle(QAPI_EVENT_VSERPORT_CHANGE, 1000);
 
-    event_name = monitor_event_names[event];
-    assert(event_name != NULL);
-
-    qmp = qdict_new();
-    timestamp_put(qmp);
-    qdict_put(qmp, "event", qstring_from_str(event_name));
-    if (data) {
-        qobject_incref(data);
-        qdict_put_obj(qmp, "data", data);
-    }
-
-    trace_monitor_protocol_event(event, event_name, qmp);
-    monitor_protocol_event_queue(event, QOBJECT(qmp));
-    QDECREF(qmp);
+    qmp_event_set_func_emit(monitor_qapi_event_queue);
 }
 
 static int do_qmp_capabilities(Monitor *mon, const QDict *params,
@@ -664,6 +608,7 @@ static void handle_user_command(Monitor *mon, const char *cmdline);
 static void monitor_data_init(Monitor *mon)
 {
     memset(mon, 0, sizeof(Monitor));
+    qemu_mutex_init(&mon->out_lock);
     mon->outbuf = qstring_new();
     /* Use *mon_cmds by default. */
     mon->cmd_table = mon_cmds;
@@ -672,6 +617,7 @@ static void monitor_data_init(Monitor *mon)
 static void monitor_data_destroy(Monitor *mon)
 {
     QDECREF(mon->outbuf);
+    qemu_mutex_destroy(&mon->out_lock);
 }
 
 char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
@@ -699,11 +645,13 @@ char *qmp_human_monitor_command(const char *command_line, bool has_cpu_index,
     handle_user_command(&hmp, command_line);
     cur_mon = old_mon;
 
+    qemu_mutex_lock(&hmp.out_lock);
     if (qstring_get_length(hmp.outbuf) > 0) {
         output = g_strdup(qstring_get_str(hmp.outbuf));
     } else {
         output = g_strdup("");
     }
+    qemu_mutex_unlock(&hmp.out_lock);
 
 out:
     monitor_data_destroy(&hmp);
@@ -937,19 +885,12 @@ static void do_trace_event_set_state(Monitor *mon, const QDict *qdict)
 {
     const char *tp_name = qdict_get_str(qdict, "name");
     bool new_state = qdict_get_bool(qdict, "option");
+    Error *local_err = NULL;
 
-    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);
+    qmp_trace_event_set_state(tp_name, new_state, true, true, &local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
     }
 }
 
@@ -1042,10 +983,10 @@ CommandInfoList *qmp_query_commands(Error **errp)
 EventInfoList *qmp_query_events(Error **errp)
 {
     EventInfoList *info, *ev_list = NULL;
-    MonitorEvent e;
+    QAPIEvent e;
 
-    for (e = 0 ; e < QEVENT_MAX ; e++) {
-        const char *event_name = monitor_event_names[e];
+    for (e = 0 ; e < QAPI_EVENT_MAX ; e++) {
+        const char *event_name = QAPIEvent_lookup[e];
         assert(event_name != NULL);
         info = g_malloc0(sizeof(*info));
         info->value = g_malloc0(sizeof(*info->value));
@@ -1098,6 +1039,7 @@ static void do_info_registers(Monitor *mon, const QDict *qdict)
 static void do_info_jit(Monitor *mon, const QDict *qdict)
 {
     dump_exec_info((FILE *)mon, monitor_fprintf);
+    dump_drift_info((FILE *)mon, monitor_fprintf);
 }
 
 static void do_info_history(Monitor *mon, const QDict *qdict)
@@ -1129,7 +1071,15 @@ static void do_info_cpu_stats(Monitor *mon, const QDict *qdict)
 
 static void do_trace_print_events(Monitor *mon, const QDict *qdict)
 {
-    trace_print_events((FILE *)mon, &monitor_fprintf);
+    TraceEventInfoList *events = qmp_trace_event_get_state("*", NULL);
+    TraceEventInfoList *elem;
+
+    for (elem = events; elem != NULL; elem = elem->next) {
+        monitor_printf(mon, "%s : state %u\n",
+                       elem->value->name,
+                       elem->value->state == TRACE_EVENT_STATE_ENABLED ? 1 : 0);
+    }
+    qapi_free_TraceEventInfoList(events);
 }
 
 static int client_migrate_info(Monitor *mon, const QDict *qdict,
@@ -1282,6 +1232,10 @@ static void memory_dump(Monitor *mon, int count, int format, int wsize,
                     flags = 1;
             }
         }
+#endif
+#ifdef TARGET_PPC
+        flags = msr_le << 16;
+        flags |= env->bfd_mach;
 #endif
         monitor_disas(mon, env, addr, count, is_physical, flags);
         return;
@@ -2005,7 +1959,7 @@ static void do_info_numa(Monitor *mon, const QDict *qdict)
         }
         monitor_printf(mon, "\n");
         monitor_printf(mon, "node %d size: %" PRId64 " MB\n", i,
-            node_mem[i] >> 20);
+            numa_info[i].node_mem >> 20);
     }
 }
 
@@ -2588,8 +2542,10 @@ static int monitor_fdset_dup_fd_find_remove(int dup_fd, bool remove)
                     if (QLIST_EMPTY(&mon_fdset->dup_fds)) {
                         monitor_fdset_cleanup(mon_fdset);
                     }
+                    return -1;
+                } else {
+                    return mon_fdset->id;
                 }
-                return mon_fdset->id;
             }
         }
     }
@@ -2601,9 +2557,9 @@ int monitor_fdset_dup_fd_find(int dup_fd)
     return monitor_fdset_dup_fd_find_remove(dup_fd, false);
 }
 
-int monitor_fdset_dup_fd_remove(int dup_fd)
+void monitor_fdset_dup_fd_remove(int dup_fd)
 {
-    return monitor_fdset_dup_fd_find_remove(dup_fd, true);
+    monitor_fdset_dup_fd_find_remove(dup_fd, true);
 }
 
 int monitor_handle_fd_param(Monitor *mon, const char *fdname)
@@ -2611,16 +2567,33 @@ int monitor_handle_fd_param(Monitor *mon, const char *fdname)
     int fd;
     Error *local_err = NULL;
 
-    if (!qemu_isdigit(fdname[0]) && mon) {
+    fd = monitor_handle_fd_param2(mon, fdname, &local_err);
+    if (local_err) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+    }
+    return fd;
+}
 
+int monitor_handle_fd_param2(Monitor *mon, const char *fdname, Error **errp)
+{
+    int fd;
+    Error *local_err = NULL;
+
+    if (!qemu_isdigit(fdname[0]) && mon) {
         fd = monitor_get_fd(mon, fdname, &local_err);
+    } else {
+        fd = qemu_parse_fd(fdname);
         if (fd == -1) {
-            qerror_report_err(local_err);
-            error_free(local_err);
-            return -1;
+            error_setg(&local_err, "Invalid file descriptor number '%s'",
+                       fdname);
         }
+    }
+    if (local_err) {
+        error_propagate(errp, local_err);
+        assert(fd == -1);
     } else {
-        fd = qemu_parse_fd(fdname);
+        assert(fd != -1);
     }
 
     return fd;
@@ -2817,13 +2790,6 @@ static mon_cmd_t info_cmds[] = {
         .help       = "show the current VM status (running|paused)",
         .mhandler.cmd = hmp_info_status,
     },
-    {
-        .name       = "pcmcia",
-        .args_type  = "",
-        .params     = "",
-        .help       = "show guest PCMCIA status",
-        .mhandler.cmd = pcmcia_info,
-    },
     {
         .name       = "mice",
         .args_type  = "",
@@ -2940,6 +2906,20 @@ static mon_cmd_t info_cmds[] = {
         .help       = "show the TPM device",
         .mhandler.cmd = hmp_info_tpm,
     },
+    {
+        .name       = "memdev",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show memory backends",
+        .mhandler.cmd = hmp_info_memdev,
+    },
+    {
+        .name       = "memory-devices",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show memory devices",
+        .mhandler.cmd = hmp_info_memory_devices,
+    },
     {
         .name       = NULL,
     },
@@ -4228,28 +4208,59 @@ static void file_completion(Monitor *mon, const char *input)
     closedir(ffs);
 }
 
-typedef struct MonitorBlockComplete {
-    Monitor *mon;
-    const char *input;
-} MonitorBlockComplete;
+static const char *next_arg_type(const char *typestr)
+{
+    const char *p = strchr(typestr, ':');
+    return (p != NULL ? ++p : typestr);
+}
 
-static void block_completion_it(void *opaque, BlockDriverState *bs)
+static void add_completion_option(ReadLineState *rs, const char *str,
+                                  const char *option)
 {
-    const char *name = bdrv_get_device_name(bs);
-    MonitorBlockComplete *mbc = opaque;
-    Monitor *mon = mbc->mon;
-    const char *input = mbc->input;
+    if (!str || !option) {
+        return;
+    }
+    if (!strncmp(option, str, strlen(str))) {
+        readline_add_completion(rs, option);
+    }
+}
 
-    if (input[0] == '\0' ||
-        !strncmp(name, (char *)input, strlen(input))) {
-        readline_add_completion(mon->rs, name);
+void chardev_add_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    size_t len;
+    ChardevBackendInfoList *list, *start;
+
+    if (nb_args != 2) {
+        return;
     }
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+
+    start = list = qmp_query_chardev_backends(NULL);
+    while (list) {
+        const char *chr_name = list->value->name;
+
+        if (!strncmp(chr_name, str, len)) {
+            readline_add_completion(rs, chr_name);
+        }
+        list = list->next;
+    }
+    qapi_free_ChardevBackendInfoList(start);
 }
 
-static const char *next_arg_type(const char *typestr)
+void netdev_add_completion(ReadLineState *rs, int nb_args, const char *str)
 {
-    const char *p = strchr(typestr, ':');
-    return (p != NULL ? ++p : typestr);
+    size_t len;
+    int i;
+
+    if (nb_args != 2) {
+        return;
+    }
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    for (i = 0; NetClientOptionsKind_lookup[i]; i++) {
+        add_completion_option(rs, str, NetClientOptionsKind_lookup[i]);
+    }
 }
 
 void device_add_completion(ReadLineState *rs, int nb_args, const char *str)
@@ -4303,23 +4314,91 @@ void object_add_completion(ReadLineState *rs, int nb_args, const char *str)
     g_slist_free(list);
 }
 
-static void device_del_bus_completion(ReadLineState *rs,  BusState *bus,
-                                      const char *str, size_t len)
+static void peripheral_device_del_completion(ReadLineState *rs,
+                                             const char *str, size_t len)
 {
-    BusChild *kid;
+    Object *peripheral;
+    GSList *list = NULL, *item;
 
-    QTAILQ_FOREACH(kid, &bus->children, sibling) {
-        DeviceState *dev = kid->child;
-        BusState *dev_child;
+    peripheral = object_resolve_path("/machine/peripheral/", NULL);
+    if (peripheral == NULL) {
+        return;
+    }
+
+    object_child_foreach(peripheral, qdev_build_hotpluggable_device_list,
+                         &list);
+
+    for (item = list; item; item = g_slist_next(item)) {
+        DeviceState *dev = item->data;
 
         if (dev->id && !strncmp(str, dev->id, len)) {
             readline_add_completion(rs, dev->id);
         }
+    }
+
+    g_slist_free(list);
+}
+
+void chardev_remove_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    size_t len;
+    ChardevInfoList *list, *start;
 
-        QLIST_FOREACH(dev_child, &dev->child_bus, sibling) {
-            device_del_bus_completion(rs, dev_child, str, len);
+    if (nb_args != 2) {
+        return;
+    }
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+
+    start = list = qmp_query_chardev(NULL);
+    while (list) {
+        ChardevInfo *chr = list->value;
+
+        if (!strncmp(chr->label, str, len)) {
+            readline_add_completion(rs, chr->label);
         }
+        list = list->next;
     }
+    qapi_free_ChardevInfoList(start);
+}
+
+static void ringbuf_completion(ReadLineState *rs, const char *str)
+{
+    size_t len;
+    ChardevInfoList *list, *start;
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+
+    start = list = qmp_query_chardev(NULL);
+    while (list) {
+        ChardevInfo *chr_info = list->value;
+
+        if (!strncmp(chr_info->label, str, len)) {
+            CharDriverState *chr = qemu_chr_find(chr_info->label);
+            if (chr && chr_is_ringbuf(chr)) {
+                readline_add_completion(rs, chr_info->label);
+            }
+        }
+        list = list->next;
+    }
+    qapi_free_ChardevInfoList(start);
+}
+
+void ringbuf_read_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    if (nb_args != 2) {
+        return;
+    }
+    ringbuf_completion(rs, str);
+}
+
+void ringbuf_write_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    if (nb_args != 2) {
+        return;
+    }
+    ringbuf_completion(rs, str);
 }
 
 void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
@@ -4332,7 +4411,7 @@ void device_del_completion(ReadLineState *rs, int nb_args, const char *str)
 
     len = strlen(str);
     readline_set_completion_index(rs, len);
-    device_del_bus_completion(rs, sysbus_get_default(), str, len);
+    peripheral_device_del_completion(rs, str, len);
 }
 
 void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
@@ -4359,6 +4438,212 @@ void object_del_completion(ReadLineState *rs, int nb_args, const char *str)
     qapi_free_ObjectPropertyInfoList(start);
 }
 
+void sendkey_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    int i;
+    char *sep;
+    size_t len;
+
+    if (nb_args != 2) {
+        return;
+    }
+    sep = strrchr(str, '-');
+    if (sep) {
+        str = sep + 1;
+    }
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    for (i = 0; i < Q_KEY_CODE_MAX; i++) {
+        if (!strncmp(str, QKeyCode_lookup[i], len)) {
+            readline_add_completion(rs, QKeyCode_lookup[i]);
+        }
+    }
+}
+
+void set_link_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    size_t len;
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    if (nb_args == 2) {
+        NetClientState *ncs[255];
+        int count, i;
+        count = qemu_find_net_clients_except(NULL, ncs,
+                                             NET_CLIENT_OPTIONS_KIND_NONE, 255);
+        for (i = 0; i < count; i++) {
+            const char *name = ncs[i]->name;
+            if (!strncmp(str, name, len)) {
+                readline_add_completion(rs, name);
+            }
+        }
+    } else if (nb_args == 3) {
+        add_completion_option(rs, str, "on");
+        add_completion_option(rs, str, "off");
+    }
+}
+
+void netdev_del_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    int len, count, i;
+    NetClientState *ncs[255];
+
+    if (nb_args != 2) {
+        return;
+    }
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    count = qemu_find_net_clients_except(NULL, ncs, NET_CLIENT_OPTIONS_KIND_NIC,
+                                         255);
+    for (i = 0; i < count; i++) {
+        QemuOpts *opts;
+        const char *name = ncs[i]->name;
+        if (strncmp(str, name, len)) {
+            continue;
+        }
+        opts = qemu_opts_find(qemu_find_opts_err("netdev", NULL), name);
+        if (opts) {
+            readline_add_completion(rs, name);
+        }
+    }
+}
+
+void watchdog_action_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    int i;
+
+    if (nb_args != 2) {
+        return;
+    }
+    readline_set_completion_index(rs, strlen(str));
+    for (i = 0; WatchdogExpirationAction_lookup[i]; i++) {
+        add_completion_option(rs, str, WatchdogExpirationAction_lookup[i]);
+    }
+}
+
+void migrate_set_capability_completion(ReadLineState *rs, int nb_args,
+                                       const char *str)
+{
+    size_t len;
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    if (nb_args == 2) {
+        int i;
+        for (i = 0; i < MIGRATION_CAPABILITY_MAX; i++) {
+            const char *name = MigrationCapability_lookup[i];
+            if (!strncmp(str, name, len)) {
+                readline_add_completion(rs, name);
+            }
+        }
+    } else if (nb_args == 3) {
+        add_completion_option(rs, str, "on");
+        add_completion_option(rs, str, "off");
+    }
+}
+
+void host_net_add_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    int i;
+    size_t len;
+    if (nb_args != 2) {
+        return;
+    }
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    for (i = 0; host_net_devices[i]; i++) {
+        if (!strncmp(host_net_devices[i], str, len)) {
+            readline_add_completion(rs, host_net_devices[i]);
+        }
+    }
+}
+
+void host_net_remove_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    NetClientState *ncs[255];
+    int count, i, len;
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    if (nb_args == 2) {
+        count = qemu_find_net_clients_except(NULL, ncs,
+                                             NET_CLIENT_OPTIONS_KIND_NONE, 255);
+        for (i = 0; i < count; i++) {
+            int id;
+            char name[16];
+
+            if (net_hub_id_for_client(ncs[i], &id)) {
+                continue;
+            }
+            snprintf(name, sizeof(name), "%d", id);
+            if (!strncmp(str, name, len)) {
+                readline_add_completion(rs, name);
+            }
+        }
+        return;
+    } else if (nb_args == 3) {
+        count = qemu_find_net_clients_except(NULL, ncs,
+                                             NET_CLIENT_OPTIONS_KIND_NIC, 255);
+        for (i = 0; i < count; i++) {
+            const char *name;
+
+            name = ncs[i]->name;
+            if (!strncmp(str, name, len)) {
+                readline_add_completion(rs, name);
+            }
+        }
+        return;
+    }
+}
+
+static void vm_completion(ReadLineState *rs, const char *str)
+{
+    size_t len;
+    BlockDriverState *bs = NULL;
+
+    len = strlen(str);
+    readline_set_completion_index(rs, len);
+    while ((bs = bdrv_next(bs))) {
+        SnapshotInfoList *snapshots, *snapshot;
+
+        if (!bdrv_can_snapshot(bs)) {
+            continue;
+        }
+        if (bdrv_query_snapshot_info_list(bs, &snapshots, NULL)) {
+            continue;
+        }
+        snapshot = snapshots;
+        while (snapshot) {
+            char *completion = snapshot->value->name;
+            if (!strncmp(str, completion, len)) {
+                readline_add_completion(rs, completion);
+            }
+            completion = snapshot->value->id;
+            if (!strncmp(str, completion, len)) {
+                readline_add_completion(rs, completion);
+            }
+            snapshot = snapshot->next;
+        }
+        qapi_free_SnapshotInfoList(snapshots);
+    }
+
+}
+
+void delvm_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    if (nb_args == 2) {
+        vm_completion(rs, str);
+    }
+}
+
+void loadvm_completion(ReadLineState *rs, int nb_args, const char *str)
+{
+    if (nb_args == 2) {
+        vm_completion(rs, str);
+    }
+}
+
 static void monitor_find_completion_by_table(Monitor *mon,
                                              const mon_cmd_t *cmd_table,
                                              char **args,
@@ -4366,9 +4651,9 @@ static void monitor_find_completion_by_table(Monitor *mon,
 {
     const char *cmdname;
     int i;
-    const char *ptype, *str;
+    const char *ptype, *str, *name;
     const mon_cmd_t *cmd;
-    MonitorBlockComplete mbs;
+    BlockDriverState *bs;
 
     if (nb_args <= 1) {
         /* command completion */
@@ -4420,22 +4705,18 @@ static void monitor_find_completion_by_table(Monitor *mon,
             break;
         case 'B':
             /* block device name completion */
-            mbs.mon = mon;
-            mbs.input = str;
             readline_set_completion_index(mon->rs, strlen(str));
-            bdrv_iterate(block_completion_it, &mbs);
+            for (bs = bdrv_next(NULL); bs; bs = bdrv_next(bs)) {
+                name = bdrv_get_device_name(bs);
+                if (str[0] == '\0' ||
+                    !strncmp(name, str, strlen(str))) {
+                    readline_add_completion(mon->rs, name);
+                }
+            }
             break;
         case 's':
         case 'S':
-            if (!strcmp(cmd->name, "sendkey")) {
-                char *sep = strrchr(str, '-');
-                if (sep)
-                    str = sep + 1;
-                readline_set_completion_index(mon->rs, strlen(str));
-                for (i = 0; i < Q_KEY_CODE_MAX; i++) {
-                    cmd_completion(mon, str, QKeyCode_lookup[i]);
-                }
-            } else if (!strcmp(cmd->name, "help|?")) {
+            if (!strcmp(cmd->name, "help|?")) {
                 monitor_find_completion_by_table(mon, cmd_table,
                                                  &args[1], nb_args - 1);
             }
@@ -4458,8 +4739,11 @@ static void monitor_find_completion(void *opaque,
         return;
     }
 #ifdef DEBUG_COMPLETION
-    for (i = 0; i < nb_args; i++) {
-        monitor_printf(mon, "arg%d = '%s'\n", i, args[i]);
+    {
+        int i;
+        for (i = 0; i < nb_args; i++) {
+            monitor_printf(mon, "arg%d = '%s'\n", i, args[i]);
+        }
     }
 #endif
 
@@ -4925,7 +5209,9 @@ static void monitor_event(void *opaque, int event)
 
     switch (event) {
     case CHR_EVENT_MUX_IN:
+        qemu_mutex_lock(&mon->out_lock);
         mon->mux_out = 0;
+        qemu_mutex_unlock(&mon->out_lock);
         if (mon->reset_seen) {
             readline_restart(mon->rs);
             monitor_resume(mon);
@@ -4945,13 +5231,16 @@ static void monitor_event(void *opaque, int event)
         } else {
             mon->suspend_cnt++;
         }
+        qemu_mutex_lock(&mon->out_lock);
         mon->mux_out = 1;
+        qemu_mutex_unlock(&mon->out_lock);
         break;
 
     case CHR_EVENT_OPENED:
         monitor_printf(mon, "QEMU %s monitor - type 'help' for more "
                        "information\n", QEMU_VERSION);
         if (!mon->mux_out) {
+            readline_restart(mon->rs);
             readline_show_prompt(mon->rs);
         }
         mon->reset_seen = 1;
@@ -5010,13 +5299,18 @@ static void monitor_readline_flush(void *opaque)
     monitor_flush(opaque);
 }
 
+static void __attribute__((constructor)) monitor_lock_init(void)
+{
+    qemu_mutex_init(&monitor_lock);
+}
+
 void monitor_init(CharDriverState *chr, int flags)
 {
     static int is_first_init = 1;
     Monitor *mon;
 
     if (is_first_init) {
-        monitor_protocol_event_init();
+        monitor_qapi_event_init();
         sortcmdlist();
         is_first_init = 0;
     }
@@ -5047,7 +5341,10 @@ void monitor_init(CharDriverState *chr, int flags)
                               monitor_event, mon);
     }
 
+    qemu_mutex_lock(&monitor_lock);
     QLIST_INSERT_HEAD(&mon_list, mon, entry);
+    qemu_mutex_unlock(&monitor_lock);
+
     if (!default_mon || (flags & MONITOR_IS_DEFAULT))
         default_mon = mon;
 }
@@ -5075,7 +5372,7 @@ ReadLineState *monitor_get_rs(Monitor *mon)
 }
 
 int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
-                                BlockDriverCompletionFunc *completion_cb,
+                                BlockCompletionFunc *completion_cb,
                                 void *opaque)
 {
     int err;
@@ -5107,7 +5404,7 @@ int monitor_read_bdrv_key_start(Monitor *mon, BlockDriverState *bs,
 }
 
 int monitor_read_block_device_key(Monitor *mon, const char *device,
-                                  BlockDriverCompletionFunc *completion_cb,
+                                  BlockCompletionFunc *completion_cb,
                                   void *opaque)
 {
     BlockDriverState *bs;
@@ -5142,3 +5439,10 @@ QemuOptsList qemu_mon_opts = {
         { /* end of list */ }
     },
 };
+
+#ifndef TARGET_I386
+void qmp_rtc_reset_reinjection(Error **errp)
+{
+    error_set(errp, QERR_FEATURE_DISABLED, "rtc-reset-reinjection");
+}
+#endif
This page took 0.055989 seconds and 4 git commands to generate.