summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwangyang <wangyang25@otcaix.iscas.ac.cn>2026-08-13 18:39:06 +0800
committerMichael Tokarev <mjt@tls.msk.ru>2026-08-25 14:11:14 +0300
commit173828812d0f20009431792c0716dd864df7e0c3 (patch)
tree0d014e0ca1e01fbf93ef0696fb0d405c5d29f74d
parent1d9ee023d3be92264e1ed9d8ae0c4a6d5d0a504d (diff)
downloadqemu-173828812d0f20009431792c0716dd864df7e0c3.tar.gz
qemu-173828812d0f20009431792c0716dd864df7e0c3.zip
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> (cherry picked from commit 12289f2f9a0f1ffa6a75c2b189a0273dc455dfb0) Signed-off-by: Michael Tokarev <mjt@tls.msk.ru>
-rw-r--r--target/riscv/cpu.c8
-rw-r--r--target/riscv/op_helper.c11
2 files changed, 18 insertions, 1 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 9e4f54d250..bf4855ec02 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1116,6 +1116,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
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 0cdbb0138c..c5dc18a27b 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -142,7 +142,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);
}