From 611a711f7be0bd099206d542658170d9457e3fe2 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Fri, 2 Mar 2018 19:30:18 -0500 Subject: [PATCH] arm: add MPU support to M profile CPUs The M series MPU is almost the same as the already implemented R profile MPU (v7 PMSA). So all we need to implement here is the MPU register interface in the system register space. This implementation has the same restriction as the R profile MPU that it doesn't permit regions to be sized down smaller than 1K. We also do not yet implement support for MPU_CTRL.HFNMIENA; this bit should if zero disable use of the MPU when running HardFault, NMI or with FAULTMASK set to 1 (ie at an execution priority of less than zero) -- if the MPU is enabled we don't treat these cases any differently. Backports commit 29c483a506070e8f554c77d22686f405e30b9114 from qemu --- qemu/target/arm/cpu.h | 6 ++++++ qemu/target/arm/helper.c | 25 ++++++++++++++++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/qemu/target/arm/cpu.h b/qemu/target/arm/cpu.h index 616f7746..e127487c 100644 --- a/qemu/target/arm/cpu.h +++ b/qemu/target/arm/cpu.h @@ -424,6 +424,7 @@ typedef struct CPUARMState { uint32_t dfsr; /* Debug Fault Status Register */ uint32_t mmfar; /* MemManage Fault Address */ uint32_t bfar; /* BusFault Address */ + unsigned mpu_ctrl; /* MPU_CTRL (some bits kept in sctlr_el[1]) */ int exception; uint32_t secure; /* Is CPU in Secure state? (not guest visible) */ } v7m; @@ -1149,6 +1150,11 @@ FIELD(V7M_DFSR, DWTTRAP, 2, 1) FIELD(V7M_DFSR, VCATCH, 3, 1) FIELD(V7M_DFSR, EXTERNAL, 4, 1) +/* v7M MPU_CTRL bits */ +FIELD(V7M_MPU_CTRL, ENABLE, 0, 1) +FIELD(V7M_MPU_CTRL, HFNMIENA, 1, 1) +FIELD(V7M_MPU_CTRL, PRIVDEFENA, 2, 1) + /* If adding a feature bit which corresponds to a Linux ELF * HWCAP bit, remember to update the feature-bit-to-hwcap * mapping in linux-user/elfload.c:get_elf_hwcap(). diff --git a/qemu/target/arm/helper.c b/qemu/target/arm/helper.c index 19a081cb..c197d3f7 100644 --- a/qemu/target/arm/helper.c +++ b/qemu/target/arm/helper.c @@ -6227,6 +6227,10 @@ static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx) static inline bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx) { + if (arm_feature(env, ARM_FEATURE_M)) { + return !(env->v7m.mpu_ctrl & R_V7M_MPU_CTRL_ENABLE_MASK); + } + if (mmu_idx == ARMMMUIdx_S2NS) { return (env->cp15.hcr_el2 & HCR_VM) == 0; } @@ -7352,6 +7356,25 @@ static inline void get_phys_addr_pmsav7_default(CPUARMState *env, } } +static bool pmsav7_use_background_region(ARMCPU *cpu, + ARMMMUIdx mmu_idx, bool is_user) +{ + /* Return true if we should use the default memory map as a + * "background" region if there are no hits against any MPU regions. + */ + CPUARMState *env = &cpu->env; + + if (is_user) { + return false; + } + + if (arm_feature(env, ARM_FEATURE_M)) { + return env->v7m.mpu_ctrl & R_V7M_MPU_CTRL_PRIVDEFENA_MASK; + } else { + return regime_sctlr(env, mmu_idx) & SCTLR_BR; + } +} + static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, int access_type, ARMMMUIdx mmu_idx, hwaddr *phys_ptr, int *prot, uint32_t *fsr) @@ -7439,7 +7462,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address, } if (n == -1) { /* no hits */ - if (is_user || !(regime_sctlr(env, mmu_idx) & SCTLR_BR)) { + if (!pmsav7_use_background_region(cpu, mmu_idx, is_user)) { /* background fault */ *fsr = 0; return true;