On 7/3/25 3:21 PM, Charalampos Mitrodimas wrote:
Add a regression test to verify that MEPC properly masks the lower
bits when an address with mode bits is written to it, as required by
the RISC-V Privileged Architecture specification.

The test sets STVEC to an address with bit 0 set (vectored mode),
triggers an illegal instruction exception, copies STVEC to MEPC in the
trap handler, and verifies that MEPC masks bits [1:0] correctly for
IALIGN=32.

Without the fix, MEPC retains the mode bits (returns non-zero/FAIL).
With the fix, MEPC clears bits [1:0] (returns 0/PASS).

Signed-off-by: Charalampos Mitrodimas <charmi...@posteo.net>
---

The additional test is appreciated. Thanks!


Reviewed-by: Daniel Henrique Barboza <dbarb...@ventanamicro.com>

  tests/tcg/riscv64/Makefile.softmmu-target |  4 ++
  tests/tcg/riscv64/test-mepc-masking.S     | 73 +++++++++++++++++++++++
  2 files changed, 77 insertions(+)
  create mode 100644 tests/tcg/riscv64/test-mepc-masking.S

diff --git a/tests/tcg/riscv64/Makefile.softmmu-target 
b/tests/tcg/riscv64/Makefile.softmmu-target
index 7c1d44d3f4..3ca595335d 100644
--- a/tests/tcg/riscv64/Makefile.softmmu-target
+++ b/tests/tcg/riscv64/Makefile.softmmu-target
@@ -20,5 +20,9 @@ EXTRA_RUNS += run-issue1060
  run-issue1060: issue1060
        $(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
+EXTRA_RUNS += run-test-mepc-masking
+run-test-mepc-masking: test-mepc-masking
+       $(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
+
  # We don't currently support the multiarch system tests
  undefine MULTIARCH_TESTS
diff --git a/tests/tcg/riscv64/test-mepc-masking.S 
b/tests/tcg/riscv64/test-mepc-masking.S
new file mode 100644
index 0000000000..fccd2a7ac4
--- /dev/null
+++ b/tests/tcg/riscv64/test-mepc-masking.S
@@ -0,0 +1,73 @@
+/*
+ * Test for MEPC masking bug fix
+ *
+ * This test verifies that MEPC properly masks the lower bits according
+ * to the RISC-V specification when vectored mode bits from STVEC are
+ * written to MEPC.
+ */
+
+       .option norvc
+
+       .text
+       .global _start
+_start:
+       /* Set up machine trap vector */
+       lla     t0, machine_trap_handler
+       csrw    mtvec, t0
+
+       /* Set STVEC with vectored mode (mode bits = 01) */
+       li      t0, 0x80004001
+       csrw    stvec, t0
+
+       /* Clear medeleg to handle exceptions in M-mode */
+       csrw    medeleg, zero
+
+       /* Trigger illegal instruction exception */
+       .word   0xffffffff
+
+test_completed:
+       /* Exit with result in a0 */
+       /* a0 = 0: success (bits [1:0] were masked) */
+       /* a0 != 0: failure (some bits were not masked) */
+       j       _exit
+
+machine_trap_handler:
+       /* Check if illegal instruction (mcause = 2) */
+       csrr    t0, mcause
+       li      t1, 2
+       bne     t0, t1, skip_test
+
+       /* Test: Copy STVEC (with mode bits) to MEPC */
+       csrr    t0, stvec       /* t0 = 0x80004001 */
+       csrw    mepc, t0        /* Write to MEPC */
+       csrr    t1, mepc        /* Read back MEPC */
+
+       /* Check if bits [1:0] are masked (IALIGN=32 without RVC) */
+       andi    a0, t1, 3       /* a0 = 0 if both bits masked correctly */
+
+       /* Set correct return address */
+       lla     t0, test_completed
+       csrw    mepc, t0
+
+skip_test:
+       mret
+
+/* Exit with semihosting */
+_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 8
+semiargs:
+       .space  16


Reply via email to