@samitouri / QOSamiQemu / commits / 12289f2f9a

target/riscv: honor zicbo* envcfg gating in linux-user mode

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 <alistair.francis@wdc.com> Signed-off-by: wangyang <wangyang25@otcaix.iscas.ac.cn> Message-ID: <9b2f22fc402b48b8ba81f72be8ed04bc@wangyang25.otcaix.iscas.ac.cn> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

wangyang committed Aug 13, 2026 at 18:39 UTC 12289f2f9a0f1ffa6a75c2b189a0273dc455dfb0
2 files changed +18 -1
target/riscv/cpu.c
+8
@@ -1062,6 +1062,14 @@ static void riscv_cpu_reset_hold(Object *obj, ResetType type)
1062 #else
1063 env->priv = PRV_U;
1064 env->senvcfg = 0;
1065 + /*
1066 + * Match the user-mode view of a typical firmware/kernel setup where
1067 + * cbo.zero is enabled for user mode; the CBCFE/CBIE bits stay zero,
1068 + * so the cache-management operations remain illegal in user mode.
1069 + */
1070 + if (riscv_cpu_cfg(env)->ext_zicboz) {
1071 + env->senvcfg |= SENVCFG_CBZE;
1072 + }
1073 env->menvcfg = 0;
1074 #endif /* !CONFIG_USER_ONLY */
1075
target/riscv/tcg/op_helper.c
+10 -1
@@ -152,7 +152,16 @@ target_ulong helper_csrrw_i128(CPURISCVState *env, int csr,
152 static void check_zicbo_envcfg(CPURISCVState *env, target_ulong envbits,
153 uintptr_t ra)
154 {
155 -#ifndef CONFIG_USER_ONLY
155 +#if defined(CONFIG_USER_ONLY)
156 + /*
157 + * linux-user: the machine-level envcfg fields are not part of the
158 + * user-mode environment; only the user-mode view of the enabling
159 + * bits (senvcfg, as initialized for the guest) applies.
160 + */
161 + if (!get_field(env->senvcfg, envbits)) {
162 + riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
163 + }
164 +#else
165 if ((env->priv < PRV_M) && !get_field(env->menvcfg, envbits)) {
166 riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra);
167 }