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

Re: [PATCH v3 2/2] xen/console: unify printout behavior for UART emulators



On Fri, Jun 06, 2025 at 08:11:26PM +0000, dmkhn@xxxxxxxxx wrote:
> From: Denis Mukhin <dmukhin@xxxxxxxx>
> 
> If virtual UART from domain X prints on the physical console, the behavior is
> updated to (see [1]):
> - console focus in domain X: do not prefix messages;
> - no console focus in domain X: prefix all messages with "(dX)".
> 
> Use guest_printk() in all current in-hypervisor UART emulators. That aligns 
> the
> behavior with debug I/O port 0xe9 handler on x86 and slightly improves the
> logging since guest_printk() already prints the domain ID. guest_printk() was
> modified to account for console focus ownership.
> 
> Modify guest_console_write() for hardware domain case by adding domain ID to
> the message when hwdom does not have console focus.
> 
> [1] 
> https://lore.kernel.org/xen-devel/alpine.DEB.2.22.394.2412121655360.463523@ubuntu-linux-20-04-desktop/
> Signed-off-by: Denis Mukhin <dmukhin@xxxxxxxx>
> ---
> Changes since v2:
> - dropped rate-limiting change for vuart
> ---
>  xen/arch/arm/vpl011.c      |  6 +++---
>  xen/arch/arm/vuart.c       |  2 +-
>  xen/drivers/char/console.c | 23 +++++++++++++++++++++--
>  3 files changed, 25 insertions(+), 6 deletions(-)
> 
> diff --git a/xen/arch/arm/vpl011.c b/xen/arch/arm/vpl011.c
> index 480fc664fc..2b6f2a09bc 100644
> --- a/xen/arch/arm/vpl011.c
> +++ b/xen/arch/arm/vpl011.c
> @@ -87,7 +87,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t 
> data)
>      {
>          if ( intf->out_prod == 1 )
>          {
> -            printk("%c", data);
> +            guest_printk(d, "%c", data);
>              intf->out_prod = 0;
>          }
>          else
> @@ -95,7 +95,7 @@ static void vpl011_write_data_xen(struct domain *d, uint8_t 
> data)
>              if ( data != '\n' )
>                  intf->out[intf->out_prod++] = '\n';
>              intf->out[intf->out_prod++] = '\0';
> -            printk("%s", intf->out);
> +            guest_printk(d, "%s", intf->out);
>              intf->out_prod = 0;
>          }
>      }
> @@ -107,7 +107,7 @@ static void vpl011_write_data_xen(struct domain *d, 
> uint8_t data)
>              if ( data != '\n' )
>                  intf->out[intf->out_prod++] = '\n';
>              intf->out[intf->out_prod++] = '\0';
> -            printk("DOM%u: %s", d->domain_id, intf->out);
> +            guest_printk(d, "%s", intf->out);
>              intf->out_prod = 0;
>          }
>      }
> diff --git a/xen/arch/arm/vuart.c b/xen/arch/arm/vuart.c
> index bd2f425214..6641f9d775 100644
> --- a/xen/arch/arm/vuart.c
> +++ b/xen/arch/arm/vuart.c
> @@ -89,7 +89,7 @@ static void vuart_print_char(struct vcpu *v, char c)
>          if ( c != '\n' )
>              uart->buf[uart->idx++] = '\n';
>          uart->buf[uart->idx] = '\0';
> -        printk(XENLOG_G_DEBUG "DOM%u: %s", d->domain_id, uart->buf);
> +        guest_printk(d, XENLOG_G_DEBUG "%s", uart->buf);
>          uart->idx = 0;
>      }
>      spin_unlock(&uart->lock);
> diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
> index 6e77b4af82..3855962af7 100644
> --- a/xen/drivers/char/console.c
> +++ b/xen/drivers/char/console.c
> @@ -740,7 +740,17 @@ static long 
> guest_console_write(XEN_GUEST_HANDLE_PARAM(char) buffer,
>          if ( is_hardware_domain(cd) )
>          {
>              /* Use direct console output as it could be interactive */
> +            char prefix[16] = "";
> +            struct domain *consd;
> +
> +            consd = console_get_domain();
> +            if ( consd != cd )
> +                snprintf(prefix, sizeof(prefix), "(d%d) ", cd->domain_id);
> +            console_put_domain(consd);
> +
>              nrspin_lock_irq(&console_lock);
> +            if ( prefix[0] != '\0' )
> +                console_send(prefix, strlen(prefix), flags);
>              console_send(kbuf, kcount, flags);
>              nrspin_unlock_irq(&console_lock);
>          }
> @@ -1032,12 +1042,21 @@ void printk(const char *fmt, ...)
>      va_end(args);
>  }
>  
> +/*
> + * Print message from the guest on the diagnostic console.
> + * Prefixes all messages w/ "(dX)" if domain X does not own physical console
> + * focus.
> + */
>  void guest_printk(const struct domain *d, const char *fmt, ...)
>  {
>      va_list args;
> -    char prefix[16];
> +    char prefix[16] = "";
> +    struct domain *consd;
>  
> -    snprintf(prefix, sizeof(prefix), "(d%d) ", d->domain_id);
> +    consd = console_get_domain();
> +    if ( consd != d )
> +        snprintf(prefix, sizeof(prefix), "(d%d) ", d->domain_id);
> +    console_put_domain(consd);

It might be helpful to abstract this into a separate helper, as it's
used by both functions:

static void fill_console_prefix(char *prefix, unsigned int len,
                                const struct domain *d)
{
    struct domain *consd = console_get_domain();

    if ( consd ? consd != d : !is_hardware_domain(d)) )
       snprintf(prefix, len, "(d%d) ", d->domain_id);
    console_put_domain(consd);
}

Note the above code should also handle the current discussion of not
printing the (d0) prefix for the hardware domain when the console
target is Xen.  I think this keeps the previous behavior when console
input is switched to Xen, while still providing unified (dX) prefixes
otherwise.

Thanks, Roger.



 


Rackspace

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