RV32 write_minstretcfg() replaces the full 64-bit register, clearing
minstretcfgh and its privilege-inhibit bits.
Replace only bits 31:0, as write_mcyclecfg() does. Test that a low-half
write preserves both set and clear xINH bits in minstretcfgh.
Fixes: b54a84c15e38 ("target/riscv: Add cycle & instret privilege mode
filtering support")
Signed-off-by: TANG Tiancheng <[email protected]>
---
target/riscv/tcg/csr.c | 2 +-
tests/tcg/riscv32/pmu-minstretcfg-rv32.S | 52 ++++++++++++++++++++++++++++++++
tests/tcg/riscv32/system/meson.build | 7 +++++
3 files changed, 60 insertions(+), 1 deletion(-)
diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
index
57030724f85a897e21e5082b9857411b50f932ac..f9f43a9c12e1afdbdf6c7202c167988389963c10
100644
--- a/target/riscv/tcg/csr.c
+++ b/target/riscv/tcg/csr.c
@@ -1167,7 +1167,7 @@ static RISCVException write_minstretcfg(CPURISCVState
*env, int csrno,
uint64_t inh_avail_mask;
if (riscv_cpu_mxl(env) == MXL_RV32) {
- env->minstretcfg = val;
+ env->minstretcfg = deposit64(env->minstretcfg, 0, 32, val);
} else {
inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MINSTRETCFG_BIT_MINH;
inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFG_BIT_UINH : 0;
diff --git a/tests/tcg/riscv32/pmu-minstretcfg-rv32.S
b/tests/tcg/riscv32/pmu-minstretcfg-rv32.S
new file mode 100644
index
0000000000000000000000000000000000000000..59ee516cea9d09d0945033a77e788e4387cd684f
--- /dev/null
+++ b/tests/tcg/riscv32/pmu-minstretcfg-rv32.S
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* CSR numbers for older assemblers. */
+#define CSR_MINSTRETCFG 0x322
+#define CSR_MINSTRETCFGH 0x722
+
+/* RV32 writes to minstretcfg must preserve minstretcfgh. */
+
+ .option norvc
+ .option norelax
+
+ .text
+ .global _start
+_start:
+ /*
+ * Use complementary patterns to check both set and clear xINH bits.
+ * All fields in the low half are WPRI, so write zero there.
+ * Exit status 1 or 2 identifies the pattern that was not preserved.
+ */
+ li t4, 1
+ li t0, 0x54000000 /* MINH, UINH, VUINH */
+ csrw CSR_MINSTRETCFGH, t0
+ csrw CSR_MINSTRETCFG, zero
+ csrr t1, CSR_MINSTRETCFGH
+ bne t0, t1, exit
+
+ li t4, 2
+ li t0, 0x28000000 /* SINH, VSINH */
+ csrw CSR_MINSTRETCFGH, t0
+ csrw CSR_MINSTRETCFG, zero
+ csrr t1, CSR_MINSTRETCFGH
+ bne t0, t1, exit
+ li t4, 0
+
+exit:
+ lla a1, semiargs
+ li t0, 0x20026 /* ADP_Stopped_ApplicationExit */
+ sw t0, 0(a1)
+ sw t4, 4(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 8
diff --git a/tests/tcg/riscv32/system/meson.build
b/tests/tcg/riscv32/system/meson.build
index
cfe2d854b729a8dfdbce2373e73b91b470db6b4e..5f417c0c51e17840072104812f5854dfb65d1d06
100644
--- a/tests/tcg/riscv32/system/meson.build
+++ b/tests/tcg/riscv32/system/meson.build
@@ -29,6 +29,13 @@ tests += {
},
}
+tests += {
+ 'pmu-minstretcfg-rv32.S': {
+ 'cflags': cflags,
+ 'qemu_args': ['-cpu', 'max', qemu_args],
+ },
+}
+
if 'qemu-system-riscv32' in emulators
tcg_tests += {
'riscv32-softmmu': {
--
2.43.0