On Sun, 2026-07-26 at 11:05 +0300, A-Shehab wrote:
> The Zicfilp landing-pad enable (LPE, bit 2) and Zicfiss shadow-stack
> enable (SSE, bit 3) controls live in the low 32 bits of menvcfg and
> henvcfg, and the CFI specification defines them for both RV32 and
> RV64.
> 
> QEMU only adds MENVCFG_LPE/MENVCFG_SSE (and the henvcfg equivalents)
> to
> the writable mask inside the "riscv_cpu_mxl(env) == MXL_RV64" block,
> so
> on RV32 these bits are silently dropped and the features cannot be
> enabled. This is inconsistent with write_senvcfg(), which already
> handles SENVCFG_LPE/SENVCFG_SSE regardless of MXLEN.
> 
> Hoist the LPE/SSE mask handling out of the RV64-only block in
> write_menvcfg() and write_henvcfg() so the bits become writable on
> RV32
> as well. The upper-half writers (write_menvcfgh/write_henvcfgh) are
> unaffected because these bits reside in the low 32 bits.
> 
> Reproducible on qemu-system-riscv32 -cpu
> rv32,zicfilp=true,zicfiss=true:
> an M-mode write of menvcfg.{LPE,SSE} reads back as zero, while the
> same
> program on rv64 keeps the bits set.
> 
> Fixes: 4923f672e3d7 ("target/riscv: Introduce elp state and enabling
> controls for zicfilp")
> Fixes: 8205bc127a83 ("target/riscv: introduce ssp and enabling
> controls for zicfiss")
> Resolves: https://gitlab.com/qemu-project/qemu/-/issues/4045
> Signed-off-by: A-Shehab <[email protected]>

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
> v2: Rebase on current master; the file moved from target/riscv/csr.c
> to
>     target/riscv/tcg/csr.c (noted by Daniel Henrique Barboza). No
>     functional change.
> 
> v1:
> https://lore.kernel.org/qemu-devel/[email protected]/
> 
>  target/riscv/tcg/csr.c | 45 +++++++++++++++++++++++++---------------
> --
>  1 file changed, 27 insertions(+), 18 deletions(-)
> 
> diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c
> index 36f2004bc5..0182e4c408 100644
> --- a/target/riscv/tcg/csr.c
> +++ b/target/riscv/tcg/csr.c
> @@ -3216,6 +3216,19 @@ static RISCVException
> write_menvcfg(CPURISCVState *env, int csrno,
>                      MENVCFG_CBZE;
>      bool stce_changed = false;
>  
> +    /*
> +     * menvcfg.LPE (Zicfilp) and menvcfg.SSE (Zicfiss) reside in the
> low
> +     * 32 bits and are defined for both RV32 and RV64, so they must
> be
> +     * writable regardless of MXLEN.
> +     */
> +    if (cfg->ext_zicfilp) {
> +        mask |= MENVCFG_LPE;
> +    }
> +
> +    if (cfg->ext_zicfiss) {
> +        mask |= MENVCFG_SSE;
> +    }
> +
>      if (riscv_cpu_mxl(env) == MXL_RV64) {
>          mask |= (cfg->ext_svpbmt ? MENVCFG_PBMTE : 0) |
>                  (cfg->ext_sstc ? MENVCFG_STCE : 0) |
> @@ -3223,14 +3236,6 @@ static RISCVException
> write_menvcfg(CPURISCVState *env, int csrno,
>                  (cfg->ext_svadu ? MENVCFG_ADUE : 0) |
>                  (cfg->ext_ssdbltrp ? MENVCFG_DTE : 0);
>  
> -        if (env_archcpu(env)->cfg.ext_zicfilp) {
> -            mask |= MENVCFG_LPE;
> -        }
> -
> -        if (env_archcpu(env)->cfg.ext_zicfiss) {
> -            mask |= MENVCFG_SSE;
> -        }
> -
>          /* Update PMM field only if the value is valid according to
> Zjpm v1.0 */
>          if (env_archcpu(env)->cfg.ext_smnpm &&
>              get_field(val, MENVCFG_PMM) != PMM_FIELD_RESERVED) {
> @@ -3378,20 +3383,24 @@ static RISCVException
> write_henvcfg(CPURISCVState *env, int csrno,
>          return ret;
>      }
>  
> +    /*
> +     * henvcfg.LPE (Zicfilp) and henvcfg.SSE (Zicfiss) reside in the
> low
> +     * 32 bits and are defined for both RV32 and RV64, so they must
> be
> +     * writable regardless of MXLEN.
> +     */
> +    if (cfg->ext_zicfilp) {
> +        mask |= HENVCFG_LPE;
> +    }
> +
> +    /* H can light up SSE for VS only if HS had it from menvcfg */
> +    if (cfg->ext_zicfiss && get_field(env->menvcfg, MENVCFG_SSE)) {
> +        mask |= HENVCFG_SSE;
> +    }
> +
>      if (riscv_cpu_mxl(env) == MXL_RV64) {
>          mask |= env->menvcfg & (HENVCFG_PBMTE | HENVCFG_STCE |
> HENVCFG_ADUE |
>                                  HENVCFG_DTE);
>  
> -        if (env_archcpu(env)->cfg.ext_zicfilp) {
> -            mask |= HENVCFG_LPE;
> -        }
> -
> -        /* H can light up SSE for VS only if HS had it from menvcfg
> */
> -        if (env_archcpu(env)->cfg.ext_zicfiss &&
> -            get_field(env->menvcfg, MENVCFG_SSE)) {
> -            mask |= HENVCFG_SSE;
> -        }
> -
>          /* Update PMM field only if the value is valid according to
> Zjpm v1.0 */
>          if (env_archcpu(env)->cfg.ext_ssnpm &&
>              get_field(val, HENVCFG_PMM) != PMM_FIELD_RESERVED) {

Reply via email to