Unverified Commit c13b169f authored by Joel Sing's avatar Joel Sing Committed by Palmer Dabbelt
Browse files

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: default avatarJoel Sing <joel@sing.id.au>
Reviewed-by: default avatarPalmer Dabbelt <palmer@sifive.com>
Reviewed-by: default avatarRichard Henderson <richard.henderson@linaro.org>
Signed-off-by: default avatarPalmer Dabbelt <palmer@sifive.com>
parent 591bddea
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -297,6 +297,7 @@ static void riscv_cpu_reset(CPUState *cs)
    env->pc = env->resetvec;
#endif
    cs->exception_index = EXCP_NONE;
    env->load_res = -1;
    set_default_nan_mode(1, &env->fp_status);
}

+10 −0
Original line number Diff line number Diff line
@@ -132,6 +132,16 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
    }
    /* tlb_flush is unnecessary as mode is contained in mmu_idx */
    env->priv = newpriv;

    /*
     * Clear the load reservation - otherwise a reservation placed in one
     * context/process can be used by another, resulting in an SC succeeding
     * incorrectly. Version 2.2 of the ISA specification explicitly requires
     * this behaviour, while later revisions say that the kernel "should" use
     * an SC instruction to force the yielding of a load reservation on a
     * preemptive context switch. As a result, do both.
     */
    env->load_res = -1;
}

/* get_physical_address - get the physical address for this virtual address
+7 −1
Original line number Diff line number Diff line
@@ -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);