Skip to content

Commit

Permalink
target-arm: Use correct mmu_idx for unprivileged loads and stores
Browse files Browse the repository at this point in the history
The MMU index to use for unprivileged loads and stores is more
complicated than we currently implement:
 * for A64, it should be "if at EL1, access as if EL0; otherwise
   access at current EL"
 * for A32/T32, it should be "if EL2, UNPREDICTABLE; otherwise
   access as if at EL0".

In both cases, if we want to make the access for Secure EL0
this is not the same mmu_idx as for Non-Secure EL0.

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Greg Bellows <greg.bellows@linaro.org>
  • Loading branch information
pm215 committed Feb 5, 2015
1 parent c1e3781 commit 579d21c
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 3 deletions.
19 changes: 18 additions & 1 deletion target-arm/translate-a64.c
Expand Up @@ -123,6 +123,23 @@ void a64_translate_init(void)
#endif
}

static inline ARMMMUIdx get_a64_user_mem_index(DisasContext *s)
{
/* Return the mmu_idx to use for A64 "unprivileged load/store" insns:
* if EL1, access as if EL0; otherwise access at current EL
*/
switch (s->mmu_idx) {
case ARMMMUIdx_S12NSE1:
return ARMMMUIdx_S12NSE0;
case ARMMMUIdx_S1SE1:
return ARMMMUIdx_S1SE0;
case ARMMMUIdx_S2NS:
g_assert_not_reached();
default:
return s->mmu_idx;
}
}

void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
fprintf_function cpu_fprintf, int flags)
{
Expand Down Expand Up @@ -2107,7 +2124,7 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
}
} else {
TCGv_i64 tcg_rt = cpu_reg(s, rt);
int memidx = is_unpriv ? MMU_USER_IDX : get_mem_index(s);
int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);

if (is_store) {
do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx);
Expand Down
26 changes: 24 additions & 2 deletions target-arm/translate.c
Expand Up @@ -113,6 +113,28 @@ void arm_translate_init(void)
a64_translate_init();
}

static inline ARMMMUIdx get_a32_user_mem_index(DisasContext *s)
{
/* Return the mmu_idx to use for A32/T32 "unprivileged load/store"
* insns:
* if PL2, UNPREDICTABLE (we choose to implement as if PL0)
* otherwise, access as if at PL0.
*/
switch (s->mmu_idx) {
case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_S12NSE0:
case ARMMMUIdx_S12NSE1:
return ARMMMUIdx_S12NSE0;
case ARMMMUIdx_S1E3:
case ARMMMUIdx_S1SE0:
case ARMMMUIdx_S1SE1:
return ARMMMUIdx_S1SE0;
case ARMMMUIdx_S2NS:
default:
g_assert_not_reached();
}
}

static inline TCGv_i32 load_cpu_offset(int offset)
{
TCGv_i32 tmp = tcg_temp_new_i32();
Expand Down Expand Up @@ -8797,7 +8819,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
tmp2 = load_reg(s, rn);
if ((insn & 0x01200000) == 0x00200000) {
/* ldrt/strt */
i = MMU_USER_IDX;
i = get_a32_user_mem_index(s);
} else {
i = get_mem_index(s);
}
Expand Down Expand Up @@ -10177,7 +10199,7 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
break;
case 0xe: /* User privilege. */
tcg_gen_addi_i32(addr, addr, imm);
memidx = MMU_USER_IDX;
memidx = get_a32_user_mem_index(s);
break;
case 0x9: /* Post-decrement. */
imm = -imm;
Expand Down

0 comments on commit 579d21c

Please sign in to comment.