aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2022-10-12 15:59:10 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2022-10-12 15:59:10 -0400
commitcdda364e1da45edcb70fad7fa77bd2bb5e6c023f (patch)
tree34ac767f482da3f14a5a8ab2b3d0ab962a72a3dc /target
parent7fa24b8d61be040ba58bed6fc1c16fd5fb7b6af0 (diff)
parent915f62844cf62e428c7c178149b5ff1cbe129b07 (diff)
downloadqemu-cdda364e1da45edcb70fad7fa77bd2bb5e6c023f.zip
qemu-cdda364e1da45edcb70fad7fa77bd2bb5e6c023f.tar.gz
qemu-cdda364e1da45edcb70fad7fa77bd2bb5e6c023f.tar.bz2
Merge tag 'pull-target-arm-20221010' of https://git.linaro.org/people/pmaydell/qemu-arm into staging
target-arm queue: * Retry KVM_CREATE_VM call if it fails EINTR * allow setting SCR_EL3.EnTP2 when FEAT_SME is implemented * docs/nuvoton: Update URL for images * refactoring of page table walk code * hw/arm/boot: set CPTR_EL3.ESM and SCR_EL3.EnTP2 when booting Linux with EL3 * Don't allow guest to use unimplemented granule sizes * Report FEAT_GTG support # -----BEGIN PGP SIGNATURE----- # # iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmNEK54ZHHBldGVyLm1h # eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3kzHD/9StYmulAf0iwe1ZNp6NavK # CioOgZi6XyZl4rS2DrCf6/IO5XRFJP68byZd4Po554r2jcPc149yTuQAn4wb7d5e # kejMZRQeWsXdxschhoVzDp9fgfzyZBn9X+gbdEZFFPWzOHMyWuu4cTok0dAKQvQY # tZDLGmKeTv4MRUFJCri0310Sq0T0v/nAX/AyFtpvIr2SBx7DVCWYY02s5R4Yy5+M # ntDWb0j12r78/bPwI1ll+g19JXUV5Tfh9AsbcYjKv45kdftz/Xc8fBiSiEpxyMrF # mnVrr3kesZHOYAnOr2K1MnwsF0vU41kRg7kMRqSnu7pZXlI/8tmRyXoPR3c2aDbW # Q5HWtsA48j2h0CJ0ESzl5SQnl3TSPa94m/HmpRSBFrYkU727QgnWDhUmBb4n54xs # 9iBJDhcKGZLq68CB2+j6ENdRNTndolr14OwwEns0lbkoiCKUOQY3AigtZJQGRBGM # J5r3ED7jfTWpvP6vpp5X484fK6KVprSMxsRFDkmiwhbb3J+WtKLxbSlgsWIrkZ7s # +JgTGfGB8sD9hJVuFZYyPQb/XWP8Bb8jfgsLsTu1vW9Xs1ASrLimFYdRO3hhwSg3 # c5yubz6Vu9GB/JYh7hGprlMD5Yv48AA3if70hOu2d4P8A4OitavT7o+4Thwqjhds # cSV1RsBJ8ha6L3CziZaKrQ== # =s+1f # -----END PGP SIGNATURE----- # gpg: Signature made Mon 10 Oct 2022 10:26:38 EDT # gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE # gpg: issuer "peter.maydell@linaro.org" # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full] # gpg: aka "Peter Maydell <pmaydell@gmail.com>" [full] # gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full] # gpg: aka "Peter Maydell <peter@archaic.org.uk>" [unknown] # Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE * tag 'pull-target-arm-20221010' of https://git.linaro.org/people/pmaydell/qemu-arm: (28 commits) docs/system/arm/emulation.rst: Report FEAT_GTG support target/arm: Use ARMGranuleSize in ARMVAParameters target/arm: Don't allow guest to use unimplemented granule sizes hw/arm/boot: set CPTR_EL3.ESM and SCR_EL3.EnTP2 when booting Linux with EL3 target/arm: Use tlb_set_page_full target/arm: Fix cacheattr in get_phys_addr_disabled target/arm: Split out get_phys_addr_disabled target/arm: Fix ATS12NSO* from S PL1 target/arm: Pass HCR to attribute subroutines. target/arm: Remove env argument from combined_attrs_fwb target/arm: Hoist read of *is_secure in S1_ptw_translate target/arm: Introduce arm_hcr_el2_eff_secstate target/arm: Drop secure check for HCR.TGE vs SCTLR_EL1.M target/arm: Reorg regime_translation_disabled target/arm: Fold secure and non-secure a-profile mmu indexes target/arm: Add is_secure parameter to do_ats_write target/arm: Merge regime_is_secure into get_phys_addr target/arm: Add TBFLAG_M32.SECURE target/arm: Add is_secure parameter to v7m_read_half_insn target/arm: Split out get_phys_addr_with_secure ... Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'target')
-rw-r--r--target/arm/cpu-param.h2
-rw-r--r--target/arm/cpu.h181
-rw-r--r--target/arm/helper.c332
-rw-r--r--target/arm/internals.h150
-rw-r--r--target/arm/kvm.c4
-rw-r--r--target/arm/m_helper.c29
-rw-r--r--target/arm/ptw.c570
-rw-r--r--target/arm/tlb_helper.c9
-rw-r--r--target/arm/translate-a64.c8
-rw-r--r--target/arm/translate.c9
10 files changed, 710 insertions, 584 deletions
diff --git a/target/arm/cpu-param.h b/target/arm/cpu-param.h
index 68ffb12..0868182 100644
--- a/target/arm/cpu-param.h
+++ b/target/arm/cpu-param.h
@@ -32,6 +32,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif
-#define NB_MMU_MODES 15
+#define NB_MMU_MODES 8
#endif
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 85dc263..e3dbef5 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1664,33 +1664,33 @@ static inline void xpsr_write(CPUARMState *env, uint32_t val, uint32_t mask)
#define HPFAR_NS (1ULL << 63)
-#define SCR_NS (1U << 0)
-#define SCR_IRQ (1U << 1)
-#define SCR_FIQ (1U << 2)
-#define SCR_EA (1U << 3)
-#define SCR_FW (1U << 4)
-#define SCR_AW (1U << 5)
-#define SCR_NET (1U << 6)
-#define SCR_SMD (1U << 7)
-#define SCR_HCE (1U << 8)
-#define SCR_SIF (1U << 9)
-#define SCR_RW (1U << 10)
-#define SCR_ST (1U << 11)
-#define SCR_TWI (1U << 12)
-#define SCR_TWE (1U << 13)
-#define SCR_TLOR (1U << 14)
-#define SCR_TERR (1U << 15)
-#define SCR_APK (1U << 16)
-#define SCR_API (1U << 17)
-#define SCR_EEL2 (1U << 18)
-#define SCR_EASE (1U << 19)
-#define SCR_NMEA (1U << 20)
-#define SCR_FIEN (1U << 21)
-#define SCR_ENSCXT (1U << 25)
-#define SCR_ATA (1U << 26)
-#define SCR_FGTEN (1U << 27)
-#define SCR_ECVEN (1U << 28)
-#define SCR_TWEDEN (1U << 29)
+#define SCR_NS (1ULL << 0)
+#define SCR_IRQ (1ULL << 1)
+#define SCR_FIQ (1ULL << 2)
+#define SCR_EA (1ULL << 3)
+#define SCR_FW (1ULL << 4)
+#define SCR_AW (1ULL << 5)
+#define SCR_NET (1ULL << 6)
+#define SCR_SMD (1ULL << 7)
+#define SCR_HCE (1ULL << 8)
+#define SCR_SIF (1ULL << 9)
+#define SCR_RW (1ULL << 10)
+#define SCR_ST (1ULL << 11)
+#define SCR_TWI (1ULL << 12)
+#define SCR_TWE (1ULL << 13)
+#define SCR_TLOR (1ULL << 14)
+#define SCR_TERR (1ULL << 15)
+#define SCR_APK (1ULL << 16)
+#define SCR_API (1ULL << 17)
+#define SCR_EEL2 (1ULL << 18)
+#define SCR_EASE (1ULL << 19)
+#define SCR_NMEA (1ULL << 20)
+#define SCR_FIEN (1ULL << 21)
+#define SCR_ENSCXT (1ULL << 25)
+#define SCR_ATA (1ULL << 26)
+#define SCR_FGTEN (1ULL << 27)
+#define SCR_ECVEN (1ULL << 28)
+#define SCR_TWEDEN (1ULL << 29)
#define SCR_TWEDEL MAKE_64BIT_MASK(30, 4)
#define SCR_TME (1ULL << 34)
#define SCR_AMVOFFEN (1ULL << 35)
@@ -2412,15 +2412,15 @@ static inline bool arm_is_secure(CPUARMState *env)
* Return true if the current security state has AArch64 EL2 or AArch32 Hyp.
* This corresponds to the pseudocode EL2Enabled()
*/
+static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure)
+{
+ return arm_feature(env, ARM_FEATURE_EL2)
+ && (!secure || (env->cp15.scr_el3 & SCR_EEL2));
+}
+
static inline bool arm_is_el2_enabled(CPUARMState *env)
{
- if (arm_feature(env, ARM_FEATURE_EL2)) {
- if (arm_is_secure_below_el3(env)) {
- return (env->cp15.scr_el3 & SCR_EEL2) != 0;
- }
- return true;
- }
- return false;
+ return arm_is_el2_enabled_secstate(env, arm_is_secure_below_el3(env));
}
#else
@@ -2434,6 +2434,11 @@ static inline bool arm_is_secure(CPUARMState *env)
return false;
}
+static inline bool arm_is_el2_enabled_secstate(CPUARMState *env, bool secure)
+{
+ return false;
+}
+
static inline bool arm_is_el2_enabled(CPUARMState *env)
{
return false;
@@ -2446,6 +2451,7 @@ static inline bool arm_is_el2_enabled(CPUARMState *env)
* "for all purposes other than a direct read or write access of HCR_EL2."
* Not included here is HCR_RW.
*/
+uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure);
uint64_t arm_hcr_el2_eff(CPUARMState *env);
uint64_t arm_hcrx_el2_eff(CPUARMState *env);
@@ -2884,26 +2890,27 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
* table over and over.
* 6. we need separate EL1/EL2 mmu_idx for handling the Privileged Access
* Never (PAN) bit within PSTATE.
+ * 7. we fold together the secure and non-secure regimes for A-profile,
+ * because there are no banked system registers for aarch64, so the
+ * process of switching between secure and non-secure is
+ * already heavyweight.
*
* This gives us the following list of cases:
*
- * NS EL0 EL1&0 stage 1+2 (aka NS PL0)
- * NS EL1 EL1&0 stage 1+2 (aka NS PL1)
- * NS EL1 EL1&0 stage 1+2 +PAN
- * NS EL0 EL2&0
- * NS EL2 EL2&0
- * NS EL2 EL2&0 +PAN
- * NS EL2 (aka NS PL2)
- * S EL0 EL1&0 (aka S PL0)
- * S EL1 EL1&0 (not used if EL3 is 32 bit)
- * S EL1 EL1&0 +PAN
- * S EL3 (aka S PL1)
+ * EL0 EL1&0 stage 1+2 (aka NS PL0)
+ * EL1 EL1&0 stage 1+2 (aka NS PL1)
+ * EL1 EL1&0 stage 1+2 +PAN
+ * EL0 EL2&0
+ * EL2 EL2&0
+ * EL2 EL2&0 +PAN
+ * EL2 (aka NS PL2)
+ * EL3 (aka S PL1)
*
- * for a total of 11 different mmu_idx.
+ * for a total of 8 different mmu_idx.
*
* R profile CPUs have an MPU, but can use the same set of MMU indexes
- * as A profile. They only need to distinguish NS EL0 and NS EL1 (and
- * NS EL2 if we ever model a Cortex-R52).
+ * as A profile. They only need to distinguish EL0 and EL1 (and
+ * EL2 if we ever model a Cortex-R52).
*
* M profile CPUs are rather different as they do not have a true MMU.
* They have the following different MMU indexes:
@@ -2942,9 +2949,6 @@ bool write_cpustate_to_list(ARMCPU *cpu, bool kvm_sync);
#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
@@ -2958,22 +2962,14 @@ typedef enum ARMMMUIdx {
/*
* A-profile.
*/
- 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,
+ 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_E20_2 = 3 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E10_1_PAN = 4 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E20_2_PAN = 5 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E2 = 6 | ARM_MMU_IDX_A,
+ ARMMMUIdx_E3 = 7 | ARM_MMU_IDX_A,
/*
* These are not allocated TLBs and are used only for AT system
@@ -2982,9 +2978,6 @@ typedef enum ARMMMUIdx {
ARMMMUIdx_Stage1_E0 = 0 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1 = 1 | ARM_MMU_IDX_NOTLB,
ARMMMUIdx_Stage1_E1_PAN = 2 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage1_SE0 = 3 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage1_SE1 = 4 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage1_SE1_PAN = 5 | ARM_MMU_IDX_NOTLB,
/*
* Not allocated a TLB: used only for second stage of an S12 page
* table walk, or for descriptor loads during first stage of an S1
@@ -2992,8 +2985,8 @@ typedef enum ARMMMUIdx {
* then various TLB flush insns which currently are no-ops or flush
* only stage 1 MMU indexes will need to change to flush stage 2.
*/
- ARMMMUIdx_Stage2 = 6 | ARM_MMU_IDX_NOTLB,
- ARMMMUIdx_Stage2_S = 7 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage2 = 3 | ARM_MMU_IDX_NOTLB,
+ ARMMMUIdx_Stage2_S = 4 | ARM_MMU_IDX_NOTLB,
/*
* M-profile.
@@ -3023,14 +3016,7 @@ typedef enum ARMMMUIdxBit {
TO_CORE_BIT(E2),
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(E3),
TO_CORE_BIT(MUser),
TO_CORE_BIT(MPriv),
@@ -3203,6 +3189,8 @@ FIELD(TBFLAG_M32, NEW_FP_CTXT_NEEDED, 3, 1) /* Not cached. */
FIELD(TBFLAG_M32, FPCCR_S_WRONG, 4, 1) /* Not cached. */
/* Set if MVE insns are definitely not predicated by VPR or LTPSIZE */
FIELD(TBFLAG_M32, MVE_NO_PRED, 5, 1) /* Not cached. */
+/* Set if in secure mode */
+FIELD(TBFLAG_M32, SECURE, 6, 1)
/*
* Bit usage when in AArch64 state
@@ -4109,6 +4097,39 @@ static inline bool isar_feature_aa64_tgran16_2_lpa2(const ARMISARegisters *id)
return t >= 3 || (t == 0 && isar_feature_aa64_tgran16_lpa2(id));
}
+static inline bool isar_feature_aa64_tgran4(const ARMISARegisters *id)
+{
+ return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 0;
+}
+
+static inline bool isar_feature_aa64_tgran16(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16) >= 1;
+}
+
+static inline bool isar_feature_aa64_tgran64(const ARMISARegisters *id)
+{
+ return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64) >= 0;
+}
+
+static inline bool isar_feature_aa64_tgran4_2(const ARMISARegisters *id)
+{
+ unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4_2);
+ return t >= 2 || (t == 0 && isar_feature_aa64_tgran4(id));
+}
+
+static inline bool isar_feature_aa64_tgran16_2(const ARMISARegisters *id)
+{
+ unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN16_2);
+ return t >= 2 || (t == 0 && isar_feature_aa64_tgran16(id));
+}
+
+static inline bool isar_feature_aa64_tgran64_2(const ARMISARegisters *id)
+{
+ unsigned t = FIELD_EX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN64_2);
+ return t >= 2 || (t == 0 && isar_feature_aa64_tgran64(id));
+}
+
static inline bool isar_feature_aa64_ccidx(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64mmfr2, ID_AA64MMFR2, CCIDX) != 0;
diff --git a/target/arm/helper.c b/target/arm/helper.c
index db3b1ea..dde64a4 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -1752,8 +1752,9 @@ static void vbar_write(CPUARMState *env, const ARMCPRegInfo *ri,
static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
{
/* Begin with base v8.0 state. */
- uint32_t valid_mask = 0x3fff;
+ uint64_t valid_mask = 0x3fff;
ARMCPU *cpu = env_archcpu(env);
+ uint64_t changed;
/*
* Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always
@@ -1789,6 +1790,9 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
if (cpu_isar_feature(aa64_doublefault, cpu)) {
valid_mask |= SCR_EASE | SCR_NMEA;
}
+ if (cpu_isar_feature(aa64_sme, cpu)) {
+ valid_mask |= SCR_ENTP2;
+ }
} else {
valid_mask &= ~(SCR_RW | SCR_ST);
if (cpu_isar_feature(aa32_ras, cpu)) {
@@ -1813,7 +1817,22 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
/* Clear all-context RES0 bits. */
value &= valid_mask;
- raw_write(env, ri, value);
+ changed = env->cp15.scr_el3 ^ value;
+ env->cp15.scr_el3 = value;
+
+ /*
+ * If SCR_EL3.NS changes, i.e. arm_is_secure_below_el3, then
+ * we must invalidate all TLBs below EL3.
+ */
+ if (changed & SCR_NS) {
+ tlb_flush_by_mmuidx(env_cpu(env), (ARMMMUIdxBit_E10_0 |
+ ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E2));
+ }
}
static void scr_reset(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -2644,9 +2663,6 @@ 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;
@@ -2659,9 +2675,6 @@ 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;
@@ -3188,7 +3201,8 @@ static CPAccessResult ats_access(CPUARMState *env, const ARMCPRegInfo *ri,
#ifdef CONFIG_TCG
static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
- MMUAccessType access_type, ARMMMUIdx mmu_idx)
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
+ bool is_secure)
{
bool ret;
uint64_t par64;
@@ -3196,7 +3210,8 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
ARMMMUFaultInfo fi = {};
GetPhysAddrResult res = {};
- ret = get_phys_addr(env, value, access_type, mmu_idx, &res, &fi);
+ ret = get_phys_addr_with_secure(env, value, access_type, mmu_idx,
+ is_secure, &res, &fi);
/*
* ATS operations only do S1 or S1+S2 translations, so we never
@@ -3308,8 +3323,8 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
/* Create a 64-bit PAR */
par64 = (1 << 11); /* LPAE bit always set */
if (!ret) {
- par64 |= res.phys & ~0xfffULL;
- if (!res.attrs.secure) {
+ par64 |= res.f.phys_addr & ~0xfffULL;
+ if (!res.f.attrs.secure) {
par64 |= (1 << 9); /* NS */
}
par64 |= (uint64_t)res.cacheattrs.attrs << 56; /* ATTR */
@@ -3333,13 +3348,13 @@ static uint64_t do_ats_write(CPUARMState *env, uint64_t value,
*/
if (!ret) {
/* We do not set any attribute bits in the PAR */
- if (res.page_size == (1 << 24)
+ if (res.f.lg_page_size == 24
&& arm_feature(env, ARM_FEATURE_V7)) {
- par64 = (res.phys & 0xff000000) | (1 << 1);
+ par64 = (res.f.phys_addr & 0xff000000) | (1 << 1);
} else {
- par64 = res.phys & 0xfffff000;
+ par64 = res.f.phys_addr & 0xfffff000;
}
- if (!res.attrs.secure) {
+ if (!res.f.attrs.secure) {
par64 |= (1 << 9); /* NS */
}
} else {
@@ -3367,17 +3382,17 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
/* stage 1 current state PL1: ATS1CPR, ATS1CPW, ATS1CPRP, ATS1CPWP */
switch (el) {
case 3:
- mmu_idx = ARMMMUIdx_SE3;
+ mmu_idx = ARMMMUIdx_E3;
+ secure = true;
break;
case 2:
g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
/* fall through */
case 1:
if (ri->crm == 9 && (env->uncached_cpsr & CPSR_PAN)) {
- mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN
- : ARMMMUIdx_Stage1_E1_PAN);
+ mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
} else {
- mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1;
+ mmu_idx = ARMMMUIdx_Stage1_E1;
}
break;
default:
@@ -3388,14 +3403,15 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
/* stage 1 current state PL0: ATS1CUR, ATS1CUW */
switch (el) {
case 3:
- mmu_idx = ARMMMUIdx_SE10_0;
+ mmu_idx = ARMMMUIdx_E10_0;
+ secure = true;
break;
case 2:
g_assert(!secure); /* ARMv8.4-SecEL2 is 64-bit only */
mmu_idx = ARMMMUIdx_Stage1_E0;
break;
case 1:
- mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0;
+ mmu_idx = ARMMMUIdx_Stage1_E0;
break;
default:
g_assert_not_reached();
@@ -3404,16 +3420,18 @@ static void ats_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
case 4:
/* stage 1+2 NonSecure PL1: ATS12NSOPR, ATS12NSOPW */
mmu_idx = ARMMMUIdx_E10_1;
+ secure = false;
break;
case 6:
/* stage 1+2 NonSecure PL0: ATS12NSOUR, ATS12NSOUW */
mmu_idx = ARMMMUIdx_E10_0;
+ secure = false;
break;
default:
g_assert_not_reached();
}
- par64 = do_ats_write(env, value, access_type, mmu_idx);
+ par64 = do_ats_write(env, value, access_type, mmu_idx, secure);
A32_BANKED_CURRENT_REG_SET(env, par, par64);
#else
@@ -3429,7 +3447,8 @@ static void ats1h_write(CPUARMState *env, const ARMCPRegInfo *ri,
MMUAccessType access_type = ri->opc2 & 1 ? MMU_DATA_STORE : MMU_DATA_LOAD;
uint64_t par64;
- par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2);
+ /* There is no SecureEL2 for AArch32. */
+ par64 = do_ats_write(env, value, access_type, ARMMMUIdx_E2, false);
A32_BANKED_CURRENT_REG_SET(env, par, par64);
#else
@@ -3461,36 +3480,37 @@ static void ats_write64(CPUARMState *env, const ARMCPRegInfo *ri,
switch (ri->opc1) {
case 0: /* AT S1E1R, AT S1E1W, AT S1E1RP, AT S1E1WP */
if (ri->crm == 9 && (env->pstate & PSTATE_PAN)) {
- mmu_idx = (secure ? ARMMMUIdx_Stage1_SE1_PAN
- : ARMMMUIdx_Stage1_E1_PAN);
+ mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
} else {
- mmu_idx = secure ? ARMMMUIdx_Stage1_SE1 : ARMMMUIdx_Stage1_E1;
+ mmu_idx = ARMMMUIdx_Stage1_E1;
}
break;
case 4: /* AT S1E2R, AT S1E2W */
- mmu_idx = secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2;
+ mmu_idx = ARMMMUIdx_E2;
break;
case 6: /* AT S1E3R, AT S1E3W */
- mmu_idx = ARMMMUIdx_SE3;
+ mmu_idx = ARMMMUIdx_E3;
+ secure = true;
break;
default:
g_assert_not_reached();
}
break;
case 2: /* AT S1E0R, AT S1E0W */
- mmu_idx = secure ? ARMMMUIdx_Stage1_SE0 : ARMMMUIdx_Stage1_E0;
+ mmu_idx = ARMMMUIdx_Stage1_E0;
break;
case 4: /* AT S12E1R, AT S12E1W */
- mmu_idx = secure ? ARMMMUIdx_SE10_1 : ARMMMUIdx_E10_1;
+ mmu_idx = ARMMMUIdx_E10_1;
break;
case 6: /* AT S12E0R, AT S12E0W */
- mmu_idx = secure ? ARMMMUIdx_SE10_0 : ARMMMUIdx_E10_0;
+ mmu_idx = ARMMMUIdx_E10_0;
break;
default:
g_assert_not_reached();
}
- env->cp15.par_el[1] = do_ats_write(env, value, access_type, mmu_idx);
+ env->cp15.par_el[1] = do_ats_write(env, value, access_type,
+ mmu_idx, secure);
#else
/* Handled by hardware accelerator. */
g_assert_not_reached();
@@ -3753,11 +3773,6 @@ static void vmsa_tcr_ttbr_el2_write(CPUARMState *env, const ARMCPRegInfo *ri,
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);
@@ -3777,11 +3792,6 @@ static void vttbr_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint16_t mask = ARMMMUIdxBit_E10_1 |
ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0;
-
- if (arm_is_secure_below_el3(env)) {
- mask >>= ARM_MMU_IDX_A_NS;
- }
-
tlb_flush_by_mmuidx(cs, mask);
raw_write(env, ri, value);
}
@@ -4252,11 +4262,6 @@ static int vae1_tlbmask(CPUARMState *env)
ARMMMUIdxBit_E10_1_PAN |
ARMMMUIdxBit_E10_0;
}
-
- if (arm_is_secure_below_el3(env)) {
- mask >>= ARM_MMU_IDX_A_NS;
- }
-
return mask;
}
@@ -4283,10 +4288,6 @@ static int vae1_tlbbits(CPUARMState *env, uint64_t addr)
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);
}
@@ -4319,30 +4320,17 @@ static int alle1_tlbmask(CPUARMState *env)
* stage 2 translations, whereas most other scopes only invalidate
* stage 1 translations.
*/
- if (arm_is_secure_below_el3(env)) {
- return ARMMMUIdxBit_SE10_1 |
- ARMMMUIdxBit_SE10_1_PAN |
- ARMMMUIdxBit_SE10_0;
- } else {
- return ARMMMUIdxBit_E10_1 |
- ARMMMUIdxBit_E10_1_PAN |
- ARMMMUIdxBit_E10_0;
- }
+ return (ARMMMUIdxBit_E10_1 |
+ ARMMMUIdxBit_E10_1_PAN |
+ ARMMMUIdxBit_E10_0);
}
static int e2_tlbmask(CPUARMState *env)
{
- 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;
- }
+ return (ARMMMUIdxBit_E20_0 |
+ ARMMMUIdxBit_E20_2 |
+ ARMMMUIdxBit_E20_2_PAN |
+ ARMMMUIdxBit_E2);
}
static void tlbi_aa64_alle1_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4369,7 +4357,7 @@ static void tlbi_aa64_alle3_write(CPUARMState *env, const ARMCPRegInfo *ri,
ARMCPU *cpu = env_archcpu(env);
CPUState *cs = CPU(cpu);
- tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_SE3);
+ tlb_flush_by_mmuidx(cs, ARMMMUIdxBit_E3);
}
static void tlbi_aa64_alle1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4395,7 +4383,7 @@ static void tlbi_aa64_alle3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
- tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_SE3);
+ tlb_flush_by_mmuidx_all_cpus_synced(cs, ARMMMUIdxBit_E3);
}
static void tlbi_aa64_vae2_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4423,7 +4411,7 @@ static void tlbi_aa64_vae3_write(CPUARMState *env, const ARMCPRegInfo *ri,
CPUState *cs = CPU(cpu);
uint64_t pageaddr = sextract64(value << 12, 0, 56);
- tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_SE3);
+ tlb_flush_page_by_mmuidx(cs, pageaddr, ARMMMUIdxBit_E3);
}
static void tlbi_aa64_vae1is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4462,12 +4450,10 @@ static void tlbi_aa64_vae2is_write(CPUARMState *env, const ARMCPRegInfo *ri,
{
CPUState *cs = env_cpu(env);
uint64_t pageaddr = sextract64(value << 12, 0, 56);
- bool secure = arm_is_secure_below_el3(env);
- int mask = secure ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2;
- int bits = tlbbits_for_regime(env, secure ? ARMMMUIdx_SE2 : ARMMMUIdx_E2,
- pageaddr);
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E2, pageaddr);
- tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr, mask, bits);
+ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
+ ARMMMUIdxBit_E2, bits);
}
static void tlbi_aa64_vae3is_write(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -4475,10 +4461,10 @@ static void tlbi_aa64_vae3is_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_SE3, pageaddr);
+ int bits = tlbbits_for_regime(env, ARMMMUIdx_E3, pageaddr);
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(cs, pageaddr,
- ARMMMUIdxBit_SE3, bits);
+ ARMMMUIdxBit_E3, bits);
}
#ifdef TARGET_AARCH64
@@ -4487,6 +4473,24 @@ typedef struct {
uint64_t length;
} TLBIRange;
+static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg)
+{
+ /*
+ * Note that the TLBI range TG field encoding differs from both
+ * TG0 and TG1 encodings.
+ */
+ switch (tg) {
+ case 1:
+ return Gran4K;
+ case 2:
+ return Gran16K;
+ case 3:
+ return Gran64K;
+ default:
+ return GranInvalid;
+ }
+}
+
static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
uint64_t value)
{
@@ -4495,17 +4499,19 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, ARMMMUIdx mmuidx,
uint64_t select = sextract64(value, 36, 1);
ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true);
TLBIRange ret = { };
+ ARMGranuleSize gran;
page_size_granule = extract64(value, 46, 2);
+ gran = tlbi_range_tg_to_gran_size(page_size_granule);
/* The granule encoded in value must match the granule in use. */
- if (page_size_granule != (param.using64k ? 3 : param.using16k ? 2 : 1)) {
+ if (gran != param.gran) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n",
page_size_granule);
return ret;
}
- page_shift = (page_size_granule - 1) * 2 + 12;
+ page_shift = arm_granule_bits(gran);
num = extract64(value, 39, 5);
scale = extract64(value, 44, 2);
exponent = (5 * scale) + 1;
@@ -4584,8 +4590,7 @@ static void tlbi_aa64_rvae1is_write(CPUARMState *env,
static int vae2_tlbmask(CPUARMState *env)
{
- return (arm_is_secure_below_el3(env)
- ? ARMMMUIdxBit_SE2 : ARMMMUIdxBit_E2);
+ return ARMMMUIdxBit_E2;
}
static void tlbi_aa64_rvae2_write(CPUARMState *env,
@@ -4631,8 +4636,7 @@ static void tlbi_aa64_rvae3_write(CPUARMState *env,
* flush-last-level-only.
*/
- do_rvae_write(env, value, ARMMMUIdxBit_SE3,
- tlb_force_broadcast(env));
+ do_rvae_write(env, value, ARMMMUIdxBit_E3, tlb_force_broadcast(env));
}
static void tlbi_aa64_rvae3is_write(CPUARMState *env,
@@ -4646,7 +4650,7 @@ static void tlbi_aa64_rvae3is_write(CPUARMState *env,
* flush-last-level-only or inner/outer specific flushes.
*/
- do_rvae_write(env, value, ARMMMUIdxBit_SE3, true);
+ do_rvae_write(env, value, ARMMMUIdxBit_E3, true);
}
#endif
@@ -5245,15 +5249,15 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri,
}
/*
- * Return the effective value of HCR_EL2.
+ * Return the effective value of HCR_EL2, at the given security state.
* Bits that are not included here:
* RW (read from SCR_EL3.RW as needed)
*/
-uint64_t arm_hcr_el2_eff(CPUARMState *env)
+uint64_t arm_hcr_el2_eff_secstate(CPUARMState *env, bool secure)
{
uint64_t ret = env->cp15.hcr_el2;
- if (!arm_is_el2_enabled(env)) {
+ if (!arm_is_el2_enabled_secstate(env, secure)) {
/*
* "This register has no effect if EL2 is not enabled in the
* current Security state". This is ARMv8.4-SecEL2 speak for
@@ -5312,6 +5316,11 @@ uint64_t arm_hcr_el2_eff(CPUARMState *env)
return ret;
}
+uint64_t arm_hcr_el2_eff(CPUARMState *env)
+{
+ return arm_hcr_el2_eff_secstate(env, arm_is_secure_below_el3(env));
+}
+
/*
* Corresponds to ARM pseudocode function ELIsInHost().
*/
@@ -10259,8 +10268,7 @@ 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 || mmu_idx == ARMMMUIdx_SE20_0)
- ? 2 : 1;
+ el = mmu_idx == ARMMMUIdx_E20_0 ? 2 : 1;
}
return env->cp15.sctlr_el[el];
}
@@ -10299,20 +10307,105 @@ static int aa64_va_parameter_tcma(uint64_t tcr, ARMMMUIdx mmu_idx)
}
}
+static ARMGranuleSize tg0_to_gran_size(int tg)
+{
+ switch (tg) {
+ case 0:
+ return Gran4K;
+ case 1:
+ return Gran64K;
+ case 2:
+ return Gran16K;
+ default:
+ return GranInvalid;
+ }
+}
+
+static ARMGranuleSize tg1_to_gran_size(int tg)
+{
+ switch (tg) {
+ case 1:
+ return Gran16K;
+ case 2:
+ return Gran4K;
+ case 3:
+ return Gran64K;
+ default:
+ return GranInvalid;
+ }
+}
+
+static inline bool have4k(ARMCPU *cpu, bool stage2)
+{
+ return stage2 ? cpu_isar_feature(aa64_tgran4_2, cpu)
+ : cpu_isar_feature(aa64_tgran4, cpu);
+}
+
+static inline bool have16k(ARMCPU *cpu, bool stage2)
+{
+ return stage2 ? cpu_isar_feature(aa64_tgran16_2, cpu)
+ : cpu_isar_feature(aa64_tgran16, cpu);
+}
+
+static inline bool have64k(ARMCPU *cpu, bool stage2)
+{
+ return stage2 ? cpu_isar_feature(aa64_tgran64_2, cpu)
+ : cpu_isar_feature(aa64_tgran64, cpu);
+}
+
+static ARMGranuleSize sanitize_gran_size(ARMCPU *cpu, ARMGranuleSize gran,
+ bool stage2)
+{
+ switch (gran) {
+ case Gran4K:
+ if (have4k(cpu, stage2)) {
+ return gran;
+ }
+ break;
+ case Gran16K:
+ if (have16k(cpu, stage2)) {
+ return gran;
+ }
+ break;
+ case Gran64K:
+ if (have64k(cpu, stage2)) {
+ return gran;
+ }
+ break;
+ case GranInvalid:
+ break;
+ }
+ /*
+ * If the guest selects a granule size that isn't implemented,
+ * the architecture requires that we behave as if it selected one
+ * that is (with an IMPDEF choice of which one to pick). We choose
+ * to implement the smallest supported granule size.
+ */
+ if (have4k(cpu, stage2)) {
+ return Gran4K;
+ }
+ if (have16k(cpu, stage2)) {
+ return Gran16K;
+ }
+ assert(have64k(cpu, stage2));
+ return Gran64K;
+}
+
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ARMMMUIdx mmu_idx, bool data)
{
uint64_t tcr = regime_tcr(env, mmu_idx);
- bool epd, hpd, using16k, using64k, tsz_oob, ds;
+ bool epd, hpd, tsz_oob, ds;
int select, tsz, tbi, max_tsz, min_tsz, ps, sh;
+ ARMGranuleSize gran;
ARMCPU *cpu = env_archcpu(env);
+ bool stage2 = mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S;
if (!regime_has_2_ranges(mmu_idx)) {
select = 0;
tsz = extract32(tcr, 0, 6);
- using64k = extract32(tcr, 14, 1);
- using16k = extract32(tcr, 15, 1);
- if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
+ gran = tg0_to_gran_size(extract32(tcr, 14, 2));
+ if (stage2) {
/* VTCR_EL2 */
hpd = false;
} else {
@@ -10330,16 +10423,13 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
select = extract64(va, 55, 1);
if (!select) {
tsz = extract32(tcr, 0, 6);
+ gran = tg0_to_gran_size(extract32(tcr, 14, 2));
epd = extract32(tcr, 7, 1);
sh = extract32(tcr, 12, 2);
- using64k = extract32(tcr, 14, 1);
- using16k = extract32(tcr, 15, 1);
hpd = extract64(tcr, 41, 1);
} else {
- int tg = extract32(tcr, 30, 2);
- using16k = tg == 1;
- using64k = tg == 3;
tsz = extract32(tcr, 16, 6);
+ gran = tg1_to_gran_size(extract32(tcr, 30, 2));
epd = extract32(tcr, 23, 1);
sh = extract32(tcr, 28, 2);
hpd = extract64(tcr, 42, 1);
@@ -10348,8 +10438,10 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
ds = extract64(tcr, 59, 1);
}
+ gran = sanitize_gran_size(cpu, gran, stage2);
+
if (cpu_isar_feature(aa64_st, cpu)) {
- max_tsz = 48 - using64k;
+ max_tsz = 48 - (gran == Gran64K);
} else {
max_tsz = 39;
}
@@ -10359,7 +10451,7 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
* adjust the effective value of DS, as documented.
*/
min_tsz = 16;
- if (using64k) {
+ if (gran == Gran64K) {
if (cpu_isar_feature(aa64_lva, cpu)) {
min_tsz = 12;
}
@@ -10368,14 +10460,14 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
switch (mmu_idx) {
case ARMMMUIdx_Stage2:
case ARMMMUIdx_Stage2_S:
- if (using16k) {
+ if (gran == Gran16K) {
ds = cpu_isar_feature(aa64_tgran16_2_lpa2, cpu);
} else {
ds = cpu_isar_feature(aa64_tgran4_2_lpa2, cpu);
}
break;
default:
- if (using16k) {
+ if (gran == Gran16K) {
ds = cpu_isar_feature(aa64_tgran16_lpa2, cpu);
} else {
ds = cpu_isar_feature(aa64_tgran4_lpa2, cpu);
@@ -10412,10 +10504,9 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
.tbi = tbi,
.epd = epd,
.hpd = hpd,
- .using16k = using16k,
- .using64k = using64k,
.tsz_oob = tsz_oob,
.ds = ds,
+ .gran = gran,
};
}
@@ -10804,22 +10895,15 @@ int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx)
switch (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:
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
return 1;
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:
+ case ARMMMUIdx_E3:
return 3;
default:
g_assert_not_reached();
@@ -10872,15 +10956,11 @@ ARMMMUIdx arm_mmu_idx_el(CPUARMState *env, int el)
}
break;
case 3:
- return ARMMMUIdx_SE3;
+ return ARMMMUIdx_E3;
default:
g_assert_not_reached();
}
- if (arm_is_secure_below_el3(env)) {
- idx &= ~ARM_MMU_IDX_A_NS;
- }
-
return idx;
}
@@ -10945,6 +11025,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
DP_TBFLAG_M32(flags, STACKCHECK, 1);
}
+ if (arm_feature(env, ARM_FEATURE_M_SECURITY) && env->v7m.secure) {
+ DP_TBFLAG_M32(flags, SECURE, 1);
+ }
+
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
}
@@ -11079,15 +11163,11 @@ static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
switch (mmu_idx) {
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
/* TODO: ARMv8.3-NV */
DP_TBFLAG_A64(flags, UNPRIV, 1);
break;
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
- 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.
diff --git a/target/arm/internals.h b/target/arm/internals.h
index 307a596..9566364 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -649,78 +649,24 @@ static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_Stage1_SE0:
- case ARMMMUIdx_Stage1_SE1:
- case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
- case ARMMMUIdx_SE10_0:
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
- case ARMMMUIdx_SE20_0:
- case ARMMMUIdx_SE20_2:
- case ARMMMUIdx_SE20_2_PAN:
return true;
default:
return false;
}
}
-/* Return true if this address translation regime is secure */
-static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
-{
- switch (mmu_idx) {
- case ARMMMUIdx_E10_0:
- case ARMMMUIdx_E10_1:
- case ARMMMUIdx_E10_1_PAN:
- case ARMMMUIdx_E20_0:
- case ARMMMUIdx_E20_2:
- case ARMMMUIdx_E20_2_PAN:
- case ARMMMUIdx_Stage1_E0:
- case ARMMMUIdx_Stage1_E1:
- case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_E2:
- case ARMMMUIdx_Stage2:
- case ARMMMUIdx_MPrivNegPri:
- case ARMMMUIdx_MUserNegPri:
- case ARMMMUIdx_MPriv:
- case ARMMMUIdx_MUser:
- return false;
- case ARMMMUIdx_SE3:
- case ARMMMUIdx_SE10_0:
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
- case ARMMMUIdx_SE20_0:
- case ARMMMUIdx_SE20_2:
- case ARMMMUIdx_SE20_2_PAN:
- case ARMMMUIdx_Stage1_SE0:
- case ARMMMUIdx_Stage1_SE1:
- case ARMMMUIdx_Stage1_SE1_PAN:
- case ARMMMUIdx_SE2:
- case ARMMMUIdx_Stage2_S:
- case ARMMMUIdx_MSPrivNegPri:
- case ARMMMUIdx_MSUserNegPri:
- case ARMMMUIdx_MSPriv:
- case ARMMMUIdx_MSUser:
- return true;
- default:
- g_assert_not_reached();
- }
-}
-
static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_Stage1_SE1_PAN:
case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_E20_2_PAN:
- case ARMMMUIdx_SE10_1_PAN:
- case ARMMMUIdx_SE20_2_PAN:
return true;
default:
return false;
@@ -731,30 +677,20 @@ static inline bool regime_is_pan(CPUARMState *env, ARMMMUIdx mmu_idx)
static inline uint32_t regime_el(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
- case ARMMMUIdx_SE20_0:
- case ARMMMUIdx_SE20_2:
- case ARMMMUIdx_SE20_2_PAN:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_E20_2_PAN:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_Stage2_S:
- case ARMMMUIdx_SE2:
case ARMMMUIdx_E2:
return 2;
- case ARMMMUIdx_SE3:
+ case ARMMMUIdx_E3:
return 3;
- case ARMMMUIdx_SE10_0:
- case ARMMMUIdx_Stage1_SE0:
- return arm_el_is_aa64(env, 3) ? 1 : 3;
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
+ case ARMMMUIdx_E10_0:
case ARMMMUIdx_Stage1_E0:
+ return arm_el_is_aa64(env, 3) || !arm_is_secure_below_el3(env) ? 1 : 3;
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_Stage1_SE1:
- case ARMMMUIdx_Stage1_SE1_PAN:
- case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
case ARMMMUIdx_MPrivNegPri:
@@ -996,9 +932,6 @@ static inline bool arm_mmu_idx_is_stage1_of_2(ARMMMUIdx mmu_idx)
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_Stage1_E1_PAN:
- case ARMMMUIdx_Stage1_SE0:
- case ARMMMUIdx_Stage1_SE1:
- case ARMMMUIdx_Stage1_SE1_PAN:
return true;
default:
return false;
@@ -1065,6 +998,35 @@ static inline uint32_t aarch64_pstate_valid_mask(const ARMISARegisters *id)
return valid;
}
+/* Granule size (i.e. page size) */
+typedef enum ARMGranuleSize {
+ /* Same order as TG0 encoding */
+ Gran4K,
+ Gran64K,
+ Gran16K,
+ GranInvalid,
+} ARMGranuleSize;
+
+/**
+ * arm_granule_bits: Return address size of the granule in bits
+ *
+ * Return the address size of the granule in bits. This corresponds
+ * to the pseudocode TGxGranuleBits().
+ */
+static inline int arm_granule_bits(ARMGranuleSize gran)
+{
+ switch (gran) {
+ case Gran64K:
+ return 16;
+ case Gran16K:
+ return 14;
+ case Gran4K:
+ return 12;
+ default:
+ g_assert_not_reached();
+ }
+}
+
/*
* Parameters of a given virtual address, as extracted from the
* translation control register (TCR) for a given regime.
@@ -1077,10 +1039,9 @@ typedef struct ARMVAParameters {
bool tbi : 1;
bool epd : 1;
bool hpd : 1;
- bool using16k : 1;
- bool using64k : 1;
bool tsz_oob : 1; /* tsz has been clamped to legal range */
bool ds : 1;
+ ARMGranuleSize gran : 2;
} ARMVAParameters;
ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
@@ -1138,13 +1099,50 @@ typedef struct ARMCacheAttrs {
/* Fields that are valid upon success. */
typedef struct GetPhysAddrResult {
- hwaddr phys;
- target_ulong page_size;
- int prot;
- MemTxAttrs attrs;
+ CPUTLBEntryFull f;
ARMCacheAttrs cacheattrs;
} GetPhysAddrResult;
+/**
+ * get_phys_addr_with_secure: get the physical address for a virtual address
+ * @env: CPUARMState
+ * @address: virtual address to get physical address for
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @mmu_idx: MMU index indicating required translation regime
+ * @is_secure: security state for the access
+ * @result: set on translation success.
+ * @fi: set to fault info if the translation fails
+ *
+ * Find the physical address corresponding to the given virtual address,
+ * by doing a translation table walk on MMU based systems or using the
+ * MPU state on MPU based systems.
+ *
+ * Returns false if the translation was successful. Otherwise, phys_ptr, attrs,
+ * prot and page_size may not be filled in, and the populated fsr value provides
+ * information on why the translation aborted, in the format of a
+ * DFSR/IFSR fault register, with the following caveats:
+ * * we honour the short vs long DFSR format differences.
+ * * the WnR bit is never set (the caller must do this).
+ * * for PSMAv5 based systems we don't bother to return a full FSR format
+ * value.
+ */
+bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
+ MMUAccessType access_type,
+ ARMMMUIdx mmu_idx, bool is_secure,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
+ __attribute__((nonnull));
+
+/**
+ * get_phys_addr: get the physical address for a virtual address
+ * @env: CPUARMState
+ * @address: virtual address to get physical address for
+ * @access_type: 0 for read, 1 for write, 2 for execute
+ * @mmu_idx: MMU index indicating required translation regime
+ * @result: set on translation success.
+ * @fi: set to fault info if the translation fails
+ *
+ * Similarly, but use the security regime of @mmu_idx.
+ */
bool get_phys_addr(CPUARMState *env, target_ulong address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index e5c1bd5..1e4de9b 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -79,7 +79,9 @@ bool kvm_arm_create_scratch_host_vcpu(const uint32_t *cpus_to_try,
if (max_vm_pa_size < 0) {
max_vm_pa_size = 0;
}
- vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size);
+ do {
+ vmfd = ioctl(kvmfd, KVM_CREATE_VM, max_vm_pa_size);
+ } while (vmfd == -1 && errno == EINTR);
if (vmfd < 0) {
goto err;
}
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 5ee4ee1..355cd4d 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -223,8 +223,8 @@ static bool v7m_stack_write(ARMCPU *cpu, uint32_t addr, uint32_t value,
}
goto pend_fault;
}
- address_space_stl_le(arm_addressspace(cs, res.attrs), res.phys, value,
- res.attrs, &txres);
+ address_space_stl_le(arm_addressspace(cs, res.f.attrs), res.f.phys_addr,
+ value, res.f.attrs, &txres);
if (txres != MEMTX_OK) {
/* BusFault trying to write the data */
if (mode == STACK_LAZYFP) {
@@ -298,8 +298,8 @@ static bool v7m_stack_read(ARMCPU *cpu, uint32_t *dest, uint32_t addr,
goto pend_fault;
}
- value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys,
- res.attrs, &txres);
+ value = address_space_ldl(arm_addressspace(cs, res.f.attrs),
+ res.f.phys_addr, res.f.attrs, &txres);
if (txres != MEMTX_OK) {
/* BusFault trying to read the data */
qemu_log_mask(CPU_LOG_INT, "...BusFault with BFSR.UNSTKERR\n");
@@ -1981,7 +1981,7 @@ static bool do_v7m_function_return(ARMCPU *cpu)
return true;
}
-static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
+static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx, bool secure,
uint32_t addr, uint16_t *insn)
{
/*
@@ -2003,8 +2003,7 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
ARMMMUFaultInfo fi = {};
MemTxResult txres;
- v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx,
- regime_is_secure(env, mmu_idx), &sattrs);
+ v8m_security_lookup(env, addr, MMU_INST_FETCH, mmu_idx, secure, &sattrs);
if (!sattrs.nsc || sattrs.ns) {
/*
* This must be the second half of the insn, and it straddles a
@@ -2023,8 +2022,8 @@ static bool v7m_read_half_insn(ARMCPU *cpu, ARMMMUIdx mmu_idx,
qemu_log_mask(CPU_LOG_INT, "...really MemManage with CFSR.IACCVIOL\n");
return false;
}
- *insn = address_space_lduw_le(arm_addressspace(cs, res.attrs), res.phys,
- res.attrs, &txres);
+ *insn = address_space_lduw_le(arm_addressspace(cs, res.f.attrs),
+ res.f.phys_addr, res.f.attrs, &txres);
if (txres != MEMTX_OK) {
env->v7m.cfsr[M_REG_NS] |= R_V7M_CFSR_IBUSERR_MASK;
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_BUS, false);
@@ -2070,8 +2069,8 @@ static bool v7m_read_sg_stack_word(ARMCPU *cpu, ARMMMUIdx mmu_idx,
}
return false;
}
- value = address_space_ldl(arm_addressspace(cs, res.attrs), res.phys,
- res.attrs, &txres);
+ value = address_space_ldl(arm_addressspace(cs, res.f.attrs),
+ res.f.phys_addr, res.f.attrs, &txres);
if (txres != MEMTX_OK) {
/* BusFault trying to read the data */
qemu_log_mask(CPU_LOG_INT,
@@ -2109,7 +2108,7 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
/* We want to do the MPU lookup as secure; work out what mmu_idx that is */
mmu_idx = arm_v7m_mmu_idx_for_secstate(env, true);
- if (!v7m_read_half_insn(cpu, mmu_idx, env->regs[15], &insn)) {
+ if (!v7m_read_half_insn(cpu, mmu_idx, true, env->regs[15], &insn)) {
return false;
}
@@ -2125,7 +2124,7 @@ static bool v7m_handle_execute_nsc(ARMCPU *cpu)
goto gen_invep;
}
- if (!v7m_read_half_insn(cpu, mmu_idx, env->regs[15] + 2, &insn)) {
+ if (!v7m_read_half_insn(cpu, mmu_idx, true, env->regs[15] + 2, &insn)) {
return false;
}
@@ -2818,8 +2817,8 @@ uint32_t HELPER(v7m_tt)(CPUARMState *env, uint32_t addr, uint32_t op)
} else {
mrvalid = true;
}
- r = res.prot & PAGE_READ;
- rw = res.prot & PAGE_WRITE;
+ r = res.f.prot & PAGE_READ;
+ rw = res.f.prot & PAGE_WRITE;
} else {
r = false;
rw = false;
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 2ddfc02..23f16f4 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -16,8 +16,8 @@
static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool s1_is_el0, GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+ bool is_secure, bool s1_is_el0,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
__attribute__((nonnull));
/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
@@ -65,12 +65,6 @@ unsigned int arm_pamax(ARMCPU *cpu)
ARMMMUIdx stage_1_mmu_idx(ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
- case ARMMMUIdx_SE10_0:
- return ARMMMUIdx_Stage1_SE0;
- case ARMMMUIdx_SE10_1:
- return ARMMMUIdx_Stage1_SE1;
- case ARMMMUIdx_SE10_1_PAN:
- return ARMMMUIdx_Stage1_SE1_PAN;
case ARMMMUIdx_E10_0:
return ARMMMUIdx_Stage1_E0;
case ARMMMUIdx_E10_1:
@@ -95,11 +89,8 @@ static bool regime_translation_big_endian(CPUARMState *env, ARMMMUIdx mmu_idx)
static 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_Stage1_SE0:
case ARMMMUIdx_MUser:
case ARMMMUIdx_MSUser:
case ARMMMUIdx_MUserNegPri:
@@ -131,12 +122,13 @@ static uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, int ttbrn)
}
/* Return true if the specified stage of address translation is disabled */
-static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx)
+static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx,
+ bool is_secure)
{
uint64_t hcr_el2;
if (arm_feature(env, ARM_FEATURE_M)) {
- switch (env->v7m.mpu_ctrl[regime_is_secure(env, mmu_idx)] &
+ switch (env->v7m.mpu_ctrl[is_secure] &
(R_V7M_MPU_CTRL_ENABLE_MASK | R_V7M_MPU_CTRL_HFNMIENA_MASK)) {
case R_V7M_MPU_CTRL_ENABLE_MASK:
/* Enabled, but not for HardFault and NMI */
@@ -154,29 +146,47 @@ static bool regime_translation_disabled(CPUARMState *env, ARMMMUIdx mmu_idx)
}
}
- hcr_el2 = arm_hcr_el2_eff(env);
+ hcr_el2 = arm_hcr_el2_eff_secstate(env, is_secure);
- if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
+ switch (mmu_idx) {
+ case ARMMMUIdx_Stage2:
+ case ARMMMUIdx_Stage2_S:
/* HCR.DC means HCR.VM behaves as 1 */
return (hcr_el2 & (HCR_DC | HCR_VM)) == 0;
- }
- if (hcr_el2 & HCR_TGE) {
- /* TGE means that NS EL0/1 act as if SCTLR_EL1.M is zero */
- if (!regime_is_secure(env, mmu_idx) && regime_el(env, mmu_idx) == 1) {
+ case ARMMMUIdx_E10_0:
+ case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
+ /* TGE means that EL0/1 act as if SCTLR_EL1.M is zero */
+ if (hcr_el2 & HCR_TGE) {
return true;
}
- }
+ break;
- if ((hcr_el2 & HCR_DC) && arm_mmu_idx_is_stage1_of_2(mmu_idx)) {
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
/* HCR.DC means SCTLR_EL1.M behaves as 0 */
- return true;
+ if (hcr_el2 & HCR_DC) {
+ return true;
+ }
+ break;
+
+ case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_E2:
+ case ARMMMUIdx_E3:
+ break;
+
+ default:
+ g_assert_not_reached();
}
return (regime_sctlr(env, mmu_idx) & SCTLR_M) == 0;
}
-static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs)
+static bool ptw_attrs_are_device(uint64_t hcr, ARMCacheAttrs cacheattrs)
{
/*
* For an S1 page table walk, the stage 1 attributes are always
@@ -188,7 +198,7 @@ static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs)
* when cacheattrs.attrs bit [2] is 0.
*/
assert(cacheattrs.is_s2_format);
- if (arm_hcr_el2_eff(env) & HCR_FWB) {
+ if (hcr & HCR_FWB) {
return (cacheattrs.attrs & 0x4) == 0;
} else {
return (cacheattrs.attrs & 0xc) == 0;
@@ -197,28 +207,31 @@ static bool ptw_attrs_are_device(CPUARMState *env, ARMCacheAttrs cacheattrs)
/* Translate a S1 pagetable walk through S2 if needed. */
static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
- hwaddr addr, bool *is_secure,
+ hwaddr addr, bool *is_secure_ptr,
ARMMMUFaultInfo *fi)
{
+ bool is_secure = *is_secure_ptr;
+ ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
+
if (arm_mmu_idx_is_stage1_of_2(mmu_idx) &&
- !regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
- ARMMMUIdx s2_mmu_idx = *is_secure ? ARMMMUIdx_Stage2_S
- : ARMMMUIdx_Stage2;
+ !regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
GetPhysAddrResult s2 = {};
+ uint64_t hcr;
int ret;
- ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx, false,
- &s2, fi);
+ ret = get_phys_addr_lpae(env, addr, MMU_DATA_LOAD, s2_mmu_idx,
+ is_secure, false, &s2, fi);
if (ret) {
assert(fi->type != ARMFault_None);
fi->s2addr = addr;
fi->stage2 = true;
fi->s1ptw = true;
- fi->s1ns = !*is_secure;
+ fi->s1ns = !is_secure;
return ~0;
}
- if ((arm_hcr_el2_eff(env) & HCR_PTW) &&
- ptw_attrs_are_device(env, s2.cacheattrs)) {
+
+ hcr = arm_hcr_el2_eff_secstate(env, is_secure);
+ if ((hcr & HCR_PTW) && ptw_attrs_are_device(hcr, s2.cacheattrs)) {
/*
* PTW set and S1 walk touched S2 Device memory:
* generate Permission fault.
@@ -227,22 +240,23 @@ static hwaddr S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
fi->s2addr = addr;
fi->stage2 = true;
fi->s1ptw = true;
- fi->s1ns = !*is_secure;
+ fi->s1ns = !is_secure;
return ~0;
}
if (arm_is_secure_below_el3(env)) {
/* Check if page table walk is to secure or non-secure PA space. */
- if (*is_secure) {
- *is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
+ if (is_secure) {
+ is_secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
} else {
- *is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
+ is_secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
}
+ *is_secure_ptr = is_secure;
} else {
- assert(!*is_secure);
+ assert(!is_secure);
}
- addr = s2.phys;
+ addr = s2.f.phys_addr;
}
return addr;
}
@@ -462,7 +476,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
/* 1Mb section. */
phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
ap = (desc >> 10) & 3;
- result->page_size = 1024 * 1024;
+ result->f.lg_page_size = 20; /* 1MB */
} else {
/* Lookup l2 entry. */
if (type == 1) {
@@ -483,12 +497,12 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
case 1: /* 64k page. */
phys_addr = (desc & 0xffff0000) | (address & 0xffff);
ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
- result->page_size = 0x10000;
+ result->f.lg_page_size = 16;
break;
case 2: /* 4k page. */
phys_addr = (desc & 0xfffff000) | (address & 0xfff);
ap = (desc >> (4 + ((address >> 9) & 6))) & 3;
- result->page_size = 0x1000;
+ result->f.lg_page_size = 12;
break;
case 3: /* 1k page, or ARMv6/XScale "extended small (4k) page" */
if (type == 1) {
@@ -496,7 +510,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
if (arm_feature(env, ARM_FEATURE_XSCALE)
|| arm_feature(env, ARM_FEATURE_V6)) {
phys_addr = (desc & 0xfffff000) | (address & 0xfff);
- result->page_size = 0x1000;
+ result->f.lg_page_size = 12;
} else {
/*
* UNPREDICTABLE in ARMv5; we choose to take a
@@ -507,7 +521,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
}
} else {
phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
- result->page_size = 0x400;
+ result->f.lg_page_size = 10;
}
ap = (desc >> 4) & 3;
break;
@@ -516,14 +530,14 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
g_assert_not_reached();
}
}
- result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
- result->prot |= result->prot ? PAGE_EXEC : 0;
- if (!(result->prot & (1 << access_type))) {
+ result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
+ result->f.prot |= result->f.prot ? PAGE_EXEC : 0;
+ if (!(result->f.prot & (1 << access_type))) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
}
- result->phys = phys_addr;
+ result->f.phys_addr = phys_addr;
return false;
do_fault:
fi->domain = domain;
@@ -593,11 +607,11 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
phys_addr = (desc & 0xff000000) | (address & 0x00ffffff);
phys_addr |= (uint64_t)extract32(desc, 20, 4) << 32;
phys_addr |= (uint64_t)extract32(desc, 5, 4) << 36;
- result->page_size = 0x1000000;
+ result->f.lg_page_size = 24; /* 16MB */
} else {
/* Section. */
phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
- result->page_size = 0x100000;
+ result->f.lg_page_size = 20; /* 1MB */
}
ap = ((desc >> 10) & 3) | ((desc >> 13) & 4);
xn = desc & (1 << 4);
@@ -622,12 +636,12 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
case 1: /* 64k page. */
phys_addr = (desc & 0xffff0000) | (address & 0xffff);
xn = desc & (1 << 15);
- result->page_size = 0x10000;
+ result->f.lg_page_size = 16;
break;
case 2: case 3: /* 4k page. */
phys_addr = (desc & 0xfffff000) | (address & 0xfff);
xn = desc & 1;
- result->page_size = 0x1000;
+ result->f.lg_page_size = 12;
break;
default:
/* Never happens, but compiler isn't smart enough to tell. */
@@ -635,7 +649,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
}
}
if (domain_prot == 3) {
- result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
} else {
if (pxn && !regime_is_user(env, mmu_idx)) {
xn = 1;
@@ -653,14 +667,14 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
fi->type = ARMFault_AccessFlag;
goto do_fault;
}
- result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
+ result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
} else {
- result->prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
+ result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
}
- if (result->prot && !xn) {
- result->prot |= PAGE_EXEC;
+ if (result->f.prot && !xn) {
+ result->f.prot |= PAGE_EXEC;
}
- if (!(result->prot & (1 << access_type))) {
+ if (!(result->f.prot & (1 << access_type))) {
/* Access permission fault. */
fi->type = ARMFault_Permission;
goto do_fault;
@@ -671,9 +685,9 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
* the CPU doesn't support TZ or this is a non-secure translation
* regime, because the attribute will already be non-secure.
*/
- result->attrs.secure = false;
+ result->f.attrs.secure = false;
}
- result->phys = phys_addr;
+ result->f.phys_addr = phys_addr;
return false;
do_fault:
fi->domain = domain;
@@ -965,8 +979,8 @@ static bool check_s2_mmu_setup(ARMCPU *cpu, bool is_aa64, int level,
*/
static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool s1_is_el0, GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+ bool is_secure, bool s1_is_el0,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
{
ARMCPU *cpu = env_archcpu(env);
/* Read an LPAE long-descriptor translation table. */
@@ -1048,13 +1062,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
}
}
- if (param.using64k) {
- stride = 13;
- } else if (param.using16k) {
- stride = 11;
- } else {
- stride = 9;
- }
+ stride = arm_granule_bits(param.gran) - 3;
/*
* Note that QEMU ignores shareability and cacheability attributes,
@@ -1183,7 +1191,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
* remain non-secure. We implement this by just ORing in the NSTable/NS
* bits at each step.
*/
- tableattrs = regime_is_secure(env, mmu_idx) ? 0 : (1 << 4);
+ tableattrs = is_secure ? 0 : (1 << 4);
for (;;) {
uint64_t descriptor;
bool nstable;
@@ -1284,16 +1292,16 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
ns = mmu_idx == ARMMMUIdx_Stage2;
xn = extract32(attrs, 11, 2);
- result->prot = get_S2prot(env, ap, xn, s1_is_el0);
+ result->f.prot = get_S2prot(env, ap, xn, s1_is_el0);
} else {
ns = extract32(attrs, 3, 1);
xn = extract32(attrs, 12, 1);
pxn = extract32(attrs, 11, 1);
- result->prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
+ result->f.prot = get_S1prot(env, mmu_idx, aarch64, ap, ns, xn, pxn);
}
fault_type = ARMFault_Permission;
- if (!(result->prot & (1 << access_type))) {
+ if (!(result->f.prot & (1 << access_type))) {
goto do_fault;
}
@@ -1303,11 +1311,11 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
* the CPU doesn't support TZ or this is a non-secure translation
* regime, because the attribute will already be non-secure.
*/
- result->attrs.secure = false;
+ result->f.attrs.secure = false;
}
/* When in aarch64 mode, and BTI is enabled, remember GP in the IOTLB. */
if (aarch64 && guarded && cpu_isar_feature(aa64_bti, cpu)) {
- arm_tlb_bti_gp(&result->attrs) = true;
+ arm_tlb_bti_gp(&result->f.attrs) = true;
}
if (mmu_idx == ARMMMUIdx_Stage2 || mmu_idx == ARMMMUIdx_Stage2_S) {
@@ -1333,8 +1341,8 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
result->cacheattrs.shareability = extract32(attrs, 6, 2);
}
- result->phys = descaddr;
- result->page_size = page_size;
+ result->f.phys_addr = descaddr;
+ result->f.lg_page_size = ctz64(page_size);
return false;
do_fault:
@@ -1357,14 +1365,14 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
uint32_t base;
bool is_user = regime_is_user(env, mmu_idx);
- if (regime_translation_disabled(env, mmu_idx)) {
+ if (regime_translation_disabled(env, mmu_idx, is_secure)) {
/* MPU disabled. */
- result->phys = address;
- result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ result->f.phys_addr = address;
+ result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return false;
}
- result->phys = address;
+ result->f.phys_addr = address;
for (n = 7; n >= 0; n--) {
base = env->cp15.c6_region[n];
if ((base & 1) == 0) {
@@ -1400,16 +1408,16 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
fi->level = 1;
return true;
}
- result->prot = PAGE_READ | PAGE_WRITE;
+ result->f.prot = PAGE_READ | PAGE_WRITE;
break;
case 2:
- result->prot = PAGE_READ;
+ result->f.prot = PAGE_READ;
if (!is_user) {
- result->prot |= PAGE_WRITE;
+ result->f.prot |= PAGE_WRITE;
}
break;
case 3:
- result->prot = PAGE_READ | PAGE_WRITE;
+ result->f.prot = PAGE_READ | PAGE_WRITE;
break;
case 5:
if (is_user) {
@@ -1417,10 +1425,10 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
fi->level = 1;
return true;
}
- result->prot = PAGE_READ;
+ result->f.prot = PAGE_READ;
break;
case 6:
- result->prot = PAGE_READ;
+ result->f.prot = PAGE_READ;
break;
default:
/* Bad permission. */
@@ -1428,12 +1436,12 @@ static bool get_phys_addr_pmsav5(CPUARMState *env, uint32_t address,
fi->level = 1;
return true;
}
- result->prot |= PAGE_EXEC;
+ result->f.prot |= PAGE_EXEC;
return false;
}
static void get_phys_addr_pmsav7_default(CPUARMState *env, ARMMMUIdx mmu_idx,
- int32_t address, int *prot)
+ int32_t address, uint8_t *prot)
{
if (!arm_feature(env, ARM_FEATURE_M)) {
*prot = PAGE_READ | PAGE_WRITE;
@@ -1517,11 +1525,11 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
int n;
bool is_user = regime_is_user(env, mmu_idx);
- result->phys = address;
- result->page_size = TARGET_PAGE_SIZE;
- result->prot = 0;
+ result->f.phys_addr = address;
+ result->f.lg_page_size = TARGET_PAGE_BITS;
+ result->f.prot = 0;
- if (regime_translation_disabled(env, mmu_idx) ||
+ if (regime_translation_disabled(env, mmu_idx, secure) ||
m_is_ppb_region(env, address)) {
/*
* MPU disabled or M profile PPB access: use default memory map.
@@ -1531,7 +1539,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
* which always does a direct read using address_space_ldl(), rather
* than going via this function, so we don't need to check that here.
*/
- get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot);
+ get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->f.prot);
} else { /* MPU enabled */
for (n = (int)cpu->pmsav7_dregion - 1; n >= 0; n--) {
/* region search */
@@ -1573,7 +1581,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
if (ranges_overlap(base, rmask,
address & TARGET_PAGE_MASK,
TARGET_PAGE_SIZE)) {
- result->page_size = 1;
+ result->f.lg_page_size = 0;
}
continue;
}
@@ -1611,7 +1619,7 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
continue;
}
if (rsize < TARGET_PAGE_BITS) {
- result->page_size = 1 << rsize;
+ result->f.lg_page_size = rsize;
}
break;
}
@@ -1622,7 +1630,8 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
fi->type = ARMFault_Background;
return true;
}
- get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot);
+ get_phys_addr_pmsav7_default(env, mmu_idx, address,
+ &result->f.prot);
} else { /* a MPU hit! */
uint32_t ap = extract32(env->pmsav7.dracr[n], 8, 3);
uint32_t xn = extract32(env->pmsav7.dracr[n], 12, 1);
@@ -1639,16 +1648,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
case 5:
break; /* no access */
case 3:
- result->prot |= PAGE_WRITE;
+ result->f.prot |= PAGE_WRITE;
/* fall through */
case 2:
case 6:
- result->prot |= PAGE_READ | PAGE_EXEC;
+ result->f.prot |= PAGE_READ | PAGE_EXEC;
break;
case 7:
/* for v7M, same as 6; for R profile a reserved value */
if (arm_feature(env, ARM_FEATURE_M)) {
- result->prot |= PAGE_READ | PAGE_EXEC;
+ result->f.prot |= PAGE_READ | PAGE_EXEC;
break;
}
/* fall through */
@@ -1664,16 +1673,16 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
case 1:
case 2:
case 3:
- result->prot |= PAGE_WRITE;
+ result->f.prot |= PAGE_WRITE;
/* fall through */
case 5:
case 6:
- result->prot |= PAGE_READ | PAGE_EXEC;
+ result->f.prot |= PAGE_READ | PAGE_EXEC;
break;
case 7:
/* for v7M, same as 6; for R profile a reserved value */
if (arm_feature(env, ARM_FEATURE_M)) {
- result->prot |= PAGE_READ | PAGE_EXEC;
+ result->f.prot |= PAGE_READ | PAGE_EXEC;
break;
}
/* fall through */
@@ -1686,14 +1695,14 @@ static bool get_phys_addr_pmsav7(CPUARMState *env, uint32_t address,
/* execute never */
if (xn) {
- result->prot &= ~PAGE_EXEC;
+ result->f.prot &= ~PAGE_EXEC;
}
}
}
fi->type = ARMFault_Permission;
fi->level = 1;
- return !(result->prot & (1 << access_type));
+ return !(result->f.prot & (1 << access_type));
}
bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
@@ -1719,9 +1728,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
uint32_t addr_page_base = address & TARGET_PAGE_MASK;
uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
- result->page_size = TARGET_PAGE_SIZE;
- result->phys = address;
- result->prot = 0;
+ result->f.lg_page_size = TARGET_PAGE_BITS;
+ result->f.phys_addr = address;
+ result->f.prot = 0;
if (mregion) {
*mregion = -1;
}
@@ -1733,7 +1742,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
* are done in arm_v7m_load_vector(), which always does a direct
* read using address_space_ldl(), rather than going via this function.
*/
- if (regime_translation_disabled(env, mmu_idx)) { /* MPU disabled */
+ if (regime_translation_disabled(env, mmu_idx, secure)) { /* MPU disabled */
hit = true;
} else if (m_is_ppb_region(env, address)) {
hit = true;
@@ -1771,13 +1780,13 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
ranges_overlap(base, limit - base + 1,
addr_page_base,
TARGET_PAGE_SIZE)) {
- result->page_size = 1;
+ result->f.lg_page_size = 0;
}
continue;
}
if (base > addr_page_base || limit < addr_page_limit) {
- result->page_size = 1;
+ result->f.lg_page_size = 0;
}
if (matchregion != -1) {
@@ -1803,7 +1812,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
if (matchregion == -1) {
/* hit using the background region */
- get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->prot);
+ get_phys_addr_pmsav7_default(env, mmu_idx, address, &result->f.prot);
} else {
uint32_t ap = extract32(env->pmsav8.rbar[secure][matchregion], 1, 2);
uint32_t xn = extract32(env->pmsav8.rbar[secure][matchregion], 0, 1);
@@ -1818,9 +1827,9 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
xn = 1;
}
- result->prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
- if (result->prot && !xn && !(pxn && !is_user)) {
- result->prot |= PAGE_EXEC;
+ result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap);
+ if (result->f.prot && !xn && !(pxn && !is_user)) {
+ result->f.prot |= PAGE_EXEC;
}
/*
* We don't need to look the attribute up in the MAIR0/MAIR1
@@ -1833,7 +1842,7 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
fi->type = ARMFault_Permission;
fi->level = 1;
- return !(result->prot & (1 << access_type));
+ return !(result->f.prot & (1 << access_type));
}
static bool v8m_is_sau_exempt(CPUARMState *env,
@@ -1997,9 +2006,9 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
} else {
fi->type = ARMFault_QEMU_SFault;
}
- result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE;
- result->phys = address;
- result->prot = 0;
+ result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS;
+ result->f.phys_addr = address;
+ result->f.prot = 0;
return true;
}
} else {
@@ -2009,7 +2018,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
* might downgrade a secure access to nonsecure.
*/
if (sattrs.ns) {
- result->attrs.secure = false;
+ result->f.attrs.secure = false;
} else if (!secure) {
/*
* NS access to S memory must fault.
@@ -2022,9 +2031,9 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
* for M_FAKE_FSR_SFAULT in arm_v7m_cpu_do_interrupt().
*/
fi->type = ARMFault_QEMU_SFault;
- result->page_size = sattrs.subpage ? 1 : TARGET_PAGE_SIZE;
- result->phys = address;
- result->prot = 0;
+ result->f.lg_page_size = sattrs.subpage ? 0 : TARGET_PAGE_BITS;
+ result->f.phys_addr = address;
+ result->f.prot = 0;
return true;
}
}
@@ -2033,7 +2042,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
ret = pmsav8_mpu_lookup(env, address, access_type, mmu_idx, secure,
result, fi, NULL);
if (sattrs.subpage) {
- result->page_size = 1;
+ result->f.lg_page_size = 0;
}
return ret;
}
@@ -2047,14 +2056,14 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
* ref: shared/translation/attrs/S2AttrDecode()
* .../S2ConvertAttrsHints()
*/
-static uint8_t convert_stage2_attrs(CPUARMState *env, uint8_t s2attrs)
+static uint8_t convert_stage2_attrs(uint64_t hcr, uint8_t s2attrs)
{
uint8_t hiattr = extract32(s2attrs, 2, 2);
uint8_t loattr = extract32(s2attrs, 0, 2);
uint8_t hihint = 0, lohint = 0;
if (hiattr != 0) { /* normal memory */
- if (arm_hcr_el2_eff(env) & HCR_CD) { /* cache disabled */
+ if (hcr & HCR_CD) { /* cache disabled */
hiattr = loattr = 1; /* non-cacheable */
} else {
if (hiattr != 1) { /* Write-through or write-back */
@@ -2100,12 +2109,12 @@ static uint8_t combine_cacheattr_nibble(uint8_t s1, uint8_t s2)
* s1 and s2 for the HCR_EL2.FWB == 0 case, returning the
* combined attributes in MAIR_EL1 format.
*/
-static uint8_t combined_attrs_nofwb(CPUARMState *env,
+static uint8_t combined_attrs_nofwb(uint64_t hcr,
ARMCacheAttrs s1, ARMCacheAttrs s2)
{
uint8_t s1lo, s2lo, s1hi, s2hi, s2_mair_attrs, ret_attrs;
- s2_mair_attrs = convert_stage2_attrs(env, s2.attrs);
+ s2_mair_attrs = convert_stage2_attrs(hcr, s2.attrs);
s1lo = extract32(s1.attrs, 0, 4);
s2lo = extract32(s2_mair_attrs, 0, 4);
@@ -2160,8 +2169,7 @@ static uint8_t force_cacheattr_nibble_wb(uint8_t attr)
* s1 and s2 for the HCR_EL2.FWB == 1 case, returning the
* combined attributes in MAIR_EL1 format.
*/
-static uint8_t combined_attrs_fwb(CPUARMState *env,
- ARMCacheAttrs s1, ARMCacheAttrs s2)
+static uint8_t combined_attrs_fwb(ARMCacheAttrs s1, ARMCacheAttrs s2)
{
switch (s2.attrs) {
case 7:
@@ -2206,7 +2214,7 @@ static uint8_t combined_attrs_fwb(CPUARMState *env,
* @s1: Attributes from stage 1 walk
* @s2: Attributes from stage 2 walk
*/
-static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
+static ARMCacheAttrs combine_cacheattrs(uint64_t hcr,
ARMCacheAttrs s1, ARMCacheAttrs s2)
{
ARMCacheAttrs ret;
@@ -2233,10 +2241,10 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
}
/* Combine memory type and cacheability attributes */
- if (arm_hcr_el2_eff(env) & HCR_FWB) {
- ret.attrs = combined_attrs_fwb(env, s1, s2);
+ if (hcr & HCR_FWB) {
+ ret.attrs = combined_attrs_fwb(s1, s2);
} else {
- ret.attrs = combined_attrs_nofwb(env, s1, s2);
+ ret.attrs = combined_attrs_nofwb(hcr, s1, s2);
}
/*
@@ -2259,35 +2267,86 @@ static ARMCacheAttrs combine_cacheattrs(CPUARMState *env,
return ret;
}
-/**
- * get_phys_addr - get the physical address for this virtual address
- *
- * Find the physical address corresponding to the given virtual address,
- * by doing a translation table walk on MMU based systems or using the
- * MPU state on MPU based systems.
- *
- * Returns false if the translation was successful. Otherwise, phys_ptr, attrs,
- * prot and page_size may not be filled in, and the populated fsr value provides
- * information on why the translation aborted, in the format of a
- * DFSR/IFSR fault register, with the following caveats:
- * * we honour the short vs long DFSR format differences.
- * * the WnR bit is never set (the caller must do this).
- * * for PSMAv5 based systems we don't bother to return a full FSR format
- * value.
- *
- * @env: CPUARMState
- * @address: virtual address to get physical address for
- * @access_type: 0 for read, 1 for write, 2 for execute
- * @mmu_idx: MMU index indicating required translation regime
- * @result: set on translation success.
- * @fi: set to fault info if the translation fails
+/*
+ * MMU disabled. S1 addresses within aa64 translation regimes are
+ * still checked for bounds -- see AArch64.S1DisabledOutput().
*/
-bool get_phys_addr(CPUARMState *env, target_ulong address,
- MMUAccessType access_type, ARMMMUIdx mmu_idx,
- GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
+static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
+ MMUAccessType access_type,
+ ARMMMUIdx mmu_idx, bool is_secure,
+ GetPhysAddrResult *result,
+ ARMMMUFaultInfo *fi)
+{
+ uint8_t memattr = 0x00; /* Device nGnRnE */
+ uint8_t shareability = 0; /* non-sharable */
+
+ if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) {
+ int r_el = regime_el(env, mmu_idx);
+
+ if (arm_el_is_aa64(env, r_el)) {
+ int pamax = arm_pamax(env_archcpu(env));
+ uint64_t tcr = env->cp15.tcr_el[r_el];
+ int addrtop, tbi;
+
+ tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
+ if (access_type == MMU_INST_FETCH) {
+ tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
+ }
+ tbi = (tbi >> extract64(address, 55, 1)) & 1;
+ addrtop = (tbi ? 55 : 63);
+
+ if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
+ fi->type = ARMFault_AddressSize;
+ fi->level = 0;
+ fi->stage2 = false;
+ return 1;
+ }
+
+ /*
+ * When TBI is disabled, we've just validated that all of the
+ * bits above PAMax are zero, so logically we only need to
+ * clear the top byte for TBI. But it's clearer to follow
+ * the pseudocode set of addrdesc.paddress.
+ */
+ address = extract64(address, 0, 52);
+ }
+
+ /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */
+ if (r_el == 1) {
+ uint64_t hcr = arm_hcr_el2_eff_secstate(env, is_secure);
+ if (hcr & HCR_DC) {
+ if (hcr & HCR_DCT) {
+ memattr = 0xf0; /* Tagged, Normal, WB, RWA */
+ } else {
+ memattr = 0xff; /* Normal, WB, RWA */
+ }
+ }
+ }
+ if (memattr == 0 && access_type == MMU_INST_FETCH) {
+ if (regime_sctlr(env, mmu_idx) & SCTLR_I) {
+ memattr = 0xee; /* Normal, WT, RA, NT */
+ } else {
+ memattr = 0x44; /* Normal, NC, No */
+ }
+ shareability = 2; /* outer sharable */
+ }
+ result->cacheattrs.is_s2_format = false;
+ }
+
+ result->f.phys_addr = address;
+ result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
+ result->f.lg_page_size = TARGET_PAGE_BITS;
+ result->cacheattrs.shareability = shareability;
+ result->cacheattrs.attrs = memattr;
+ return 0;
+}
+
+bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
+ bool is_secure, GetPhysAddrResult *result,
+ ARMMMUFaultInfo *fi)
{
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
- bool is_secure = regime_is_secure(env, mmu_idx);
if (mmu_idx != s1_mmu_idx) {
/*
@@ -2298,50 +2357,52 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
hwaddr ipa;
int s1_prot;
int ret;
- bool ipa_secure;
+ bool ipa_secure, s2walk_secure;
ARMCacheAttrs cacheattrs1;
ARMMMUIdx s2_mmu_idx;
bool is_el0;
+ uint64_t hcr;
- ret = get_phys_addr(env, address, access_type, s1_mmu_idx,
- result, fi);
+ ret = get_phys_addr_with_secure(env, address, access_type,
+ s1_mmu_idx, is_secure, result, fi);
/* If S1 fails or S2 is disabled, return early. */
- if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2)) {
+ if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
+ is_secure)) {
return ret;
}
- ipa = result->phys;
- ipa_secure = result->attrs.secure;
- if (arm_is_secure_below_el3(env)) {
- if (ipa_secure) {
- result->attrs.secure = !(env->cp15.vstcr_el2 & VSTCR_SW);
- } else {
- result->attrs.secure = !(env->cp15.vtcr_el2 & VTCR_NSW);
- }
+ ipa = result->f.phys_addr;
+ ipa_secure = result->f.attrs.secure;
+ if (is_secure) {
+ /* Select TCR based on the NS bit from the S1 walk. */
+ s2walk_secure = !(ipa_secure
+ ? env->cp15.vstcr_el2 & VSTCR_SW
+ : env->cp15.vtcr_el2 & VTCR_NSW);
} else {
assert(!ipa_secure);
+ s2walk_secure = false;
}
- s2_mmu_idx = (result->attrs.secure
+ s2_mmu_idx = (s2walk_secure
? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2);
- is_el0 = mmu_idx == ARMMMUIdx_E10_0 || mmu_idx == ARMMMUIdx_SE10_0;
+ is_el0 = mmu_idx == ARMMMUIdx_E10_0;
/*
* S1 is done, now do S2 translation.
* Save the stage1 results so that we may merge
* prot and cacheattrs later.
*/
- s1_prot = result->prot;
+ s1_prot = result->f.prot;
cacheattrs1 = result->cacheattrs;
memset(result, 0, sizeof(*result));
ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
- is_el0, result, fi);
+ s2walk_secure, is_el0, result, fi);
fi->s2addr = ipa;
/* Combine the S1 and S2 perms. */
- result->prot &= s1_prot;
+ result->f.prot &= s1_prot;
/* If S2 fails, return early. */
if (ret) {
@@ -2349,7 +2410,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
}
/* Combine the S1 and S2 cache attributes. */
- if (arm_hcr_el2_eff(env) & HCR_DC) {
+ hcr = arm_hcr_el2_eff_secstate(env, is_secure);
+ if (hcr & HCR_DC) {
/*
* HCR.DC forces the first stage attributes to
* Normal Non-Shareable,
@@ -2362,20 +2424,19 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
}
cacheattrs1.shareability = 0;
}
- result->cacheattrs = combine_cacheattrs(env, cacheattrs1,
+ result->cacheattrs = combine_cacheattrs(hcr, cacheattrs1,
result->cacheattrs);
- /* Check if IPA translates to secure or non-secure PA space. */
- if (arm_is_secure_below_el3(env)) {
- if (ipa_secure) {
- result->attrs.secure =
- !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW));
- } else {
- result->attrs.secure =
- !((env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))
- || (env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW)));
- }
- }
+ /*
+ * Check if IPA translates to secure or non-secure PA space.
+ * Note that VSTCR overrides VTCR and {N}SW overrides {N}SA.
+ */
+ result->f.attrs.secure =
+ (is_secure
+ && !(env->cp15.vstcr_el2 & (VSTCR_SA | VSTCR_SW))
+ && (ipa_secure
+ || !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
+
return 0;
} else {
/*
@@ -2390,8 +2451,8 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
* cannot upgrade an non-secure translation regime's attributes
* to secure.
*/
- result->attrs.secure = is_secure;
- result->attrs.user = regime_is_user(env, mmu_idx);
+ result->f.attrs.secure = is_secure;
+ result->f.attrs.user = regime_is_user(env, mmu_idx);
/*
* Fast Context Switch Extension. This doesn't exist at all in v8.
@@ -2408,7 +2469,7 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
if (arm_feature(env, ARM_FEATURE_PMSA)) {
bool ret;
- result->page_size = TARGET_PAGE_SIZE;
+ result->f.lg_page_size = TARGET_PAGE_BITS;
if (arm_feature(env, ARM_FEATURE_V8)) {
/* PMSAv8 */
@@ -2429,84 +2490,22 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
(access_type == MMU_DATA_STORE ? "writing" : "execute"),
(uint32_t)address, mmu_idx,
ret ? "Miss" : "Hit",
- result->prot & PAGE_READ ? 'r' : '-',
- result->prot & PAGE_WRITE ? 'w' : '-',
- result->prot & PAGE_EXEC ? 'x' : '-');
+ result->f.prot & PAGE_READ ? 'r' : '-',
+ result->f.prot & PAGE_WRITE ? 'w' : '-',
+ result->f.prot & PAGE_EXEC ? 'x' : '-');
return ret;
}
/* Definitely a real MMU, not an MPU */
- if (regime_translation_disabled(env, mmu_idx)) {
- uint64_t hcr;
- uint8_t memattr;
-
- /*
- * MMU disabled. S1 addresses within aa64 translation regimes are
- * still checked for bounds -- see AArch64.TranslateAddressS1Off.
- */
- if (mmu_idx != ARMMMUIdx_Stage2 && mmu_idx != ARMMMUIdx_Stage2_S) {
- int r_el = regime_el(env, mmu_idx);
- if (arm_el_is_aa64(env, r_el)) {
- int pamax = arm_pamax(env_archcpu(env));
- uint64_t tcr = env->cp15.tcr_el[r_el];
- int addrtop, tbi;
-
- tbi = aa64_va_parameter_tbi(tcr, mmu_idx);
- if (access_type == MMU_INST_FETCH) {
- tbi &= ~aa64_va_parameter_tbid(tcr, mmu_idx);
- }
- tbi = (tbi >> extract64(address, 55, 1)) & 1;
- addrtop = (tbi ? 55 : 63);
-
- if (extract64(address, pamax, addrtop - pamax + 1) != 0) {
- fi->type = ARMFault_AddressSize;
- fi->level = 0;
- fi->stage2 = false;
- return 1;
- }
-
- /*
- * When TBI is disabled, we've just validated that all of the
- * bits above PAMax are zero, so logically we only need to
- * clear the top byte for TBI. But it's clearer to follow
- * the pseudocode set of addrdesc.paddress.
- */
- address = extract64(address, 0, 52);
- }
- }
- result->phys = address;
- result->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
- result->page_size = TARGET_PAGE_SIZE;
-
- /* Fill in cacheattr a-la AArch64.TranslateAddressS1Off. */
- hcr = arm_hcr_el2_eff(env);
- result->cacheattrs.shareability = 0;
- result->cacheattrs.is_s2_format = false;
- if (hcr & HCR_DC) {
- if (hcr & HCR_DCT) {
- memattr = 0xf0; /* Tagged, Normal, WB, RWA */
- } else {
- memattr = 0xff; /* Normal, WB, RWA */
- }
- } else if (access_type == MMU_INST_FETCH) {
- if (regime_sctlr(env, mmu_idx) & SCTLR_I) {
- memattr = 0xee; /* Normal, WT, RA, NT */
- } else {
- memattr = 0x44; /* Normal, NC, No */
- }
- result->cacheattrs.shareability = 2; /* outer sharable */
- } else {
- memattr = 0x00; /* Device, nGnRnE */
- }
- result->cacheattrs.attrs = memattr;
- return 0;
+ if (regime_translation_disabled(env, mmu_idx, is_secure)) {
+ return get_phys_addr_disabled(env, address, access_type, mmu_idx,
+ is_secure, result, fi);
}
-
if (regime_using_lpae_format(env, mmu_idx)) {
- return get_phys_addr_lpae(env, address, access_type, mmu_idx, false,
- result, fi);
+ return get_phys_addr_lpae(env, address, access_type, mmu_idx,
+ is_secure, false, result, fi);
} else if (regime_sctlr(env, mmu_idx) & SCTLR_XP) {
return get_phys_addr_v6(env, address, access_type, mmu_idx,
is_secure, result, fi);
@@ -2516,6 +2515,47 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
}
}
+bool get_phys_addr(CPUARMState *env, target_ulong address,
+ MMUAccessType access_type, ARMMMUIdx mmu_idx,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
+{
+ bool is_secure;
+
+ switch (mmu_idx) {
+ case ARMMMUIdx_E10_0:
+ case ARMMMUIdx_E10_1:
+ case ARMMMUIdx_E10_1_PAN:
+ case ARMMMUIdx_E20_0:
+ case ARMMMUIdx_E20_2:
+ case ARMMMUIdx_E20_2_PAN:
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
+ case ARMMMUIdx_E2:
+ is_secure = arm_is_secure_below_el3(env);
+ break;
+ case ARMMMUIdx_Stage2:
+ case ARMMMUIdx_MPrivNegPri:
+ case ARMMMUIdx_MUserNegPri:
+ case ARMMMUIdx_MPriv:
+ case ARMMMUIdx_MUser:
+ is_secure = false;
+ break;
+ case ARMMMUIdx_E3:
+ case ARMMMUIdx_Stage2_S:
+ case ARMMMUIdx_MSPrivNegPri:
+ case ARMMMUIdx_MSUserNegPri:
+ case ARMMMUIdx_MSPriv:
+ case ARMMMUIdx_MSUser:
+ is_secure = true;
+ break;
+ default:
+ g_assert_not_reached();
+ }
+ return get_phys_addr_with_secure(env, address, access_type, mmu_idx,
+ is_secure, result, fi);
+}
+
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
MemTxAttrs *attrs)
{
@@ -2527,10 +2567,10 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
bool ret;
ret = get_phys_addr(env, addr, MMU_DATA_LOAD, mmu_idx, &res, &fi);
- *attrs = res.attrs;
+ *attrs = res.f.attrs;
if (ret) {
return -1;
}
- return res.phys;
+ return res.f.phys_addr;
}
diff --git a/target/arm/tlb_helper.c b/target/arm/tlb_helper.c
index ad225b1..4960139 100644
--- a/target/arm/tlb_helper.c
+++ b/target/arm/tlb_helper.c
@@ -227,17 +227,16 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
* target page size are handled specially, so for those we
* pass in the exact addresses.
*/
- if (res.page_size >= TARGET_PAGE_SIZE) {
- res.phys &= TARGET_PAGE_MASK;
+ if (res.f.lg_page_size >= TARGET_PAGE_BITS) {
+ res.f.phys_addr &= TARGET_PAGE_MASK;
address &= TARGET_PAGE_MASK;
}
/* Notice and record tagged memory. */
if (cpu_isar_feature(aa64_mte, cpu) && res.cacheattrs.attrs == 0xf0) {
- arm_tlb_mte_tagged(&res.attrs) = true;
+ arm_tlb_mte_tagged(&res.f.attrs) = true;
}
- tlb_set_page_with_attrs(cs, address, res.phys, res.attrs,
- res.prot, mmu_idx, res.page_size);
+ tlb_set_page_full(cs, mmu_idx, address, &res.f);
return true;
} else if (probe) {
return false;
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index 78b2d91..5b67375 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -111,14 +111,6 @@ static int get_a64_user_mem_index(DisasContext *s)
case ARMMMUIdx_E20_2_PAN:
useridx = ARMMMUIdx_E20_0;
break;
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
- useridx = ARMMMUIdx_SE10_0;
- break;
- case ARMMMUIdx_SE20_2:
- case ARMMMUIdx_SE20_2_PAN:
- useridx = ARMMMUIdx_SE20_0;
- break;
default:
g_assert_not_reached();
}
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 5aaccbb..2f72afe 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -237,16 +237,12 @@ static inline int get_a32_user_mem_index(DisasContext *s)
* otherwise, access as if at PL0.
*/
switch (s->mmu_idx) {
+ case ARMMMUIdx_E3:
case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E10_1_PAN:
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
- case ARMMMUIdx_SE3:
- case ARMMMUIdx_SE10_0:
- case ARMMMUIdx_SE10_1:
- case ARMMMUIdx_SE10_1_PAN:
- return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
case ARMMMUIdx_MUser:
case ARMMMUIdx_MPriv:
return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
@@ -9351,8 +9347,7 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->vfp_enabled = 1;
dc->be_data = MO_TE;
dc->v7m_handler_mode = EX_TBFLAG_M32(tb_flags, HANDLER);
- dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
- regime_is_secure(env, dc->mmu_idx);
+ dc->v8m_secure = EX_TBFLAG_M32(tb_flags, SECURE);
dc->v8m_stackcheck = EX_TBFLAG_M32(tb_flags, STACKCHECK);
dc->v8m_fpccr_s_wrong = EX_TBFLAG_M32(tb_flags, FPCCR_S_WRONG);
dc->v7m_new_fp_ctxt_needed =