On Thu, 4 Dec 2025, Grygorii Strashko wrote: > From: Grygorii Strashko <[email protected]> > > When 2 or more domains are created and: > - one is hwdom with "hvc0" (console_io) console > - other DomUs with vpl011 or "hvc0" (console_io) console > console output from hwdom may mix with output from other domains. > > Example: > [ 2.288816] Key type id_legacy registered > [ 2.291894] n(XEN) DOM1: [ 1.016950] DMA: preallocated 128 KiB > GFP_KERNEL|GFP_DMA32 pool for atomic allocations > fs4filelayout_init: NFSv4 File Layout Driver Registering... > (XEN) DOM1: [ 1.018846] audit: initializing netlink subsys (disabled) > > This happens because for hwdom the console output is produced by domain and > handled by Xen as stream of chars, which can be interrupted when hwdom is > scheduled out and so, cause console output mix. > The Xen consoleio code trying to mimic serial HW behavior for hwdom > unconditionally by sending available data to serial HW on arrival. > Xen consoleio code does not account for Xen console input focus, comparing > to emulated serial hw, like vpl011, which does the same for domain with > active Xen console input focus only. > > Switching console input focus to Xen improves situation, but not enough. > > This patch changes consoleio code to account for domain with active Xen > console input focus - console output will be sent directly to serial HW > only if domain has active Xen console input focus. For other domains - > console output will be buffered and sync on per-line basis. > > Example output: > (d2) [ 4.263417] Key type id_legacy registered > (XEN) DOM1: [ 4.658080] Advanced Linux Sound Architecture Driver > Initialized. > (d2) [ 4.277824] nfs4filelayout_init: NFSv4 File Layout Driver > Registering... > > Signed-off-by: Grygorii Strashko <[email protected]>
I independently wrote this patch which also supports console reads. Sorry about the mixed messages. --- xen/console: handle multiple domains using console_io hypercalls Allow multiple dom0less domains to use the console_io hypercalls to print to the console. Handle them in a similar way to vpl011: only the domain which has focus can read from the console. All domains can write to the console but the ones without focus have a prefix. In this case the prefix is applied by using guest_printk instead of printk or console_puts which is what the original code was already doing. Signed-off-by: Stefano Stabellini <[email protected]> --- xen/drivers/char/console.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index dcc31170f2..826bee3848 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -729,6 +729,7 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, unsigned int flags = opt_console_to_ring ? CONSOLE_ALL : CONSOLE_DEFAULT; struct domain *cd = current->domain; + struct domain *input; while ( count > 0 ) { @@ -741,17 +742,26 @@ static long guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer, if ( copy_from_guest(kbuf, buffer, kcount) ) return -EFAULT; - if ( is_hardware_domain(cd) ) + input = console_get_domain(); + if (input && cd == input) { + if ( cd->pbuf_idx ) + { + cd->pbuf[cd->pbuf_idx] = '\0'; + console_send(cd->pbuf, cd->pbuf_idx + 1, flags); + cd->pbuf_idx = 0; + } /* Use direct console output as it could be interactive */ nrspin_lock_irq(&console_lock); console_send(kbuf, kcount, flags); nrspin_unlock_irq(&console_lock); + console_put_domain(input); } else { char *kin = kbuf, *kout = kbuf, c; + console_put_domain(input); /* Strip non-printable characters */ do { @@ -793,6 +803,7 @@ long do_console_io( { long rc; unsigned int idx, len; + struct domain *d; rc = xsm_console_io(XSM_OTHER, current->domain, cmd); if ( rc ) @@ -813,6 +824,13 @@ long do_console_io( if ( count > INT_MAX ) break; + d = console_get_domain(); + if ( d != current->domain ) + { + console_put_domain(d); + return 0; + } + rc = 0; while ( (serial_rx_cons != serial_rx_prod) && (rc < count) ) { @@ -824,12 +842,14 @@ long do_console_io( len = count - rc; if ( copy_to_guest_offset(buffer, rc, &serial_rx_ring[idx], len) ) { + console_put_domain(d); rc = -EFAULT; break; } rc += len; serial_rx_cons += len; } + console_put_domain(d); break; default: rc = -ENOSYS; -- 2.25.1
