e2k: Fix read and write probe access.

Signed-off-by: Denis Drakhnya <numas13@gmail.com>
This commit is contained in:
Denis Drakhnia 2021-03-15 21:41:53 +02:00 committed by Denis Drakhnia
parent 6cbcdc4d5c
commit c03d91b7c0
4 changed files with 71 additions and 26 deletions

View File

@ -19,11 +19,11 @@ DEF_HELPER_1(signal_return, void, env)
DEF_HELPER_4(setwd, void, env, int, int, int) 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_4(probe_read_access, TCG_CALL_NO_RWG, int, env, tl, int, int)
DEF_HELPER_FLAGS_2(probe_write_access, TCG_CALL_NO_RWG, int, env, tl) 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_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_3(aau_am, void, env, int, int)
DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int) DEF_HELPER_4(dam_lock_addr, void, env, i64, int, int)
DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int) DEF_HELPER_4(dam_unlock_addr, int, env, i64, int, int)

View File

@ -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; E2KAauPrefState *ps = chan < 2 ? &env->aau.pl : &env->aau.pr;
E2KAauAreaState *as = &ps->area[area]; 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); target_ulong page = ptr & ~(TARGET_PAGE_SIZE - 1);
if (as->last_page == 0 || page != as->last_page) { 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; return 0;
} }
as->last_page = page; as->last_page = page;

View File

@ -5,22 +5,35 @@
#include "qemu/host-utils.h" #include "qemu/host-utils.h"
#include "exec/helper-proto.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; int flags;
void *ignore; 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);
} }
int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr) return 1;
}
int HELPER(probe_read_access)(CPUE2KState *env, target_ulong addr,
int size, int mmu_idx)
{ {
int flags; return e2k_probe_access(env, addr, size, MMU_DATA_LOAD, mmu_idx);
void *ignore; }
flags = probe_access_flags(env, addr, MMU_DATA_STORE, 0, true, &ignore, 0); int HELPER(probe_write_access)(CPUE2KState *env, target_ulong addr,
int size, int mmu_idx)
return (flags & TLB_INVALID_MASK) == 0; {
return e2k_probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx);
} }

View File

@ -3672,6 +3672,30 @@ static MemOp scan_st_mas(Instr *instr, MemOp memop, bool *skip, bool *check)
return memop; 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, static void gen_ld_raw_i64(Instr *instr, TCGv_i32 tag, TCGv addr,
MemOp memop, bool skip, bool save) 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(); TCGLabel *l1 = gen_new_label();
TCGv_i32 t0 = tcg_temp_new_i32(); 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); tcg_gen_brcondi_i32(TCG_COND_NE, t0, 0, l1);
/* address is not available */ /* 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(); TCGLabel *l1 = gen_new_label();
TCGv_i32 t3 = tcg_temp_new_i32(); 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); tcg_gen_brcondi_i32(TCG_COND_NE, t3, 0, l1);
/* address is not available */ /* address is not available */
@ -3851,7 +3875,8 @@ static void gen_atomic_cmpxchg_i32(Instr *instr, TCGv_i32 value, TCGv addr,
if (instr->sm) { \ if (instr->sm) { \
TCGv_i32 t0 = tcg_temp_new_i32(); \ 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_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0); \
\ \
tcg_temp_free_i32(t0); \ tcg_temp_free_i32(t0); \
@ -3904,7 +3929,7 @@ static void gen_st_raw_i128(Instr *instr, TCGv addr,
if (instr->sm) { if (instr->sm) {
TCGv_i32 t0 = tcg_temp_new_i32(); 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_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
@ -3985,7 +4010,7 @@ static void gen_stm_raw_i128(Instr *instr, TCGv addr,
if (instr->sm) { if (instr->sm) {
TCGv_i32 t0 = tcg_temp_new_i32(); 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_gen_brcondi_i32(TCG_COND_EQ, t0, 0, l0);
tcg_temp_free_i32(t0); tcg_temp_free_i32(t0);
@ -4349,7 +4374,7 @@ static void gen_staaqp(Instr *instr)
if (instr->sm) { if (instr->sm) {
TCGv_i32 t1 = tcg_temp_new_i32(); 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_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
} }
@ -4403,7 +4428,7 @@ static void gen_staa_i64(Instr *instr)
if (instr->sm) { if (instr->sm) {
TCGv_i32 t1 = tcg_temp_new_i32(); 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_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
} }
@ -4457,7 +4482,7 @@ static void gen_staa_i32(Instr *instr, MemOp memop)
if (instr->sm) { if (instr->sm) {
TCGv_i32 t1 = tcg_temp_new_i32(); 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_gen_brcondi_i32(TCG_COND_EQ, t1, 0, l0);
tcg_temp_free_i32(t1); 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); 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 t0 = tcg_const_i32(instr->chan);
TCGv_i32 t1 = tcg_const_i32(instr->area); TCGv_i32 t1 = tcg_const_i32(instr->area);
TCGv_i32 t2 = tcg_const_i32(instr->ind); 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(t2);
tcg_temp_free_i32(t1); tcg_temp_free_i32(t1);
tcg_temp_free_i32(t0); 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; ctx->aau_am[instr->chan] = instr->am ? instr->area : -1;
// TODO: check ind has proper alignment // TODO: check ind has proper alignment
// TODO: check ind is less than mrng // TODO: check ind is less than mrng
gen_mova_ptr(t0, instr);
switch(instr->opc) { switch(instr->opc) {
case 1: /* movab */ case 1: /* movab */
case 2: /* movah */ case 2: /* movah */
case 3: /* movaw */ case 3: /* movaw */
case 4: /* movad */ case 4: /* movad */
gen_mova_ptr(t0, instr, 1 << (instr->opc - 1), ctx->mmuidx);
gen_checked_ld(ctx, instr, t0); gen_checked_ld(ctx, instr, t0);
break; break;
case 5: /* movaq */ case 5: /* movaq */
e2k_todo_illop(ctx, "movaq"); e2k_todo_illop(ctx, "movaq");
break; break;
case 7: /* movaqp */ case 7: /* movaqp */
gen_mova_ptr(t0, instr, 16, ctx->mmuidx);
gen_checked_ld_qp(ctx, instr, t0); gen_checked_ld_qp(ctx, instr, t0);
break; break;
default: default: