Only jvt.mode=0 is implemented, and jvt.mode is a WARL field, so a
software write of a reserved mode encoding must read back with the
implemented mode. write_jvt() currently stores the raw value, which
retains the reserved bits and makes a subsequent cm.jt trap. Mask the
written value with JVT_BASE and add a TCG test case covering the
readback.

Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4408
Reviewed-by: Alistair Francis <[email protected]>
Signed-off-by: wangyang <[email protected]>
---
 target/riscv/tcg/csr.c               |  6 ++++-
 tests/tcg/riscv64/system/meson.build |  9 +++++++
 tests/tcg/riscv64/test-jvt-warl.S    | 38 ++++++++++++++++++++++++++++
 3 files changed, 52 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/riscv64/test-jvt-warl.S

diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index 061bc9db77..d16c9cd3c7 100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -5904,7 +5904,11 @@ static RISCVException read_jvt(CPURISCVState *env, int 
csrno,
 static RISCVException write_jvt(CPURISCVState *env, int csrno,
                                 target_ulong val, uintptr_t ra)
 {
-    env->jvt = val;
+    /*
+     * jvt.mode is WARL and only mode 0 is implemented, so drop the
+     * reserved mode encodings instead of storing them.
+     */
+    env->jvt = val & JVT_BASE;
     return RISCV_EXCP_NONE;
 }
 
diff --git a/tests/tcg/riscv64/system/meson.build 
b/tests/tcg/riscv64/system/meson.build
index c2d7d09887..90ad6b7e85 100644
--- a/tests/tcg/riscv64/system/meson.build
+++ b/tests/tcg/riscv64/system/meson.build
@@ -61,6 +61,15 @@ tests += {
   }
 }
 
+# Zcmt is incompatible with the Zcd extension, so the default rv64 CPU
+# cannot be used here.
+tests += {
+  'test-jvt-warl.S': {
+    'cflags': cflags + ['-march=rv64gc_zicsr'],
+    'qemu_args': ['-cpu', 'rv64,zcmt=true,zcd=false', qemu_args],
+  }
+}
+
 if 'qemu-system-riscv64' in emulators
   tcg_tests += {
     'riscv64-softmmu': {
diff --git a/tests/tcg/riscv64/test-jvt-warl.S 
b/tests/tcg/riscv64/test-jvt-warl.S
new file mode 100644
index 0000000000..3dade6c506
--- /dev/null
+++ b/tests/tcg/riscv64/test-jvt-warl.S
@@ -0,0 +1,38 @@
+/*
+ * Zcmt jvt WARL test.
+ *
+ * jvt.mode is a WARL field and QEMU implements mode 0 only, so a write of a
+ * reserved mode encoding must read back with the mode field cleared.
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+.option norvc
+       .text
+       .global _start
+_start:
+       li      t0, 0x123bf
+       csrw    0x017, t0
+       csrr    t1, 0x017
+       li      t2, 0x12380
+       li      a0, 1
+       bne     t1, t2, _exit
+
+       li      a0, 0
+
+_exit:
+       lla     a1, semiargs
+       li      t0, 0x20026             /* ADP_Stopped_ApplicationExit */
+       sd      t0, 0(a1)
+       sd      a0, 8(a1)
+       li      a0, 0x20                /* TARGET_SYS_EXIT_EXTENDED */
+       .balign 16
+       slli    zero, zero, 0x1f
+       ebreak
+       srai    zero, zero, 0x7
+       j       .
+
+       .data
+       .balign 16
+semiargs:
+       .space  16
-- 
2.55.0.windows.2


Reply via email to