From c03d91b7c06cbf6cfe6d6dd64a97e40686814afc Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Mon, 15 Mar 2021 21:41:53 +0200 Subject: [PATCH] e2k: Fix read and write probe access. Signed-off-by: Denis Drakhnya --- target/e2k/helper.h | 6 ++--- target/e2k/helper_aau.c | 5 ++-- target/e2k/helper_sm.c | 33 +++++++++++++++++-------- target/e2k/translate.c | 53 ++++++++++++++++++++++++++++++++--------- 4 files changed, 71 insertions(+), 26 deletions(-) diff --git a/target/e2k/helper.h b/target/e2k/helper.h index eaeeff26b0..c0922e4b11 100644 --- a/target/e2k/helper.h +++ b/target/e2k/helper.h @@ -19,11 +19,11 @@ DEF_HELPER_1(signal_return, void, env) DEF_HELPER_4(setwd, void, env, int, int, int) -DEF_HELPER_FLAGS_2(probe_read_access, TCG_CALL_NO_RWG, int, env, tl) -DEF_HELPER_FLAGS_2(probe_write_access, TCG_CALL_NO_RWG, int, env, tl) +DEF_HELPER_FLAGS_4(probe_read_access, TCG_CALL_NO_RWG, int, env, tl, int, int) +DEF_HELPER_FLAGS_4(probe_write_access, TCG_CALL_NO_RWG, int, env, tl, int, int) DEF_HELPER_1(aau_load_program, void, env) -DEF_HELPER_4(mova_ptr, tl, env, int, int, int) +DEF_HELPER_6(mova_ptr, tl, env, int, int, int, int, int) DEF_HELPER_3(aau_am, void, env, int, int) DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int) DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int) diff --git a/target/e2k/helper_aau.c b/target/e2k/helper_aau.c index e3a3f653a3..962b6ec8d6 100644 --- a/target/e2k/helper_aau.c +++ b/target/e2k/helper_aau.c @@ -45,7 +45,8 @@ void HELPER(aau_load_program)(CPUE2KState *env) } } -target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind) +target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind, + int size, int mmu_idx) { E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr; E2KAauAreaState *as = &ps->area[area]; @@ -55,7 +56,7 @@ target_ulong HELPER(mova_ptr)(CPUE2KState *env, int chan, int area, int ind) target_ulong page = ptr & ~(TARGET_PAGE_SIZE - 1); if (as->last_page == 0 || page != as->last_page) { - if (!helper_probe_read_access(env, page)) { + if (!helper_probe_read_access(env, ptr, size, mmu_idx)) { return 0; } as->last_page = page; diff --git a/target/e2k/helper_sm.c b/target/e2k/helper_sm.c index 6d02cdc8b6..66b9619fc4 100644 --- a/target/e2k/helper_sm.c +++ b/target/e2k/helper_sm.c @@ -5,22 +5,35 @@ #include "qemu/host-utils.h" #include "exec/helper-proto.h" -int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr) +static int e2k_probe_access(CPUE2KState *env, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx) { + target_ulong addr_end = addr + size; int flags; void *ignore; - flags = probe_access_flags(env, addr, MMU_DATA_LOAD, 0, true, &ignore, 0); + flags = probe_access_flags(env, addr, access_type, mmu_idx, + true, &ignore, 0); - return (flags & TLB_INVALID_MASK) == 0; + if (flags & TLB_INVALID_MASK) { + return 0; + } else if ((addr & ~TARGET_PAGE_MASK) != (addr_end & ~TARGET_PAGE_MASK)) { + flags = probe_access_flags(env, addr_end, access_type, mmu_idx, + true, &ignore, 0); + return !(flags & TLB_INVALID_MASK); + } + + return 1; } -int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr) +int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr, + int size, int mmu_idx) { - int flags; - void *ignore; - - flags = probe_access_flags(env, addr, MMU_DATA_STORE, 0, true, &ignore, 0); - - return (flags & TLB_INVALID_MASK) == 0; + return e2k_probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx); +} + +int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr, + int size, int mmu_idx) +{ + return e2k_probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx); } diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 151d6371f9..1a6c453860 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -3672,6 +3672,30 @@ static MemOp scan_st_mas(Instr *instr, MemOp memop, bool *skip, bool *check) return memop; } +static void gen_probe_read_access(TCGv_i32 ret, TCGv addr, int size, + int mmu_idx) +{ + TCGv_i32 t0 = tcg_const_i32(size); + TCGv_i32 t1 = tcg_const_i32(mmu_idx); + + gen_helper_probe_read_access(ret, cpu_env, addr, t0, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + +static void gen_probe_write_access(TCGv_i32 ret, TCGv addr, int size, + int mmu_idx) +{ + TCGv_i32 t0 = tcg_const_i32(size); + TCGv_i32 t1 = tcg_const_i32(mmu_idx); + + gen_helper_probe_write_access(ret, cpu_env, addr, t0, t1); + + tcg_temp_free_i32(t1); + tcg_temp_free_i32(t0); +} + static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr, MemOp memop, bool skip, bool save) { @@ -3682,7 +3706,7 @@ static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr, TCGLabel *l1 = gen_new_label(); TCGv_i32 t0 = tcg_temp_new_i32(); - gen_helper_probe_read_access(t0, cpu_env, addr); + gen_probe_read_access(t0, addr, memop_size(memop), instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1); /* address is not available */ @@ -3742,7 +3766,7 @@ static void gen_ld_raw_i128(Instr *instr, TCGv_i32 tag, TCGv addr, TCGLabel *l1 = gen_new_label(); TCGv_i32 t3 = tcg_temp_new_i32(); - gen_helper_probe_read_access(t3, cpu_env, addr); + gen_probe_read_access(t3, addr, 16, instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_NE, t3, 0, l1); /* address is not available */ @@ -3851,7 +3875,8 @@ static void gen_atomic_cmpxchg_i32(Instr *instr, TCGv_i32 value, TCGv addr, if (instr->sm) { \ TCGv_i32 t0 = tcg_temp_new_i32(); \ \ - gen_helper_probe_write_access(t0, cpu_env, addr); \ + gen_probe_write_access(t0, addr, memop_size(memop), \ + instr->ctx->mmuidx); \ tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); \ \ tcg_temp_free_i32(t0); \ @@ -3904,7 +3929,7 @@ static void gen_st_raw_i128(Instr *instr, TCGv addr, if (instr->sm) { TCGv_i32 t0 = tcg_temp_new_i32(); - gen_helper_probe_write_access(t0, cpu_env, addr); + gen_probe_write_access(t0, addr, 16, instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); tcg_temp_free_i32(t0); @@ -3985,7 +4010,7 @@ static void gen_stm_raw_i128(Instr *instr, TCGv addr, if (instr->sm) { TCGv_i32 t0 = tcg_temp_new_i32(); - gen_helper_probe_write_access(t0, cpu_env, addr); + gen_probe_write_access(t0, addr, 16, instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); tcg_temp_free_i32(t0); @@ -4349,7 +4374,7 @@ static void gen_staaqp(Instr *instr) if (instr->sm) { TCGv_i32 t1 = tcg_temp_new_i32(); - gen_helper_probe_write_access(t1, cpu_env, t0); + gen_probe_write_access(t1, t0, 16, instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0); tcg_temp_free_i32(t1); } @@ -4403,7 +4428,7 @@ static void gen_staa_i64(Instr *instr) if (instr->sm) { TCGv_i32 t1 = tcg_temp_new_i32(); - gen_helper_probe_write_access(t1, cpu_env, t0); + gen_probe_write_access(t1, t0, memop_size(memop), instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0); tcg_temp_free_i32(t1); } @@ -4457,7 +4482,7 @@ static void gen_staa_i32(Instr *instr, MemOp memop) if (instr->sm) { TCGv_i32 t1 = tcg_temp_new_i32(); - gen_helper_probe_write_access(t1, cpu_env, t0); + gen_probe_write_access(t1, t0, memop_size(memop), instr->ctx->mmuidx); tcg_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0); tcg_temp_free_i32(t1); } @@ -6784,12 +6809,17 @@ static void gen_checked_ld_qp(DisasContext *ctx, Mova *instr, TCGv addr) tagged_free_ptr(r); } -static inline void gen_mova_ptr(TCGv ret, Mova *instr) +static void gen_mova_ptr(TCGv ret, Mova *instr, int size, int mmu_idx) { TCGv_i32 t0 = tcg_const_i32(instr->chan); TCGv_i32 t1 = tcg_const_i32(instr->area); TCGv_i32 t2 = tcg_const_i32(instr->ind); - gen_helper_mova_ptr(ret, cpu_env, t0, t1, t2); + TCGv_i32 t3 = tcg_const_i32(size); + TCGv_i32 t4 = tcg_const_i32(mmu_idx); + + gen_helper_mova_ptr(ret, cpu_env, t0, t1, t2, t3, t4); + tcg_temp_free_i32(t4); + tcg_temp_free_i32(t3); tcg_temp_free_i32(t2); tcg_temp_free_i32(t1); tcg_temp_free_i32(t0); @@ -6803,19 +6833,20 @@ static void gen_mova(DisasContext *ctx, Mova *instr) ctx->aau_am[instr->chan] = instr->am ? instr->area : -1; // TODO: check ind has proper alignment // TODO: check ind is less than mrng - gen_mova_ptr(t0, instr); switch(instr->opc) { case 1: /* movab */ case 2: /* movah */ case 3: /* movaw */ case 4: /* movad */ + gen_mova_ptr(t0, instr, 1 << (instr->opc - 1), ctx->mmuidx); gen_checked_ld(ctx, instr, t0); break; case 5: /* movaq */ e2k_todo_illop(ctx, "movaq"); break; case 7: /* movaqp */ + gen_mova_ptr(t0, instr, 16, ctx->mmuidx); gen_checked_ld_qp(ctx, instr, t0); break; default: