mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
arm/ptw: Honour WXN/UWXN and SIF in short-format descriptors
Currently the handling of page protection in the short-format descriptor is open-coded. This means that we forgot to update it to handle some newer architectural features, including: * handling of SCTLR.{UWXN,WXN} * handling of SCR.SIF Make the short-format descriptor code call the same get_S1prot() that we already use for the LPAE descriptor format. This makes the code simpler and means it now correctly honours the WXN/UWXN and SIF bits. Signed-off-by: Pavel Skripkin <paskripkin@gmail.com> Message-id: 20241118152537.45277-1-paskripkin@gmail.com [PMM: fixed a couple of checkpatch nits, tweaked commit message] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
0231bdc895
commit
0340cb6e31
1 changed files with 24 additions and 31 deletions
|
@ -85,6 +85,10 @@ static bool get_phys_addr_gpc(CPUARMState *env, S1Translate *ptw,
|
||||||
GetPhysAddrResult *result,
|
GetPhysAddrResult *result,
|
||||||
ARMMMUFaultInfo *fi);
|
ARMMMUFaultInfo *fi);
|
||||||
|
|
||||||
|
static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
|
||||||
|
int user_rw, int prot_rw, int xn, int pxn,
|
||||||
|
ARMSecuritySpace in_pa, ARMSecuritySpace out_pa);
|
||||||
|
|
||||||
/* 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,
|
||||||
|
@ -1148,7 +1152,7 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
|
||||||
hwaddr phys_addr;
|
hwaddr phys_addr;
|
||||||
uint32_t dacr;
|
uint32_t dacr;
|
||||||
bool ns;
|
bool ns;
|
||||||
int user_prot;
|
ARMSecuritySpace out_space;
|
||||||
|
|
||||||
/* Pagetable walk. */
|
/* Pagetable walk. */
|
||||||
/* Lookup l1 descriptor. */
|
/* Lookup l1 descriptor. */
|
||||||
|
@ -1240,16 +1244,19 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
out_space = ptw->in_space;
|
||||||
|
if (ns) {
|
||||||
|
/*
|
||||||
|
* The NS bit will (as required by the architecture) have no effect if
|
||||||
|
* the CPU doesn't support TZ or this is a non-secure translation
|
||||||
|
* regime, because the output space will already be non-secure.
|
||||||
|
*/
|
||||||
|
out_space = ARMSS_NonSecure;
|
||||||
|
}
|
||||||
if (domain_prot == 3) {
|
if (domain_prot == 3) {
|
||||||
result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
result->f.prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
|
||||||
} else {
|
} else {
|
||||||
if (pxn && !regime_is_user(env, mmu_idx)) {
|
int user_rw, prot_rw;
|
||||||
xn = 1;
|
|
||||||
}
|
|
||||||
if (xn && access_type == MMU_INST_FETCH) {
|
|
||||||
fi->type = ARMFault_Permission;
|
|
||||||
goto do_fault;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (arm_feature(env, ARM_FEATURE_V6K) &&
|
if (arm_feature(env, ARM_FEATURE_V6K) &&
|
||||||
(regime_sctlr(env, mmu_idx) & SCTLR_AFE)) {
|
(regime_sctlr(env, mmu_idx) & SCTLR_AFE)) {
|
||||||
|
@ -1259,37 +1266,23 @@ static bool get_phys_addr_v6(CPUARMState *env, S1Translate *ptw,
|
||||||
fi->type = ARMFault_AccessFlag;
|
fi->type = ARMFault_AccessFlag;
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
result->f.prot = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
|
prot_rw = simple_ap_to_rw_prot(env, mmu_idx, ap >> 1);
|
||||||
user_prot = simple_ap_to_rw_prot_is_user(ap >> 1, 1);
|
user_rw = simple_ap_to_rw_prot_is_user(ap >> 1, 1);
|
||||||
} else {
|
} else {
|
||||||
result->f.prot = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
|
prot_rw = ap_to_rw_prot(env, mmu_idx, ap, domain_prot);
|
||||||
user_prot = ap_to_rw_prot_is_user(env, mmu_idx, ap, domain_prot, 1);
|
user_rw = ap_to_rw_prot_is_user(env, mmu_idx, ap, domain_prot, 1);
|
||||||
}
|
|
||||||
if (result->f.prot && !xn) {
|
|
||||||
result->f.prot |= PAGE_EXEC;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result->f.prot = get_S1prot(env, mmu_idx, false, user_rw, prot_rw,
|
||||||
|
xn, pxn, result->f.attrs.space, out_space);
|
||||||
if (!(result->f.prot & (1 << access_type))) {
|
if (!(result->f.prot & (1 << access_type))) {
|
||||||
/* Access permission fault. */
|
/* Access permission fault. */
|
||||||
fi->type = ARMFault_Permission;
|
fi->type = ARMFault_Permission;
|
||||||
goto do_fault;
|
goto do_fault;
|
||||||
}
|
}
|
||||||
if (regime_is_pan(env, mmu_idx) &&
|
|
||||||
!regime_is_user(env, mmu_idx) &&
|
|
||||||
user_prot &&
|
|
||||||
access_type != MMU_INST_FETCH) {
|
|
||||||
/* Privileged Access Never fault */
|
|
||||||
fi->type = ARMFault_Permission;
|
|
||||||
goto do_fault;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ns) {
|
|
||||||
/* The NS bit will (as required by the architecture) have no effect if
|
|
||||||
* the CPU doesn't support TZ or this is a non-secure translation
|
|
||||||
* regime, because the attribute will already be non-secure.
|
|
||||||
*/
|
|
||||||
result->f.attrs.secure = false;
|
|
||||||
result->f.attrs.space = ARMSS_NonSecure;
|
|
||||||
}
|
}
|
||||||
|
result->f.attrs.space = out_space;
|
||||||
|
result->f.attrs.secure = arm_space_is_secure(out_space);
|
||||||
result->f.phys_addr = phys_addr;
|
result->f.phys_addr = phys_addr;
|
||||||
return false;
|
return false;
|
||||||
do_fault:
|
do_fault:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue