[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH] hw/char/riscv_htif: Fix 64-bit var write order in 32-bit sys
|
From: |
Alistair Francis |
|
Subject: |
Re: [PATCH] hw/char/riscv_htif: Fix 64-bit var write order in 32-bit system |
|
Date: |
Mon, 5 Aug 2024 09:49:03 +1000 |
On Wed, Jul 31, 2024 at 12:51 AM Nikita Novikov <n.novikov@syntacore.com> wrote:
>
> When we are trying to write 64-bit value in 32-bit system, the value in HTIF
> device divides
> on 2 separate 32-bit parts. So device expects write to xHOST_OFFSET1 first,
> then to xHOST_OFFSET2.
> But some compilers (ex. CLANG) can change the writing queue (xHOST_OFFSET2
> first, xHOST_OFFSET1 second)
> because of machine instructions order swapping. That causes wrong behaviour
> of HTIF device.
I don't follow, isn't this MMIO why is the compiler swapping the order?
> This patch is removing dependency of writing order, so the device will work
> correctly regardless of compilers.
Urgh, the HTIF is undocumented, so there isn't really a way to know if
this is right or not.
It kind of seems like the QEMU implementation is the best
documentation at the moment [1], so I'm reluctant to make this change.
>
> Signed-off-by: Nikita Novikov <n.novikov@syntacore.com>
> ---
> hw/char/riscv_htif.c | 43 +++++++++++++++++++-----------------
> include/hw/char/riscv_htif.h | 11 +++++++--
> 2 files changed, 32 insertions(+), 22 deletions(-)
>
> diff --git a/hw/char/riscv_htif.c b/hw/char/riscv_htif.c
> index 9bef60def1..d914f158ea 100644
> --- a/hw/char/riscv_htif.c
> +++ b/hw/char/riscv_htif.c
> @@ -233,7 +233,8 @@ static void htif_handle_tohost_write(HTIFState *s,
> uint64_t val_written)
> if (cmd == HTIF_CONSOLE_CMD_GETC) {
> /* this should be a queue, but not yet implemented as such */
> s->pending_read = val_written;
> - s->tohost = 0; /* clear to indicate we read */
> + s->tohost = 0;
> + s->tohost_status = 0x0; /* clear to indicate we read */
This seems like a separate change?
> return;
> } else if (cmd == HTIF_CONSOLE_CMD_PUTC) {
> uint8_t ch = (uint8_t)payload;
> @@ -258,7 +259,8 @@ static void htif_handle_tohost_write(HTIFState *s,
> uint64_t val_written)
> * }
> */
> s->fromhost = (val_written >> 48 << 48) | (resp << 16 >> 16);
> - s->tohost = 0; /* clear to indicate we read */
> + s->tohost = 0;
> + s->tohost_status = 0x0; /* clear to indicate we read */
> }
>
> #define TOHOST_OFFSET1 (s->tohost_offset)
> @@ -291,32 +293,33 @@ static void htif_mm_write(void *opaque, hwaddr addr,
> {
> HTIFState *s = opaque;
> if (addr == TOHOST_OFFSET1) {
> - if (s->tohost == 0x0) {
> - s->allow_tohost = 1;
> - s->tohost = value & 0xFFFFFFFF;
> - } else {
> - s->allow_tohost = 0;
> - }
> + s->tohost = deposit64(s->tohost, 0, 32, value);
> + s->tohost_status |= 0x1;
> } else if (addr == TOHOST_OFFSET2) {
> - if (s->allow_tohost) {
> - s->tohost |= value << 32;
> - htif_handle_tohost_write(s, s->tohost);
> - }
> + s->tohost = deposit64(s->tohost, 32, 32, value);
> + s->tohost_status |= 0x2;
Won't this break existing users?
> } else if (addr == FROMHOST_OFFSET1) {
> - s->fromhost_inprogress = 1;
> - s->fromhost = value & 0xFFFFFFFF;
> + s->fromhost = deposit64(s->fromhost, 0, 32, value);
> + s->fromhost_status |= 0x1;
> } else if (addr == FROMHOST_OFFSET2) {
> - s->fromhost |= value << 32;
> - s->fromhost_inprogress = 0;
> + s->fromhost = deposit64(s->fromhost, 32, 32, value);
> + s->fromhost_status |= 0x2;
> } else {
> - qemu_log("Invalid htif write: address %016" PRIx64 "\n",
> - (uint64_t)addr);
> + qemu_log("Invalid htif write: address %016" HWADDR_PRIu "\n", addr);
> + }
> + if (s->tohost_status == 0x3) {
> + htif_handle_tohost_write(s, s->tohost);
> + s->tohost_status = 0x0;
> }
> }
1: https://github.com/riscv-software-src/opensbi/issues/238
Alistair
>
> static const MemoryRegionOps htif_mm_ops = {
> .read = htif_mm_read,
> .write = htif_mm_write,
> + .valid.min_access_size = 4,
> + .valid.max_access_size = 8,
> + .impl.min_access_size = 4,
> + .impl.max_access_size = 4
> };
>
> HTIFState *htif_mm_init(MemoryRegion *address_space, Chardev *chr,
> @@ -343,8 +346,8 @@ HTIFState *htif_mm_init(MemoryRegion *address_space,
> Chardev *chr,
> s->tohost_offset = tohost_offset;
> s->fromhost_offset = fromhost_offset;
> s->pending_read = 0;
> - s->allow_tohost = 0;
> - s->fromhost_inprogress = 0;
> + s->tohost_status = 0;
> + s->fromhost_status = 0;
> qemu_chr_fe_init(&s->chr, chr, &error_abort);
> qemu_chr_fe_set_handlers(&s->chr, htif_can_recv, htif_recv, htif_event,
> htif_be_change, s, NULL, true);
> diff --git a/include/hw/char/riscv_htif.h b/include/hw/char/riscv_htif.h
> index df493fdf6b..2b6d50dc60 100644
> --- a/include/hw/char/riscv_htif.h
> +++ b/include/hw/char/riscv_htif.h
> @@ -27,8 +27,15 @@
> #define TYPE_HTIF_UART "riscv.htif.uart"
>
> typedef struct HTIFState {
> - int allow_tohost;
> - int fromhost_inprogress;
> + /*
> + * Vars below can be in 4 states:
> + * 0x0 - nothing written
> + * 0x1 - xHOST_OFFEST1 written
> + * 0x2 - xHOST_OFFSET2 written
> + * 0x3 - Both written
> + */
> + int tohost_status;
> + int fromhost_status;
>
> uint64_t tohost;
> uint64_t fromhost;
> --
> 2.34.1
>
>
| [Prev in Thread] |
Current Thread |
[Next in Thread] |
- Re: [PATCH] hw/char/riscv_htif: Fix 64-bit var write order in 32-bit system,
Alistair Francis <=