qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH for-1.6] chardev: fix CHR_EVENT_OPENED events for mu


From: Michael Roth
Subject: [Qemu-devel] [PATCH for-1.6] chardev: fix CHR_EVENT_OPENED events for mux chardevs
Date: Tue, 30 Jul 2013 08:19:18 -0500

As of bd5c51ee6c4f1c79cae5ad2516d711a27b4ea8ec, chardevs no longer use
bottom-halves to issue CHR_EVENT_OPENED events. To maintain past
semantics, we instead defer the CHR_EVENT_OPENED events toward the end
of chardev initialization.

For muxes, this isn't good enough, since a range of FEs must be able
to attach to the mux prior to any CHR_EVENT_OPENED being issued, else
each FE will immediately print it's initial output (prompts, banners,
etc.) just prior to us switching to the next FE as part of
initialization.

The is new and confusing behavior for users, as they'll see output for
things like the HMP monitor, even though their the current mux focus
may be a guest serial port with potentially no output.

We fix this by further deferring CHR_EVENT_OPENED events for FEs
associated with muxes until after machine init by flagging mux chardevs
with 'explicit_be_open', which suppresses emission of CHR_EVENT_OPENED
events until we explicitly set the mux as opened later.

Currently, we must defer till after machine init since we potentially
associate FEs with muxes as part of realize (for instance,
serial_isa_realizefn).

Signed-off-by: Michael Roth <address@hidden>
Cc: address@hidden
---
 include/sysemu/char.h |   17 +++++++++++++++++
 qemu-char.c           |   29 +++++++++++++++++++++++++++++
 vl.c                  |    5 +++++
 3 files changed, 51 insertions(+)

diff --git a/include/sysemu/char.h b/include/sysemu/char.h
index e65e4a4..29cef26 100644
--- a/include/sysemu/char.h
+++ b/include/sysemu/char.h
@@ -77,6 +77,7 @@ struct CharDriverState {
     int explicit_fe_open;
     int explicit_be_open;
     int avail_connections;
+    int is_mux;
     QemuOpts *opts;
     QTAILQ_ENTRY(CharDriverState) next;
 };
@@ -278,6 +279,22 @@ void qemu_chr_info_print(Monitor *mon, const QObject 
*ret_data);
 void qemu_chr_info(Monitor *mon, QObject **ret_data);
 CharDriverState *qemu_chr_find(const char *name);
 
+/**
+ * @qemu_chr_mux_realize
+ *
+ * Called after processing of default and command-line-specified
+ * chardevs to deliver CHR_EVENT_OPENED events to any FEs attached
+ * to a mux chardev. This is done here to ensure that
+ * output/prompts/banners are only displayed for the FE that has
+ * focus when initial command-line processing/machine init is
+ * completed.
+ *
+ * After this point, any new FE attached to any new or existing
+ * mux will receive CHR_EVENT_OPENED notifications for the BE
+ * immediately.
+ */
+void qemu_chr_mux_realize(void);
+
 QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename);
 
 void register_char_driver(const char *name, CharDriverState *(*open)(QemuOpts 
*));
diff --git a/qemu-char.c b/qemu-char.c
index 3f606c9..091b949 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -91,6 +91,8 @@
 static QTAILQ_HEAD(CharDriverStateHead, CharDriverState) chardevs =
     QTAILQ_HEAD_INITIALIZER(chardevs);
 
+static bool muxes_realized;
+
 void qemu_chr_be_event(CharDriverState *s, int event)
 {
     /* Keep track if the char device is open */
@@ -492,6 +494,11 @@ static CharDriverState *qemu_chr_open_mux(CharDriverState 
*drv)
     chr->chr_accept_input = mux_chr_accept_input;
     /* Frontend guest-open / -close notification is not support with muxes */
     chr->chr_set_fe_open = NULL;
+    /* only default to opened state if we've realized the initial
+     * set of muxes
+     */
+    chr->explicit_be_open = muxes_realized ? 0 : 1;
+    chr->is_mux = 1;
 
     return chr;
 }
@@ -3412,6 +3419,28 @@ CharDriverState *qemu_chr_find(const char *name)
     return NULL;
 }
 
+void qemu_chr_mux_realize(void)
+{
+    CharDriverState *chr;
+
+    QTAILQ_FOREACH(chr, &chardevs, next) {
+        if (chr->is_mux) {
+            MuxDriver *d = chr->opaque;
+            int i;
+
+            /* send OPENED to all already-attached FEs */
+            for (i = 0; i < d->mux_cnt; i++) {
+                mux_chr_send_event(d, i, CHR_EVENT_OPENED);
+            }
+            /* mark mux as OPENED so any new FEs will immediately receive
+             * OPENED event
+             */
+            qemu_chr_be_generic_open(chr);
+        }
+    }
+    muxes_realized = true;
+}
+
 /* Get a character (serial) device interface.  */
 CharDriverState *qemu_char_get_next_serial(void)
 {
diff --git a/vl.c b/vl.c
index 25b8f2f..64f24df 100644
--- a/vl.c
+++ b/vl.c
@@ -4407,6 +4407,11 @@ int main(int argc, char **argv, char **envp)
      * when bus is created by qdev.c */
     qemu_register_reset(qbus_reset_all_fn, sysbus_get_default());
     qemu_run_machine_init_done_notifiers();
+    /* this must be done after machine init, since we register FEs with muxes
+     * as part of realize functions like serial_isa_realizefn when -nographic
+     * is specified
+     */
+    qemu_chr_mux_realize();
 
     qemu_system_reset(VMRESET_SILENT);
     if (loadvm) {
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]