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/Makefile.softmmu-target |  4 +++
 tests/tcg/riscv32/pmu-minstretcfg-rv32.S  | 48 +++++++++++++++++++++++++++++++
 3 files changed, 53 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/Makefile.softmmu-target 
b/tests/tcg/riscv32/Makefile.softmmu-target
index 
67d334974577e14ff36e7c51067ebcab4c1349bd..43c162fd337f7b0d5d3e4dedb3f5b06b2821fd88
 100644
--- a/tests/tcg/riscv32/Makefile.softmmu-target
+++ b/tests/tcg/riscv32/Makefile.softmmu-target
@@ -20,3 +20,7 @@ QEMU_OPTS += -M virt -display none -semihosting -device 
loader,file=
 TESTS += smcdeleg-minh-rv32
 run-smcdeleg-minh-rv32: smcdeleg-minh-rv32
        $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
+
+TESTS += pmu-minstretcfg-rv32
+run-pmu-minstretcfg-rv32: pmu-minstretcfg-rv32
+       $(call run-test, $<, $(QEMU) -cpu max $(QEMU_OPTS)$<)
diff --git a/tests/tcg/riscv32/pmu-minstretcfg-rv32.S 
b/tests/tcg/riscv32/pmu-minstretcfg-rv32.S
new file mode 100644
index 
0000000000000000000000000000000000000000..44f6127da1babe04d6d1094dce5f37528282bee3
--- /dev/null
+++ b/tests/tcg/riscv32/pmu-minstretcfg-rv32.S
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+
+/* 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    0x722, t0               /* minstretcfgh */
+       csrw    0x322, zero             /* minstretcfg */
+       csrr    t1, 0x722
+       bne     t0, t1, exit
+
+       li      t4, 2
+       li      t0, 0x28000000          /* SINH, VSINH */
+       csrw    0x722, t0               /* minstretcfgh */
+       csrw    0x322, zero             /* minstretcfg */
+       csrr    t1, 0x722
+       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

-- 
2.43.0


Reply via email to