summaryrefslogtreecommitdiffstats
path: root/target/riscv/insn_trans/trans_rva.inc.c
diff options
context:
space:
mode:
authorJoel Sing2019-06-24 20:08:38 +0200
committerPalmer Dabbelt2019-06-26 07:37:04 +0200
commitc13b169f1a3dd158d6c75727cdc388f95988db39 (patch)
treed23c2fd911b809c36128fa626e36076a31253826 /target/riscv/insn_trans/trans_rva.inc.c
parentRISC-V: Add support for the Zicsr extension (diff)
downloadqemu-c13b169f1a3dd158d6c75727cdc388f95988db39.tar.gz
qemu-c13b169f1a3dd158d6c75727cdc388f95988db39.tar.xz
qemu-c13b169f1a3dd158d6c75727cdc388f95988db39.zip
RISC-V: Clear load reservations on context switch and SC
This prevents a load reservation from being placed in one context/process, then being used in another, resulting in an SC succeeding incorrectly and breaking atomics. Signed-off-by: Joel Sing <joel@sing.id.au> Reviewed-by: Palmer Dabbelt <palmer@sifive.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Palmer Dabbelt <palmer@sifive.com>
Diffstat (limited to 'target/riscv/insn_trans/trans_rva.inc.c')
-rw-r--r--target/riscv/insn_trans/trans_rva.inc.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/target/riscv/insn_trans/trans_rva.inc.c b/target/riscv/insn_trans/trans_rva.inc.c
index f6dbbc065e..fadd88849e 100644
--- a/target/riscv/insn_trans/trans_rva.inc.c
+++ b/target/riscv/insn_trans/trans_rva.inc.c
@@ -61,7 +61,7 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, TCGMemOp mop)
gen_set_label(l1);
/*
- * Address comparion failure. However, we still need to
+ * Address comparison failure. However, we still need to
* provide the memory barrier implied by AQ/RL.
*/
tcg_gen_mb(TCG_MO_ALL + a->aq * TCG_BAR_LDAQ + a->rl * TCG_BAR_STRL);
@@ -69,6 +69,12 @@ static inline bool gen_sc(DisasContext *ctx, arg_atomic *a, TCGMemOp mop)
gen_set_gpr(a->rd, dat);
gen_set_label(l2);
+ /*
+ * Clear the load reservation, since an SC must fail if there is
+ * an SC to any address, in between an LR and SC pair.
+ */
+ tcg_gen_movi_tl(load_res, -1);
+
tcg_temp_free(dat);
tcg_temp_free(src1);
tcg_temp_free(src2);