mirror of https://github.com/xemu-project/xemu.git
target/arm: Pipe ARMSecuritySpace through ptw.c
Add input and output space members to S1Translate. Set and adjust them in S1_ptw_translate, and the various points at which we drop secure state. Initialize the space in get_phys_addr; for now leave get_phys_addr_with_secure considering only secure vs non-secure spaces. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20230620124418.805717-11-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
86a438b462
commit
90c6629393
|
@ -21,11 +21,13 @@
|
||||||
typedef struct S1Translate {
|
typedef struct S1Translate {
|
||||||
ARMMMUIdx in_mmu_idx;
|
ARMMMUIdx in_mmu_idx;
|
||||||
ARMMMUIdx in_ptw_idx;
|
ARMMMUIdx in_ptw_idx;
|
||||||
|
ARMSecuritySpace in_space;
|
||||||
bool in_secure;
|
bool in_secure;
|
||||||
bool in_debug;
|
bool in_debug;
|
||||||
bool out_secure;
|
bool out_secure;
|
||||||
bool out_rw;
|
bool out_rw;
|
||||||
bool out_be;
|
bool out_be;
|
||||||
|
ARMSecuritySpace out_space;
|
||||||
hwaddr out_virt;
|
hwaddr out_virt;
|
||||||
hwaddr out_phys;
|
hwaddr out_phys;
|
||||||
void *out_host;
|
void *out_host;
|
||||||
|
@ -249,6 +251,7 @@ static bool S2_attrs_are_device(uint64_t hcr, uint8_t attrs)
|
||||||
static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||||
hwaddr addr, ARMMMUFaultInfo *fi)
|
hwaddr addr, ARMMMUFaultInfo *fi)
|
||||||
{
|
{
|
||||||
|
ARMSecuritySpace space = ptw->in_space;
|
||||||
bool is_secure = ptw->in_secure;
|
bool is_secure = ptw->in_secure;
|
||||||
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
|
ARMMMUIdx mmu_idx = ptw->in_mmu_idx;
|
||||||
ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
|
ARMMMUIdx s2_mmu_idx = ptw->in_ptw_idx;
|
||||||
|
@ -266,6 +269,9 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||||
.in_mmu_idx = s2_mmu_idx,
|
.in_mmu_idx = s2_mmu_idx,
|
||||||
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
|
.in_ptw_idx = ptw_idx_for_stage_2(env, s2_mmu_idx),
|
||||||
.in_secure = s2_mmu_idx == ARMMMUIdx_Stage2_S,
|
.in_secure = s2_mmu_idx == ARMMMUIdx_Stage2_S,
|
||||||
|
.in_space = (s2_mmu_idx == ARMMMUIdx_Stage2_S ? ARMSS_Secure
|
||||||
|
: space == ARMSS_Realm ? ARMSS_Realm
|
||||||
|
: ARMSS_NonSecure),
|
||||||
.in_debug = true,
|
.in_debug = true,
|
||||||
};
|
};
|
||||||
GetPhysAddrResult s2 = { };
|
GetPhysAddrResult s2 = { };
|
||||||
|
@ -277,11 +283,15 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||||
ptw->out_phys = s2.f.phys_addr;
|
ptw->out_phys = s2.f.phys_addr;
|
||||||
pte_attrs = s2.cacheattrs.attrs;
|
pte_attrs = s2.cacheattrs.attrs;
|
||||||
ptw->out_secure = s2.f.attrs.secure;
|
ptw->out_secure = s2.f.attrs.secure;
|
||||||
|
ptw->out_space = s2.f.attrs.space;
|
||||||
} else {
|
} else {
|
||||||
/* Regime is physical. */
|
/* Regime is physical. */
|
||||||
ptw->out_phys = addr;
|
ptw->out_phys = addr;
|
||||||
pte_attrs = 0;
|
pte_attrs = 0;
|
||||||
ptw->out_secure = s2_mmu_idx == ARMMMUIdx_Phys_S;
|
ptw->out_secure = s2_mmu_idx == ARMMMUIdx_Phys_S;
|
||||||
|
ptw->out_space = (s2_mmu_idx == ARMMMUIdx_Phys_S ? ARMSS_Secure
|
||||||
|
: space == ARMSS_Realm ? ARMSS_Realm
|
||||||
|
: ARMSS_NonSecure);
|
||||||
}
|
}
|
||||||
ptw->out_host = NULL;
|
ptw->out_host = NULL;
|
||||||
ptw->out_rw = false;
|
ptw->out_rw = false;
|
||||||
|
@ -303,6 +313,7 @@ static bool S1_ptw_translate(CPUARMState *env, S1Translate *ptw,
|
||||||
ptw->out_rw = full->prot & PAGE_WRITE;
|
ptw->out_rw = full->prot & PAGE_WRITE;
|
||||||
pte_attrs = full->pte_attrs;
|
pte_attrs = full->pte_attrs;
|
||||||
ptw->out_secure = full->attrs.secure;
|
ptw->out_secure = full->attrs.secure;
|
||||||
|
ptw->out_space = full->attrs.space;
|
||||||
#else
|
#else
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
#endif
|
#endif
|
||||||
|
@ -355,7 +366,10 @@ static uint32_t arm_ldl_ptw(CPUARMState *env, S1Translate *ptw,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Page tables are in MMIO. */
|
/* Page tables are in MMIO. */
|
||||||
MemTxAttrs attrs = { .secure = ptw->out_secure };
|
MemTxAttrs attrs = {
|
||||||
|
.secure = ptw->out_secure,
|
||||||
|
.space = ptw->out_space,
|
||||||
|
};
|
||||||
AddressSpace *as = arm_addressspace(cs, attrs);
|
AddressSpace *as = arm_addressspace(cs, attrs);
|
||||||
MemTxResult result = MEMTX_OK;
|
MemTxResult result = MEMTX_OK;
|
||||||
|
|
||||||
|
@ -398,7 +412,10 @@ static uint64_t arm_ldq_ptw(CPUARMState *env, S1Translate *ptw,
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
/* Page tables are in MMIO. */
|
/* Page tables are in MMIO. */
|
||||||
MemTxAttrs attrs = { .secure = ptw->out_secure };
|
MemTxAttrs attrs = {
|
||||||
|
.secure = ptw->out_secure,
|
||||||
|
.space = ptw->out_space,
|
||||||
|
};
|
||||||
AddressSpace *as = arm_addressspace(cs, attrs);
|
AddressSpace *as = arm_addressspace(cs, attrs);
|
||||||
MemTxResult result = MEMTX_OK;
|
MemTxResult result = MEMTX_OK;
|
||||||
|
|
||||||
|
@ -909,6 +926,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
|
||||||
* regime, because the attribute will already be non-secure.
|
* regime, because the attribute will already be non-secure.
|
||||||
*/
|
*/
|
||||||
result->f.attrs.secure = false;
|
result->f.attrs.secure = false;
|
||||||
|
result->f.attrs.space = ARMSS_NonSecure;
|
||||||
}
|
}
|
||||||
result->f.phys_addr = phys_addr;
|
result->f.phys_addr = phys_addr;
|
||||||
return false;
|
return false;
|
||||||
|
@ -1616,6 +1634,7 @@ static bool get_phys_addr_lpae(CPUARMState *env, S1Translate *ptw,
|
||||||
* regime, because the attribute will already be non-secure.
|
* regime, because the attribute will already be non-secure.
|
||||||
*/
|
*/
|
||||||
result->f.attrs.secure = false;
|
result->f.attrs.secure = false;
|
||||||
|
result->f.attrs.space = ARMSS_NonSecure;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regime_is_stage2(mmu_idx)) {
|
if (regime_is_stage2(mmu_idx)) {
|
||||||
|
@ -2400,6 +2419,7 @@ static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
|
||||||
*/
|
*/
|
||||||
if (sattrs.ns) {
|
if (sattrs.ns) {
|
||||||
result->f.attrs.secure = false;
|
result->f.attrs.secure = false;
|
||||||
|
result->f.attrs.space = ARMSS_NonSecure;
|
||||||
} else if (!secure) {
|
} else if (!secure) {
|
||||||
/*
|
/*
|
||||||
* NS access to S memory must fault.
|
* NS access to S memory must fault.
|
||||||
|
@ -2750,6 +2770,7 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
|
||||||
bool is_secure = ptw->in_secure;
|
bool is_secure = ptw->in_secure;
|
||||||
bool ret, ipa_secure;
|
bool ret, ipa_secure;
|
||||||
ARMCacheAttrs cacheattrs1;
|
ARMCacheAttrs cacheattrs1;
|
||||||
|
ARMSecuritySpace ipa_space;
|
||||||
bool is_el0;
|
bool is_el0;
|
||||||
uint64_t hcr;
|
uint64_t hcr;
|
||||||
|
|
||||||
|
@ -2762,10 +2783,12 @@ static bool get_phys_addr_twostage(CPUARMState *env, S1Translate *ptw,
|
||||||
|
|
||||||
ipa = result->f.phys_addr;
|
ipa = result->f.phys_addr;
|
||||||
ipa_secure = result->f.attrs.secure;
|
ipa_secure = result->f.attrs.secure;
|
||||||
|
ipa_space = result->f.attrs.space;
|
||||||
|
|
||||||
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
|
is_el0 = ptw->in_mmu_idx == ARMMMUIdx_Stage1_E0;
|
||||||
ptw->in_mmu_idx = ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
ptw->in_mmu_idx = ipa_secure ? ARMMMUIdx_Stage2_S : ARMMMUIdx_Stage2;
|
||||||
ptw->in_secure = ipa_secure;
|
ptw->in_secure = ipa_secure;
|
||||||
|
ptw->in_space = ipa_space;
|
||||||
ptw->in_ptw_idx = ptw_idx_for_stage_2(env, ptw->in_mmu_idx);
|
ptw->in_ptw_idx = ptw_idx_for_stage_2(env, ptw->in_mmu_idx);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2854,11 +2877,12 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|
||||||
ARMMMUIdx s1_mmu_idx;
|
ARMMMUIdx s1_mmu_idx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The page table entries may downgrade secure to non-secure, but
|
* The page table entries may downgrade Secure to NonSecure, but
|
||||||
* cannot upgrade an non-secure translation regime's attributes
|
* cannot upgrade a NonSecure translation regime's attributes
|
||||||
* to secure.
|
* to Secure or Realm.
|
||||||
*/
|
*/
|
||||||
result->f.attrs.secure = is_secure;
|
result->f.attrs.secure = is_secure;
|
||||||
|
result->f.attrs.space = ptw->in_space;
|
||||||
|
|
||||||
switch (mmu_idx) {
|
switch (mmu_idx) {
|
||||||
case ARMMMUIdx_Phys_S:
|
case ARMMMUIdx_Phys_S:
|
||||||
|
@ -2910,7 +2934,7 @@ static bool get_phys_addr_with_struct(CPUARMState *env, S1Translate *ptw,
|
||||||
|
|
||||||
default:
|
default:
|
||||||
/* Single stage uses physical for ptw. */
|
/* Single stage uses physical for ptw. */
|
||||||
ptw->in_ptw_idx = is_secure ? ARMMMUIdx_Phys_S : ARMMMUIdx_Phys_NS;
|
ptw->in_ptw_idx = arm_space_to_phys(ptw->in_space);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2985,6 +3009,7 @@ bool get_phys_addr_with_secure(CPUARMState *env, target_ulong address,
|
||||||
S1Translate ptw = {
|
S1Translate ptw = {
|
||||||
.in_mmu_idx = mmu_idx,
|
.in_mmu_idx = mmu_idx,
|
||||||
.in_secure = is_secure,
|
.in_secure = is_secure,
|
||||||
|
.in_space = arm_secure_to_space(is_secure),
|
||||||
};
|
};
|
||||||
return get_phys_addr_with_struct(env, &ptw, address, access_type,
|
return get_phys_addr_with_struct(env, &ptw, address, access_type,
|
||||||
result, fi);
|
result, fi);
|
||||||
|
@ -2994,7 +3019,10 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
|
||||||
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
||||||
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
GetPhysAddrResult *result, ARMMMUFaultInfo *fi)
|
||||||
{
|
{
|
||||||
bool is_secure;
|
S1Translate ptw = {
|
||||||
|
.in_mmu_idx = mmu_idx,
|
||||||
|
};
|
||||||
|
ARMSecuritySpace ss;
|
||||||
|
|
||||||
switch (mmu_idx) {
|
switch (mmu_idx) {
|
||||||
case ARMMMUIdx_E10_0:
|
case ARMMMUIdx_E10_0:
|
||||||
|
@ -3007,30 +3035,55 @@ bool get_phys_addr(CPUARMState *env, target_ulong address,
|
||||||
case ARMMMUIdx_Stage1_E1:
|
case ARMMMUIdx_Stage1_E1:
|
||||||
case ARMMMUIdx_Stage1_E1_PAN:
|
case ARMMMUIdx_Stage1_E1_PAN:
|
||||||
case ARMMMUIdx_E2:
|
case ARMMMUIdx_E2:
|
||||||
is_secure = arm_is_secure_below_el3(env);
|
ss = arm_security_space_below_el3(env);
|
||||||
break;
|
break;
|
||||||
case ARMMMUIdx_Stage2:
|
case ARMMMUIdx_Stage2:
|
||||||
|
/*
|
||||||
|
* For Secure EL2, we need this index to be NonSecure;
|
||||||
|
* otherwise this will already be NonSecure or Realm.
|
||||||
|
*/
|
||||||
|
ss = arm_security_space_below_el3(env);
|
||||||
|
if (ss == ARMSS_Secure) {
|
||||||
|
ss = ARMSS_NonSecure;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ARMMMUIdx_Phys_NS:
|
case ARMMMUIdx_Phys_NS:
|
||||||
case ARMMMUIdx_MPrivNegPri:
|
case ARMMMUIdx_MPrivNegPri:
|
||||||
case ARMMMUIdx_MUserNegPri:
|
case ARMMMUIdx_MUserNegPri:
|
||||||
case ARMMMUIdx_MPriv:
|
case ARMMMUIdx_MPriv:
|
||||||
case ARMMMUIdx_MUser:
|
case ARMMMUIdx_MUser:
|
||||||
is_secure = false;
|
ss = ARMSS_NonSecure;
|
||||||
break;
|
break;
|
||||||
case ARMMMUIdx_E3:
|
|
||||||
case ARMMMUIdx_Stage2_S:
|
case ARMMMUIdx_Stage2_S:
|
||||||
case ARMMMUIdx_Phys_S:
|
case ARMMMUIdx_Phys_S:
|
||||||
case ARMMMUIdx_MSPrivNegPri:
|
case ARMMMUIdx_MSPrivNegPri:
|
||||||
case ARMMMUIdx_MSUserNegPri:
|
case ARMMMUIdx_MSUserNegPri:
|
||||||
case ARMMMUIdx_MSPriv:
|
case ARMMMUIdx_MSPriv:
|
||||||
case ARMMMUIdx_MSUser:
|
case ARMMMUIdx_MSUser:
|
||||||
is_secure = true;
|
ss = ARMSS_Secure;
|
||||||
|
break;
|
||||||
|
case ARMMMUIdx_E3:
|
||||||
|
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
|
||||||
|
cpu_isar_feature(aa64_rme, env_archcpu(env))) {
|
||||||
|
ss = ARMSS_Root;
|
||||||
|
} else {
|
||||||
|
ss = ARMSS_Secure;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ARMMMUIdx_Phys_Root:
|
||||||
|
ss = ARMSS_Root;
|
||||||
|
break;
|
||||||
|
case ARMMMUIdx_Phys_Realm:
|
||||||
|
ss = ARMSS_Realm;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
return get_phys_addr_with_secure(env, address, access_type, mmu_idx,
|
|
||||||
is_secure, result, fi);
|
ptw.in_space = ss;
|
||||||
|
ptw.in_secure = arm_space_is_secure(ss);
|
||||||
|
return get_phys_addr_with_struct(env, &ptw, address, access_type,
|
||||||
|
result, fi);
|
||||||
}
|
}
|
||||||
|
|
||||||
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
|
hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
|
||||||
|
@ -3038,9 +3091,12 @@ hwaddr arm_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr,
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = ARM_CPU(cs);
|
ARMCPU *cpu = ARM_CPU(cs);
|
||||||
CPUARMState *env = &cpu->env;
|
CPUARMState *env = &cpu->env;
|
||||||
|
ARMMMUIdx mmu_idx = arm_mmu_idx(env);
|
||||||
|
ARMSecuritySpace ss = arm_security_space(env);
|
||||||
S1Translate ptw = {
|
S1Translate ptw = {
|
||||||
.in_mmu_idx = arm_mmu_idx(env),
|
.in_mmu_idx = mmu_idx,
|
||||||
.in_secure = arm_is_secure(env),
|
.in_space = ss,
|
||||||
|
.in_secure = arm_space_is_secure(ss),
|
||||||
.in_debug = true,
|
.in_debug = true,
|
||||||
};
|
};
|
||||||
GetPhysAddrResult res = {};
|
GetPhysAddrResult res = {};
|
||||||
|
|
Loading…
Reference in New Issue