On Thu, 8 May 2025 at 09:31, Paolo Bonzini <pbonz...@redhat.com> wrote:
>
> While we model a 16-elements RX FIFO since the PL011 model was
> introduced in commit cdbdb648b7c ("ARM Versatile Platform Baseboard
> emulation"), we only read 1 char at a time!

We could say that this is the Rust version of the C implementation's
commit 3e0f118f8259 ("hw/char/pl011: Really use RX FIFO depth").

> Have the IOCanReadHandler handler return how many elements are
> available, and use that in the IOReadHandler handler.
>
> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com>
> ---
>  docs/devel/rust.rst              |  2 +-
>  rust/hw/char/pl011/src/device.rs | 14 +++++++-------
>  2 files changed, 8 insertions(+), 8 deletions(-)
>
> diff --git a/docs/devel/rust.rst b/docs/devel/rust.rst
> index 4de86375021..171d908e0b0 100644
> --- a/docs/devel/rust.rst
> +++ b/docs/devel/rust.rst
> @@ -119,7 +119,7 @@ QEMU includes four crates:
>    for the ``hw/char/pl011.c`` and ``hw/timer/hpet.c`` files.
>
>  .. [#issues] The ``pl011`` crate is synchronized with ``hw/char/pl011.c``
> -   as of commit 02b1f7f61928.  The ``hpet`` crate is synchronized as of
> +   as of commit 3e0f118f82.  The ``hpet`` crate is synchronized as of
>     commit 1433e38cc8.  Both are lacking tracing functionality.
>
>  This section explains how to work with them.
> diff --git a/rust/hw/char/pl011/src/device.rs 
> b/rust/hw/char/pl011/src/device.rs
> index 94b31659849..7f28bb25a9b 100644
> --- a/rust/hw/char/pl011/src/device.rs
> +++ b/rust/hw/char/pl011/src/device.rs
> @@ -580,19 +580,19 @@ fn write(&self, offset: hwaddr, value: u64, _size: u32) 
> {
>      fn can_receive(&self) -> u32 {
>          let regs = self.regs.borrow();
>          // trace_pl011_can_receive(s->lcr, s->read_count, r);

This commented out tracepoint needs adjusting: the C version
is now
  trace_pl011_can_receive(s->lcr, s->read_count, fifo_depth, fifo_available)
where fifo_available is what we here open-code as
"regs.fifo_depth() - regs.read_count" in the return value.

I mention this because it affects whether you want to write
this open-coded or with a local variable.

> -        u32::from(regs.read_count < regs.fifo_depth())
> +        regs.fifo_depth() - regs.read_count
>      }
>
>      fn receive(&self, buf: &[u8]) {
> -        if buf.is_empty() {
> -            return;
> -        }
>          let mut regs = self.regs.borrow_mut();
> -        let c: u32 = buf[0].into();
> -        let update_irq = !regs.loopback_enabled() && 
> regs.fifo_rx_put(c.into());
> +        let mut update_irq = false;
> +        for &c in buf {
> +            let c: u32 = c.into();
> +            update_irq |= !regs.loopback_enabled() && 
> regs.fifo_rx_put(c.into());
> +        }

We're now checking loopback_enabled() on every iteration
(admittedly we previously also checked it for every character
but with the extra overhead of calling receive() too ;-))

Could we write this the same way the C code does with an
early-return before the for loop?

Also, the C version has a helpful comment about that:
    /*
     * In loopback mode, the RX input signal is internally disconnected
     * from the entire receiving logics; thus, all inputs are ignored,
     * and BREAK detection on RX input signal is also not performed.
     */

that it would be good to have in the Rust implementation so
we don't lose it as and when we drop the C impl.

> +
>          // Release the BqlRefCell before calling self.update()
>          drop(regs);
> -
>          if update_irq {
>              self.update();
>          }

thanks
-- PMM

Reply via email to