On Thu, Sep 10, 2026 at 10:39:42PM +0800, TANG Tiancheng wrote:
> 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]>
Reviewed-by: Chao Liu <[email protected]>

Thanks,
Chao

> ---
>  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
> 

Reply via email to