On Thu, Sep 10, 2026 at 10:39:41PM +0800, TANG Tiancheng wrote:
> Smcdeleg requires MINH to read as zero through sireg*. The RV64 callback
> masks it by modifying the machine register; the RV32 high-half callback
> does not mask it.
> 
> Return a masked copy without changing mcyclecfg or minstretcfg. Test both
> configuration registers on RV32 and RV64.
> 
> Fixes: d9fa41e10156 ("target/riscv: Bugfix make bit 62 read-only 0 for sireg* 
> cfg CSR read")
> Signed-off-by: TANG Tiancheng <[email protected]>
Reviewed-by: Chao Liu <[email protected]>

Thanks,
Chao

> ---
>  target/riscv/tcg/csr.c                 |  8 ++--
>  tests/tcg/riscv32/smcdeleg-minh-rv32.S | 78 
> ++++++++++++++++++++++++++++++++++
>  tests/tcg/riscv32/system/meson.build   |  7 +++
>  tests/tcg/riscv64/smcdeleg-minh.S      | 78 
> ++++++++++++++++++++++++++++++++++
>  tests/tcg/riscv64/system/meson.build   |  7 +++
>  5 files changed, 174 insertions(+), 4 deletions(-)
> 
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 
> 60caee32dc0cf5b6a8492e0cf8ff15f71acc2087..57030724f85a897e21e5082b9857411b50f932ac
>  100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -1607,7 +1607,7 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int 
> cfg_index, target_ulong *val,
>              wr_mask &= ~MCYCLECFG_BIT_MINH;
>              env->mcyclecfg = (new_val & wr_mask) | (env->mcyclecfg & 
> ~wr_mask);
>          } else {
> -            *val = env->mcyclecfg &= ~MHPMEVENT_BIT_MINH;
> +            *val = env->mcyclecfg & ~MCYCLECFG_BIT_MINH;
>          }
>          break;
>      case 2:             /* INSTRETCFG */
> @@ -1616,7 +1616,7 @@ static int rmw_cd_ctr_cfg(CPURISCVState *env, int 
> cfg_index, target_ulong *val,
>              env->minstretcfg = (new_val & wr_mask) |
>                                 (env->minstretcfg & ~wr_mask);
>          } else {
> -            *val = env->minstretcfg &= ~MHPMEVENT_BIT_MINH;
> +            *val = env->minstretcfg & ~MINSTRETCFG_BIT_MINH;
>          }
>          break;
>      default:
> @@ -1642,7 +1642,7 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int 
> cfg_index, target_ulong *val,
>              cfgh = (new_val & wr_mask) | (cfgh & ~wr_mask);
>              env->mcyclecfg = deposit64(env->mcyclecfg, 32, 32, cfgh);
>          } else {
> -            *val = cfgh;
> +            *val = cfgh & ~MCYCLECFGH_BIT_MINH;
>          }
>          break;
>      case 2:          /* INSTRETCFGH */
> @@ -1652,7 +1652,7 @@ static int rmw_cd_ctr_cfgh(CPURISCVState *env, int 
> cfg_index, target_ulong *val,
>              cfgh = (new_val & wr_mask) | (cfgh & ~wr_mask);
>              env->minstretcfg = deposit64(env->minstretcfg, 32, 32, cfgh);
>          } else {
> -            *val = cfgh;
> +            *val = cfgh & ~MINSTRETCFGH_BIT_MINH;
>          }
>          break;
>      default:
> diff --git a/tests/tcg/riscv32/smcdeleg-minh-rv32.S 
> b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..db467b95cf1441e3440f59097401cf6956d294d3
> --- /dev/null
> +++ b/tests/tcg/riscv32/smcdeleg-minh-rv32.S
> @@ -0,0 +1,78 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +/* CSR numbers for older assemblers. */
> +#define CSR_SISELECT         0x150
> +#define CSR_SIREG5           0x156
> +#define CSR_MENVCFGH         0x31a
> +#define CSR_MCYCLECFGH       0x721
> +#define CSR_MINSTRETCFGH     0x722
> +
> +     .option norvc
> +     .option norelax
> +
> +     .text
> +     .global _start
> +_start:
> +     /*
> +      * Failure bits:
> +      * 0: delegated cyclecfgh exposes MINH
> +      * 1: reading delegated cyclecfgh clears mcyclecfgh.MINH
> +      * 2: delegated instretcfgh exposes MINH
> +      * 3: reading delegated instretcfgh clears minstretcfgh.MINH
> +      */
> +     li      t4, 0
> +     li      t0, 1
> +     slli    t0, t0, 30              /* MINH in the high half */
> +     csrw    CSR_MCYCLECFGH, t0
> +     csrw    CSR_MINSTRETCFGH, t0
> +     li      t1, 1
> +     slli    t1, t1, 28              /* menvcfgh.CDE */
> +     csrw    CSR_MENVCFGH, t1
> +     li      t1, 5                   /* Delegate cycle and instret. */
> +     csrw    mcounteren, t1
> +
> +     /* Check the delegated view, then the underlying machine register. */
> +     li      t1, 0x40                /* siselect: cycle */
> +     csrw    CSR_SISELECT, t1
> +     csrr    t1, CSR_SIREG5
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     or      t4, t4, t1
> +     csrr    t1, CSR_MCYCLECFGH
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     xori    t1, t1, 1
> +     slli    t1, t1, 1
> +     or      t4, t4, t1
> +
> +     li      t1, 0x42                /* siselect: instret */
> +     csrw    CSR_SISELECT, t1
> +     csrr    t1, CSR_SIREG5
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     slli    t1, t1, 2
> +     or      t4, t4, t1
> +     csrr    t1, CSR_MINSTRETCFGH
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     xori    t1, t1, 1
> +     slli    t1, t1, 3
> +     or      t4, t4, t1
> +
> +     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 
> 16f9a06c9485ed75b3d127d6b9d090f5eaad4486..cfe2d854b729a8dfdbce2373e73b91b470db6b4e
>  100644
> --- a/tests/tcg/riscv32/system/meson.build
> +++ b/tests/tcg/riscv32/system/meson.build
> @@ -22,6 +22,13 @@ tests += {
>    },
>  }
>  
> +tests += {
> +  'smcdeleg-minh-rv32.S': {
> +    'cflags': cflags,
> +    'qemu_args': ['-cpu', 'max', qemu_args],
> +  },
> +}
> +
>  if 'qemu-system-riscv32' in emulators
>    tcg_tests += {
>      'riscv32-softmmu': {
> diff --git a/tests/tcg/riscv64/smcdeleg-minh.S 
> b/tests/tcg/riscv64/smcdeleg-minh.S
> new file mode 100644
> index 
> 0000000000000000000000000000000000000000..38d3c30f0afaa416a46322f2b892e5969172a60f
> --- /dev/null
> +++ b/tests/tcg/riscv64/smcdeleg-minh.S
> @@ -0,0 +1,78 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +/* CSR numbers for older assemblers. */
> +#define CSR_SISELECT         0x150
> +#define CSR_SIREG2           0x152
> +#define CSR_MENVCFG          0x30a
> +#define CSR_MCYCLECFG        0x321
> +#define CSR_MINSTRETCFG      0x322
> +
> +     .option norvc
> +     .option norelax
> +
> +     .text
> +     .global _start
> +_start:
> +     /*
> +      * Failure bits:
> +      * 0: delegated cyclecfg exposes MINH
> +      * 1: reading delegated cyclecfg clears mcyclecfg.MINH
> +      * 2: delegated instretcfg exposes MINH
> +      * 3: reading delegated instretcfg clears minstretcfg.MINH
> +      */
> +     li      t4, 0
> +     li      t0, 1
> +     slli    t0, t0, 62              /* MINH */
> +     csrw    CSR_MCYCLECFG, t0
> +     csrw    CSR_MINSTRETCFG, t0
> +     li      t1, 1
> +     slli    t1, t1, 60              /* menvcfg.CDE */
> +     csrw    CSR_MENVCFG, t1
> +     li      t1, 5                   /* Delegate cycle and instret. */
> +     csrw    mcounteren, t1
> +
> +     /* Check the delegated view, then the underlying machine register. */
> +     li      t1, 0x40                /* siselect: cycle */
> +     csrw    CSR_SISELECT, t1
> +     csrr    t1, CSR_SIREG2
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     or      t4, t4, t1
> +     csrr    t1, CSR_MCYCLECFG
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     xori    t1, t1, 1
> +     slli    t1, t1, 1
> +     or      t4, t4, t1
> +
> +     li      t1, 0x42                /* siselect: instret */
> +     csrw    CSR_SISELECT, t1
> +     csrr    t1, CSR_SIREG2
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     slli    t1, t1, 2
> +     or      t4, t4, t1
> +     csrr    t1, CSR_MINSTRETCFG
> +     and     t1, t1, t0
> +     sltu    t1, zero, t1
> +     xori    t1, t1, 1
> +     slli    t1, t1, 3
> +     or      t4, t4, t1
> +
> +     lla     a1, semiargs
> +     li      t0, 0x20026             /* ADP_Stopped_ApplicationExit */
> +     sd      t0, 0(a1)
> +     sd      t4, 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 16
> +semiargs:
> +     .space  16
> diff --git a/tests/tcg/riscv64/system/meson.build 
> b/tests/tcg/riscv64/system/meson.build
> index 
> 668a9a76070b6f16087b08ea84683d883312e951..5d91381c62d77ae7e37c129112d6367f692df660
>  100644
> --- a/tests/tcg/riscv64/system/meson.build
> +++ b/tests/tcg/riscv64/system/meson.build
> @@ -75,6 +75,13 @@ tests += {
>    },
>  }
>  
> +tests += {
> +  'smcdeleg-minh.S': {
> +    'cflags': cflags,
> +    'qemu_args': ['-cpu', 'max', qemu_args],
> +  },
> +}
> +
>  if 'qemu-system-riscv64' in emulators
>    tcg_tests += {
>      'riscv64-softmmu': {
> 
> -- 
> 2.43.0
> 

Reply via email to