diff options
Diffstat (limited to 'target-arm/cpu.h')
-rw-r--r-- | target-arm/cpu.h | 115 |
1 files changed, 92 insertions, 23 deletions
diff --git a/target-arm/cpu.h b/target-arm/cpu.h index d6e0d4debd..92c6ac6264 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -98,7 +98,7 @@ typedef uint32_t ARMReadCPFunc(void *opaque, int cp_info, struct arm_boot_info; -#define NB_MMU_MODES 4 +#define NB_MMU_MODES 7 /* We currently assume float and double are IEEE single and double precision respectively. @@ -1579,13 +1579,92 @@ static inline CPUARMState *cpu_init(const char *cpu_model) #define cpu_signal_handler cpu_arm_signal_handler #define cpu_list arm_cpu_list -/* MMU modes definitions */ +/* ARM has the following "translation regimes" (as the ARM ARM calls them): + * + * If EL3 is 64-bit: + * + NonSecure EL1 & 0 stage 1 + * + NonSecure EL1 & 0 stage 2 + * + NonSecure EL2 + * + Secure EL1 & EL0 + * + Secure EL3 + * If EL3 is 32-bit: + * + NonSecure PL1 & 0 stage 1 + * + NonSecure PL1 & 0 stage 2 + * + NonSecure PL2 + * + Secure PL0 & PL1 + * (reminder: for 32 bit EL3, Secure PL1 is *EL3*, not EL1.) + * + * For QEMU, an mmu_idx is not quite the same as a translation regime because: + * 1. we need to split the "EL1 & 0" regimes into two mmu_idxes, because they + * may differ in access permissions even if the VA->PA map is the same + * 2. we want to cache in our TLB the full VA->IPA->PA lookup for a stage 1+2 + * translation, which means that we have one mmu_idx that deals with two + * concatenated translation regimes [this sort of combined s1+2 TLB is + * architecturally permitted] + * 3. we don't need to allocate an mmu_idx to translations that we won't be + * handling via the TLB. The only way to do a stage 1 translation without + * the immediate stage 2 translation is via the ATS or AT system insns, + * which can be slow-pathed and always do a page table walk. + * 4. we can also safely fold together the "32 bit EL3" and "64 bit EL3" + * translation regimes, because they map reasonably well to each other + * and they can't both be active at the same time. + * This gives us the following list of mmu_idx values: + * + * NS EL0 (aka NS PL0) stage 1+2 + * NS EL1 (aka NS PL1) stage 1+2 + * NS EL2 (aka NS PL2) + * S EL3 (aka S PL1) + * S EL0 (aka S PL0) + * S EL1 (not used if EL3 is 32 bit) + * NS EL0+1 stage 2 + * + * (The last of these is an mmu_idx because we want to be able to use the TLB + * for the accesses done as part of a stage 1 page table walk, rather than + * having to walk the stage 2 page table over and over.) + * + * Our enumeration includes at the end some entries which are not "true" + * mmu_idx values in that they don't have corresponding TLBs and are only + * valid for doing slow path page table walks. + * + * The constant names here are patterned after the general style of the names + * of the AT/ATS operations. + * The values used are carefully arranged to make mmu_idx => EL lookup easy. + */ +typedef enum ARMMMUIdx { + ARMMMUIdx_S12NSE0 = 0, + ARMMMUIdx_S12NSE1 = 1, + ARMMMUIdx_S1E2 = 2, + ARMMMUIdx_S1E3 = 3, + ARMMMUIdx_S1SE0 = 4, + ARMMMUIdx_S1SE1 = 5, + ARMMMUIdx_S2NS = 6, + /* Indexes below here don't have TLBs and are used only for AT system + * instructions or for the first stage of an S12 page table walk. + */ + ARMMMUIdx_S1NSE0 = 7, + ARMMMUIdx_S1NSE1 = 8, +} ARMMMUIdx; + #define MMU_MODE0_SUFFIX _user #define MMU_MODE1_SUFFIX _kernel #define MMU_USER_IDX 0 -static inline int cpu_mmu_index (CPUARMState *env) + +/* Return the exception level we're running at if this is our mmu_idx */ +static inline int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx) { - return arm_current_el(env); + assert(mmu_idx < ARMMMUIdx_S2NS); + return mmu_idx & 3; +} + +/* Determine the current mmu_idx to use for normal loads/stores */ +static inline int cpu_mmu_index(CPUARMState *env) +{ + int el = arm_current_el(env); + + if (el < 2 && arm_is_secure_below_el3(env)) { + return ARMMMUIdx_S1SE0 + el; + } + return el; } /* Return the Exception Level targeted by debug exceptions; @@ -1652,9 +1731,13 @@ static inline bool arm_singlestep_active(CPUARMState *env) /* Bit usage in the TB flags field: bit 31 indicates whether we are * in 32 or 64 bit mode. The meaning of the other bits depends on that. + * We put flags which are shared between 32 and 64 bit mode at the top + * of the word, and flags which apply to only one mode at the bottom. */ #define ARM_TBFLAG_AARCH64_STATE_SHIFT 31 #define ARM_TBFLAG_AARCH64_STATE_MASK (1U << ARM_TBFLAG_AARCH64_STATE_SHIFT) +#define ARM_TBFLAG_MMUIDX_SHIFT 28 +#define ARM_TBFLAG_MMUIDX_MASK (0x7 << ARM_TBFLAG_MMUIDX_SHIFT) /* Bit usage when in AArch32 state: */ #define ARM_TBFLAG_THUMB_SHIFT 0 @@ -1663,8 +1746,6 @@ static inline bool arm_singlestep_active(CPUARMState *env) #define ARM_TBFLAG_VECLEN_MASK (0x7 << ARM_TBFLAG_VECLEN_SHIFT) #define ARM_TBFLAG_VECSTRIDE_SHIFT 4 #define ARM_TBFLAG_VECSTRIDE_MASK (0x3 << ARM_TBFLAG_VECSTRIDE_SHIFT) -#define ARM_TBFLAG_PRIV_SHIFT 6 -#define ARM_TBFLAG_PRIV_MASK (1 << ARM_TBFLAG_PRIV_SHIFT) #define ARM_TBFLAG_VFPEN_SHIFT 7 #define ARM_TBFLAG_VFPEN_MASK (1 << ARM_TBFLAG_VFPEN_SHIFT) #define ARM_TBFLAG_CONDEXEC_SHIFT 8 @@ -1690,8 +1771,6 @@ static inline bool arm_singlestep_active(CPUARMState *env) #define ARM_TBFLAG_NS_MASK (1 << ARM_TBFLAG_NS_SHIFT) /* Bit usage when in AArch64 state */ -#define ARM_TBFLAG_AA64_EL_SHIFT 0 -#define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT) #define ARM_TBFLAG_AA64_FPEN_SHIFT 2 #define ARM_TBFLAG_AA64_FPEN_MASK (1 << ARM_TBFLAG_AA64_FPEN_SHIFT) #define ARM_TBFLAG_AA64_SS_ACTIVE_SHIFT 3 @@ -1702,14 +1781,14 @@ static inline bool arm_singlestep_active(CPUARMState *env) /* some convenience accessor macros */ #define ARM_TBFLAG_AARCH64_STATE(F) \ (((F) & ARM_TBFLAG_AARCH64_STATE_MASK) >> ARM_TBFLAG_AARCH64_STATE_SHIFT) +#define ARM_TBFLAG_MMUIDX(F) \ + (((F) & ARM_TBFLAG_MMUIDX_MASK) >> ARM_TBFLAG_MMUIDX_SHIFT) #define ARM_TBFLAG_THUMB(F) \ (((F) & ARM_TBFLAG_THUMB_MASK) >> ARM_TBFLAG_THUMB_SHIFT) #define ARM_TBFLAG_VECLEN(F) \ (((F) & ARM_TBFLAG_VECLEN_MASK) >> ARM_TBFLAG_VECLEN_SHIFT) #define ARM_TBFLAG_VECSTRIDE(F) \ (((F) & ARM_TBFLAG_VECSTRIDE_MASK) >> ARM_TBFLAG_VECSTRIDE_SHIFT) -#define ARM_TBFLAG_PRIV(F) \ - (((F) & ARM_TBFLAG_PRIV_MASK) >> ARM_TBFLAG_PRIV_SHIFT) #define ARM_TBFLAG_VFPEN(F) \ (((F) & ARM_TBFLAG_VFPEN_MASK) >> ARM_TBFLAG_VFPEN_SHIFT) #define ARM_TBFLAG_CONDEXEC(F) \ @@ -1724,8 +1803,6 @@ static inline bool arm_singlestep_active(CPUARMState *env) (((F) & ARM_TBFLAG_PSTATE_SS_MASK) >> ARM_TBFLAG_PSTATE_SS_SHIFT) #define ARM_TBFLAG_XSCALE_CPAR(F) \ (((F) & ARM_TBFLAG_XSCALE_CPAR_MASK) >> ARM_TBFLAG_XSCALE_CPAR_SHIFT) -#define ARM_TBFLAG_AA64_EL(F) \ - (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT) #define ARM_TBFLAG_AA64_FPEN(F) \ (((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT) #define ARM_TBFLAG_AA64_SS_ACTIVE(F) \ @@ -1749,8 +1826,7 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, if (is_a64(env)) { *pc = env->pc; - *flags = ARM_TBFLAG_AARCH64_STATE_MASK - | (arm_current_el(env) << ARM_TBFLAG_AA64_EL_SHIFT); + *flags = ARM_TBFLAG_AARCH64_STATE_MASK; if (fpen == 3 || (fpen == 1 && arm_current_el(env) != 0)) { *flags |= ARM_TBFLAG_AA64_FPEN_MASK; } @@ -1768,21 +1844,12 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, } } } else { - int privmode; *pc = env->regs[15]; *flags = (env->thumb << ARM_TBFLAG_THUMB_SHIFT) | (env->vfp.vec_len << ARM_TBFLAG_VECLEN_SHIFT) | (env->vfp.vec_stride << ARM_TBFLAG_VECSTRIDE_SHIFT) | (env->condexec_bits << ARM_TBFLAG_CONDEXEC_SHIFT) | (env->bswap_code << ARM_TBFLAG_BSWAP_CODE_SHIFT); - if (arm_feature(env, ARM_FEATURE_M)) { - privmode = !((env->v7m.exception == 0) && (env->v7m.control & 1)); - } else { - privmode = (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR; - } - if (privmode) { - *flags |= ARM_TBFLAG_PRIV_MASK; - } if (!(access_secure_reg(env))) { *flags |= ARM_TBFLAG_NS_MASK; } @@ -1810,6 +1877,8 @@ static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, << ARM_TBFLAG_XSCALE_CPAR_SHIFT); } + *flags |= (cpu_mmu_index(env) << ARM_TBFLAG_MMUIDX_SHIFT); + *cs_base = 0; } |