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
