target/arm: Split out get_phys_addr_twostage

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20221011031911.2408754-12-richard.henderson@linaro.org
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Richard Henderson 2022-10-10 20:18:58 -07:00 committed by Peter Maydell
parent f3639a64f6
commit 3f5a74c543
1 changed files with 100 additions and 91 deletions

View File

@ -31,6 +31,13 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
__attribute__((nonnull));
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
target_ulong address,
MMUAccessType access_type,
GetPhysAddrResult *result,
ARMMMUFaultInfo *fi)
__attribute__((nonnull));
/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
static const uint8_t pamax_map[] = {
[0] = 32,
@ -2428,37 +2435,25 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
return 0;
}
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
target_ulong address,
MMUAccessType access_type,
GetPhysAddrResult *result,
ARMMMUFaultInfo *fi)
{
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
bool is_secure = ptw->in_secure;
if (mmu_idx != s1_mmu_idx) {
/*
* Call ourselves recursively to do the stage 1 and then stage 2
* translations if mmu_idx is a two-stage regime.
*/
if (arm_feature(env, ARM_FEATURE_EL2)) {
hwaddr ipa;
int s1_prot;
int ret;
bool is_secure = ptw->in_secure;
bool ipa_secure, s2walk_secure;
ARMCacheAttrs cacheattrs1;
bool is_el0;
uint64_t hcr;
ptw->in_mmu_idx = s1_mmu_idx;
ret = get_phys_addr_with_struct(env, ptw, address, access_type,
result, fi);
ret = get_phys_addr_with_struct(env, ptw, address, access_type, result, fi);
/* If S1 fails or S2 is disabled, return early. */
if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2,
is_secure)) {
if (ret || regime_translation_disabled(env, ARMMMUIdx_Stage2, is_secure)) {
return ret;
}
@ -2474,22 +2469,19 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
s2walk_secure = false;
}
ptw->in_mmu_idx =
s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
ptw->in_secure = s2walk_secure;
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.
* Save the stage1 results so that we may merge prot and cacheattrs later.
*/
s1_prot = result->f.prot;
cacheattrs1 = result->cacheattrs;
memset(result, 0, sizeof(*result));
ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
is_el0, result, fi);
ret = get_phys_addr_lpae(env, ptw, ipa, access_type, is_el0, result, fi);
fi->s2addr = ipa;
/* Combine the S1 and S2 perms. */
@ -2529,11 +2521,28 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|| !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
return 0;
} else {
}
static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
target_ulong address,
MMUAccessType access_type,
GetPhysAddrResult *result,
ARMMMUFaultInfo *fi)
{
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
ARMMMUIdx s1_mmu_idx = stage_1_mmu_idx(mmu_idx);
bool is_secure = ptw->in_secure;
if (mmu_idx != s1_mmu_idx) {
/*
* For non-EL2 CPUs a stage1+stage2 translation is just stage 1.
* Call ourselves recursively to do the stage 1 and then stage 2
* translations if mmu_idx is a two-stage regime, and EL2 present.
* Otherwise, a stage1+stage2 translation is just stage 1.
*/
mmu_idx = stage_1_mmu_idx(mmu_idx);
ptw->in_mmu_idx = mmu_idx = s1_mmu_idx;
if (arm_feature(env, ARM_FEATURE_EL2)) {
return get_phys_addr_twostage(env, ptw, address, access_type,
result, fi);
}
}