[PATCH] virtio_console: add console port to list before hvc_alloc()
flat view
HOTtoday
From: Foo Bar <hidden>
Date: 2026-11-01 02:24:43
Also in:
lkml
Subsystem:
char and misc drivers, the rest, virtio console driver · Maintainers:
Arnd Bergmann, Greg Kroah-Hartman, Linus Torvalds, Amit Shah
From: Murat Seker <redacted> init_port_console() calls hvc_alloc() before adding the port to pdrvdata.consoles. When the port is the preferred console (for example console=hvc0), hvc_alloc() registers it, and register_console() replays the log buffer through put_chars(). put_chars() looks the port up by vtermno in pdrvdata.consoles, does not find it yet and returns -EPIPE, so hvc discards every message printed before virtio-console probed. The messages are still in the kernel log, but a host capturing the virtio console never receives them. Add the port to the list before calling hvc_alloc(), and remove it again if hvc_alloc() fails. The out_vq, outvq_lock and portdev used by put_chars() are set up in add_port() before init_port_console() runs, and the other users of cons.hvc check it through is_console_port(). Tested on x86_64 QEMU/KVM with KASAN, PROVE_LOCKING and DEBUG_LIST: with console=hvc0 the virtio console now starts at [0.000000] instead of at virtio-console probe; with hvc0 next to ttyS0 both carry the full log; with earlycon (no replay) output is unchanged; and hot-adding and removing extra virtconsole ports still works. No new warnings. Fixes: 38edf58d73c2 ("virtio: console: don't assume a single console port.") Signed-off-by: Murat Seker <redacted> --- drivers/char/virtio_console.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-)
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 019bcae81af5..a31fdac65891 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c@@ -1280,18 +1280,28 @@ static int init_port_console(struct port *port) return ret; port->cons.vtermno = ret; + + /* + * hvc_alloc() may register the console, which replays the log buffer + * through put_chars(). put_chars() finds the port on this list, so + * add it first or the replayed messages are dropped. + */ + spin_lock_irq(&pdrvdata_lock); + list_add_tail(&port->cons.list, &pdrvdata.consoles); + spin_unlock_irq(&pdrvdata_lock); + port->cons.hvc = hvc_alloc(port->cons.vtermno, 0, &hv_ops, PAGE_SIZE); if (IS_ERR(port->cons.hvc)) { ret = PTR_ERR(port->cons.hvc); dev_err(port->dev, "error %d allocating hvc for port\n", ret); port->cons.hvc = NULL; + spin_lock_irq(&pdrvdata_lock); + list_del(&port->cons.list); + spin_unlock_irq(&pdrvdata_lock); ida_free(&vtermno_ida, port->cons.vtermno); return ret; } - spin_lock_irq(&pdrvdata_lock); - list_add_tail(&port->cons.list, &pdrvdata.consoles); - spin_unlock_irq(&pdrvdata_lock); port->guest_connected = true; /* Notify host of port being opened */
--
2.53.0-Meta