From nobody Sat Sep 26 20:51:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789093107270337.48580078758425; Thu, 10 Sep 2026 19:18:27 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x4qph-0003Kv-2Y; Thu, 10 Sep 2026 22:17:41 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x4qUG-0007Nj-Jf; Thu, 10 Sep 2026 21:55:39 -0400 Received: from smtp81.cstnet.cn ([159.226.251.81] helo=cstnet.cn) by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1x4qTz-0007b5-3r; Thu, 10 Sep 2026 21:55:28 -0400 Received: from DESKTOP-7FLBREN (unknown [124.16.137.194]) by APP-03 (Coremail) with SMTP id rQCowACHjz1sX6NqA05fBw--.10502S4; Fri, 11 Sep 2026 09:54:57 +0800 (CST) Message-ID: <41f744bcf7604f71ae13108069efd94e@wangyang25.otcaix.iscas.ac.cn> In-Reply-To: References: MIME-Version: 1.0 From: "wangyang" To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, "Palmer Dabbelt" , "Alistair Francis" , "Weiwei Li" , "Daniel Henrique Barboza" , "Liu Zhiwei" , "Chao Liu" , "Laurent Vivier" , "Helge Deller" , "Pierrick Bouvier" Date: 11 Sep 2026 09:54:57 +0800 Subject: [PATCH v2 1/2] linux-user/riscv: honor zicntr=false for base counterCSRs Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: rQCowACHjz1sX6NqA05fBw--.10502S4 X-Coremail-Antispam: 1UD129KBjvJXoW7trWkAryrZFykCF1xtr15XFb_yoW8Wr4Dpr 4kWa47WrZ5tas2ka97trsrWF1fWa1fG3y7Gws293ykGw45A3yUGrs0qF1UJF18WFZxCwsx uFW7tw4kCF48AFDanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUdqb7Iv0xC_Kw4lb4IE77IF4wAFF20E14v26ryj6rWUM7CY07I2 0VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI 8067AKxVWUGwA2048vs2IY020Ec7CjxVAFwI0_Gr0_Xr1l8cAvFVAK0II2c7xJM28CjxkF 64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcV CY1x0267AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIE14v26r1j6r4UM28EF7xvwVC2z280aVCY 1x0267AKxVW8JVW8Jr1lnxkEFVAIw20F6cxK64vIFxWle2I262IYc4CY6c8Ij28IcVAaY2 xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_Jrv_JF1lYx0Ex4A2 jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvEwIxGrwACY4xI67k042 43AVAKzVAKj4xxM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14v26r1q6r43MxkI ecxEwVAFwVWkMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I 8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8 ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x 0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8Jr1l6VACY4xI67k04243AbIYCTnIWI evJa73UjIFyTuYvjxUyLIDDUUUU X-Originating-IP: [124.16.137.194] X-CM-SenderInfo: 5zdqw5xdqjjk46rwut1l0ox2xfdvhtffof0/ Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=159.226.251.81; envelope-from=wangyang25@otcaix.iscas.ac.cn; helo=cstnet.cn X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1789093114181158500 Content-Type: text/plain; charset="utf-8" In user-only builds, the base cycle and instret CSRs bypass the zicntr feature gate because the check is inside the system-mode block. Move the check before the conditional block so an explicitly disabled zicntr extension makes the CSRs illegal in linux-user mode. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4148 Reviewed-by: Alistair Francis Signed-off-by: wangyang --- Changes since v1: - Rebased onto current master; the code change is unchanged. - Resent as patch 1/2 in the complete series. target/riscv/tcg/csr.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/target/riscv/tcg/csr.c b/target/riscv/tcg/csr.c index bd4b6dc114..061bc9db77 100644 --- a/target/riscv/tcg/csr.c +++ b/target/riscv/tcg/csr.c @@ -111,6 +111,13 @@ static RISCVException vs(CPURISCVState *env, int csrno) =20 static RISCVException ctr(CPURISCVState *env, int csrno) { + if ((csrno >=3D CSR_CYCLE && csrno <=3D CSR_INSTRET) || + (csrno >=3D CSR_CYCLEH && csrno <=3D CSR_INSTRETH)) { + if (!riscv_cpu_cfg(env)->ext_zicntr) { + return RISCV_EXCP_ILLEGAL_INST; + } + } + #if !defined(CONFIG_USER_ONLY) RISCVCPU *cpu =3D env_archcpu(env); int ctr_index; @@ -127,10 +134,6 @@ static RISCVException ctr(CPURISCVState *env, int csrn= o) =20 if ((csrno >=3D CSR_CYCLE && csrno <=3D CSR_INSTRET) || (csrno >=3D CSR_CYCLEH && csrno <=3D CSR_INSTRETH)) { - if (!riscv_cpu_cfg(env)->ext_zicntr) { - return RISCV_EXCP_ILLEGAL_INST; - } - goto skip_ext_pmu_check; } =20 From nobody Sat Sep 26 20:51:35 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org Return-Path: Received: from lists1p.gnu.org (lists1p.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1789093341169166.3397777519042; Thu, 10 Sep 2026 19:22:21 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists1p.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1x4qtt-0005Uy-6q; Thu, 10 Sep 2026 22:22:01 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists1p.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1x4qUG-0007Ni-HS; Thu, 10 Sep 2026 21:55:39 -0400 Received: from smtp81.cstnet.cn ([159.226.251.81] helo=cstnet.cn) by eggs.gnu.org with esmtps (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1x4qTw-0007c1-9E; Thu, 10 Sep 2026 21:55:17 -0400 Received: from DESKTOP-7FLBREN (unknown [124.16.137.194]) by APP-03 (Coremail) with SMTP id rQCowACHjz1sX6NqA05fBw--.10502S5; Fri, 11 Sep 2026 09:54:58 +0800 (CST) Message-ID: In-Reply-To: References: MIME-Version: 1.0 From: "wangyang" To: qemu-devel@nongnu.org Cc: qemu-riscv@nongnu.org, "Palmer Dabbelt" , "Alistair Francis" , "Weiwei Li" , "Daniel Henrique Barboza" , "Liu Zhiwei" , "Chao Liu" , "Laurent Vivier" , "Helge Deller" , "Pierrick Bouvier" Date: 11 Sep 2026 09:54:58 +0800 Subject: [PATCH v2 2/2] linux-user/riscv: invalidate reservations after stores Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: rQCowACHjz1sX6NqA05fBw--.10502S5 X-Coremail-Antispam: 1UD129KBjvJXoWfGw4DtFy5uF4kuryUJryDGFg_yoWkZr4xpF 4kCrW2krWrtF97J3yIyF4UCFn5Za1F9rW3W39avwnavF45JrZIyr1DK3yakry5WFWkXr12 9Fyqvw15C3yUX3JanT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUdqb7Iv0xC_Kw4lb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I2 0VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI 8067AKxVWUXwA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF 64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVWUJVWUCwA2z4x0Y4vE2Ix0cI8IcV CY1x0267AKxVW8JVWxJwA2z4x0Y4vEx4A2jsIE14v26r1j6r4UM28EF7xvwVC2z280aVCY 1x0267AKxVW8JVW8Jr1lnxkEFVAIw20F6cxK64vIFxWle2I262IYc4CY6c8Ij28IcVAaY2 xG8wAqx4xG64xvF2IEw4CE5I8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_Jrv_JF1lYx0Ex4A2 jsIE14v26r1j6r4UMcvjeVCFs4IE7xkEbVWUJVW8JwACjcxG0xvEwIxGrwACY4xI67k042 43AVAKzVAKj4xxM4IIrI8v6xkF7I0E8cxan2IY04v7MxkF7I0En4kS14v26r1q6r43MxkI ecxEwVAFwVWkMxAIw28IcxkI7VAKI48JMxC20s026xCaFVCjc4AY6r1j6r4UMI8I3I0E5I 8CrVAFwI0_Jr0_Jr4lx2IqxVCjr7xvwVAFwI0_JrI_JrWlx4CE17CEb7AF67AKxVWUtVW8 ZwCIc40Y0x0EwIxGrwCI42IY6xIIjxv20xvE14v26r1j6r1xMIIF0xvE2Ix0cI8IcVCY1x 0267AKxVW8JVWxJwCI42IY6xAIw20EY4v20xvaj40_Jr0_JF4lIxAIcVC2z280aVAFwI0_ Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8Jr1l6VACY4xI67k04243AbIYCTnIWI evJa73UjIFyTuYvjxUgYiRDUUUU X-Originating-IP: [124.16.137.194] X-CM-SenderInfo: 5zdqw5xdqjjk46rwut1l0ox2xfdvhtffof0/ Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists1p.gnu.org; Received-SPF: pass client-ip=159.226.251.81; envelope-from=wangyang25@otcaix.iscas.ac.cn; helo=cstnet.cn X-Spam_score_int: -41 X-Spam_score: -4.2 X-Spam_bar: ---- X-Spam_report: (-4.2 / 5.0 requ) BAYES_00=-1.9, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: qemu development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZM-MESSAGEID: 1789093344047158500 Content-Type: text/plain; charset="utf-8" In linux-user parallel execution, AMO and ordinary integer stores do not invalidate load reservations held by another hart. A store that preserves the numeric value can therefore leave the reservation intact and allow a later SC to succeed. Use the existing EXCP_ATOMIC path to re-execute LR, SC, AMO, and ordinary integer store instructions in a serial context. The completed store and reservation invalidation then cannot be interleaved with another guest hart. Track the LR access size and invalidate every other-hart reservation whose byte range overlaps the completed store. A successful SC uses the same invalidation helper. Clear the reservation when cloning a new linux-user RISC-V hart so that a child cannot inherit the parent's reservation state. The change is limited to linux-user TCG and the base scalar integer/ A-extension translator paths. Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/4149 Signed-off-by: wangyang --- Changes since v1: - Cover ordinary base scalar integer stores as well as AMOs. - Serialize the memory operation and invalidation with EXCP_ATOMIC. - Track the LR access range and clear reservations after hart cloning. - The implementation changed materially, so fresh review is requested. linux-user/riscv/target_cpu.h | 2 + target/riscv/cpu.c | 3 ++ target/riscv/cpu.h | 3 ++ target/riscv/helper.h | 5 +++ target/riscv/tcg/insn_trans/trans_rva.c.inc | 24 ++++++++++++ target/riscv/tcg/insn_trans/trans_rvi.c.inc | 11 ++++++ .../riscv/tcg/insn_trans/trans_rvzawrs.c.inc | 3 ++ target/riscv/tcg/op_helper.c | 35 +++++++++++++++++ target/riscv/tcg/translate.c | 38 +++++++++++++++++++ 9 files changed, 124 insertions(+) diff --git a/linux-user/riscv/target_cpu.h b/linux-user/riscv/target_cpu.h index 9c642367a3..eff18b37ba 100644 --- a/linux-user/riscv/target_cpu.h +++ b/linux-user/riscv/target_cpu.h @@ -9,6 +9,8 @@ static inline void cpu_clone_regs_child(CPURISCVState *env,= target_ulong newsp, } =20 env->gpr[xA0] =3D 0; + env->load_res =3D -1; + env->load_res_size =3D 0; } =20 static inline void cpu_clone_regs_parent(CPURISCVState *env, unsigned flag= s) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 5fff9d745e..da4c1a090b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1084,6 +1084,9 @@ static void riscv_cpu_reset_hold(Object *obj, ResetTy= pe type) env->xl =3D riscv_cpu_mxl(env); cs->exception_index =3D RISCV_EXCP_NONE; env->load_res =3D -1; +#ifdef CONFIG_USER_ONLY + env->load_res_size =3D 0; +#endif set_default_nan_mode(1, &env->fp_status); /* Default NaN value: sign bit clear, frac msb set */ set_float_default_nan_pattern(0b01000000, &env->fp_status); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index c2138dbd4b..8c8ffe94cd 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -264,6 +264,9 @@ struct CPUArchState { =20 uint64_t pc; uint64_t load_res; +#ifdef CONFIG_USER_ONLY + uint64_t load_res_size; +#endif uint64_t load_val; =20 /* Floating-Point state */ diff --git a/target/riscv/helper.h b/target/riscv/helper.h index 4fc2d3a155..aab92bf132 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1357,3 +1357,8 @@ DEF_HELPER_1(ssamoswap_disabled, void, env) =20 /* Zalrsc SC write probe */ DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl) + +#ifdef CONFIG_USER_ONLY +/* Invalidate reservations overlapping a completed linux-user store. */ +DEF_HELPER_3(riscv_invalidate_reservations, void, env, tl, tl) +#endif diff --git a/target/riscv/tcg/insn_trans/trans_rva.c.inc b/target/riscv/tcg= /insn_trans/trans_rva.c.inc index 44c1696fe4..248a8c60d7 100644 --- a/target/riscv/tcg/insn_trans/trans_rva.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rva.c.inc @@ -32,6 +32,11 @@ =20 static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) { +#ifdef CONFIG_USER_ONLY + if (!gen_riscv_reservation_serialize(ctx)) { + return false; + } +#endif TCGv src1; =20 mop |=3D MO_ALIGN; @@ -53,6 +58,9 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemO= p mop) =20 /* Put addr in load_res, data in load_val. */ tcg_gen_mov_tl(load_res, src1); +#ifdef CONFIG_USER_ONLY + tcg_gen_movi_tl(load_res_size, memop_size(mop)); +#endif gen_set_gpr(ctx, a->rd, load_val); =20 return true; @@ -60,9 +68,17 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, Mem= Op mop) =20 static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) { +#ifdef CONFIG_USER_ONLY + if (!gen_riscv_reservation_serialize(ctx)) { + return false; + } +#endif TCGv dest, src1, src2; TCGLabel *l1 =3D gen_new_label(); TCGLabel *l2 =3D gen_new_label(); +#ifdef CONFIG_USER_ONLY + TCGLabel *l3 =3D gen_new_label(); +#endif =20 mop |=3D MO_ALIGN; mop |=3D ctx->mo_endianness; @@ -79,6 +95,11 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, Mem= Op mop) src2 =3D get_gpr(ctx, a->rs2, EXT_NONE); tcg_gen_atomic_cmpxchg_tl(dest, load_res, load_val, src2, ctx->mem_idx, mop); +#ifdef CONFIG_USER_ONLY + tcg_gen_brcond_tl(TCG_COND_NE, dest, load_val, l3); + gen_riscv_invalidate_reservations(src1, mop); + gen_set_label(l3); +#endif tcg_gen_setcond_tl(TCG_COND_NE, dest, dest, load_val); gen_set_gpr(ctx, a->rd, dest); tcg_gen_br(l2); @@ -104,6 +125,9 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, Me= mOp mop) * an SC to any address, in between an LR and SC pair. */ tcg_gen_movi_tl(load_res, -1); +#ifdef CONFIG_USER_ONLY + tcg_gen_movi_tl(load_res_size, 0); +#endif =20 return true; } diff --git a/target/riscv/tcg/insn_trans/trans_rvi.c.inc b/target/riscv/tcg= /insn_trans/trans_rvi.c.inc index cc1b5dbbad..40b4c9aa4a 100644 --- a/target/riscv/tcg/insn_trans/trans_rvi.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rvi.c.inc @@ -489,6 +489,9 @@ static bool gen_store_tl(DisasContext *ctx, arg_sb *a, = MemOp memop) } =20 tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); +#ifdef CONFIG_USER_ONLY + gen_riscv_invalidate_reservations(addr, memop); +#endif return true; } =20 @@ -518,11 +521,19 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb = *a, MemOp memop) } tcg_gen_qemu_st_i128(t16, addrl, ctx->mem_idx, memop); } +#ifdef CONFIG_USER_ONLY + gen_riscv_invalidate_reservations(addrl, memop); +#endif return true; } =20 static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { +#ifdef CONFIG_USER_ONLY + if (!gen_riscv_reservation_serialize(ctx)) { + return false; + } +#endif memop |=3D ctx->mo_endianness; if (ctx->cfg_ptr->ext_zama16b) { memop |=3D MO_ATOM_WITHIN16; diff --git a/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc b/target/riscv= /tcg/insn_trans/trans_rvzawrs.c.inc index 0eef033838..1831bbcfc0 100644 --- a/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc +++ b/target/riscv/tcg/insn_trans/trans_rvzawrs.c.inc @@ -32,6 +32,9 @@ static bool trans_wrs_sto(DisasContext *ctx, arg_wrs_sto = *a) =20 /* Clear the load reservation (if any). */ tcg_gen_movi_tl(load_res, -1); +#ifdef CONFIG_USER_ONLY + tcg_gen_movi_tl(load_res_size, 0); +#endif =20 gen_update_pc(ctx, ctx->cur_insn_len); tcg_gen_exit_tb(NULL, 0); diff --git a/target/riscv/tcg/op_helper.c b/target/riscv/tcg/op_helper.c index 3e94005d2b..b67c7718db 100644 --- a/target/riscv/tcg/op_helper.c +++ b/target/riscv/tcg/op_helper.c @@ -19,6 +19,9 @@ */ =20 #include "qemu/osdep.h" +#ifdef CONFIG_USER_ONLY +#include "qemu/rcu.h" +#endif #include "cpu.h" #include "target/riscv/tcg/csr.h" #ifndef CONFIG_USER_ONLY @@ -298,6 +301,38 @@ void helper_sc_probe_write(CPURISCVState *env, target_= ulong addr, probe_write(env, addr, size, mmu_idx, ra); } =20 +#ifdef CONFIG_USER_ONLY + +void helper_riscv_invalidate_reservations(CPURISCVState *env, + target_ulong addr, + target_ulong size) +{ + CPUState *cpu; + + /* EXCP_ATOMIC keeps other guest harts out while this list is updated.= */ + WITH_RCU_READ_LOCK_GUARD() { + CPU_FOREACH(cpu) { + CPURISCVState *other_env =3D cpu_env(cpu); + target_ulong reservation =3D other_env->load_res; + target_ulong reservation_size =3D other_env->load_res_size; + bool overlap; + + if (other_env =3D=3D env || reservation =3D=3D (target_ulong)-= 1) { + continue; + } + overlap =3D reservation < addr + ? addr - reservation < reservation_size + : reservation - addr < size; + if (overlap) { + other_env->load_res =3D -1; + other_env->load_res_size =3D 0; + } + } + } +} + +#endif + #ifndef CONFIG_USER_ONLY =20 target_ulong helper_sret(CPURISCVState *env) diff --git a/target/riscv/tcg/translate.c b/target/riscv/tcg/translate.c index 9684dbe752..cce3b6dc72 100644 --- a/target/riscv/tcg/translate.c +++ b/target/riscv/tcg/translate.c @@ -42,6 +42,9 @@ static TCGv cpu_gpr[32], cpu_gprh[32], cpu_pc; static TCGv_i64 cpu_fpr[32]; /* assume F and D extensions */ static TCGv_i32 cpu_vl, cpu_vstart; static TCGv load_res; +#ifdef CONFIG_USER_ONLY +static TCGv load_res_size; +#endif static TCGv load_val; =20 /* @@ -1141,10 +1144,34 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg= _r2 *a, DisasExtend ext, return gen_unary(ctx, a, ext, f_tl); } =20 +#ifdef CONFIG_USER_ONLY +static bool gen_riscv_reservation_serialize(DisasContext *ctx) +{ + /* Keep the memory operation and reservation update in one guest step.= */ + if (tb_cflags(ctx->base.tb) & CF_PARALLEL) { + gen_helper_exit_atomic(tcg_env); + ctx->base.is_jmp =3D DISAS_NORETURN; + return false; + } + return true; +} + +static void gen_riscv_invalidate_reservations(TCGv addr, MemOp mop) +{ + gen_helper_riscv_invalidate_reservations(tcg_env, addr, + tcg_constant_tl(memop_size(mo= p))); +} +#endif + static bool gen_amo(DisasContext *ctx, arg_atomic *a, void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), MemOp mop) { +#ifdef CONFIG_USER_ONLY + if (!gen_riscv_reservation_serialize(ctx)) { + return false; + } +#endif TCGv dest =3D dest_gpr(ctx, a->rd); TCGv src1, src2 =3D get_gpr(ctx, a->rs2, EXT_NONE); MemOp size =3D mop & MO_SIZE; @@ -1159,6 +1186,9 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 =3D get_address(ctx, a->rs1, 0); func(dest, src1, src2, ctx->mem_idx, mop); +#ifdef CONFIG_USER_ONLY + gen_riscv_invalidate_reservations(src1, mop); +#endif =20 gen_set_gpr(ctx, a->rd, dest); return true; @@ -1482,6 +1512,10 @@ void riscv_translate_init(void) size_t pc_offset =3D offsetof(CPURISCVState, pc) + field_offset; size_t res_offset =3D offsetof(CPURISCVState, load_res) + field_off= set; size_t val_offset =3D offsetof(CPURISCVState, load_val) + field_off= set; +#ifdef CONFIG_USER_ONLY + size_t res_size_offset =3D offsetof(CPURISCVState, load_res_size) + + field_offset; +#endif =20 for (i =3D 1; i < 32; i++) { cpu_gpr[i] =3D tcg_global_mem_new(tcg_env, @@ -1501,5 +1535,9 @@ void riscv_translate_init(void) cpu_vl =3D tcg_global_mem_new_i32(tcg_env, vl_offset, "vl"); cpu_vstart =3D tcg_global_mem_new_i32(tcg_env, vstart_offset, "vstart"= ); load_res =3D tcg_global_mem_new(tcg_env, res_offset, "load_res"); +#ifdef CONFIG_USER_ONLY + load_res_size =3D tcg_global_mem_new(tcg_env, res_size_offset, + "load_res_size"); +#endif load_val =3D tcg_global_mem_new(tcg_env, val_offset, "load_val"); }