Have callers set MO_ALIGN in the MemOp bits. Perform the access first, filling the TLB in the process. If the tlb cannot be filled, access is not permitted, and an exception is raised. Thus remove the now unnecessary do_raise_exception() call.
Since the TLB is filled, use probe_access() to get CP0_LLAddr. Move env->CP0_LLAddr and env->lladdr assignments so we don't update them when an alignment fault occurs. Since we have a handy MemOpIdx, replace the legacy cpu_ld*_mmuidx_ra() calls by cpu_ld*_mmu() equivalent. Suggested-by: Richard Henderson <[email protected]> Signed-off-by: Philippe Mathieu-Daudé <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-Id: <[email protected]> --- target/mips/tcg/ldst_helper.c | 26 +++++++++++++++----------- target/mips/tcg/translate.c | 2 +- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/target/mips/tcg/ldst_helper.c b/target/mips/tcg/ldst_helper.c index b36b12d87d6..1b25466b496 100644 --- a/target/mips/tcg/ldst_helper.c +++ b/target/mips/tcg/ldst_helper.c @@ -28,23 +28,27 @@ #include "internal.h" #ifndef CONFIG_USER_ONLY +#include "accel/tcg/probe.h" +#include "exec/tlb-flags.h" #define HELPER_LD_ATOMIC(name, insn, almask, do_cast) \ target_ulong helper_##name(CPUMIPSState *env, target_ulong arg, \ uint32_t memop_idx) \ { \ - MemOpIdx oi = memop_idx; \ - unsigned mem_idx = get_mmuidx(oi); \ - if (arg & almask) { \ - if (!(env->hflags & MIPS_HFLAG_DM)) { \ - env->CP0_BadVAddr = arg; \ - } \ - do_raise_exception(env, EXCP_AdEL, GETPC()); \ - } \ - env->CP0_LLAddr = cpu_mips_translate_address(env, arg, MMU_DATA_LOAD, \ - GETPC()); \ + MemOpIdx oi = memop_idx; \ + unsigned mem_idx = get_mmuidx(oi); \ + unsigned size = memop_size(get_memop(oi)); \ + uintptr_t ra = GETPC(); \ + CPUTLBEntryFull *full; \ + void *host_unused; \ + int flags; \ + \ + env->llval = do_cast cpu_##insn##_mmu(env, arg, oi, ra); \ + flags = probe_access_full(env, arg, size, MMU_DATA_LOAD, mem_idx, \ + true, &host_unused, &full, ra); \ + assert(!(flags & TLB_INVALID_MASK)); \ + env->CP0_LLAddr = full->phys_addr; \ env->lladdr = arg; \ - env->llval = do_cast cpu_##insn##_mmuidx_ra(env, arg, mem_idx, GETPC()); \ return env->llval; \ } HELPER_LD_ATOMIC(ll, ldl, 0x3, (target_long)(int32_t)) diff --git a/target/mips/tcg/translate.c b/target/mips/tcg/translate.c index ee6199875cf..fff6390f5d4 100644 --- a/target/mips/tcg/translate.c +++ b/target/mips/tcg/translate.c @@ -1936,7 +1936,7 @@ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx_ignored, \ static inline void op_ld_##insn(TCGv ret, TCGv arg1, int mem_idx, \ DisasContext *ctx) \ { \ - MemOpIdx oi = make_memop_idx(memop, mem_idx); \ + MemOpIdx oi = make_memop_idx(memop | MO_ALIGN, mem_idx); \ gen_helper_##insn(ret, tcg_env, arg1, tcg_constant_i32(oi)); \ } #endif -- 2.53.0
