On Tue, 2026-09-01 at 17:16 +0800, Zephyr Li wrote:
> helper_wrs_nto() may raise an illegal or virtual-instruction
> exception.
> However, trans_wrs_nto() does not save the decoded opcode before
> calling
> the helper. As a result, exception unwinding leaves env->bins stale
> and
> trap handling reports an incorrect value in tval.
> 
> Call decode_save_opc() before the helper so the faulting instruction
> encoding is restored for trap handling.
> 
> Add a TCG test that delegates the mstatus.TW-triggered illegal-
> instruction
> exception to S-mode and checks scause, sepc and stval.
> 
> Fixes: b62e0ce76098 ("target/riscv: Raise exceptions on wrs.nto")
> Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4080
> Signed-off-by: Zephyr Li <[email protected]>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  .../riscv/tcg/insn_trans/trans_rvzawrs.c.inc  |  2 +
>  tests/tcg/riscv64/Makefile.softmmu-target     |  4 +
>  tests/tcg/riscv64/test-zawrs-stval.S          | 87
> +++++++++++++++++++
>  3 files changed, 93 insertions(+)
>  create mode 100644 tests/tcg/riscv64/test-zawrs-stval.S
> 
> diff --git a/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc
> b/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc
> index 0eef033..ecebec0 100644
> --- a/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc
> +++ b/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc
> @@ -54,6 +54,8 @@ static bool trans_wrs_nto(DisasContext *ctx,
> arg_wrs_nto *a)
>       * exception, as handled by the wrs.nto helper.
>       */
>  #ifndef CONFIG_USER_ONLY
> +    /* Save the opcode in case the helper raises an exception. */
> +    decode_save_opc(ctx, 0);
>      gen_helper_wrs_nto(tcg_env);
>  #endif
>  
> diff --git a/tests/tcg/riscv64/Makefile.softmmu-target
> b/tests/tcg/riscv64/Makefile.softmmu-target
> index 6a219c3..979df2c 100644
> --- a/tests/tcg/riscv64/Makefile.softmmu-target
> +++ b/tests/tcg/riscv64/Makefile.softmmu-target
> @@ -20,6 +20,10 @@ EXTRA_RUNS += run-issue1060
>  run-issue1060: issue1060
>       $(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
>  
> +EXTRA_RUNS += run-test-zawrs-stval
> +run-test-zawrs-stval: test-zawrs-stval
> +     $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
> +
>  EXTRA_RUNS += run-test-mepc-masking
>  run-test-mepc-masking: test-mepc-masking
>       $(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
> diff --git a/tests/tcg/riscv64/test-zawrs-stval.S
> b/tests/tcg/riscv64/test-zawrs-stval.S
> new file mode 100644
> index 0000000..42a9901
> --- /dev/null
> +++ b/tests/tcg/riscv64/test-zawrs-stval.S
> @@ -0,0 +1,87 @@
> +/*
> + * Test that WRS.NTO writes the instruction encoding to stval when
> + * mstatus.TW causes an illegal-instruction exception in S-mode.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +     .option norvc
> +
> +     .text
> +     .global _start
> +_start:
> +     /* Unexpected traps to M-mode fail the test. */
> +     lla     t0, machine_trap
> +     csrw    mtvec, t0
> +
> +     /* Delegate illegal-instruction exceptions to S-mode. */
> +     li      t0, 1 << 2
> +     csrs    medeleg, t0
> +
> +     lla     t0, supervisor_trap
> +     csrw    stvec, t0
> +
> +     /* Give S-mode read, write and execute access to all memory.
> */
> +     li      t0, -1
> +     csrw    pmpaddr0, t0
> +     li      t0, 0xf
> +     csrw    pmpcfg0, t0
> +
> +     /* Set mstatus.TW and select S-mode for mret. */
> +     li      t0, 3 << 11
> +     csrc    mstatus, t0
> +     li      t0, (1 << 21) | (1 << 11)
> +     csrs    mstatus, t0
> +
> +     lla     t0, supervisor_start
> +     csrw    mepc, t0
> +     mret
> +
> +supervisor_start:
> +     /* WRS.NTO must trap because mstatus.TW is set. */
> +     li      a0, 1
> +wrs_nto:
> +     .word   0x00d00073
> +     j       _exit
> +
> +machine_trap:
> +     li      a0, 2
> +     j       _exit
> +
> +supervisor_trap:
> +     li      a0, 3
> +
> +     csrr    t0, scause
> +     li      t1, 2
> +     bne     t0, t1, _exit
> +
> +     csrr    t0, sepc
> +     lla     t1, wrs_nto
> +     bne     t0, t1, _exit
> +
> +     csrr    t1, stval
> +     lwu     t2, 0(t0)
> +     bne     t1, t2, _exit
> +     li      t2, 0x00d00073
> +     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 */
> +
> +     /* Semihosting call sequence. */
> +     .balign 16
> +     slli    zero, zero, 0x1f
> +     ebreak
> +     srai    zero, zero, 0x7
> +     j       .
> +
> +     .data
> +     .balign 16
> +semiargs:
> +     .space  16

Reply via email to