mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
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:
parent
f3639a64f6
commit
3f5a74c543
1 changed files with 100 additions and 91 deletions
|
@ -31,6 +31,13 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
|
||||||
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
||||||
__attribute__((nonnull));
|
__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. */
|
/* This mapping is common between ID_AA64MMFR0.PARANGE and TCR_ELx.{I}PS. */
|
||||||
static const uint8_t pamax_map[] = {
|
static const uint8_t pamax_map[] = {
|
||||||
[0] = 32,
|
[0] = 32,
|
||||||
|
@ -2428,37 +2435,25 @@ static bool get_phys_addr_disabled(CPUARMState *env, target_ulong address,
|
||||||
return 0;
|
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,
|
target_ulong address,
|
||||||
MMUAccessType access_type,
|
MMUAccessType access_type,
|
||||||
GetPhysAddrResult *result,
|
GetPhysAddrResult *result,
|
||||||
ARMMMUFaultInfo *fi)
|
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;
|
hwaddr ipa;
|
||||||
int s1_prot;
|
int s1_prot;
|
||||||
int ret;
|
int ret;
|
||||||
|
bool is_secure = ptw->in_secure;
|
||||||
bool ipa_secure, s2walk_secure;
|
bool ipa_secure, s2walk_secure;
|
||||||
ARMCacheAttrs cacheattrs1;
|
ARMCacheAttrs cacheattrs1;
|
||||||
bool is_el0;
|
bool is_el0;
|
||||||
uint64_t hcr;
|
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 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)) {
|
||||||
is_secure)) {
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2474,22 +2469,19 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|
||||||
s2walk_secure = false;
|
s2walk_secure = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ptw->in_mmu_idx =
|
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
|
||||||
s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
ptw->in_mmu_idx = s2walk_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
||||||
ptw->in_secure = s2walk_secure;
|
ptw->in_secure = s2walk_secure;
|
||||||
is_el0 = mmu_idx == ARMMMUIdx_E10_0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* S1 is done, now do S2 translation.
|
* S1 is done, now do S2 translation.
|
||||||
* Save the stage1 results so that we may merge
|
* Save the stage1 results so that we may merge prot and cacheattrs later.
|
||||||
* prot and cacheattrs later.
|
|
||||||
*/
|
*/
|
||||||
s1_prot = result->f.prot;
|
s1_prot = result->f.prot;
|
||||||
cacheattrs1 = result->cacheattrs;
|
cacheattrs1 = result->cacheattrs;
|
||||||
memset(result, 0, sizeof(*result));
|
memset(result, 0, sizeof(*result));
|
||||||
|
|
||||||
ret = get_phys_addr_lpae(env, ptw, ipa, access_type,
|
ret = get_phys_addr_lpae(env, ptw, ipa, access_type, is_el0, result, fi);
|
||||||
is_el0, result, fi);
|
|
||||||
fi->s2addr = ipa;
|
fi->s2addr = ipa;
|
||||||
|
|
||||||
/* Combine the S1 and S2 perms. */
|
/* 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))));
|
|| !(env->cp15.vtcr_el2 & (VTCR_NSA | VTCR_NSW))));
|
||||||
|
|
||||||
return 0;
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue