> On 10. Feb 2026, at 11:17, Peter Maydell <[email protected]> wrote:
> 
> We log a GUEST_ERROR message "PL011 data written to disabled UART" if
> the guest writes data to the TX FIFO when it has not set the enable
> bit in the UART.  The idea is to note that the guest has done
> something dubious but let it work anyway.  However, since we print
> this message for every output character, it floods the logs when
> running a guest that does this.
> 
> Keep a note of whether we've printed the log message or not, so we
> only output it once.  If the guest actively disables the UART, we
> re-arm the log message.
> 
> Notably, the Linux kernel does not bother to enable the UART if it is
> used for earlycon, relying on the firmware having already done that.
> 
> Signed-off-by: Peter Maydell <[email protected]>
Reviewed-by: Mohamed Mediouni <[email protected]>
> ---
> The log messages here were getting in my way trying to debug something
> else, but I didn't want to just delete them completely.
> 
> hw/char/pl011.c         | 24 ++++++++++++++++++++++--
> include/hw/char/pl011.h |  1 +
> 2 files changed, 23 insertions(+), 2 deletions(-)
> 
> diff --git a/hw/char/pl011.c b/hw/char/pl011.c
> index b2ca68e3e8..cb12c3e224 100644
> --- a/hw/char/pl011.c
> +++ b/hw/char/pl011.c
> @@ -227,10 +227,25 @@ static void pl011_loopback_tx(PL011State *s, uint32_t 
> value)
> static void pl011_write_txdata(PL011State *s, uint8_t data)
> {
>     if (!(s->cr & CR_UARTEN)) {
> -        qemu_log_mask(LOG_GUEST_ERROR,
> -                      "PL011 data written to disabled UART\n");
> +        /*
> +         * Only log this message once, not every time the guest outputs:
> +         * otherwise we would flood the logs with this message, making
> +         * harder to debug guests. (Some very popular guests like Linux
> +         * don't actively enable the UART.)
> +         */
> +        if (!s->logged_disabled_uart) {
> +            qemu_log_mask(LOG_GUEST_ERROR,
> +                          "PL011 data written to disabled UART\n");
> +            s->logged_disabled_uart = true;
> +        }
>     }
>     if (!(s->cr & CR_TXE)) {
> +        /*
> +         * We don't bother with the only-log-once machinery for this check
> +         * because TXE is enabled by default from PL011 reset, so there
> +         * isn't likely to be existing in-the-wild guest code that trips
> +         * over this one.
> +         */
>         qemu_log_mask(LOG_GUEST_ERROR,
>                       "PL011 data written to disabled TX UART\n");
>     }
> @@ -457,6 +472,10 @@ static void pl011_write(void *opaque, hwaddr offset,
>         break;
>     case 12: /* UARTCR */
>         /* ??? Need to implement the enable bit.  */
> +        if ((s->cr ^ value) & CR_UARTEN) {
> +            /* Re-arm the log warning when the guest toggles UARTEN */
> +            s->logged_disabled_uart = false;
> +        }
>         s->cr = value;
>         pl011_loopback_mdmctrl(s);
>         break;
> @@ -665,6 +684,7 @@ static void pl011_reset(DeviceState *dev)
>     s->ifl = 0x12;
>     s->cr = 0x300;
>     s->flags = 0;
> +    s->logged_disabled_uart = false;
>     pl011_reset_rx_fifo(s);
>     pl011_reset_tx_fifo(s);
> }
> diff --git a/include/hw/char/pl011.h b/include/hw/char/pl011.h
> index ff735b5234..5695787650 100644
> --- a/include/hw/char/pl011.h
> +++ b/include/hw/char/pl011.h
> @@ -51,6 +51,7 @@ struct PL011State {
>     qemu_irq irq[6];
>     Clock *clk;
>     bool migrate_clk;
> +    bool logged_disabled_uart;
>     const unsigned char *id;
>     /*
>      * Since some users embed this struct directly, we must
> -- 
> 2.43.0
> 
> 


Reply via email to