From patchwork Thu Oct 10 10:18:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829889 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E1696CF11C6 for ; Thu, 10 Oct 2024 10:21:28 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHd-0006RK-KX; Thu, 10 Oct 2024 06:20:37 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHb-0006QR-Tq for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:35 -0400 Received: from mail-ej1-x635.google.com ([2a00:1450:4864:20::635]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHa-0003Xg-9F for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:35 -0400 Received: by mail-ej1-x635.google.com with SMTP id a640c23a62f3a-a9932aa108cso119595866b.2 for ; Thu, 10 Oct 2024 03:20:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555632; x=1729160432; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=wZr22C6GyP2zNyIOBJrfarPfi36zfJfEl98MesRI/BA=; b=lXL/MEWBxjy7Lv6Gdwuv8yohK1f5mN7R6lx9HQMP43wgablvUhFm4eVmMNWfvxC+X/ QBds6U0kcCNzPBNSf6oYGZfT9iwwymN5lkxVzgoPOfTeIJE+5QepBso9YXJ7llIEIB6K 7Gn/6waiFWMr2hS7WPMC0/ENke/GVIyVzvzgeTym/kR9CchJDmC+2tgcj/+lISD8Mic8 Jgyl2QsPWQ5kpABN+xKV2P+oh9/34hdGsGrgOV8LGBjykvXIulPB/a4uMOJR9a/b4gDH hogBCEMzo5w13qFl4pjbmaC7qmnk7a892bzuTEXmNgBsCT4pCGjPYYLpBSd38qKqYErv n3nw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555632; x=1729160432; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wZr22C6GyP2zNyIOBJrfarPfi36zfJfEl98MesRI/BA=; b=vzt92ZmmZ4P76yzwEGehVnr8e7SrhV2Af9+L7HIWUQaJHoBMbrizDFXzCoz2JFXYyG Y14oCdxa/H0GgllqBlNieqoqvmgGGVlLIFQU4Rehjduea8iJGuKCIrvFZK0+FDDkC4h8 5QZqkHW+13kTtDEN97NhwFncxLiI+UZCZ43WPhvri3TFYOvNQD4ex+9dLFyRo88GBBl9 SGWR2zNw9NwL+mqNN+ZPxf3F03CKAXuHqMAO6lmsPHF89UEU3bNv2sD3wAjfZrhgsZV8 hY2jJzXEWPWfJdDUmg/hE/G7tggCZ5Z3C2cXdn/c1byu0METM0Q8ICyGw5sTuChvPwHg AsgQ== X-Forwarded-Encrypted: i=1; AJvYcCUMc6LGCQ9Y1IB5o0x3TS9OswuUiqoIONbjGl+k+qsrUBKZXnaFUQPrOLbtxFkRf1I60CkuoJ13pKow@nongnu.org X-Gm-Message-State: AOJu0YwYu+xv19wd66XD6ZwNJX3YqpPD4eLO9XL0zLS2jhfzJJSHIbz7 8wlPedEb/jmx4Fi/vreimLGHV5re1PRGcgez/0PsEW1cYBZQPQ8t X-Google-Smtp-Source: AGHT+IF66KnSarY4tEERSdoeZ3NcK1JPl1l8E5rZ5HZGG4ugXPRq5Tg/2q+ac4hxvYDoGSTb9jJrcQ== X-Received: by 2002:a17:907:7b9e:b0:a8d:fa3:bb24 with SMTP id a640c23a62f3a-a998d19fc52mr483919066b.23.1728555631809; Thu, 10 Oct 2024 03:20:31 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:31 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 1/7] chardev/char: rename `char-mux.c` to `char-mux-fe.c` Date: Thu, 10 Oct 2024 12:18:32 +0200 Message-Id: <20241010101838.331032-2-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::635; envelope-from=r.peniaev@gmail.com; helo=mail-ej1-x635.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org In the following patches backend multiplexer will be introduced and the implementation will be named as follows: `char-mux-be.c`. This patch renames the frontend multiplexer from `char-mux.c` to `char-mux-fe.c`. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/{char-mux.c => char-mux-fe.c} | 0 chardev/meson.build | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename chardev/{char-mux.c => char-mux-fe.c} (100%) diff --git a/chardev/char-mux.c b/chardev/char-mux-fe.c similarity index 100% rename from chardev/char-mux.c rename to chardev/char-mux-fe.c diff --git a/chardev/meson.build b/chardev/meson.build index 70070a8279a9..778444a00ca6 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -2,7 +2,7 @@ chardev_ss.add(files( 'char-fe.c', 'char-file.c', 'char-io.c', - 'char-mux.c', + 'char-mux-fe.c', 'char-null.c', 'char-pipe.c', 'char-ringbuf.c', From patchwork Thu Oct 10 10:18:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829892 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E61EFCF11C6 for ; Thu, 10 Oct 2024 10:22:02 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHg-0006Sr-43; Thu, 10 Oct 2024 06:20:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHd-0006R0-7T for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:37 -0400 Received: from mail-ej1-x62c.google.com ([2a00:1450:4864:20::62c]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHa-0003Xm-FC for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:36 -0400 Received: by mail-ej1-x62c.google.com with SMTP id a640c23a62f3a-a99422929c5so89630066b.0 for ; Thu, 10 Oct 2024 03:20:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555633; x=1729160433; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=hKDzqyax2qKyd+N8mhq+Mp3gABt7BQpJI6OVdd7Cz18=; b=BCnRZ7rOQSWnGkcGN2v11kPfdc45zqJMMDAosLIS3lbLrI3myvQIqq98ys36bAr3k2 q37tN6i8wInMPKxLzrNxpulV+3/wNZ4DLpbh7TUzopoqnLeH96a3gzE19TqJCdgKT1bJ W0m1JvrweTOqL+Vy2wc77b6tr6qN1M6eWsVel6lG+Jmk8Zo8XLFKrkMoIImLDzOO2R4g gP3vO70yybIjHT12m7U+eceYnZG3IxsL3FKOWMarnAfl4rKSznp12jf1FMcFMiD52v6Y QA0zszMH3573BXFj7PkRlQfyXqQLbqcqJSvTOKVz7uHTX4QUqXIW6pJMDM53gdDwglO/ Ox/A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555633; x=1729160433; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=hKDzqyax2qKyd+N8mhq+Mp3gABt7BQpJI6OVdd7Cz18=; b=vQOCjJ5ch+RcC8Uv7dezBt2aXlDNBz5owLqWiWYQAyI3CAcP7Ow7b/paGB4vWvAwPf JC20ufFOFGxgcD8O204yv0TFQ5NA7ZFvrs4chZ/Wew4fP2Nmweeqxq65H3CwG1aTSHB4 2aa1zE733q1RDToH1yQKm8FkgFIRmn2KLo01Eh3EfAQRMtdJjnuphDiBA5QTLBhZyty6 Dcf2M8UvssBfWtDGYZzKu3bmtDDnRFTe6TdNZUPs0dVzKzwHFkxkoEdNv+GwBHOd1FnY 5VWfwbfZnnbxsxy41RD1YAvxL8OgRMkT+zIVdT4KD9UESeQ7JGDEePioBvWqIUzI44+3 uRuA== X-Forwarded-Encrypted: i=1; AJvYcCUZp0NAoD5Zv++GU0u20zIEkn4w7dFQi3F1zljK3V/cSNFQk2PzPSZIxUoVR0OIwTWErdz/bgn/tj8A@nongnu.org X-Gm-Message-State: AOJu0YzkLJE55g3evmurGXepVpdHLeh+dT02rDfXStrU+RbjvvMc2in9 Lqw9FLbRIEY5s1qaP/JOQLU8zdVlOMQRdwyP6Qs9d9M18OYnc0IKPWC2ig== X-Google-Smtp-Source: AGHT+IG5JfdBMKYCTEiPbju1tQDeHqOpCUSX07QskTqYCko846g2j9tgNukhKsbH4xYneLzXNnPE6Q== X-Received: by 2002:a17:907:7e83:b0:a99:446f:4c1 with SMTP id a640c23a62f3a-a998d20e83dmr513675666b.33.1728555632338; Thu, 10 Oct 2024 03:20:32 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:32 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 2/7] chardev/char: move away mux suspend/resume calls Date: Thu, 10 Oct 2024 12:18:33 +0200 Message-Id: <20241010101838.331032-3-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::62c; envelope-from=r.peniaev@gmail.com; helo=mail-ej1-x62c.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The suspend/resume open multiplexer calls are generic and will be used for frontend (current mux) and backend (will follow) implementations. Move them away from the `char-mux-fe.c` to more generic `char.c` file. Also for the sake of clarity these renames were made: s/suspend_mux_open/mux_suspend_open/g s/resume_mux_open/mux_resume_open/g No functional changes are made. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-mux-fe.c | 63 ++------------------------------- chardev/char.c | 72 ++++++++++++++++++++++++++++++++++++++ chardev/chardev-internal.h | 3 ++ include/chardev/char.h | 5 +-- system/vl.c | 4 +-- 5 files changed, 82 insertions(+), 65 deletions(-) diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c index 673971ca1798..cd9ff0c5dc12 100644 --- a/chardev/char-mux-fe.c +++ b/chardev/char-mux-fe.c @@ -33,13 +33,6 @@ /* MUX driver for serial I/O splitting */ -/* - * Set to false by suspend_mux_open. Open events are delayed until - * resume_mux_open. Usually suspend_mux_open is called before - * command line processing and resume_mux_open afterwards. - */ -static bool muxes_opened = true; - /* Called with chr_write_lock held. */ static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) { @@ -239,15 +232,10 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) } } -void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) +void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event) { - MuxFeChardev *d = MUX_FE_CHARDEV(chr); int i; - if (!muxes_opened) { - return; - } - /* Send the event to all registered listeners */ for (i = 0; i < d->mux_cnt; i++) { mux_chr_send_event(d, i, event); @@ -335,7 +323,7 @@ static void qemu_chr_open_mux(Chardev *chr, /* only default to opened state if we've realized the initial * set of muxes */ - *be_opened = muxes_opened; + *be_opened = mux_is_opened(); qemu_chr_fe_init(&d->chr, drv, errp); } @@ -355,53 +343,6 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, mux->chardev = g_strdup(chardev); } -/** - * 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. - */ -static void open_muxes(Chardev *chr) -{ - /* send OPENED to all already-attached FEs */ - mux_chr_send_all_event(chr, CHR_EVENT_OPENED); - - /* - * mark mux as OPENED so any new FEs will immediately receive - * OPENED event - */ - chr->be_open = 1; -} - -void suspend_mux_open(void) -{ - muxes_opened = false; -} - -static int chardev_options_parsed_cb(Object *child, void *opaque) -{ - Chardev *chr = (Chardev *)child; - - if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { - open_muxes(chr); - } - - return 0; -} - -void resume_mux_open(void) -{ - muxes_opened = true; - object_child_foreach(get_chardevs_root(), - chardev_options_parsed_cb, NULL); -} - static void char_mux_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); diff --git a/chardev/char.c b/chardev/char.c index 9d180f996dfb..d38a0c76a51e 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -43,6 +43,13 @@ #include "chardev-internal.h" +/* + * Set to false by mux_suspend_open(). Open events are delayed until + * mux_resume_open(). Usually mux_suspend_open() is called before + * command line processing and mux_resume_open() afterwards. + */ +static bool muxes_opened = true; + /***********************************************************/ /* character device */ @@ -1259,6 +1266,71 @@ void qemu_chr_cleanup(void) object_unparent(get_chardevs_root()); } +/** + * 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. + */ +static void open_muxes(Chardev *chr) +{ + /* send OPENED to all already-attached FEs */ + mux_chr_send_all_event(chr, CHR_EVENT_OPENED); + + /* + * mark mux as OPENED so any new FEs will immediately receive + * OPENED event + */ + chr->be_open = 1; +} + +void mux_suspend_open(void) +{ + muxes_opened = false; +} + +static int chardev_options_parsed_cb(Object *child, void *opaque) +{ + Chardev *chr = (Chardev *)child; + + if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { + open_muxes(chr); + } + + return 0; +} + +void mux_resume_open(void) +{ + muxes_opened = true; + object_child_foreach(get_chardevs_root(), + chardev_options_parsed_cb, NULL); +} + +bool mux_is_opened(void) +{ + return muxes_opened; +} + +void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) +{ + if (!mux_is_opened()) { + return; + } + + if (CHARDEV_IS_MUX_FE(chr)) { + MuxFeChardev *d = MUX_FE_CHARDEV(chr); + + mux_fe_chr_send_all_event(d, event); + } +} + static void register_types(void) { type_register_static(&char_type_info); diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index 1b943c81bcd8..a77f0bdaccfa 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -63,6 +63,9 @@ DECLARE_INSTANCE_CHECKER(MuxFeChardev, MUX_FE_CHARDEV, void mux_set_focus(Chardev *chr, int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); +/* Mux type dependent calls */ +void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event); + Object *get_chardevs_root(void); #endif /* CHARDEV_INTERNAL_H */ diff --git a/include/chardev/char.h b/include/chardev/char.h index d9d23b6232db..0bec974f9d73 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -317,7 +317,8 @@ extern int term_escape_char; GSource *qemu_chr_timeout_add_ms(Chardev *chr, guint ms, GSourceFunc func, void *private); -void suspend_mux_open(void); -void resume_mux_open(void); +bool mux_is_opened(void); +void mux_suspend_open(void); +void mux_resume_open(void); #endif diff --git a/system/vl.c b/system/vl.c index fe547ca47c27..6222e0625b1e 100644 --- a/system/vl.c +++ b/system/vl.c @@ -3690,7 +3690,7 @@ void qemu_init(int argc, char **argv) qemu_create_machine(machine_opts_dict); - suspend_mux_open(); + mux_suspend_open(); qemu_disable_default_devices(); qemu_setup_display(); @@ -3768,5 +3768,5 @@ void qemu_init(int argc, char **argv) qemu_init_displays(); accel_setup_post(current_machine); os_setup_post(); - resume_mux_open(); + mux_resume_open(); } From patchwork Thu Oct 10 10:18:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829894 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 56B44CF11C6 for ; Thu, 10 Oct 2024 10:22:35 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHf-0006Rx-95; Thu, 10 Oct 2024 06:20:39 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHd-0006Qz-6p for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:37 -0400 Received: from mail-lf1-x136.google.com ([2a00:1450:4864:20::136]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHb-0003Xx-1p for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:36 -0400 Received: by mail-lf1-x136.google.com with SMTP id 2adb3069b0e04-539885dd4bcso958599e87.0 for ; Thu, 10 Oct 2024 03:20:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555633; x=1729160433; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=G7795s3+Tby/c7sooRXSohBfy29e7ZGsDck71B2OYAg=; b=S87rCP/f/JIWDEFuxV1gPoFQ1yi9sLWFcdFLlOsH2M7F+aaGLIs5GjFavGQw8JfBcC LR3JJezeAG+i/hJQS2K3ASIj/NZzCSRltpNlq+MUGjJPd9hapVCDVwNuzsmd53TXogmk S97iNKW3FPJ2RUyE4RfoItVZMp5AWPO8HnbuO5jV0aECQ8dx3ukQjiDdSFZdiNPuyoaU KyVUbH4quASRfHgVLHHZWy3bMXbqjNOye3Yay5uDZQAn5Z003TfGdE0l0AhhdDn7+ECy 67oqt1I4Bq/52vLCX8oO6G3COlCO/oMoVPEuojNiS/aRmKaPvSbyR0WU7J3rFJEGivTO p0VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555633; x=1729160433; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G7795s3+Tby/c7sooRXSohBfy29e7ZGsDck71B2OYAg=; b=NSE2Ik4qQckI0Gkah/2sreGBNBkxp4XhkPQGCIWYIiv5WT69won0ph9cR443XbU/N3 L5o+nMc3a8OswYsEbkgMhEd/9exdZJwcD92QT3o6CXaAlIaWVx0VlWzTFgeKhhvY0PxR OrAh/GvXE5ZBXG1V4WWrb7/73VJi97Vjmu6fJYUxc5DVd/8E2yMsyPbDFi6FoxU/Nt+o cFAgRFVus7vy2G5qvUIAvIRnZr3lkBKkKHB47rl+InwPjtT8TFKV2rhqk7ruaSghNCh7 LRqTA0ioSsjfr7igzgJrflMADzIFY9mp8A22nyiu0GRZU/TWj0BOsXmIg4ATb97h8rm+ +0GQ== X-Forwarded-Encrypted: i=1; AJvYcCUOypc0AIm/2I8M+yTl5vYVoL8nWgmAWoUovrVrjVT73CdUAArd7sE/e3I/mPXMGZtZaboBWrXCXOxp@nongnu.org X-Gm-Message-State: AOJu0YzeIfUPOjTjXT+zmBtDwuQhRVsUYYwFFkTLINckiZeCScooGj+0 4JAcZjWTaI77nTvMrcpxQfzPYHRTpIDgX+/iu26mPyPgDDIdoo8x X-Google-Smtp-Source: AGHT+IFrtRXZztqCU344Sc+aoTtin1a2jZRYj2vvmCXWshIQc0iuENuUifSJeZjxeesWbjJR/kuWYg== X-Received: by 2002:a05:6512:1244:b0:539:9092:809e with SMTP id 2adb3069b0e04-539c49691a8mr3686387e87.50.1728555632912; Thu, 10 Oct 2024 03:20:32 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:32 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 3/7] chardev/char: rename frontend mux calls Date: Thu, 10 Oct 2024 12:18:34 +0200 Message-Id: <20241010101838.331032-4-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::136; envelope-from=r.peniaev@gmail.com; helo=mail-lf1-x136.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch renames calls in the frontend mux implementation to reflect its frontend nature. Patch does the following: s/mux_chr/mux_fe_chr/g No functional changes are made. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-mux-fe.c | 57 ++++++++++++++++++++++--------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/chardev/char-mux-fe.c b/chardev/char-mux-fe.c index cd9ff0c5dc12..5a8860b4310e 100644 --- a/chardev/char-mux-fe.c +++ b/chardev/char-mux-fe.c @@ -34,7 +34,7 @@ /* MUX driver for serial I/O splitting */ /* Called with chr_write_lock held. */ -static int mux_chr_write(Chardev *chr, const uint8_t *buf, int len) +static int mux_fe_chr_write(Chardev *chr, const uint8_t *buf, int len) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); int ret; @@ -117,7 +117,8 @@ static void mux_print_help(Chardev *chr) } } -static void mux_chr_send_event(MuxFeChardev *d, int mux_nr, QEMUChrEvent event) +static void mux_fe_chr_send_event(MuxFeChardev *d, int mux_nr, + QEMUChrEvent event) { CharBackend *be = d->backends[mux_nr]; @@ -126,12 +127,12 @@ static void mux_chr_send_event(MuxFeChardev *d, int mux_nr, QEMUChrEvent event) } } -static void mux_chr_be_event(Chardev *chr, QEMUChrEvent event) +static void mux_fe_chr_be_event(Chardev *chr, QEMUChrEvent event) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); if (d->focus != -1) { - mux_chr_send_event(d, d->focus, event); + mux_fe_chr_send_event(d, d->focus, event); } } @@ -180,7 +181,7 @@ static int mux_proc_byte(Chardev *chr, MuxFeChardev *d, int ch) return 0; } -static void mux_chr_accept_input(Chardev *chr) +static void mux_fe_chr_accept_input(Chardev *chr) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); int m = d->focus; @@ -193,7 +194,7 @@ static void mux_chr_accept_input(Chardev *chr) } } -static int mux_chr_can_read(void *opaque) +static int mux_fe_chr_can_read(void *opaque) { MuxFeChardev *d = MUX_FE_CHARDEV(opaque); int m = d->focus; @@ -210,7 +211,7 @@ static int mux_chr_can_read(void *opaque) return 0; } -static void mux_chr_read(void *opaque, const uint8_t *buf, int size) +static void mux_fe_chr_read(void *opaque, const uint8_t *buf, int size) { Chardev *chr = CHARDEV(opaque); MuxFeChardev *d = MUX_FE_CHARDEV(opaque); @@ -218,7 +219,7 @@ static void mux_chr_read(void *opaque, const uint8_t *buf, int size) CharBackend *be = d->backends[m]; int i; - mux_chr_accept_input(opaque); + mux_fe_chr_accept_input(opaque); for (i = 0; i < size; i++) if (mux_proc_byte(chr, d, buf[i])) { @@ -238,16 +239,16 @@ void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event) /* Send the event to all registered listeners */ for (i = 0; i < d->mux_cnt; i++) { - mux_chr_send_event(d, i, event); + mux_fe_chr_send_event(d, i, event); } } -static void mux_chr_event(void *opaque, QEMUChrEvent event) +static void mux_fe_chr_event(void *opaque, QEMUChrEvent event) { mux_chr_send_all_event(CHARDEV(opaque), event); } -static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) +static GSource *mux_fe_chr_add_watch(Chardev *s, GIOCondition cond) { MuxFeChardev *d = MUX_FE_CHARDEV(s); Chardev *chr = qemu_chr_fe_get_driver(&d->chr); @@ -260,7 +261,7 @@ static GSource *mux_chr_add_watch(Chardev *s, GIOCondition cond) return cc->chr_add_watch(chr, cond); } -static void char_mux_finalize(Object *obj) +static void char_mux_fe_finalize(Object *obj) { MuxFeChardev *d = MUX_FE_CHARDEV(obj); int i; @@ -274,15 +275,15 @@ static void char_mux_finalize(Object *obj) qemu_chr_fe_deinit(&d->chr, false); } -static void mux_chr_update_read_handlers(Chardev *chr) +static void mux_fe_chr_update_read_handlers(Chardev *chr) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); /* Fix up the real driver with mux routines */ qemu_chr_fe_set_handlers_full(&d->chr, - mux_chr_can_read, - mux_chr_read, - mux_chr_event, + mux_fe_chr_can_read, + mux_fe_chr_read, + mux_fe_chr_event, NULL, chr, chr->gcontext, true, false); @@ -296,12 +297,12 @@ void mux_set_focus(Chardev *chr, int focus) assert(focus < d->mux_cnt); if (d->focus != -1) { - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); + mux_fe_chr_send_event(d, d->focus, CHR_EVENT_MUX_OUT); } d->focus = focus; chr->be = d->backends[focus]; - mux_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); + mux_fe_chr_send_event(d, d->focus, CHR_EVENT_MUX_IN); } static void qemu_chr_open_mux(Chardev *chr, @@ -343,30 +344,30 @@ static void qemu_chr_parse_mux(QemuOpts *opts, ChardevBackend *backend, mux->chardev = g_strdup(chardev); } -static void char_mux_class_init(ObjectClass *oc, void *data) +static void char_mux_fe_class_init(ObjectClass *oc, void *data) { ChardevClass *cc = CHARDEV_CLASS(oc); cc->parse = qemu_chr_parse_mux; cc->open = qemu_chr_open_mux; - cc->chr_write = mux_chr_write; - cc->chr_accept_input = mux_chr_accept_input; - cc->chr_add_watch = mux_chr_add_watch; - cc->chr_be_event = mux_chr_be_event; - cc->chr_update_read_handler = mux_chr_update_read_handlers; + cc->chr_write = mux_fe_chr_write; + cc->chr_accept_input = mux_fe_chr_accept_input; + cc->chr_add_watch = mux_fe_chr_add_watch; + cc->chr_be_event = mux_fe_chr_be_event; + cc->chr_update_read_handler = mux_fe_chr_update_read_handlers; } -static const TypeInfo char_mux_type_info = { +static const TypeInfo char_mux_fe_type_info = { .name = TYPE_CHARDEV_MUX_FE, .parent = TYPE_CHARDEV, - .class_init = char_mux_class_init, + .class_init = char_mux_fe_class_init, .instance_size = sizeof(MuxFeChardev), - .instance_finalize = char_mux_finalize, + .instance_finalize = char_mux_fe_finalize, }; static void register_types(void) { - type_register_static(&char_mux_type_info); + type_register_static(&char_mux_fe_type_info); } type_init(register_types); From patchwork Thu Oct 10 10:18:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829893 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 14A31CF11C6 for ; Thu, 10 Oct 2024 10:22:09 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHe-0006Rs-Bu; Thu, 10 Oct 2024 06:20:38 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHd-0006Qj-1t for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:37 -0400 Received: from mail-ej1-x629.google.com ([2a00:1450:4864:20::629]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHb-0003Y9-As for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:36 -0400 Received: by mail-ej1-x629.google.com with SMTP id a640c23a62f3a-a994c322aefso341655066b.1 for ; Thu, 10 Oct 2024 03:20:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555634; x=1729160434; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=/B3uUlTe/WJMxVfEt4kkHWNRgsgqgpvt34BgS/aXzq0=; b=KitXSroHn6XrczbWDQWUI4ufYCuYsfD6p/ODQVm2ArV5CGrKkgPATeQmkdWdTgWj+V k4JElsQQ4sbdshmcIA9afcutU9UURkkQZ1HvcAmGnXHLMX+K7E7WnvDsyLo9znLv77xc V7m51Cdorf83Igy13dFuxWIazwCgovqJQ1Duhb4MXOcQ4qQGiucZ/wh5vrIlfqHcJCJ9 aUsavhLA07NmWUERtzZFN8nsn7efzvuyja9/nnhOAov9gslv7YA/Jwul1FBgPyFSXm6Q K4vpYyhZI6003TnBiyraO5KqcGcyv8iQtCGxtAUV1ehS198DMx4zDDPS3EE4omQ4+A46 Yugg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555634; x=1729160434; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/B3uUlTe/WJMxVfEt4kkHWNRgsgqgpvt34BgS/aXzq0=; b=EuiXQTJ0duMJvPaxmGPTWtbPW85/0c7hT3BK4+S9NEQLH/dUk5rQEtTHKpJ+vSJ/vU Ec4cNVRDfacyT/HnbTiMJvwOcMLZd+ziMYn9YWiDB46WoalxjmJqvNGqbgq1QwsreQRY h/xhM9NYL3CMYgCBexUnxkN+t1BfDnbDehnaYZHmz6NqVMXkR4EqbVhZswGMS9gKbiin +AnxexPYnWYNtveQs52skEhAPtmgu3Q7WqfLjAx55vHCshrVAGXo2ehpTCZJYPHEkCh2 kyZ3j+hKlGJ6djaz6kl8a36OLJf6ZNVItrk4JWWyMgjKnc/4qpukM8SiEhGoccG6rgL0 GPxg== X-Forwarded-Encrypted: i=1; AJvYcCXV6TUfac091hiSM/FxaFXf9gVOtDQ2HocthDO1sGbueNKU63oLILmGixIqpS37FwcFZbRj8FXTgjb0@nongnu.org X-Gm-Message-State: AOJu0Yw4mOy6ZUgQMRO7JOfs0HTj7iIT5V95Kl5Z5T/9v8ZbPI8+nPms 8O1t1uoSoSLP++YYUi8VgFD5uZYQv33sPj44cSeT9EqLgm0QojDsgBAAsQ== X-Google-Smtp-Source: AGHT+IHD7o2J07QLYqLkFfDnkC1JRDTpXLO6DjL5U90wWNGqiHauVuPhfJkWfB/OKKCkUhec+I/xRA== X-Received: by 2002:a17:906:7312:b0:a77:ca3b:996c with SMTP id a640c23a62f3a-a99a110835amr274730066b.16.1728555633750; Thu, 10 Oct 2024 03:20:33 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:33 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 4/7] chardev/char: introduce `mux-be-id=ID` option Date: Thu, 10 Oct 2024 12:18:35 +0200 Message-Id: <20241010101838.331032-5-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::629; envelope-from=r.peniaev@gmail.com; helo=mail-ej1-x629.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Patch introduces `mux-be-id=ID` option for all chardev devices. This is necessary to attach chardev to `mux-be` for backend multiplexing. Actual implementation wimplementation will follow. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char.c | 3 +++ qapi/char.json | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/chardev/char.c b/chardev/char.c index d38a0c76a51e..ec9a6c4d2499 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -933,6 +933,9 @@ QemuOptsList qemu_chardev_opts = { },{ .name = "mux", .type = QEMU_OPT_BOOL, + },{ + .name = "mux-be-id", + .type = QEMU_OPT_STRING, },{ .name = "signal", .type = QEMU_OPT_BOOL, diff --git a/qapi/char.json b/qapi/char.json index e04535435034..fb0dedb24383 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -199,11 +199,15 @@ # @logappend: true to append instead of truncate (default to false to # truncate) # +# @mux-be-id: id of the mux-be device for backend multiplexing +# (since: 9.2) +# # Since: 2.6 ## { 'struct': 'ChardevCommon', 'data': { '*logfile': 'str', - '*logappend': 'bool' } } + '*logappend': 'bool', + '*mux-be-id': 'str' } } ## # @ChardevFile: From patchwork Thu Oct 10 10:18:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829891 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4EC06CF11C6 for ; Thu, 10 Oct 2024 10:21:59 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHh-0006T9-Tu; Thu, 10 Oct 2024 06:20:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHg-0006Sq-2n for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:40 -0400 Received: from mail-lf1-x135.google.com ([2a00:1450:4864:20::135]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHd-0003Yl-4W for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:39 -0400 Received: by mail-lf1-x135.google.com with SMTP id 2adb3069b0e04-539983beb19so808265e87.3 for ; Thu, 10 Oct 2024 03:20:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555635; x=1729160435; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=zQWgWwVNAcci9xN5Q9kKzz6kS9fxlr0KyGlQkV4Cjz0=; b=ONXDhvvX4oeD6OSaZIK3KBuPkTpnJltNbTPdR4tMOCNONqf/KuRYc2rRp7LiiLtf4B HP5cV0HWm0pqQxgPQ/8XMTOCSFo3rJmqplw2q/Y72BX6SBKCgdf1gdijMNMLrBYONzCm LZEfcPd5qpiJs0PPGOYo4c+25q4QpAhGCXag36PkqIDOG8AqC4gDTSq3VV3dKGlXuBsL pqiLEX0gZCN+JKs2YCArxuM0kWaY6PGlEh8IRR/650zCeuwgNYR3US0dxVdLjZ57pNv4 VFVamgXF3m9tTzbfkgWa01KYd09lrC/ISj1MRxZCDKPFjfIt8h31sxcL2nX3ea8U3uJv mUXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555635; x=1729160435; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zQWgWwVNAcci9xN5Q9kKzz6kS9fxlr0KyGlQkV4Cjz0=; b=pncvAuA50GBEcz/yocVxm5OcXCsiI/4AhUcBasbgJVfxMcm69lWg8Rs8DlMhivazXI VPpdwa82EZyPaXs8UOh1ozjoT8HGwtCcD+v8P6m8ebRbkA2IPFBY9jcsZbKdyeJM7ytf NEKKEoJc70exlWYnZZe8Whk8LPZg6LjQHjEQxNki+NJ1/+MD0Gfi4EF3nppmpu2U+5zS Y78PUXHl8f6Vlow7WFCDFFAE40ygwR7EWkoRn7jwQRDMiUxwierg9MAWzVFYW/owUXUv xlP5jRPT7lSNHIpciokvhq1kFWtysmabDrQr/4+nsh5uY7BZSi+AHrwrN3r1C6+o6ddZ JCDQ== X-Forwarded-Encrypted: i=1; AJvYcCV34Tzw0ENRvxUc+cn5vt6Z3inRPIxjrG/9cFHSkb4ZVMG3IYfcblSl8ahzPidkpObzMjQSbLtSB1NL@nongnu.org X-Gm-Message-State: AOJu0YxCdifpWGIau/DYZmJynABPicpzZbYRZ69PQyQ5pQaKncE03FyF HS5yv1gLluL1rdp0YUH8+sM4SMjdynxLd29U+dAd8ydekTFfki1g X-Google-Smtp-Source: AGHT+IH85tbRjPP1pnWWFzODAFx+xX1ElraD5pJFvk7/3QwwcQ3jRfgI78ylAukbx57Uw8o7FihjJA== X-Received: by 2002:a05:6512:3096:b0:539:93b2:1373 with SMTP id 2adb3069b0e04-539c4898a04mr3403020e87.20.1728555634987; Thu, 10 Oct 2024 03:20:34 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:34 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 5/7] chardev/char-mux: implement backend chardev multiplexing Date: Thu, 10 Oct 2024 12:18:36 +0200 Message-Id: <20241010101838.331032-6-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::135; envelope-from=r.peniaev@gmail.com; helo=mail-lf1-x135.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This patch implements multiplexing capability of several backend devices, which opens up an opportunity to use a single frontend device on the guest, which can be manipulated from several backend devices. The idea of the change is trivial: keep list of backend devices (up to 4), init them on demand and forward data buffer back and forth. Patch implements another multiplexer type `mux-be`. The following is QEMU command line example: -chardev mux-be,id=mux0 \ -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \ -chardev vc,id=vc0,mux-be-id=mux0 \ -device virtconsole,chardev=mux0 \ -vnc 0.0.0.0:0 which creates 2 backend devices: text virtual console (`vc0`) and a socket (`sock0`) connected to the single virtio hvc console with the backend multiplexer (`mux0`) help. `vc0` renders text to an image, which can be shared over the VNC protocol. `sock0` is a socket backend which provides biderectional communication to the virtio hvc console. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- chardev/char-fe.c | 14 ++ chardev/char-mux-be.c | 272 +++++++++++++++++++++++++++++++++++++ chardev/char.c | 56 ++++++-- chardev/chardev-internal.h | 27 +++- chardev/meson.build | 1 + include/chardev/char.h | 1 + qapi/char.json | 25 ++++ 7 files changed, 383 insertions(+), 13 deletions(-) create mode 100644 chardev/char-mux-be.c diff --git a/chardev/char-fe.c b/chardev/char-fe.c index 71d6212b13f8..33f7a04b3c60 100644 --- a/chardev/char-fe.c +++ b/chardev/char-fe.c @@ -207,6 +207,17 @@ bool qemu_chr_fe_init(CharBackend *b, Chardev *s, Error **errp) d->backends[d->mux_cnt] = b; tag = d->mux_cnt++; + } else if (CHARDEV_IS_MUX_BE(s)) { + MuxBeChardev *d = MUX_BE_CHARDEV(s); + + if (d->frontend) { + error_setg(errp, + "multiplexed chardev '%s' is already used " + "for multiplexing", s->label); + return false; + } + d->frontend = b; + } else if (s->be) { error_setg(errp, "chardev '%s' is already in use", s->label); return false; @@ -233,6 +244,9 @@ void qemu_chr_fe_deinit(CharBackend *b, bool del) if (CHARDEV_IS_MUX_FE(b->chr)) { MuxFeChardev *d = MUX_FE_CHARDEV(b->chr); d->backends[b->tag] = NULL; + } else if (CHARDEV_IS_MUX_BE(b->chr)) { + MuxBeChardev *d = MUX_BE_CHARDEV(b->chr); + d->frontend = NULL; } if (del) { Object *obj = OBJECT(b->chr); diff --git a/chardev/char-mux-be.c b/chardev/char-mux-be.c new file mode 100644 index 000000000000..2f8a55b0dcce --- /dev/null +++ b/chardev/char-mux-be.c @@ -0,0 +1,272 @@ +/* + * QEMU Character Backend Multiplexer + * + * Author: Roman Penyaev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "qemu/osdep.h" +#include "qapi/error.h" +#include "qemu/module.h" +#include "qemu/option.h" +#include "qemu/cutils.h" +#include "chardev/char.h" +#include "sysemu/block-backend.h" +#include "qapi/qapi-commands-control.h" +#include "qapi/clone-visitor.h" +#include "qapi/qapi-builtin-visit.h" +#include "chardev-internal.h" + +/* + * MUX-BE driver for multiplexing 1 frontend device with N backend devices + */ + +/* + * Write to all backends. Different backend devices accept data with + * various rate, so it is quite possible that one device returns less, + * then others. In this case we return minimum to the caller, + * expecting caller will repeat operation soon. When repeat happens + * send to the devices which consume data faster must be avoided + * for obvious reasons not to send data, which was already sent. + */ +static int mux_be_chr_write_to_all(MuxBeChardev *d, const uint8_t *buf, int len) +{ + int r, i, ret = len; + unsigned int written; + + for (i = 0; i < d->mux_cnt; i++) { + written = d->be_written[i] - d->be_min_written; + if (written) { + /* Written in the previous call so take into account */ + ret = MIN(written, ret); + continue; + } + r = qemu_chr_fe_write(&d->backends[i], buf, len); + if (r < 0 && errno == EAGAIN) { + /* + * Fail immediately if write would block. Expect to be called + * soon on watch wake up. + */ + return r; + } else if (r < 0) { + /* + * Ignore all other errors and pretend the entire buffer is + * written to avoid this chardev being watched. This device + * becomes disabled until the following write succeeds, but + * writing continues to others. + */ + r = len; + } + d->be_written[i] += r; + ret = MIN(r, ret); + } + d->be_min_written += ret; + + return ret; +} + +/* Called with chr_write_lock held. */ +static int mux_be_chr_write(Chardev *chr, const uint8_t *buf, int len) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + return mux_be_chr_write_to_all(d, buf, len); +} + +static void mux_be_chr_send_event(MuxBeChardev *d, QEMUChrEvent event) +{ + CharBackend *fe = d->frontend; + + if (fe && fe->chr_event) { + fe->chr_event(fe->opaque, event); + } +} + +static void mux_be_chr_be_event(Chardev *chr, QEMUChrEvent event) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + + mux_be_chr_send_event(d, event); +} + +static int mux_be_chr_can_read(void *opaque) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(opaque); + CharBackend *fe = d->frontend; + + if (fe && fe->chr_can_read) { + return fe->chr_can_read(fe->opaque); + } + + return 0; +} + +static void mux_be_chr_read(void *opaque, const uint8_t *buf, int size) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(opaque); + CharBackend *fe = d->frontend; + + if (fe && fe->chr_read) { + fe->chr_read(fe->opaque, buf, size); + } +} + +void mux_be_chr_send_all_event(MuxBeChardev *d, QEMUChrEvent event) +{ + mux_be_chr_send_event(d, event); +} + +static void mux_be_chr_event(void *opaque, QEMUChrEvent event) +{ + mux_chr_send_all_event(CHARDEV(opaque), event); +} + +static GSource *mux_be_chr_add_watch(Chardev *s, GIOCondition cond) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(s); + Chardev *chr; + ChardevClass *cc; + unsigned int written; + int i; + + for (i = 0; i < d->mux_cnt; i++) { + written = d->be_written[i] - d->be_min_written; + if (written) { + /* We skip the device with already written buffer */ + continue; + } + + /* + * The first device that has no data written to it must be + * the device that recently returned EAGAIN and should be + * watched. + */ + + chr = qemu_chr_fe_get_driver(&d->backends[i]); + cc = CHARDEV_GET_CLASS(chr); + + if (!cc->chr_add_watch) { + return NULL; + } + + return cc->chr_add_watch(chr, cond); + } + + return NULL; +} + +bool mux_be_chr_attach_chardev(MuxBeChardev *d, Chardev *chr, Error **errp) +{ + bool ret; + + if (d->mux_cnt >= MAX_MUX) { + error_setg(errp, "too many uses of multiplexed chardev '%s'" + " (maximum is " stringify(MAX_MUX) ")", + d->parent.label); + return false; + } + ret = qemu_chr_fe_init(&d->backends[d->mux_cnt], chr, errp); + if (ret) { + /* Catch up with what was already written */ + d->be_written[d->mux_cnt] = d->be_min_written; + d->mux_cnt += 1; + } + + return ret; +} + +static void char_mux_be_finalize(Object *obj) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(obj); + CharBackend *fe = d->frontend; + int i; + + if (fe) { + fe->chr = NULL; + } + for (i = 0; i < d->mux_cnt; i++) { + qemu_chr_fe_deinit(&d->backends[i], false); + } +} + +static void mux_be_chr_update_read_handlers(Chardev *chr) +{ + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + int i; + + for (i = 0; i < d->mux_cnt; i++) { + /* Fix up the real driver with mux routines */ + qemu_chr_fe_set_handlers_full(&d->backends[i], + mux_be_chr_can_read, + mux_be_chr_read, + mux_be_chr_event, + NULL, + chr, + chr->gcontext, true, false); + } +} + +static void qemu_chr_open_mux_be(Chardev *chr, + ChardevBackend *backend, + bool *be_opened, + Error **errp) +{ + /* + * Only default to opened state if we've realized the initial + * set of muxes + */ + *be_opened = mux_is_opened(); +} + +static void qemu_chr_parse_mux_be(QemuOpts *opts, ChardevBackend *backend, + Error **errp) +{ + ChardevMuxBe *mux; + + backend->type = CHARDEV_BACKEND_KIND_MUX_BE; + mux = backend->u.mux_be.data = g_new0(ChardevMuxBe, 1); + qemu_chr_parse_common(opts, qapi_ChardevMuxBe_base(mux)); +} + +static void char_mux_be_class_init(ObjectClass *oc, void *data) +{ + ChardevClass *cc = CHARDEV_CLASS(oc); + + cc->parse = qemu_chr_parse_mux_be; + cc->open = qemu_chr_open_mux_be; + cc->chr_write = mux_be_chr_write; + cc->chr_add_watch = mux_be_chr_add_watch; + cc->chr_be_event = mux_be_chr_be_event; + cc->chr_update_read_handler = mux_be_chr_update_read_handlers; +} + +static const TypeInfo char_mux_be_type_info = { + .name = TYPE_CHARDEV_MUX_BE, + .parent = TYPE_CHARDEV, + .class_init = char_mux_be_class_init, + .instance_size = sizeof(MuxBeChardev), + .instance_finalize = char_mux_be_finalize, +}; + +static void register_types(void) +{ + type_register_static(&char_mux_be_type_info); +} + +type_init(register_types); diff --git a/chardev/char.c b/chardev/char.c index ec9a6c4d2499..c010679b64f7 100644 --- a/chardev/char.c +++ b/chardev/char.c @@ -341,6 +341,9 @@ static bool qemu_chr_is_busy(Chardev *s) if (CHARDEV_IS_MUX_FE(s)) { MuxFeChardev *d = MUX_FE_CHARDEV(s); return d->mux_cnt > 0; + } else if (CHARDEV_IS_MUX_BE(s)) { + MuxBeChardev *d = MUX_BE_CHARDEV(s); + return d->mux_cnt > 0; } else { return s->be != NULL; } @@ -648,7 +651,8 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, ChardevBackend *backend = NULL; const char *name = qemu_opt_get(opts, "backend"); const char *id = qemu_opts_id(opts); - char *bid = NULL; + const char *mux_be_id = NULL; + char *mux_fe_id = NULL; if (name && is_help_option(name)) { GString *str = g_string_new(""); @@ -676,10 +680,16 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, } if (qemu_opt_get_bool(opts, "mux", 0)) { - bid = g_strdup_printf("%s-base", id); + mux_fe_id = g_strdup_printf("%s-base", id); + } + mux_be_id = qemu_opt_get(opts, "mux-be-id"); + if (mux_be_id && mux_fe_id) { + error_setg(errp, "chardev: mux and mux-be can't be used for the same " + "device"); + goto out; } - chr = qemu_chardev_new(bid ? bid : id, + chr = qemu_chardev_new(mux_fe_id ? mux_fe_id : id, object_class_get_name(OBJECT_CLASS(cc)), backend, context, errp); if (chr == NULL) { @@ -687,25 +697,40 @@ static Chardev *__qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, } base = chr; - if (bid) { + if (mux_fe_id) { Chardev *mux; qapi_free_ChardevBackend(backend); backend = g_new0(ChardevBackend, 1); backend->type = CHARDEV_BACKEND_KIND_MUX; backend->u.mux.data = g_new0(ChardevMux, 1); - backend->u.mux.data->chardev = g_strdup(bid); + backend->u.mux.data->chardev = g_strdup(mux_fe_id); mux = qemu_chardev_new(id, TYPE_CHARDEV_MUX_FE, backend, context, errp); if (mux == NULL) { - object_unparent(OBJECT(chr)); - chr = NULL; - goto out; + goto unparent_and_out; } chr = mux; + } else if (mux_be_id) { + Chardev *s; + + s = qemu_chr_find(mux_be_id); + if (!s) { + error_setg(errp, "chardev: mux-be device can't be found by id '%s'", + mux_be_id); + goto unparent_and_out; + } + if (!CHARDEV_IS_MUX_BE(s)) { + error_setg(errp, "chardev: device '%s' is not a multiplexer device" + " of 'mux-de' type", mux_be_id); + goto unparent_and_out; + } + if (!mux_be_chr_attach_chardev(MUX_BE_CHARDEV(s), chr, errp)) { + goto unparent_and_out; + } } out: qapi_free_ChardevBackend(backend); - g_free(bid); + g_free(mux_fe_id); if (replay && base) { /* RR should be set on the base device, not the mux */ @@ -713,6 +738,11 @@ out: } return chr; + +unparent_and_out: + object_unparent(OBJECT(chr)); + chr = NULL; + goto out; } Chardev *qemu_chr_new_from_opts(QemuOpts *opts, GMainContext *context, @@ -1114,7 +1144,7 @@ ChardevReturn *qmp_chardev_change(const char *id, ChardevBackend *backend, return NULL; } - if (CHARDEV_IS_MUX_FE(chr)) { + if (CHARDEV_IS_MUX_FE(chr) || CHARDEV_IS_MUX_BE(chr)) { error_setg(errp, "Mux device hotswap not supported yet"); return NULL; } @@ -1302,7 +1332,7 @@ static int chardev_options_parsed_cb(Object *child, void *opaque) { Chardev *chr = (Chardev *)child; - if (!chr->be_open && CHARDEV_IS_MUX_FE(chr)) { + if (!chr->be_open && (CHARDEV_IS_MUX_FE(chr) || CHARDEV_IS_MUX_BE(chr))) { open_muxes(chr); } @@ -1329,8 +1359,10 @@ void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event) if (CHARDEV_IS_MUX_FE(chr)) { MuxFeChardev *d = MUX_FE_CHARDEV(chr); - mux_fe_chr_send_all_event(d, event); + } else if (CHARDEV_IS_MUX_BE(chr)) { + MuxBeChardev *d = MUX_BE_CHARDEV(chr); + mux_be_chr_send_all_event(d, event); } } diff --git a/chardev/chardev-internal.h b/chardev/chardev-internal.h index a77f0bdaccfa..60b41048ddd7 100644 --- a/chardev/chardev-internal.h +++ b/chardev/chardev-internal.h @@ -35,7 +35,9 @@ struct MuxFeChardev { Chardev parent; + /* Linked frontends */ CharBackend *backends[MAX_MUX]; + /* Linked backend */ CharBackend chr; int focus; int mux_cnt; @@ -55,16 +57,39 @@ struct MuxFeChardev { }; typedef struct MuxFeChardev MuxFeChardev; +struct MuxBeChardev { + Chardev parent; + /* Linked frontend */ + CharBackend *frontend; + /* Linked backends */ + CharBackend backends[MAX_MUX]; + unsigned int mux_cnt; + /* + * Counters of written bytes from a single frontend device + * to multiple backend devices. + */ + unsigned int be_written[MAX_MUX]; + unsigned int be_min_written; +}; +typedef struct MuxBeChardev MuxBeChardev; + DECLARE_INSTANCE_CHECKER(MuxFeChardev, MUX_FE_CHARDEV, TYPE_CHARDEV_MUX_FE) -#define CHARDEV_IS_MUX_FE(chr) \ +DECLARE_INSTANCE_CHECKER(MuxBeChardev, MUX_BE_CHARDEV, + TYPE_CHARDEV_MUX_BE) + +#define CHARDEV_IS_MUX_FE(chr) \ object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_FE) +#define CHARDEV_IS_MUX_BE(chr) \ + object_dynamic_cast(OBJECT(chr), TYPE_CHARDEV_MUX_BE) void mux_set_focus(Chardev *chr, int focus); void mux_chr_send_all_event(Chardev *chr, QEMUChrEvent event); /* Mux type dependent calls */ void mux_fe_chr_send_all_event(MuxFeChardev *d, QEMUChrEvent event); +void mux_be_chr_send_all_event(MuxBeChardev *d, QEMUChrEvent event); +bool mux_be_chr_attach_chardev(MuxBeChardev *d, Chardev *chr, Error **errp); Object *get_chardevs_root(void); diff --git a/chardev/meson.build b/chardev/meson.build index 778444a00ca6..3a9f5565372b 100644 --- a/chardev/meson.build +++ b/chardev/meson.build @@ -3,6 +3,7 @@ chardev_ss.add(files( 'char-file.c', 'char-io.c', 'char-mux-fe.c', + 'char-mux-be.c', 'char-null.c', 'char-pipe.c', 'char-ringbuf.c', diff --git a/include/chardev/char.h b/include/chardev/char.h index 0bec974f9d73..c58c11c4eeaf 100644 --- a/include/chardev/char.h +++ b/include/chardev/char.h @@ -232,6 +232,7 @@ OBJECT_DECLARE_TYPE(Chardev, ChardevClass, CHARDEV) #define TYPE_CHARDEV_NULL "chardev-null" #define TYPE_CHARDEV_MUX_FE "chardev-mux" +#define TYPE_CHARDEV_MUX_BE "chardev-mux-be" #define TYPE_CHARDEV_RINGBUF "chardev-ringbuf" #define TYPE_CHARDEV_PTY "chardev-pty" #define TYPE_CHARDEV_CONSOLE "chardev-console" diff --git a/qapi/char.json b/qapi/char.json index fb0dedb24383..cdec8f9cf4e2 100644 --- a/qapi/char.json +++ b/qapi/char.json @@ -336,6 +336,17 @@ 'data': { 'chardev': 'str' }, 'base': 'ChardevCommon' } +## +# @ChardevMuxBe: +# +# Configuration info for mux-be chardevs. +# +# Since: 9.2 +## +{ 'struct': 'ChardevMuxBe', + 'data': { }, + 'base': 'ChardevCommon' } + ## # @ChardevStdio: # @@ -483,6 +494,8 @@ # # @mux: (since 1.5) # +# @mux-be: (since 9.2) +# # @msmouse: emulated Microsoft serial mouse (since 1.5) # # @wctablet: emulated Wacom Penpartner serial tablet (since 2.9) @@ -525,6 +538,7 @@ 'pty', 'null', 'mux', + 'mux-be', 'msmouse', 'wctablet', { 'name': 'braille', 'if': 'CONFIG_BRLAPI' }, @@ -599,6 +613,16 @@ { 'struct': 'ChardevMuxWrapper', 'data': { 'data': 'ChardevMux' } } +## +# @ChardevMuxBeWrapper: +# +# @data: Configuration info for mux-be chardevs +# +# Since: 9.2 +## +{ 'struct': 'ChardevMuxBeWrapper', + 'data': { 'data': 'ChardevMuxBe' } } + ## # @ChardevStdioWrapper: # @@ -707,6 +731,7 @@ 'pty': 'ChardevPtyWrapper', 'null': 'ChardevCommonWrapper', 'mux': 'ChardevMuxWrapper', + 'mux-be': 'ChardevMuxBeWrapper', 'msmouse': 'ChardevCommonWrapper', 'wctablet': 'ChardevCommonWrapper', 'braille': { 'type': 'ChardevCommonWrapper', From patchwork Thu Oct 10 10:18:37 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829890 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 17739CF11CA for ; Thu, 10 Oct 2024 10:21:30 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHg-0006Ss-4k; Thu, 10 Oct 2024 06:20:40 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHf-0006S0-7d for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:39 -0400 Received: from mail-ed1-x52b.google.com ([2a00:1450:4864:20::52b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHd-0003Ys-7g for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:38 -0400 Received: by mail-ed1-x52b.google.com with SMTP id 4fb4d7f45d1cf-5c89e66012aso916759a12.2 for ; Thu, 10 Oct 2024 03:20:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555636; x=1729160436; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=bkKnsrdFCGi43KcAOWQ6sKEqNzfB3vA7f7342G3J5WA=; b=PfKaneM+KeeS/sM6wkRfNRjjXSY+jnWVTDp4mq4Xdkb9Eb3aYqAdycujAIONxerzAj GlBWuOFmmkmiJ0EM/KjusHoNFuUxFmOEWixIJOEI3yBRtg4f8+UbfZ4L6+riTlpsvDnu oQdLRATAoX0AbGSuGCVFO/CHwTJ7fCFZ1WENUbjWzpHX7YTmTWtocd3tIQocgl3wbFUT 2Oy5iIooTCk2hmjIVWZKzG6gGLC0JI2y/vbkEPC7cwiLVyGU7kAXQfzPPQXzS0lqgC5N fIa1hgtnCDYbRpZI2Mr5PaUOVDqbWFl/22t5Id58Lrn8tOJzgcwKIllbomEGiy7PdRg8 h4VA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555636; x=1729160436; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=bkKnsrdFCGi43KcAOWQ6sKEqNzfB3vA7f7342G3J5WA=; b=f3AbpJ1HeMk5pBBliv0XUX1w1Re3p9egZvbwNftUyLfQaJrHJZ2p41Up8ZHAPfWKOy m/ecZOoJIu8lEzlWN7yZCUKUx0cTs0+uUCg6UeKPOlvDrCsfNsLjoK0llOLBSQX+RHgx J/+VloEXlXZFDIjlnL1ylkZYeR0utx2YZv3HwOA/AM30EXPh4iirYzo0WqNd0SNaX1rz GGoR3CMv9mMkDgCJjocmAw6GxlSn6SPmT/QPa/QHHFPL1cozYULhbNbfmAG5CMItktI8 4qLJIeDlrnhQA8w7cMNbuQ+y7rcW37Os4SDU8f+GN3i31ZvldTrjyHF/2WligiZjlDVM iThQ== X-Forwarded-Encrypted: i=1; AJvYcCUvABEHytQVN/L+3s5dDoiW6RLroyqwyTitJDMYmQrO4CKddpeA+QPGsSVsMoW/o7JmcX57HPJ6MMt3@nongnu.org X-Gm-Message-State: AOJu0Yy0YVWkczPpTvQfTXqnqVn+K5+pSRTBo16T1boiPCVfQMX44aU0 HVpT3YdzlxA01mG4v94WjdwJcM+8/+I20A4Y/eHXrlkdZSaDNR6P X-Google-Smtp-Source: AGHT+IHfcdyJd0SNY8st1EDFipr8EjZy1cQqomXvpPGlg1hPA1Lxd904CMtR/legpMRSKt19bh+qSw== X-Received: by 2002:a17:907:c88a:b0:a99:41e4:4a80 with SMTP id a640c23a62f3a-a998d205f17mr515252266b.32.1728555635584; Thu, 10 Oct 2024 03:20:35 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:35 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 6/7] tests/unit/test-char: add unit test for the `mux-be` multiplexer Date: Thu, 10 Oct 2024 12:18:37 +0200 Message-Id: <20241010101838.331032-7-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::52b; envelope-from=r.peniaev@gmail.com; helo=mail-ed1-x52b.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org The test is trivial: several backends, 1 `mux-be`, 1 frontend do the buffer write and read. Pipe is used for EAGAIN verification. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- tests/unit/test-char.c | 218 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 216 insertions(+), 2 deletions(-) diff --git a/tests/unit/test-char.c b/tests/unit/test-char.c index f273ce522612..a376ea465eb8 100644 --- a/tests/unit/test-char.c +++ b/tests/unit/test-char.c @@ -177,7 +177,7 @@ static void char_ringbuf_test(void) qemu_opts_del(opts); } -static void char_mux_test(void) +static void char_mux_fe_test(void) { QemuOpts *opts; Chardev *chr, *base; @@ -337,6 +337,219 @@ static void char_mux_test(void) qemu_chr_fe_deinit(&chr_be2, true); } +static void char_mux_be_test(void) +{ + QemuOpts *opts; + Chardev *mux_be, *chr1, *chr2, *base; + char *data; + FeHandler h = { 0, false, 0, false, }; + CharBackend chr_be; + int ret; + +#define RB_SIZE 128 + + /* Create mux-be */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "mux0", + 1, &error_abort); + qemu_opt_set(opts, "backend", "mux-be", &error_abort); + mux_be = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(mux_be); + qemu_opts_del(opts); + + /* Create first chardev */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr1", + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr1 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr1); + qemu_opts_del(opts); + + /* Create second chardev */ + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr2", + 1, &error_abort); + qemu_opt_set(opts, "backend", "ringbuf", &error_abort); + qemu_opt_set(opts, "size", stringify(RB_SIZE), &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr2 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr2); + qemu_opts_del(opts); + + /* Attach mux-be to a frontend */ + qemu_chr_fe_init(&chr_be, mux_be, &error_abort); + qemu_chr_fe_set_handlers(&chr_be, + fe_can_read, + fe_read, + fe_event, + NULL, + &h, + NULL, true); + + /* Write to backend, chr1 */ + base = qemu_chr_find("chr1"); + g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); + + qemu_chr_be_write(base, (void *)"hello", 6); + g_assert_cmpint(h.read_count, ==, 6); + g_assert_cmpstr(h.read_buf, ==, "hello"); + h.read_count = 0; + + /* Write to backend, chr2 */ + base = qemu_chr_find("chr2"); + g_assert_cmpint(qemu_chr_be_can_write(base), !=, 0); + + qemu_chr_be_write(base, (void *)"olleh", 6); + g_assert_cmpint(h.read_count, ==, 6); + g_assert_cmpstr(h.read_buf, ==, "olleh"); + h.read_count = 0; + + /* Write to frontend, chr_be */ + ret = qemu_chr_fe_write(&chr_be, (void *)"heyhey", 6); + g_assert_cmpint(ret, ==, 6); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "heyhey"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "heyhey"); + g_free(data); + + +#ifndef _WIN32 + /* + * Create third chardev to simulate EAGAIN and watcher. + * Mainly copied from char_pipe_test(). + */ + { + gchar *tmp_path = g_dir_make_tmp("qemu-test-char.XXXXXX", NULL); + gchar *in, *out, *pipe = g_build_filename(tmp_path, "pipe", NULL); + Chardev *chr3; + int fd, len; + char buf[128]; + + in = g_strdup_printf("%s.in", pipe); + if (mkfifo(in, 0600) < 0) { + abort(); + } + out = g_strdup_printf("%s.out", pipe); + if (mkfifo(out, 0600) < 0) { + abort(); + } + + opts = qemu_opts_create(qemu_find_opts("chardev"), "chr3", + 1, &error_abort); + qemu_opt_set(opts, "backend", "pipe", &error_abort); + qemu_opt_set(opts, "path", pipe, &error_abort); + qemu_opt_set(opts, "mux-be-id", "mux0", &error_abort); + chr3 = qemu_chr_new_from_opts(opts, NULL, &error_abort); + g_assert_nonnull(chr3); + + /* Write to frontend, chr_be */ + ret = qemu_chr_fe_write(&chr_be, (void *)"thisis", 6); + g_assert_cmpint(ret, ==, 6); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "thisis"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 6); + g_assert_cmpstr(data, ==, "thisis"); + g_free(data); + + fd = open(out, O_RDWR); + ret = read(fd, buf, sizeof(buf)); + g_assert_cmpint(ret, ==, 6); + buf[ret] = 0; + g_assert_cmpstr(buf, ==, "thisis"); + close(fd); + + /* Add watch. 0 indicates no watches if nothing to wait for */ + ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + NULL, NULL); + g_assert_cmpint(ret, ==, 0); + + /* + * Write to frontend, chr_be, until EAGAIN. Make sure length is + * power of two to fit nicely the whole pipe buffer. + */ + len = 0; + while ((ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8)) + != -1) { + len += ret; + } + g_assert_cmpint(errno, ==, EAGAIN); + + /* Further all writes should cause EAGAIN */ + ret = qemu_chr_fe_write(&chr_be, (void *)"b", 1); + g_assert_cmpint(ret, ==, -1); + g_assert_cmpint(errno, ==, EAGAIN); + + /* + * Add watch. Non 0 indicates we have a blocked chardev, which + * can wakes us up when write is possible. + */ + ret = qemu_chr_fe_add_watch(&chr_be, G_IO_OUT | G_IO_HUP, + NULL, NULL); + g_assert_cmpint(ret, !=, 0); + g_source_remove(ret); + + /* Drain pipe and ring buffers */ + fd = open(out, O_RDWR); + while ((ret = read(fd, buf, MIN(sizeof(buf), len))) != -1 && len > 0) { + len -= ret; + } + close(fd); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 128); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 128); + g_free(data); + + /* + * Now we are good to go, first repeat "lost" sequence, which + * was already consumed and drained by the ring buffers, but + * pipe have not recieved that yet. + */ + ret = qemu_chr_fe_write(&chr_be, (void *)"thisisit", 8); + g_assert_cmpint(ret, ==, 8); + + ret = qemu_chr_fe_write(&chr_be, (void *)"streamisrestored", 16); + g_assert_cmpint(ret, ==, 16); + + data = qmp_ringbuf_read("chr1", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 16); + /* Only last 16 bytes, see big comment above */ + g_assert_cmpstr(data, ==, "streamisrestored"); + g_free(data); + + data = qmp_ringbuf_read("chr2", RB_SIZE, false, 0, &error_abort); + g_assert_cmpint(strlen(data), ==, 16); + /* Only last 16 bytes, see big comment above */ + g_assert_cmpstr(data, ==, "streamisrestored"); + g_free(data); + + fd = open(out, O_RDWR); + ret = read(fd, buf, sizeof(buf)); + g_assert_cmpint(ret, ==, 24); + buf[ret] = 0; + /* Both 8 and 16 bytes */ + g_assert_cmpstr(buf, ==, "thisisitstreamisrestored"); + close(fd); + } +#endif + + /* Finalize */ + qemu_chr_fe_deinit(&chr_be, false); +} static void websock_server_read(void *opaque, const uint8_t *buf, int size) { @@ -1484,7 +1697,8 @@ int main(int argc, char **argv) g_test_add_func("/char/null", char_null_test); g_test_add_func("/char/invalid", char_invalid_test); g_test_add_func("/char/ringbuf", char_ringbuf_test); - g_test_add_func("/char/mux", char_mux_test); + g_test_add_func("/char/mux", char_mux_fe_test); + g_test_add_func("/char/mux-be", char_mux_be_test); #ifdef _WIN32 g_test_add_func("/char/console/subprocess", char_console_test_subprocess); g_test_add_func("/char/console", char_console_test); From patchwork Thu Oct 10 10:18:38 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Roman Penyaev X-Patchwork-Id: 13829888 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E470FCF11C6 for ; Thu, 10 Oct 2024 10:21:19 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1syqHk-0006UC-CO; Thu, 10 Oct 2024 06:20:44 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1syqHh-0006TD-Sa for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:41 -0400 Received: from mail-ej1-x62f.google.com ([2a00:1450:4864:20::62f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1syqHe-0003ZX-SK for qemu-devel@nongnu.org; Thu, 10 Oct 2024 06:20:41 -0400 Received: by mail-ej1-x62f.google.com with SMTP id a640c23a62f3a-a994cd82a3bso106739466b.2 for ; Thu, 10 Oct 2024 03:20:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1728555637; x=1729160437; darn=nongnu.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=I/kVJhzVjNqZegRHoxyDOgPB1EKvebYmFk2tXt70azc=; b=XDbhZqt60QkBpku3j04WU98O8N/At7cyvz6Z0Hiu/T89SPUL805afvQTSdSz2ZmrC/ oYsdoMFaVANEUwZgn6UzVZA1AEmiAh5eofrmRLu6LED/TrZSQFx9Wh/5/u1YDOM3wbtK 7Q48OYXlsc7C5iQ8a69RUkAqJFwUb441qvFJcUlhaoLAIe6Z/P+CJGCn6wIZ5/HHuSCd ztzbdPPtp8OAE8Qx1ONKYlqjAyXlk3v+gTueE6nYqLxlbsyZz/Xno9jbthb1n1+L/2z/ 5gUB80R6ZUX9bEpLQ9NS459vsb7ZpNLTKY6qYDjyQfz700mp2fgpe9SayvyEQv5oS4ul Cf6w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1728555637; x=1729160437; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=I/kVJhzVjNqZegRHoxyDOgPB1EKvebYmFk2tXt70azc=; b=SeffZlfGARksKNBs2OIjyJJc9x+8Z/1njehO4HayPb1KxM1focaPlaEzc8eZsetOwg 3Ek7p8n1x/OqwCQ/sji3zXg45SSdLksysr+CzCAa2GtCY1NVPbvydRUBgbexvTkmFlaI yDOB/h0yB/nFQNEHgYInK4O2AxQJEcJgpkV2L3hWXI/hiK6PHhVk8i98Ms25tjTRrOvq XiZs5CrBN9dt+KmbiZWmH/LTSQUj5BFiKHwLNrmoo7kHF4uqLvqsRjFdS3wkwTrOsKGt Q4ZlwLUpjPgOV+eLXfHKHVe6+6TIFPRoFcN/prCSnIvUYWNkM9mymwoeG8UkcuBG1tw/ 9cWg== X-Forwarded-Encrypted: i=1; AJvYcCVdmeN3b5bCKuRfTqH02o+pmujfC+UOqJnZxmxBFPrShS9PIobXGYh3nS/yN7mJFlpjhR5g40x7eD1+@nongnu.org X-Gm-Message-State: AOJu0YzkrctoD1rdUDg7uWEBTC33N725bKQDEA/8mbOW2PagwCf+vaLL pzTTs8yrhJuE95qfQhKwfGAotkJsGMM6k7WmsbXgdW0Pdj/EvR9o4Ap6iA== X-Google-Smtp-Source: AGHT+IEXfSz7EwBl5LLGHUuTJCZGzyTvYRSBbgtstyr+NuW14WNK1wBVgyvbl/9649ZTNN8Aj8gJow== X-Received: by 2002:a17:907:7e89:b0:a99:42fe:949b with SMTP id a640c23a62f3a-a998d33ee47mr500751966b.57.1728555637095; Thu, 10 Oct 2024 03:20:37 -0700 (PDT) Received: from finn.fritz.box ([2a02:8109:8384:1400:eb7f:8fd0:f96c:766b]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-a99a7f2436fsm68240266b.53.2024.10.10.03.20.35 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 10 Oct 2024 03:20:35 -0700 (PDT) From: Roman Penyaev To: Cc: Roman Penyaev , =?utf-8?q?Marc-Andr=C3=A9_Lureau?= , qemu-devel@nongnu.org Subject: [PATCH v3 7/7] qemu-options.hx: describe multiplexing of several backend devices Date: Thu, 10 Oct 2024 12:18:38 +0200 Message-Id: <20241010101838.331032-8-r.peniaev@gmail.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241010101838.331032-1-r.peniaev@gmail.com> References: <20241010101838.331032-1-r.peniaev@gmail.com> MIME-Version: 1.0 Received-SPF: pass client-ip=2a00:1450:4864:20::62f; envelope-from=r.peniaev@gmail.com; helo=mail-ej1-x62f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org This adds a few lines describing `mux-be` multiplexer configuration for multiplexing several backend devices with a single frontend device. Signed-off-by: Roman Penyaev Cc: "Marc-André Lureau" Cc: qemu-devel@nongnu.org --- qemu-options.hx | 78 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index d5afefe5b63c..22490c529a50 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -3693,37 +3693,37 @@ DEFHEADING(Character device options:) DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, "-chardev help\n" - "-chardev null,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev null,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4=on|off][,ipv6=on|off][,nodelay=on|off]\n" - " [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off]\n" + " [,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds][,mux=on|off][,mux-be-id=id]\n" " [,logfile=PATH][,logappend=on|off][,tls-creds=ID][,tls-authz=ID] (tcp)\n" "-chardev socket,id=id,path=path[,server=on|off][,wait=on|off][,telnet=on|off][,websocket=on|off][,reconnect=seconds]\n" - " [,mux=on|off][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" + " [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off][,abstract=on|off][,tight=on|off] (unix)\n" "-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]\n" - " [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off]\n" + " [,localport=localport][,ipv4=on|off][,ipv6=on|off][,mux=on|off][,mux-be-id=id]\n" " [,logfile=PATH][,logappend=on|off]\n" - "-chardev msmouse,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev msmouse,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n" - " [,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + " [,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" "-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n" - "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev pipe,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #ifdef _WIN32 - "-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev console,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #else - "-chardev pty,id=id[,path=path][,mux=on|off][,logfile=PATH][,logappend=on|off]\n" - "-chardev stdio,id=id[,mux=on|off][,signal=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev pty,id=id[,path=path][,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" + "-chardev stdio,id=id[,mux=on|off][,mux-be-id=id][,signal=on|off][,logfile=PATH][,logappend=on|off]\n" #endif #ifdef CONFIG_BRLAPI - "-chardev braille,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev braille,id=id[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(__linux__) || defined(__sun__) || defined(__FreeBSD__) \ || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) - "-chardev serial,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev serial,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__) - "-chardev parallel,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n" + "-chardev parallel,id=id,path=path[,mux=on|off][,mux-be-id=id][,logfile=PATH][,logappend=on|off]\n" #endif #if defined(CONFIG_SPICE) "-chardev spicevmc,id=id,name=name[,debug=debug][,logfile=PATH][,logappend=on|off]\n" @@ -3735,8 +3735,8 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev, SRST The general form of a character device option is: -``-chardev backend,id=id[,mux=on|off][,options]`` - Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``, +``-chardev backend,id=id[,mux=on|off][,mux-be-id=id][,options]`` + Backend is one of: ``null``, ``socket``, ``udp``, ``msmouse``, ``mux-be``, ``vc``, ``ringbuf``, ``file``, ``pipe``, ``console``, ``serial``, ``pty``, ``stdio``, ``braille``, ``parallel``, ``spicevmc``, ``spiceport``. The specific backend will determine the @@ -3793,9 +3793,10 @@ The general form of a character device option is: the QEMU monitor, and ``-nographic`` also multiplexes the console and the monitor to stdio. - There is currently no support for multiplexing in the other - direction (where a single QEMU front end takes input and output from - multiple chardevs). + If you need to multiplex in the opposite direction (where one QEMU + interface receives input and output from multiple chardev devices), + each character device needs ``mux-be-id=id`` option. Please refer + to the paragraph below regarding chardev ``mux-be`` configuration. Every backend supports the ``logfile`` option, which supplies the path to a file to record all data transmitted via the backend. The @@ -3895,6 +3896,43 @@ The available backends are: Forward QEMU's emulated msmouse events to the guest. ``msmouse`` does not take any options. +``-chardev mux-be,id=id`` + Explicitly create chardev backend multiplexer with possibility to + multiplex in the opposite direction, where one QEMU interface + (frontend device) receives input and output from multiple chardev + backend devices. + + For example the following is a use case of 2 backend devices: text + virtual console ``vc0`` and a socket ``sock0`` connected + to a single virtio hvc console frontend device with multiplexer + ``mux0`` help. Virtual console renders text to an image, which + can be shared over the VNC protocol, in turn socket backend provides + biderectional communication to the virtio hvc console over socket. + The example configuration can be the following: + + :: + + -chardev mux-be,id=mux0 \ + -chardev socket,path=/tmp/sock,server=on,wait=off,id=sock0,mux-be-id=mux0 \ + -chardev vc,id=vc0,mux-be-id=mux0 \ + -device virtconsole,chardev=mux0 \ + -vnc 0.0.0.0:0 + + Once QEMU starts VNC client and any TTY emulator can be used to + control a single hvc console: + + :: + + # VNC client + vncviewer :0 + + # TTY emulator + socat unix-connect:/tmp/sock pty,link=/tmp/pty & \ + tio /tmp/pty + + Multiplexing of several backend devices with serveral frontend devices + is not supported. + ``-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]`` Connect to a QEMU text console. ``vc`` may optionally be given a specific size.