@samitouri / QOSamiQemu / commits / d107b74807

target/riscv: Generate access fault if sc comparison fails

The RISC-V spec states: "For the purposes of memory protection, a failed SC.W may be treated like a store." So if the comparison in sc.w fails we should still check for alignment and do a probe access to check permissions. Cc: qemu-stable@nongnu.org Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3323 Resolves: https://gitlab.com/qemu-project/qemu/-/work_items/3136 Signed-off-by: Alistair Francis <alistair.francis@wdc.com> Reviewed-by: Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com> Reviewed-by: Chao Liu <chao.liu.zevorn@gmail.com> Message-ID: <20260415233740.3027321-2-alistair.francis@wdc.com> Signed-off-by: Alistair Francis <alistair.francis@wdc.com>

Alistair Francis committed Apr 16, 2026 at 09:37 UTC d107b748072cea3f86089a4a7b2e83f1a62745f2
3 files changed +23
target/riscv/helper.h
+3
@@ -1351,3 +1351,6 @@ DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32)
1351 #ifndef CONFIG_USER_ONLY
1352 DEF_HELPER_1(ssamoswap_disabled, void, env)
1353 #endif
1354 +
1355 +/* Zalrsc SC write probe */
1356 +DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl)
target/riscv/insn_trans/trans_rva.c.inc
+6
@@ -90,6 +90,12 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop)
90 */
91 TCGBar bar_strl = (ctx->ztso || a->rl) ? TCG_BAR_STRL : 0;
92 tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + bar_strl);
93 + /*
94 + * "For the purposes of memory protection, a failed SC.W may be treated
95 + * like a store." so let's check the write access permissions
96 + */
97 + gen_helper_sc_probe_write(tcg_env, src1,
98 + tcg_constant_tl(memop_size(mop)));
99 gen_set_gpr(ctx, a->rd, tcg_constant_tl(1));
100
101 gen_set_label(l2);
target/riscv/op_helper.c
+14
@@ -267,6 +267,20 @@ void helper_cbo_inval(CPURISCVState *env, target_ulong address)
267 /* We don't emulate the cache-hierarchy, so we're done. */
268 }
269
270 +void helper_sc_probe_write(CPURISCVState *env, target_ulong addr,
271 + target_ulong size)
272 +{
273 + uintptr_t ra = GETPC();
274 + int mmu_idx = riscv_env_mmu_index(env, false);
275 +
276 + if (addr & (size - 1)) {
277 + env->badaddr = addr;
278 + riscv_raise_exception(env, RISCV_EXCP_STORE_AMO_ADDR_MIS, ra);
279 + }
280 +
281 + probe_write(env, addr, size, mmu_idx, ra);
282 +}
283 +
284 #ifndef CONFIG_USER_ONLY
285
286 target_ulong helper_sret(CPURISCVState *env)