As a matter of course, we need to access user space in kernel code, so we need to correct load/store decoders to indicate correct memory region.
Signed-off-by: Guan Xuetao <g...@mprc.pku.edu.cn> --- target-unicore32/translate.c | 36 ++++++++++++++++++++++++++---------- 1 files changed, 26 insertions(+), 10 deletions(-) diff --git a/target-unicore32/translate.c b/target-unicore32/translate.c index fd51a61..43317a6 100644 --- a/target-unicore32/translate.c +++ b/target-unicore32/translate.c @@ -33,9 +33,16 @@ typedef struct DisasContext { int condlabel; struct TranslationBlock *tb; int singlestep_enabled; +#ifndef CONFIG_USER_ONLY + int user; +#endif } DisasContext; -#define IS_USER(s) 1 +#ifndef CONFIG_USER_ONLY +#define IS_USER(s) (s->user) +#else +#define IS_USER(s) 1 +#endif /* These instructions trap after executing, so defer them until after the conditional executions state has been updated. */ @@ -1551,12 +1558,12 @@ static void do_misc(CPUUniCore32State *env, DisasContext *s, uint32_t insn) /* load/store I_offset and R_offset */ static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn) { - unsigned int i; + unsigned int mmuindex; TCGv tmp; TCGv tmp2; tmp2 = load_reg(s, UCOP_REG_N); - i = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); + mmuindex = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); /* immediate */ if (UCOP_SET_P) { @@ -1566,17 +1573,17 @@ static void do_ldst_ir(CPUUniCore32State *env, DisasContext *s, uint32_t insn) if (UCOP_SET_L) { /* load */ if (UCOP_SET_B) { - tmp = gen_ld8u(tmp2, i); + tmp = gen_ld8u(tmp2, mmuindex); } else { - tmp = gen_ld32(tmp2, i); + tmp = gen_ld32(tmp2, mmuindex); } } else { /* store */ tmp = load_reg(s, UCOP_REG_D); if (UCOP_SET_B) { - gen_st8(tmp, tmp2, i); + gen_st8(tmp, tmp2, mmuindex); } else { - gen_st32(tmp, tmp2, i); + gen_st32(tmp, tmp2, mmuindex); } } if (!UCOP_SET_P) { @@ -1679,7 +1686,7 @@ static void do_ldst_hwsb(CPUUniCore32State *env, DisasContext *s, uint32_t insn) /* load/store multiple words */ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) { - unsigned int val, i; + unsigned int val, i, mmuindex; int j, n, reg, user, loaded_base; TCGv tmp; TCGv tmp2; @@ -1700,6 +1707,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) } } + mmuindex = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); addr = load_reg(s, UCOP_REG_N); /* compute total size */ @@ -1744,7 +1752,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) } if (UCOP_SET(i)) { if (UCOP_SET_L) { /* load */ - tmp = gen_ld32(addr, IS_USER(s)); + tmp = gen_ld32(addr, mmuindex); if (reg == 31) { gen_bx(s, tmp); } else if (user) { @@ -1772,7 +1780,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) } else { tmp = load_reg(s, reg); } - gen_st32(tmp, addr, IS_USER(s)); + gen_st32(tmp, addr, mmuindex); } j++; /* no need to add after the last transfer */ @@ -1961,6 +1969,14 @@ static inline void gen_intermediate_code_internal(CPUUniCore32State *env, max_insns = CF_COUNT_MASK; } +#ifndef CONFIG_USER_ONLY + if ((env->uncached_asr & ASR_M) == ASR_MODE_USER) { + dc->user = 1; + } else { + dc->user = 0; + } +#endif + gen_icount_start(); do { if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) { -- 1.7.0.4