]> Git Repo - qemu.git/blobdiff - monitor.c
target-mips: Ignore unassigned accesses with KVM
[qemu.git] / monitor.c
index 8c17f899b365db9bbac6a6ce2578602ee0aa6cdc..cdbaa60f9849436a44ea910defe05ff5f4d5d845 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -71,6 +71,8 @@
 #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)
@@ -179,23 +181,28 @@ 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;
@@ -210,6 +217,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;
@@ -268,17 +278,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;
@@ -305,18 +320,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')
@@ -326,9 +349,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)
@@ -439,66 +463,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",
-    [QEVENT_ACPI_OST] = "ACPI_DEVICE_OST",
-};
-QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
 
-static 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;
 
@@ -510,20 +482,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,
@@ -531,8 +501,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;
@@ -548,39 +519,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
@@ -590,65 +561,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,
@@ -667,6 +609,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;
@@ -675,6 +618,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,
@@ -702,11 +646,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);
@@ -1045,10 +991,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));
@@ -1101,6 +1047,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)
@@ -5266,7 +5213,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);
@@ -5286,7 +5235,9 @@ 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:
@@ -5351,13 +5302,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;
     }
@@ -5388,7 +5344,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;
 }
@@ -5483,3 +5442,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.037817 seconds and 4 git commands to generate.