diff options
author | Rémi Denis-Courmont | 2021-01-12 11:45:00 +0100 |
---|---|---|
committer | Peter Maydell | 2021-01-19 15:38:51 +0100 |
commit | b6ad6062f1e55bd5b9407ce89e55e3a08b83827c (patch) | |
tree | d15eeb1e9e455c1cf82c80cde7e62267237b5a9a /target/arm/helper.c | |
parent | target/arm: add 64-bit S-EL2 to EL exception table (diff) | |
download | qemu-b6ad6062f1e55bd5b9407ce89e55e3a08b83827c.tar.gz qemu-b6ad6062f1e55bd5b9407ce89e55e3a08b83827c.tar.xz qemu-b6ad6062f1e55bd5b9407ce89e55e3a08b83827c.zip |
target/arm: add MMU stage 1 for Secure EL2
This adds the MMU indices for EL2 stage 1 in secure state.
To keep code contained, which is largelly identical between secure and
non-secure modes, the MMU indices are reassigned. The new assignments
provide a systematic pattern with a non-secure bit.
Signed-off-by: Rémi Denis-Courmont <remi.denis.courmont@huawei.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20210112104511.36576-8-remi.denis.courmont@huawei.com
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/helper.c')
-rw-r--r-- | target/arm/helper.c | 127 |
1 files changed, 84 insertions, 43 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 47f37b82ba..a11a76adb8 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -2862,6 +2862,9 @@ static int gt_phys_redir_timeridx(CPUARMState *env) 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; @@ -2874,6 +2877,9 @@ static int gt_virt_redir_timeridx(CPUARMState *env) 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; @@ -3577,7 +3583,7 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) 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)) { @@ -3673,7 +3679,7 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri, } 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; @@ -3988,10 +3994,15 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri, */ 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); } @@ -4442,9 +4453,15 @@ static int vae1_tlbmask(CPUARMState *env) 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 | @@ -4469,17 +4486,20 @@ static int tlbbits_for_regime(CPUARMState *env, ARMMMUIdx mmu_idx, 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); } @@ -4525,11 +4545,17 @@ static int alle1_tlbmask(CPUARMState *env) 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, @@ -4649,10 +4675,12 @@ static void tlbi_aa64_vae2is_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, @@ -9954,7 +9982,8 @@ uint64_t arm_sctlr(CPUARMState *env, int el) /* 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]; } @@ -10083,6 +10112,7 @@ static inline bool regime_is_user(CPUARMState *env, ARMMMUIdx mmu_idx) 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: @@ -12676,6 +12706,7 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx) 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: @@ -12685,6 +12716,9 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx) 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; @@ -12702,6 +12736,9 @@ ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate) 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); } @@ -12709,40 +12746,43 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el) /* 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) @@ -12907,7 +12947,8 @@ static uint32_t rebuild_hflags_a64(CPUARMState *env, int el, int fp_el, 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. |