- synchronize PSTATE.PAN with changes in CPSR.PAN in aarch32 mode - set PAN bit automatically on exception entry if SCTLR_SPAN bit is set - throw permission fault during address translation when PAN is enabled and kernel tries to access user acessible page - ignore SCTLR_XP bit for armv7 and armv8 (conflicts with SCTLR_SPAN). --- target/arm/helper.c | 6 ++++++ target/arm/ptw.c | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/target/arm/helper.c b/target/arm/helper.c index dde64a487a..5299f67e3f 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -9052,6 +9052,11 @@ void cpsr_write(CPUARMState *env, uint32_t val, uint32_t mask, } mask &= ~CACHED_CPSR_BITS; env->uncached_cpsr = (env->uncached_cpsr & ~mask) | (val & mask); + if (env->uncached_cpsr & CPSR_PAN) { + env->pstate |= PSTATE_PAN; + } else { + env->pstate &= ~PSTATE_PAN; + } if (rebuild_hflags) { arm_rebuild_hflags(env); } @@ -9592,6 +9597,7 @@ static void take_aarch32_exception(CPUARMState *env, int new_mode, /* ... the target is EL1 and SCTLR.SPAN is 0. */ if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPAN)) { env->uncached_cpsr |= CPSR_PAN; + env->pstate |= PSTATE_PAN; } break; } diff --git a/target/arm/ptw.c b/target/arm/ptw.c index 23f16f4ff7..204a73350f 100644 --- a/target/arm/ptw.c +++ b/target/arm/ptw.c @@ -659,6 +659,13 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address, goto do_fault; } + if (regime_is_pan(env, mmu_idx) && !regime_is_user(env, mmu_idx) && + simple_ap_to_rw_prot_is_user(ap >> 1, 1) && + access_type != MMU_INST_FETCH) { + fi->type = ARMFault_Permission; + goto do_fault; + } + if (arm_feature(env, ARM_FEATURE_V6K) && (regime_sctlr(env, mmu_idx) & SCTLR_AFE)) { /* The simplified model uses AP[0] as an access control bit. */ @@ -2506,7 +2513,9 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address, if (regime_using_lpae_format(env, mmu_idx)) { return get_phys_addr_lpae(env, address, access_type, mmu_idx, is_secure, false, result, fi); - } else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) { + } else if (arm_feature(env, ARM_FEATURE_V7) || + arm_feature(env, ARM_FEATURE_V8) || ( + regime_sctlr(env, mmu_idx) & SCTLR_XP)) { return get_phys_addr_v6(env, address, access_type, mmu_idx, is_secure, result, fi); } else { -- 2.25.1