On Tue, 2026-08-11 at 09:14 +0800, wangyang wrote: > In user-only builds check_zicbo_envcfg() skipped the envcfg check > entirely (#if !defined(CONFIG_USER_ONLY)), so cbo.inval/cbo.flush/ > cbo.zero retired unconditionally in linux-user even though the > machine-level envcfg fields are never initialized. Give the > user-mode build a senvcfg-based gate, and initialize SENVCFG_CBZE at > reset when ext_zicboz is enabled so cbo.zero stays usable while > cbo.inval/cbo.flush remain illegal, matching the user-mode view of a > typical firmware/kernel setup. > > Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4107 > Signed-off-by: wangyang <[email protected]>
Reviewed-by: Alistair Francis <[email protected]> Alistair > --- > 2 files changed, 18 insertions(+), 1 deletion(-) > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c > index 5a82e6563bf..45b7610aa4f 100644 > --- a/target/riscv/cpu.c > +++ b/target/riscv/cpu.c > @@ -1061,6 +1061,14 @@ static void riscv_cpu_reset_hold(Object *obj, > ResetType type) > #else > env->priv = PRV_U; > env->senvcfg = 0; > + /* > + * Match the user-mode view of a typical firmware/kernel setup > where > + * cbo.zero is enabled for user mode; the CBCFE/CBIE bits stay > zero, > + * so the cache-management operations remain illegal in user > mode. > + */ > + if (riscv_cpu_cfg(env)->ext_zicboz) { > + env->senvcfg |= SENVCFG_CBZE; > + } > env->menvcfg = 0; > #endif /* !CONFIG_USER_ONLY */ > > diff --git a/target/riscv/tcg/op_helper.c > b/target/riscv/tcg/op_helper.c > index ba3c7da375a..b9d0deacdfb 100644 > --- a/target/riscv/tcg/op_helper.c > +++ b/target/riscv/tcg/op_helper.c > @@ -146,7 +146,16 @@ target_ulong helper_csrrw_i128(CPURISCVState > *env, int csr, > static void check_zicbo_envcfg(CPURISCVState *env, target_ulong > envbits, > uintptr_t ra) > { > -#ifndef CONFIG_USER_ONLY > +#if defined(CONFIG_USER_ONLY) > + /* > + * linux-user: the machine-level envcfg fields are not part of > the > + * user-mode environment; only the user-mode view of the > enabling > + * bits (senvcfg, as initialized for the guest) applies. > + */ > + if (!get_field(env->senvcfg, envbits)) { > + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); > + } > +#else > if ((env->priv < PRV_M) && !get_field(env->menvcfg, envbits)) { > riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); > }
