target/arm: Move get_S1prot, get_S2prot to ptw.c

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20220604040607.269301-20-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-06-08 19:38:52 +01:00 committed by Peter Maydell
parent 1c73d84807
commit f8526edc2f
3 changed files with 128 additions and 131 deletions

View File

@ -10615,134 +10615,6 @@ int simple_ap_to_rw_prot_is_user(int ap, bool is_user)
}
}
/* Translate S2 section/page access permissions to protection flags
*
* @env: CPUARMState
* @s2ap: The 2-bit stage2 access permissions (S2AP)
* @xn: XN (execute-never) bits
* @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
*/
int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
{
int prot = 0;
if (s2ap & 1) {
prot |= PAGE_READ;
}
if (s2ap & 2) {
prot |= PAGE_WRITE;
}
if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
switch (xn) {
case 0:
prot |= PAGE_EXEC;
break;
case 1:
if (s1_is_el0) {
prot |= PAGE_EXEC;
}
break;
case 2:
break;
case 3:
if (!s1_is_el0) {
prot |= PAGE_EXEC;
}
break;
default:
g_assert_not_reached();
}
} else {
if (!extract32(xn, 1, 1)) {
if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
prot |= PAGE_EXEC;
}
}
}
return prot;
}
/* Translate section/page access permissions to protection flags
*
* @env: CPUARMState
* @mmu_idx: MMU index indicating required translation regime
* @is_aa64: TRUE if AArch64
* @ap: The 2-bit simple AP (AP[2:1])
* @ns: NS (non-secure) bit
* @xn: XN (execute-never) bit
* @pxn: PXN (privileged execute-never) bit
*/
int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
int ap, int ns, int xn, int pxn)
{
bool is_user = regime_is_user(env, mmu_idx);
int prot_rw, user_rw;
bool have_wxn;
int wxn = 0;
assert(mmu_idx != ARMMMUIdx_Stage2);
assert(mmu_idx != ARMMMUIdx_Stage2_S);
user_rw = simple_ap_to_rw_prot_is_user(ap, true);
if (is_user) {
prot_rw = user_rw;
} else {
if (user_rw && regime_is_pan(env, mmu_idx)) {
/* PAN forbids data accesses but doesn't affect insn fetch */
prot_rw = 0;
} else {
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
}
}
if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
return prot_rw;
}
/* TODO have_wxn should be replaced with
* ARM_FEATURE_V8 || (ARM_FEATURE_V7 && ARM_FEATURE_EL2)
* when ARM_FEATURE_EL2 starts getting set. For now we assume all LPAE
* compatible processors have EL2, which is required for [U]WXN.
*/
have_wxn = arm_feature(env, ARM_FEATURE_LPAE);
if (have_wxn) {
wxn = regime_sctlr(env, mmu_idx) & SCTLR_WXN;
}
if (is_aa64) {
if (regime_has_2_ranges(mmu_idx) && !is_user) {
xn = pxn || (user_rw & PAGE_WRITE);
}
} else if (arm_feature(env, ARM_FEATURE_V7)) {
switch (regime_el(env, mmu_idx)) {
case 1:
case 3:
if (is_user) {
xn = xn || !(user_rw & PAGE_READ);
} else {
int uwxn = 0;
if (have_wxn) {
uwxn = regime_sctlr(env, mmu_idx) & SCTLR_UWXN;
}
xn = xn || !(prot_rw & PAGE_READ) || pxn ||
(uwxn && (user_rw & PAGE_WRITE));
}
break;
case 2:
break;
}
} else {
xn = wxn = 0;
}
if (xn || (wxn && (prot_rw & PAGE_WRITE))) {
return prot_rw;
}
return prot_rw | PAGE_EXEC;
}
/*
* check_s2_mmu_setup
* @cpu: ARMCPU

View File

@ -487,6 +487,134 @@ do_fault:
return true;
}
/*
* Translate S2 section/page access permissions to protection flags
* @env: CPUARMState
* @s2ap: The 2-bit stage2 access permissions (S2AP)
* @xn: XN (execute-never) bits
* @s1_is_el0: true if this is S2 of an S1+2 walk for EL0
*/
static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
{
int prot = 0;
if (s2ap & 1) {
prot |= PAGE_READ;
}
if (s2ap & 2) {
prot |= PAGE_WRITE;
}
if (cpu_isar_feature(any_tts2uxn, env_archcpu(env))) {
switch (xn) {
case 0:
prot |= PAGE_EXEC;
break;
case 1:
if (s1_is_el0) {
prot |= PAGE_EXEC;
}
break;
case 2:
break;
case 3:
if (!s1_is_el0) {
prot |= PAGE_EXEC;
}
break;
default:
g_assert_not_reached();
}
} else {
if (!extract32(xn, 1, 1)) {
if (arm_el_is_aa64(env, 2) || prot & PAGE_READ) {
prot |= PAGE_EXEC;
}
}
}
return prot;
}
/*
* Translate section/page access permissions to protection flags
* @env: CPUARMState
* @mmu_idx: MMU index indicating required translation regime
* @is_aa64: TRUE if AArch64
* @ap: The 2-bit simple AP (AP[2:1])
* @ns: NS (non-secure) bit
* @xn: XN (execute-never) bit
* @pxn: PXN (privileged execute-never) bit
*/
static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
int ap, int ns, int xn, int pxn)
{
bool is_user = regime_is_user(env, mmu_idx);
int prot_rw, user_rw;
bool have_wxn;
int wxn = 0;
assert(mmu_idx != ARMMMUIdx_Stage2);
assert(mmu_idx != ARMMMUIdx_Stage2_S);
user_rw = simple_ap_to_rw_prot_is_user(ap, true);
if (is_user) {
prot_rw = user_rw;
} else {
if (user_rw && regime_is_pan(env, mmu_idx)) {
/* PAN forbids data accesses but doesn't affect insn fetch */
prot_rw = 0;
} else {
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
}
}
if (ns && arm_is_secure(env) && (env->cp15.scr_el3 & SCR_SIF)) {
return prot_rw;
}
/* TODO have_wxn should be replaced with
* ARM_FEATURE_V8 || (ARM_FEATURE_V7 && ARM_FEATURE_EL2)
* when ARM_FEATURE_EL2 starts getting set. For now we assume all LPAE
* compatible processors have EL2, which is required for [U]WXN.
*/
have_wxn = arm_feature(env, ARM_FEATURE_LPAE);
if (have_wxn) {
wxn = regime_sctlr(env, mmu_idx) & SCTLR_WXN;
}
if (is_aa64) {
if (regime_has_2_ranges(mmu_idx) && !is_user) {
xn = pxn || (user_rw & PAGE_WRITE);
}
} else if (arm_feature(env, ARM_FEATURE_V7)) {
switch (regime_el(env, mmu_idx)) {
case 1:
case 3:
if (is_user) {
xn = xn || !(user_rw & PAGE_READ);
} else {
int uwxn = 0;
if (have_wxn) {
uwxn = regime_sctlr(env, mmu_idx) & SCTLR_UWXN;
}
xn = xn || !(prot_rw & PAGE_READ) || pxn ||
(uwxn && (user_rw & PAGE_WRITE));
}
break;
case 2:
break;
}
} else {
xn = wxn = 0;
}
if (xn || (wxn && (prot_rw & PAGE_WRITE))) {
return prot_rw;
}
return prot_rw | PAGE_EXEC;
}
/**
* get_phys_addr_lpae: perform one stage of page table walk, LPAE format
*

View File

@ -29,9 +29,6 @@ ARMVAParameters aa32_va_parameters(CPUARMState *env, uint32_t va,
ARMMMUIdx mmu_idx);
bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
int inputsize, int stride, int outputsize);
int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0);
int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
int ap, int ns, int xn, int pxn);
#endif /* !CONFIG_USER_ONLY */
#endif /* TARGET_ARM_PTW_H */