[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 51/62] target/arm: Add ptw_idx argument to S1_ptw_translate
From: |
Richard Henderson |
Subject: |
[PATCH 51/62] target/arm: Add ptw_idx argument to S1_ptw_translate |
Date: |
Sun, 3 Jul 2022 13:54:08 +0530 |
Hoist the computation of the mmu_idx for the ptw up to
get_phys_addr_with_secure and get_phys_addr_twostage.
This removes the duplicate check for stage2 disabled
from the middle of the walk, performing it only once.
Pass ptw_idx through get_phys_addr_{v5,v6,lpae} and
arm_{ldl,ldq}_ptw.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
target/arm/ptw.c | 100 +++++++++++++++++++++++++++++++----------------
1 file changed, 67 insertions(+), 33 deletions(-)
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index e42286b4c1..6eb61849d3 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -17,7 +17,8 @@
static bool get_phys_addr_lpae(CPUARMState *env, uint64_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool is_secure, bool s1_is_el0,
+ ARMMMUIdx ptw_idx, bool is_secure,
+ bool s1_is_el0,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
__attribute__((nonnull));
@@ -190,21 +191,16 @@ static bool regime_translation_disabled(CPUARMState *env,
ARMMMUIdx mmu_idx,
}
/* Translate a S1 pagetable walk through S2 if needed. */
-static bool S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx, hwaddr addr,
+static bool S1_ptw_translate(CPUARMState *env, ARMMMUIdx mmu_idx,
+ ARMMMUIdx s2_mmu_idx, hwaddr addr,
bool *is_secure_ptr, void **hphys, hwaddr *gphys,
ARMMMUFaultInfo *fi)
{
bool is_secure = *is_secure_ptr;
- ARMMMUIdx s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
MemTxAttrs attrs = {};
PageEntryExtra extra;
int flags;
- if (!arm_mmu_idx_is_stage1_of_2(mmu_idx)
- || regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
- s2_mmu_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
- }
-
env->tlb_fi = fi;
flags = probe_access_extra(env, addr, MMU_DATA_LOAD,
arm_to_core_mmu_idx(s2_mmu_idx),
@@ -267,7 +263,8 @@ static bool S1_ptw_translate(CPUARMState *env, ARMMMUIdx
mmu_idx, hwaddr addr,
/* All loads done in the course of a page table walk go through here. */
static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
+ ARMMMUIdx mmu_idx, ARMMMUIdx ptw_idx,
+ ARMMMUFaultInfo *fi)
{
CPUState *cs = env_cpu(env);
void *hphys;
@@ -275,7 +272,7 @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr,
bool is_secure,
uint32_t data;
bool be;
- if (!S1_ptw_translate(env, mmu_idx, addr, &is_secure,
+ if (!S1_ptw_translate(env, mmu_idx, ptw_idx, addr, &is_secure,
&hphys, &gphys, fi)) {
/* Failure. */
assert(fi->s1ptw);
@@ -311,7 +308,8 @@ static uint32_t arm_ldl_ptw(CPUARMState *env, hwaddr addr,
bool is_secure,
}
static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr, bool is_secure,
- ARMMMUIdx mmu_idx, ARMMMUFaultInfo *fi)
+ ARMMMUIdx mmu_idx, ARMMMUIdx ptw_idx,
+ ARMMMUFaultInfo *fi)
{
CPUState *cs = env_cpu(env);
void *hphys;
@@ -319,7 +317,7 @@ static uint64_t arm_ldq_ptw(CPUARMState *env, hwaddr addr,
bool is_secure,
uint64_t data;
bool be;
- if (!S1_ptw_translate(env, mmu_idx, addr, &is_secure,
+ if (!S1_ptw_translate(env, mmu_idx, ptw_idx, addr, &is_secure,
&hphys, &gphys, fi)) {
/* Failure. */
assert(fi->s1ptw);
@@ -460,8 +458,8 @@ static int simple_ap_to_rw_prot(CPUARMState *env, ARMMMUIdx
mmu_idx, int ap)
static bool get_phys_addr_v5(CPUARMState *env, uint32_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool is_secure, GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+ ARMMMUIdx ptw_idx, bool is_secure,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
{
int level = 1;
uint32_t table;
@@ -480,7 +478,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t
address,
fi->type = ARMFault_Translation;
goto do_fault;
}
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
+ desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, ptw_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -518,7 +516,7 @@ static bool get_phys_addr_v5(CPUARMState *env, uint32_t
address,
/* Fine pagetable. */
table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
}
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
+ desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, ptw_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -579,8 +577,8 @@ do_fault:
static bool get_phys_addr_v6(CPUARMState *env, uint32_t address,
MMUAccessType access_type, ARMMMUIdx mmu_idx,
- bool is_secure, GetPhysAddrResult *result,
- ARMMMUFaultInfo *fi)
+ ARMMMUIdx ptw_idx, bool is_secure,
+ GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
{
ARMCPU *cpu = env_archcpu(env);
int level = 1;
@@ -603,7 +601,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t
address,
fi->type = ARMFault_Translation;
goto do_fault;
}
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
+ desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, ptw_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -656,7 +654,7 @@ static bool get_phys_addr_v6(CPUARMState *env, uint32_t
address,
ns = extract32(desc, 3, 1);
/* Lookup l2 entry. */
table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
- desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, fi);
+ desc = arm_ldl_ptw(env, table, is_secure, mmu_idx, ptw_idx, fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -1011,7 +1009,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 is_secure, bool s1_is_el0,
+ ARMMMUIdx ptw_idx, bool is_secure,
+ bool s1_is_el0,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
{
ARMCPU *cpu = env_archcpu(env);
@@ -1237,7 +1236,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, uint64_t
address,
descaddr |= (address >> (stride * (4 - level))) & indexmask;
descaddr &= ~7ULL;
nstable = extract32(tableattrs, 4, 1);
- descriptor = arm_ldq_ptw(env, descaddr, !nstable, mmu_idx, fi);
+ descriptor = arm_ldq_ptw(env, descaddr, !nstable, mmu_idx, ptw_idx,
fi);
if (fi->type != ARMFault_None) {
goto do_fault;
}
@@ -2408,7 +2407,7 @@ static bool get_phys_addr_twostage(CPUARMState *env,
target_ulong address,
bool ret;
bool ipa_secure;
ARMCacheAttrs cacheattrs1;
- ARMMMUIdx s2_mmu_idx;
+ ARMMMUIdx s2_mmu_idx, s2_ptw_idx;
bool is_el0;
uint64_t hcr;
@@ -2430,7 +2429,13 @@ static bool get_phys_addr_twostage(CPUARMState *env,
target_ulong address,
ipa_secure = false;
}
- s2_mmu_idx = (ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2);
+ if (ipa_secure) {
+ s2_mmu_idx = ARMMMUIdx_Stage2_S;
+ s2_ptw_idx = ARMMMUIdx_Phys_S;
+ } else {
+ s2_mmu_idx = ARMMMUIdx_Stage2;
+ s2_ptw_idx = ARMMMUIdx_Phys_NS;
+ }
is_el0 = s1_mmu_idx == ARMMMUIdx_Stage1_E0;
/*
@@ -2442,7 +2447,7 @@ static bool get_phys_addr_twostage(CPUARMState *env,
target_ulong address,
cacheattrs1 = result->cacheattrs;
memset(result, 0, sizeof(*result));
- ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx,
+ ret = get_phys_addr_lpae(env, ipa, access_type, s2_mmu_idx, s2_ptw_idx,
ipa_secure, is_el0, result, fi);
fi->s2addr = ipa;
@@ -2514,19 +2519,49 @@ bool get_phys_addr_with_secure(CPUARMState *env,
target_ulong address,
bool is_secure, GetPhysAddrResult *result,
ARMMMUFaultInfo *fi)
{
- ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
+ ARMMMUIdx s1_mmu_idx, s2_mmu_idx, ptw_idx;
- if (mmu_idx != s1_mmu_idx) {
+ switch (mmu_idx) {
+ case ARMMMUIdx_Phys_S:
+ case ARMMMUIdx_Phys_NS:
+ do_disabled:
+ /* Checking Phys early avoids special casing later vs regime_el. */
+ return get_phys_addr_disabled(env, address, access_type, mmu_idx,
+ is_secure, result, fi);
+
+ case ARMMMUIdx_Stage1_E0:
+ case ARMMMUIdx_Stage1_E1:
+ case ARMMMUIdx_Stage1_E1_PAN:
+ /* First stage lookup uses second stage for ptw. */
+ ptw_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
+ break;
+
+ case ARMMMUIdx_E10_0:
+ s1_mmu_idx = ARMMMUIdx_Stage1_E0;
+ goto do_twostage;
+ case ARMMMUIdx_E10_1:
+ s1_mmu_idx = ARMMMUIdx_Stage1_E1;
+ goto do_twostage;
+ case ARMMMUIdx_E10_1_PAN:
+ s1_mmu_idx = ARMMMUIdx_Stage1_E1_PAN;
+ do_twostage:
/*
* Call ourselves recursively to do the stage 1 and then stage 2
* translations if mmu_idx is a two-stage regime, and stage2 enabled.
*/
+ s2_mmu_idx = is_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
if (arm_feature(env, ARM_FEATURE_EL2) &&
- !regime_translation_disabled(env, ARMMMUIdx_Stage2, is_secure)) {
+ !regime_translation_disabled(env, s2_mmu_idx, is_secure)) {
return get_phys_addr_twostage(env, address, access_type,
s1_mmu_idx, is_secure,
result, fi);
}
+ /* fall through */
+
+ default:
+ /* Single stage and second stage uses physical for ptw. */
+ ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
+ break;
}
/*
@@ -2583,18 +2618,17 @@ bool get_phys_addr_with_secure(CPUARMState *env,
target_ulong address,
/* Definitely a real MMU, not an MPU */
if (regime_translation_disabled(env, mmu_idx, is_secure)) {
- return get_phys_addr_disabled(env, address, access_type, mmu_idx,
- is_secure, result, fi);
+ goto do_disabled;
}
if (regime_using_lpae_format(env, mmu_idx)) {
return get_phys_addr_lpae(env, address, access_type, mmu_idx,
- is_secure, false, result, fi);
+ ptw_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);
+ ptw_idx, is_secure, result, fi);
} else {
return get_phys_addr_v5(env, address, access_type, mmu_idx,
- is_secure, result, fi);
+ ptw_idx, is_secure, result, fi);
}
}
--
2.34.1
- [PATCH 43/62] target/arm: Reorg get_phys_addr_disabled, (continued)
- [PATCH 43/62] target/arm: Reorg get_phys_addr_disabled, Richard Henderson, 2022/07/03
- [PATCH 45/62] target/arm: Move ARMMMUIdx_Stage2 to a real tlb mmu_idx, Richard Henderson, 2022/07/03
- [PATCH 46/62] target/arm: Use softmmu tlbs for page table walking, Richard Henderson, 2022/07/03
- [PATCH 47/62] target/arm: Hoist check for disabled stage2 translation., Richard Henderson, 2022/07/03
- [PATCH 48/62] target/arm: Split out get_phys_addr_twostage, Richard Henderson, 2022/07/03
- [PATCH 49/62] target/arm: Use bool consistently for get_phys_addr subroutines, Richard Henderson, 2022/07/03
- [PATCH 50/62] target/arm: Only use ARMMMUIdx_Stage1* for two-stage translation, Richard Henderson, 2022/07/03
- [PATCH 52/62] target/arm: Add isar predicates for FEAT_HAFDBS, Richard Henderson, 2022/07/03
- [PATCH 54/62] target/arm: Split out S1TranslateResult type, Richard Henderson, 2022/07/03
- [PATCH 55/62] target/arm: Move be test for regime into S1TranslateResult, Richard Henderson, 2022/07/03
- [PATCH 51/62] target/arm: Add ptw_idx argument to S1_ptw_translate,
Richard Henderson <=
- [PATCH 53/62] target/arm: Extract HA and HD in aa64_va_parameters, Richard Henderson, 2022/07/03
- [PATCH 56/62] target/arm: Move S1_ptw_translate outside arm_ld[lq]_ptw, Richard Henderson, 2022/07/03
- [PATCH 57/62] target/arm: Add ARMFault_UnsuppAtomicUpdate, Richard Henderson, 2022/07/03
- [PATCH 58/62] target/arm: Remove loop from get_phys_addr_lpae, Richard Henderson, 2022/07/03
- [PATCH 59/62] target/arm: Fix fault reporting in get_phys_addr_lpae, Richard Henderson, 2022/07/03
- [PATCH 60/62] target/arm: Don't shift attrs in get_phys_addr_lpae, Richard Henderson, 2022/07/03
- [PATCH 61/62] target/arm: Consider GP an attribute in get_phys_addr_lpae, Richard Henderson, 2022/07/03
- [PATCH 62/62] target/arm: Implement FEAT_HAFDBS, Richard Henderson, 2022/07/03
- Re: [PATCH 00/62] target/arm: Implement FEAT_HAFDBS, Peter Maydell, 2022/07/04