From: Alistair Francis <[email protected]> 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: [email protected] 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 <[email protected]> Reviewed-by: Daniel Henrique Barboza <[email protected]> Reviewed-by: Chao Liu <[email protected]> Message-ID: <[email protected]> Signed-off-by: Alistair Francis <[email protected]> (cherry picked from commit d107b748072cea3f86089a4a7b2e83f1a62745f2) Signed-off-by: Michael Tokarev <[email protected]> diff --git a/target/riscv/helper.h b/target/riscv/helper.h index ddb07ca3d1..68e76a3c28 100644 --- a/target/riscv/helper.h +++ b/target/riscv/helper.h @@ -1289,3 +1289,6 @@ DEF_HELPER_4(vsm4r_vs, void, ptr, ptr, env, i32) #ifndef CONFIG_USER_ONLY DEF_HELPER_1(ssamoswap_disabled, void, env) #endif + +/* Zalrsc SC write probe */ +DEF_HELPER_FLAGS_3(sc_probe_write, TCG_CALL_NO_WG, void, env, tl, tl) diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 9cf3ae8019..a1b45cbd2c 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -84,6 +84,12 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) */ TCGBar bar_strl = (ctx->ztso || a->rl) ? TCG_BAR_STRL : 0; tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + bar_strl); + /* + * "For the purposes of memory protection, a failed SC.W may be treated + * like a store." so let's check the write access permissions + */ + gen_helper_sc_probe_write(tcg_env, src1, + tcg_constant_tl(memop_size(mop))); gen_set_gpr(ctx, a->rd, tcg_constant_tl(1)); gen_set_label(l2); diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index c34d8a4a9c..0cdbb0138c 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -265,6 +265,20 @@ void helper_cbo_inval(CPURISCVState *env, target_ulong address) /* We don't emulate the cache-hierarchy, so we're done. */ } +void helper_sc_probe_write(CPURISCVState *env, target_ulong addr, + target_ulong size) +{ + uintptr_t ra = GETPC(); + int mmu_idx = riscv_env_mmu_index(env, false); + + if (addr & (size - 1)) { + env->badaddr = addr; + riscv_raise_exception(env, RISCV_EXCP_STORE_AMO_ADDR_MIS, ra); + } + + probe_write(env, addr, size, mmu_idx, ra); +} + #ifndef CONFIG_USER_ONLY target_ulong helper_sret(CPURISCVState *env) -- 2.47.3
