mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-09-14 05:37:06 +00:00
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
This commit is contained in:
parent
09d69209a0
commit
611a711f7b
|
@ -424,6 +424,7 @@ typedef struct CPUARMState {
|
||||||
uint32_t dfsr; /* Debug Fault Status Register */
|
uint32_t dfsr; /* Debug Fault Status Register */
|
||||||
uint32_t mmfar; /* MemManage Fault Address */
|
uint32_t mmfar; /* MemManage Fault Address */
|
||||||
uint32_t bfar; /* BusFault Address */
|
uint32_t bfar; /* BusFault Address */
|
||||||
|
unsigned mpu_ctrl; /* MPU_CTRL (some bits kept in sctlr_el[1]) */
|
||||||
int exception;
|
int exception;
|
||||||
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
|
uint32_t secure; /* Is CPU in Secure state? (not guest visible) */
|
||||||
} v7m;
|
} v7m;
|
||||||
|
@ -1149,6 +1150,11 @@ FIELD(V7M_DFSR, DWTTRAP, 2, 1)
|
||||||
FIELD(V7M_DFSR, VCATCH, 3, 1)
|
FIELD(V7M_DFSR, VCATCH, 3, 1)
|
||||||
FIELD(V7M_DFSR, EXTERNAL, 4, 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
|
/* If adding a feature bit which corresponds to a Linux ELF
|
||||||
* HWCAP bit, remember to update the feature-bit-to-hwcap
|
* HWCAP bit, remember to update the feature-bit-to-hwcap
|
||||||
* mapping in linux-user/elfload.c:get_elf_hwcap().
|
* mapping in linux-user/elfload.c:get_elf_hwcap().
|
||||||
|
|
|
@ -6227,6 +6227,10 @@ static inline uint32_t regime_sctlr(CPUARMState *env, ARMMMUIdx mmu_idx)
|
||||||
static inline bool regime_translation_disabled(CPUARMState *env,
|
static inline bool regime_translation_disabled(CPUARMState *env,
|
||||||
ARMMMUIdx mmu_idx)
|
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) {
|
if (mmu_idx == ARMMMUIdx_S2NS) {
|
||||||
return (env->cp15.hcr_el2 & HCR_VM) == 0;
|
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,
|
static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
|
||||||
int access_type, ARMMMUIdx mmu_idx,
|
int access_type, ARMMMUIdx mmu_idx,
|
||||||
hwaddr *phys_ptr, int *prot, uint32_t *fsr)
|
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 (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 */
|
/* background fault */
|
||||||
*fsr = 0;
|
*fsr = 0;
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in a new issue