[PATCH 2/2] tests/tcg/riscv64: Add test for MEPC bit masking

Charalampos Mitrodimas posted 2 patches 9 months, 2 weeks ago
Maintainers: Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Weiwei Li <liwei1518@gmail.com>, Daniel Henrique Barboza <dbarboza@ventanamicro.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>
[PATCH 2/2] tests/tcg/riscv64: Add test for MEPC bit masking
Posted by Charalampos Mitrodimas 9 months, 2 weeks ago
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 <charmitro@posteo.net>
---
 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
-- 
2.47.2
Re: [PATCH 2/2] tests/tcg/riscv64: Add test for MEPC bit masking
Posted by Daniel Henrique Barboza 9 months, 2 weeks ago

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 <charmitro@posteo.net>
> ---

The additional test is appreciated. Thanks!


Reviewed-by: Daniel Henrique Barboza <dbarboza@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