From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:52183) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1V49q0-0002e4-8l for qemu-devel@nongnu.org; Tue, 30 Jul 2013 09:19:46 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1V49pu-0007eX-41 for qemu-devel@nongnu.org; Tue, 30 Jul 2013 09:19:40 -0400 Sender: fluxion From: Michael Roth Date: Tue, 30 Jul 2013 08:19:18 -0500 Message-Id: <1375190358-30371-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH for-1.6] chardev: fix CHR_EVENT_OPENED events for mux chardevs List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@us.ibm.com, mjt@tls.msk.ru, qemu-stable@nongnu.org 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 Cc: qemu-stable@nongnu.org --- 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