From: wangyang <[email protected]> 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 Reviewed-by: Alistair Francis <[email protected]> Signed-off-by: wangyang <[email protected]> Message-ID: <[email protected]> Signed-off-by: Alistair Francis <[email protected]> --- target/riscv/cpu.c | 8 ++++++++ target/riscv/tcg/op_helper.c | 11 ++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index d8f239e41d..79ddde419a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1062,6 +1062,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 acdccd1a97..a7bd42d2c6 100644 --- a/target/riscv/tcg/op_helper.c +++ b/target/riscv/tcg/op_helper.c @@ -152,7 +152,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); } -- 2.54.0
