Separate the access_type from the protection check.
Save the trouble of modifying all helper functions
by passing the new data in the control structure.
Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 9652f40ff8..d37c0ce0f1 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -64,6 +64,12 @@ typedef struct S1Translate {
* Stage 2 is indicated by in_mmu_idx set to ARMMMUIdx_Stage2{,_S}.
*/
bool in_s1_is_el0;
+ /*
+ * The set of PAGE_* bits to be use in the permission check.
+ * This is normally directly related to the access_type, but
+ * may be suppressed for debug or AT insns.
+ */
+ uint8_t in_prot_check;
bool out_rw;
bool out_be;
ARMSecuritySpace out_space;
@@ -581,6 +587,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
.in_space = s2_space,
.in_debug = true,
+ .in_prot_check = PAGE_READ,
};
GetPhysAddrResult s2 = { };
@@ -1089,7 +1096,7 @@ static bool get_phys_addr_v5(CPUARMState *env, S1Translate *ptw,
}
result->f.prot = ap_to_rw_prot(env, ptw->in_mmu_idx, ap, domain_prot);
result->f.prot |= result->f.prot ? PAGE_EXEC : 0;
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
@@ -1243,7 +1250,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
result->f.prot = get_S1prot(env, mmu_idx, false, user_rw, prot_rw,
xn, pxn, result->f.attrs.space, out_space);
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
@@ -2123,7 +2130,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
result->f.tlb_fill_flags = 0;
}
- if (!(result->f.prot & (1 << access_type))) {
+ if (ptw->in_prot_check & ~result->f.prot) {
fi->type = ARMFault_Permission;
goto do_fault;
}
@@ -2537,7 +2544,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env,
fi->type = ARMFault_Permission;
fi->level = 1;
- return !(result->f.prot & (1 << access_type));
+ return (ptw->in_prot_check & ~result->f.prot) != 0;
}
static uint32_t *regime_rbar(CPUARMState *env, ARMMMUIdx mmu_idx,
@@ -2953,7 +2960,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env,
}
}
- ret = pmsav8_mpu_lookup(env, address, access_type, 1 << access_type,
+ ret = pmsav8_mpu_lookup(env, address, access_type, ptw->in_prot_check,
mmu_idx, secure, result, fi, NULL);
if (sattrs.subpage) {
result->f.lg_page_size = 0;
@@ -3625,6 +3632,7 @@ bool get_phys_addr(CPUARMState *env, vaddr address,
S1Translate ptw = {
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
+ .in_prot_check = 1 << access_type,
};
return get_phys_addr_gpc(env, &ptw, address, access_type,
@@ -3638,6 +3646,7 @@ static hwaddr arm_cpu_get_phys_page(CPUARMState *env, vaddr addr,
.in_mmu_idx = mmu_idx,
.in_space = arm_mmu_idx_to_security_space(env, mmu_idx),
.in_debug = true,
+ .in_prot_check = PAGE_READ,
};
GetPhysAddrResult res = {};
ARMMMUFaultInfo fi = {};
--
2.43.0