On Fri, May 1, 2026 at 2:05 AM ~lexbaileylowrisc
<[email protected]> wrote:
>
> From: Lex Bailey <[email protected]>
>
> Added some tracing to the OpenTitan UART for transparency when debugging
>
> Signed-off-by: Lex Bailey <[email protected]>
> ---
>  hw/char/ot_uart.c         | 19 +++++++++++++++++++
>  hw/char/trace-events      |  8 ++++++++
>  hw/riscv/opentitan.c      |  1 +
>  include/hw/char/ot_uart.h |  1 +
>  4 files changed, 29 insertions(+)
>
> diff --git a/hw/char/ot_uart.c b/hw/char/ot_uart.c
> index d00f7bee66..910bef00f2 100644
> --- a/hw/char/ot_uart.c
> +++ b/hw/char/ot_uart.c
> @@ -20,6 +20,7 @@
>  #include "qemu/osdep.h"
>  #include "hw/char/ot_uart.h"
>  #include "qemu/fifo8.h"
> +#include "hw/core/cpu.h"
>  #include "hw/core/irq.h"
>  #include "hw/core/qdev-clock.h"
>  #include "hw/core/qdev-properties.h"
> @@ -28,6 +29,7 @@
>  #include "migration/vmstate.h"
>  #include "qemu/log.h"
>  #include "qemu/module.h"
> +#include "trace.h"
>
>  REG32(INTR_STATE, 0x00)
>      SHARED_FIELD(INTR_TX_WATERMARK, 0, 1)
> @@ -126,6 +128,9 @@ static void ot_uart_update_irqs(OtUARTState *s)
>  {
>      uint32_t state_masked = s->regs[R_INTR_STATE] & s->regs[R_INTR_ENABLE];
>
> +    trace_ot_uart_irqs(s->ot_id, s->regs[R_INTR_STATE], 
> s->regs[R_INTR_ENABLE],
> +                       state_masked);
> +
>      for (int index = 0; index < OT_UART_IRQ_NUM; index++) {
>          bool level = (state_masked & (1U << index)) != 0;
>          qemu_set_irq(s->irqs[index], level);
> @@ -402,6 +407,10 @@ static uint64_t ot_uart_get_baud(OtUARTState *s)
>      baud *= clock_get_hz(s->f_clk);
>      baud >>= 20;
>
> +    if (baud) {
> +        trace_ot_uart_check_baudrate(s->ot_id, baud);
> +    }
> +
>      return baud;
>  }
>
> @@ -503,6 +512,10 @@ static uint64_t ot_uart_read(void *opaque, hwaddr addr, 
> unsigned int size)
>          return 0;
>      }
>
> +    uint32_t pc = current_cpu->cc->get_pc(current_cpu);
> +    trace_ot_uart_io_read_out(s->ot_id, (uint32_t)addr, REG_NAME(reg),
> +                              retvalue, pc);
> +
>      return retvalue;
>  }
>
> @@ -514,6 +527,9 @@ static void ot_uart_write(void *opaque, hwaddr addr, 
> uint64_t val64,
>
>      hwaddr reg = R32_OFF(addr);
>
> +    uint32_t pc = current_cpu->cc->get_pc(current_cpu);
> +    trace_ot_uart_io_write(s->ot_id, (uint32_t)addr, REG_NAME(reg), value, 
> pc);
> +
>      switch (reg) {
>      case R_INTR_STATE:
>          /* Write 1 clear */
> @@ -665,6 +681,7 @@ static const VMStateDescription vmstate_ot_uart = {
>  };
>
>  static const Property ot_uart_properties[] = {
> +    DEFINE_PROP_STRING("ot-id", OtUARTState, ot_id),

I'm not sure we need this

Alistair

>      DEFINE_PROP_CHR("chardev", OtUARTState, chr),
>      DEFINE_PROP_BOOL("oversample-break", OtUARTState, oversample_break, 
> false),
>      DEFINE_PROP_BOOL("toggle-break", OtUARTState, toggle_break, false),
> @@ -716,6 +733,8 @@ static void ot_uart_realize(DeviceState *dev, Error 
> **errp)
>  {
>      OtUARTState *s = OT_UART(dev);
>
> +    g_assert(s->ot_id);
> +
>      s->fifo_trigger_handle = timer_new_ns(QEMU_CLOCK_VIRTUAL,
>                                            fifo_trigger_update, s);
>
> diff --git a/hw/char/trace-events b/hw/char/trace-events
> index a3fcc77287..17cc9ad2d5 100644
> --- a/hw/char/trace-events
> +++ b/hw/char/trace-events
> @@ -141,3 +141,11 @@ stm32f2xx_usart_receive(char *id, uint8_t chr) " %s 
> receiving '%c'"
>  # riscv_htif.c
>  htif_uart_write_to_host(uint8_t device, uint8_t cmd, uint64_t payload) 
> "device: %u cmd: %02u payload: %016" PRIx64
>  htif_uart_unknown_device_command(uint8_t device, uint8_t cmd, uint64_t 
> payload) "device: %u cmd: %02u payload: %016" PRIx64
> +
> +# ot_uart.c
> +ot_uart_check_baudrate(const char *id, unsigned baud) "%s: %u bps"
> +ot_uart_connect_input_clock(const char *id, const char * srcname) "%s: %s"
> +ot_uart_debug(const char *id, const char *msg) "%s: %s"
> +ot_uart_io_read_out(const char *id, uint32_t addr, const char *regname, 
> uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x"
> +ot_uart_io_write(const char *id, uint32_t addr, const char *regname, 
> uint32_t val, uint32_t pc) "%s: addr=0x%02x (%s), val=0x%x, pc=0x%x"
> +ot_uart_irqs(const char *id, uint32_t active, uint32_t mask, uint32_t eff) 
> "%s: act:0x%08x msk:0x%08x eff:0x%08x"
> diff --git a/hw/riscv/opentitan.c b/hw/riscv/opentitan.c
> index 97c33d1b53..163d3ac3d3 100644
> --- a/hw/riscv/opentitan.c
> +++ b/hw/riscv/opentitan.c
> @@ -133,6 +133,7 @@ static void lowrisc_ibex_soc_init(Object *obj)
>      object_initialize_child(obj, "plic", &s->plic, TYPE_SIFIVE_PLIC);
>
>      object_initialize_child(obj, "uart", &s->uart, TYPE_OT_UART);
> +    object_property_set_str(OBJECT(&s->uart), "ot-id", "uart0", 
> &error_fatal);
>
>      object_initialize_child(obj, "timer", &s->timer, TYPE_IBEX_TIMER);
>
> diff --git a/include/hw/char/ot_uart.h b/include/hw/char/ot_uart.h
> index 4dc51142f7..2f538e1f6f 100644
> --- a/include/hw/char/ot_uart.h
> +++ b/include/hw/char/ot_uart.h
> @@ -54,6 +54,7 @@ struct OtUARTState {
>      bool in_break;
>      guint watch_tag;
>
> +    char *ot_id;
>      Clock *f_clk;
>
>      CharFrontend chr;
> --
> 2.49.1
>

Reply via email to