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

Re: [PATCH v3] xen/console: handle multiple domains using console_io hypercalls



On Tue, 13 Jan 2026, Stefano Stabellini wrote:
> 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.
> 
> When switching focus using Ctrl-AAA, discard any unread data in the
> input buffer. Input is read quickly and the user would be aware of it
> being slow or stuck as they use Ctrl-AAA to switch focus domain.
> In that situation, it is to be expected that the unread input is lost.
> 
> The domain writes are buffered when the domain is not in focus. Push out
> the buffer when the domain enters focus.
> 
> Add the console_lock around serial_rx_cons modifications to protect it
> against concurrent writes to it.
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxx>

Ping?


> ---
> Changes in v3:
> - move serial_rx_cons before printk
> - call console_put_domain earlier on CONSOLEIO_read
> - take console_lock earlier
> - add console_lock around serial_rx_cons modifications
> 
> Changes in v2:
> - fix code style
> - pbuf_idx/idx after ada53067083e
> - don't add extra \0
> - clear input on console switch
> ---
>  xen/drivers/char/console.c | 30 +++++++++++++++++++++++++++---
>  1 file changed, 27 insertions(+), 3 deletions(-)
> 
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 2bdb4d5fb4..58c32f22ef 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -577,6 +577,10 @@ static void console_switch_input(void)
>  
>              console_rx = next_rx;
>              printk("*** Serial input to DOM%u", domid);
> +            /* Don't let the next dom read the previous dom's unread data. */
> +            nrspin_lock_irq(&console_lock);
> +            serial_rx_cons = serial_rx_prod;
> +            nrspin_unlock_irq(&console_lock);
>              break;
>          }
>      }
> @@ -730,6 +734,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 )
>      {
> @@ -742,18 +747,28 @@ 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 )
>          {
> -            /* Use direct console output as it could be interactive */
> +            struct domain_console *cons = cd->console;
> +
>              nrspin_lock_irq(&console_lock);
> +            if ( cons->idx )
> +            {
> +                console_send(cons->buf, cons->idx, flags);
> +                cons->idx = 0;
> +            }
> +            /* Use direct console output as it could be interactive */
>              console_send(kbuf, kcount, flags);
>              nrspin_unlock_irq(&console_lock);
> +            console_put_domain(input);
>          }
>          else
>          {
>              char *kin = kbuf, *kout = kbuf, c;
>              struct domain_console *cons = cd->console;
>  
> +            console_put_domain(input);
>              /* Strip non-printable characters */
>              do
>              {
> @@ -795,6 +810,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 )
> @@ -815,6 +831,11 @@ long do_console_io(
>          if ( count > INT_MAX )
>              break;
>  
> +        d = console_get_domain();
> +        console_put_domain(d);
> +        if ( d != current->domain )
> +            return 0;
> +
>          rc = 0;
>          while ( (serial_rx_cons != serial_rx_prod) && (rc < count) )
>          {
> @@ -830,7 +851,10 @@ long do_console_io(
>                  break;
>              }
>              rc += len;
> -            serial_rx_cons += len;
> +            nrspin_lock_irq(&console_lock);
> +            if ( serial_rx_cons != serial_rx_prod )
> +                serial_rx_cons += len;
> +            nrspin_unlock_irq(&console_lock);
>          }
>          break;
>      default:
> -- 
> 2.25.1
> 



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.