Commit 12289f2f9a for qemu.org

commit 12289f2f9a0f1ffa6a75c2b189a0273dc455dfb0
Author: wangyang <wangyang25@otcaix.iscas.ac.cn>
Date:   Thu Aug 13 18:39:06 2026 +0800

    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>

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);
     }