diff options
author | Guan Xuetao <gxt@mprc.pku.edu.cn> | 2012-08-10 14:42:26 +0800 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2012-08-11 09:36:58 +0000 |
commit | ef03168a8536f4427ab24a1fc43638dfbecc1bf8 (patch) | |
tree | ca3a8a5fc24f01409a927e89c62221f578f4d1f6 | |
parent | f3ccc32369532e8a069ea5b7ee201b75e668deab (diff) | |
download | qemu-ef03168a8536f4427ab24a1fc43638dfbecc1bf8.zip qemu-ef03168a8536f4427ab24a1fc43638dfbecc1bf8.tar.gz qemu-ef03168a8536f4427ab24a1fc43638dfbecc1bf8.tar.bz2 |
unicore32-softmmu: Make sure that kernel can access user space
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 <gxt@mprc.pku.edu.cn>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
-rw-r--r-- | 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 e37d5be..5ee3a59 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. */ @@ -1554,12 +1561,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 mmu_idx; TCGv tmp; TCGv tmp2; tmp2 = load_reg(s, UCOP_REG_N); - i = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); + mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); /* immediate */ if (UCOP_SET_P) { @@ -1569,17 +1576,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, mmu_idx); } else { - tmp = gen_ld32(tmp2, i); + tmp = gen_ld32(tmp2, mmu_idx); } } else { /* store */ tmp = load_reg(s, UCOP_REG_D); if (UCOP_SET_B) { - gen_st8(tmp, tmp2, i); + gen_st8(tmp, tmp2, mmu_idx); } else { - gen_st32(tmp, tmp2, i); + gen_st32(tmp, tmp2, mmu_idx); } } if (!UCOP_SET_P) { @@ -1682,7 +1689,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, mmu_idx; int j, n, reg, user, loaded_base; TCGv tmp; TCGv tmp2; @@ -1703,6 +1710,7 @@ static void do_ldst_m(CPUUniCore32State *env, DisasContext *s, uint32_t insn) } } + mmu_idx = (IS_USER(s) || (!UCOP_SET_P && UCOP_SET_W)); addr = load_reg(s, UCOP_REG_N); /* compute total size */ @@ -1747,7 +1755,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, mmu_idx); if (reg == 31) { gen_bx(s, tmp); } else if (user) { @@ -1775,7 +1783,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, mmu_idx); } j++; /* no need to add after the last transfer */ @@ -1964,6 +1972,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))) { |