#define ARM_MMU_IDX_NOTLB 0x20 /* does not have a TLB */
#define ARM_MMU_IDX_M 0x40 /* M profile */
+/* Meanings of the bits for A profile mmu idx values */
+#define ARM_MMU_IDX_A_NS 0x8
+
/* Meanings of the bits for M profile mmu idx values */
#define ARM_MMU_IDX_M_PRIV 0x1
#define ARM_MMU_IDX_M_NEGPRI 0x2
/*
* A-profile.
*/
- ARMMMUIdx_E10_0 = 0 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_0 = 1 | ARM_MMU_IDX_A,
-
- ARMMMUIdx_E10_1 = 2 | ARM_MMU_IDX_A,
- ARMMMUIdx_E10_1_PAN = 3 | ARM_MMU_IDX_A,
-
- ARMMMUIdx_E2 = 4 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2 = 5 | ARM_MMU_IDX_A,
- ARMMMUIdx_E20_2_PAN = 6 | ARM_MMU_IDX_A,
-
- ARMMMUIdx_SE10_0 = 7 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE10_1 = 8 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE10_1_PAN = 9 | ARM_MMU_IDX_A,
- ARMMMUIdx_SE3 = 10 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_0 = 0 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE20_0 = 1 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_1 = 2 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE20_2 = 3 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE10_1_PAN = 4 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE20_2_PAN = 5 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE2 = 6 | ARM_MMU_IDX_A,
+ ARMMMUIdx_SE3 = 7 | ARM_MMU_IDX_A,
+
+ ARMMMUIdx_E10_0 = ARMMMUIdx_SE10_0 | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E20_0 = ARMMMUIdx_SE20_0 | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E10_1 = ARMMMUIdx_SE10_1 | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E20_2 = ARMMMUIdx_SE20_2 | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E10_1_PAN = ARMMMUIdx_SE10_1_PAN | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E20_2_PAN = ARMMMUIdx_SE20_2_PAN | ARM_MMU_IDX_A_NS,
+ ARMMMUIdx_E2 = ARMMMUIdx_SE2 | ARM_MMU_IDX_A_NS,
/*
* These are not allocated TLBs and are used only for AT system
TO_CORE_BIT(E20_2),
TO_CORE_BIT(E20_2_PAN),
TO_CORE_BIT(SE10_0),
+ TO_CORE_BIT(SE20_0),
TO_CORE_BIT(SE10_1),
+ TO_CORE_BIT(SE20_2),
TO_CORE_BIT(SE10_1_PAN),
+ TO_CORE_BIT(SE20_2_PAN),
+ TO_CORE_BIT(SE2),
TO_CORE_BIT(SE3),
TO_CORE_BIT(MUser),
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_SE20_0:
+ case ARMMMUIdx_SE20_2:
+ case ARMMMUIdx_SE20_2_PAN:
return GTIMER_HYP;
default:
return GTIMER_PHYS;
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_SE20_0:
+ case ARMMMUIdx_SE20_2:
+ case ARMMMUIdx_SE20_2_PAN:
return GTIMER_HYPVIRT;
default:
return GTIMER_VIRT;
mmu_idx = ARMMMUIdx_SE3;
break;
case 2:
- g_assert(!secure); /* TODO: ARMv8.4-SecEL2 */
+ g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
/* fall through */
case 1:
if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
}
break;
case 4: /* AT S1E2R, AT S1E2W */
- mmu_idx = ARMMMUIdx_E2;
+ mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2;
break;
case 6: /* AT S1E3R, AT S1E3W */
mmu_idx = ARMMMUIdx_SE3;
*/
if (extract64(raw_read(env, ri) ^ value, 48, 16) &&
(arm_hcr_el2_eff(env) & HCR_E2H)) {
- tlb_flush_by_mmuidx(env_cpu(env),
- ARMMMUIdxBit_E20_2 |
- ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E20_0);
+ uint16_t mask = ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0;
+
+ if (arm_is_secure_below_el3(env)) {
+ mask >>= ARM_MMU_IDX_A_NS;
+ }
+
+ tlb_flush_by_mmuidx(env_cpu(env), mask);
}
raw_write(env, ri, value);
}
uint64_t hcr = arm_hcr_el2_eff(env);
if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
- return ARMMMUIdxBit_E20_2 |
- ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E20_0;
+ uint16_t mask = ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E20_0;
+
+ if (arm_is_secure_below_el3(env)) {
+ mask >>= ARM_MMU_IDX_A_NS;
+ }
+
+ return mask;
} else if (arm_is_secure_below_el3(env)) {
return ARMMMUIdxBit_SE10_1 |
ARMMMUIdxBit_SE10_1_PAN |
static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
{
+ uint64_t hcr = arm_hcr_el2_eff(env);
ARMMMUIdx mmu_idx;
/* Only the regime of the mmu_idx below is significant. */
- if (arm_is_secure_below_el3(env)) {
- mmu_idx = ARMMMUIdx_SE10_0;
- } else if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE))
- == (HCR_E2H | HCR_TGE)) {
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
mmu_idx = ARMMMUIdx_E20_0;
} else {
mmu_idx = ARMMMUIdx_E10_0;
}
+
+ if (arm_is_secure_below_el3(env)) {
+ mmu_idx &= ~ARM_MMU_IDX_A_NS;
+ }
+
return tlbbits_for_regime(env, mmu_idx, addr);
}
static int e2_tlbmask(CPUARMState *env)
{
- /* TODO: ARMv8.4-SecEL2 */
- return ARMMMUIdxBit_E20_0 |
- ARMMMUIdxBit_E20_2 |
- ARMMMUIdxBit_E20_2_PAN |
- ARMMMUIdxBit_E2;
+ if (arm_is_secure_below_el3(env)) {
+ return ARMMMUIdxBit_SE20_0 |
+ ARMMMUIdxBit_SE20_2 |
+ ARMMMUIdxBit_SE20_2_PAN |
+ ARMMMUIdxBit_SE2;
+ } else {
+ return ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E2;
+ }
}
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
uint64_t pageaddr = sextract64(value << 12, 0, 56);
- int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
+ bool secure = arm_is_secure_below_el3(env);
+ int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2;
+ int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_E2 : ARMMMUIdx_SE2,
+ pageaddr);
- tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
- ARMMMUIdxBit_E2, bits);
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
}
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
/* Only EL0 needs to be adjusted for EL1&0 or EL2&0. */
if (el == 0) {
ARMMMUIdx mmu_idx = arm_mmu_idx_el(env, 0);
- el = (mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1);
+ el = (mmu_idx == ARMMMUIdx_E20_0 || mmu_idx == ARMMMUIdx_SE20_0)
+ ? 2 : 1;
}
return env->cp15.sctlr_el[el];
}
switch (mmu_idx) {
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_SE20_0:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_MUser:
case ARMMMUIdx_MSUser:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_SE10_0:
+ case ARMMMUIdx_SE20_0:
return 0;
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E2:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_SE2:
+ case ARMMMUIdx_SE20_2:
+ case ARMMMUIdx_SE20_2_PAN:
return 2;
case ARMMMUIdx_SE3:
return 3;
ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
{
+ ARMMMUIdx idx;
+ uint64_t hcr;
+
if (arm_feature(env, ARM_FEATURE_M)) {
return arm_v7m_mmu_idx_for_secstate(env, env->v7m.secure);
}
/* See ARM pseudo-function ELIsInHost. */
switch (el) {
case 0:
- if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdx_SE10_0;
- }
- if ((env->cp15.hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)
- && arm_el_is_aa64(env, 2)) {
- return ARMMMUIdx_E20_0;
+ hcr = arm_hcr_el2_eff(env);
+ if ((hcr & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
+ idx = ARMMMUIdx_E20_0;
+ } else {
+ idx = ARMMMUIdx_E10_0;
}
- return ARMMMUIdx_E10_0;
+ break;
case 1:
- if (arm_is_secure_below_el3(env)) {
- if (env->pstate & PSTATE_PAN) {
- return ARMMMUIdx_SE10_1_PAN;
- }
- return ARMMMUIdx_SE10_1;
- }
if (env->pstate & PSTATE_PAN) {
- return ARMMMUIdx_E10_1_PAN;
+ idx = ARMMMUIdx_E10_1_PAN;
+ } else {
+ idx = ARMMMUIdx_E10_1;
}
- return ARMMMUIdx_E10_1;
+ break;
case 2:
- /* TODO: ARMv8.4-SecEL2 */
/* Note that TGE does not apply at EL2. */
- if ((env->cp15.hcr_el2 & HCR_E2H) && arm_el_is_aa64(env, 2)) {
+ if (arm_hcr_el2_eff(env) & HCR_E2H) {
if (env->pstate & PSTATE_PAN) {
- return ARMMMUIdx_E20_2_PAN;
+ idx = ARMMMUIdx_E20_2_PAN;
+ } else {
+ idx = ARMMMUIdx_E20_2;
}
- return ARMMMUIdx_E20_2;
+ } else {
+ idx = ARMMMUIdx_E2;
}
- return ARMMMUIdx_E2;
+ break;
case 3:
return ARMMMUIdx_SE3;
default:
g_assert_not_reached();
}
+
+ if (arm_is_secure_below_el3(env)) {
+ idx &= ~ARM_MMU_IDX_A_NS;
+ }
+
+ return idx;
}
ARMMMUIdx arm_mmu_idx(CPUARMState *env)
break;
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
- /* TODO: ARMv8.4-SecEL2 */
+ case ARMMMUIdx_SE20_2:
+ case ARMMMUIdx_SE20_2_PAN:
/*
* Note that EL20_2 is gated by HCR_EL2.E2H == 1, but EL20_0 is
* gated by HCR_EL2.<E2H,TGE> == '11', and so is LDTR.