mirror of
https://github.com/xemu-project/xemu.git
synced 2024-11-27 21:40:49 +00:00
target/arm: Move v8m_security_lookup to ptw.c
This function has one private helper, v8m_is_sau_exempt, so move that at the same time. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220604040607.269301-12-richard.henderson@linaro.org Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
c8e436c9f7
commit
2c1f429df3
@ -9,7 +9,6 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/units.h"
|
||||
#include "qemu/log.h"
|
||||
#include "target/arm/idau.h"
|
||||
#include "trace.h"
|
||||
#include "cpu.h"
|
||||
#include "internals.h"
|
||||
@ -11693,128 +11692,6 @@ bool m_is_system_region(CPUARMState *env, uint32_t address)
|
||||
return arm_feature(env, ARM_FEATURE_M) && extract32(address, 29, 3) == 0x7;
|
||||
}
|
||||
|
||||
static bool v8m_is_sau_exempt(CPUARMState *env,
|
||||
uint32_t address, MMUAccessType access_type)
|
||||
{
|
||||
/* The architecture specifies that certain address ranges are
|
||||
* exempt from v8M SAU/IDAU checks.
|
||||
*/
|
||||
return
|
||||
(access_type == MMU_INST_FETCH && m_is_system_region(env, address)) ||
|
||||
(address >= 0xe0000000 && address <= 0xe0002fff) ||
|
||||
(address >= 0xe000e000 && address <= 0xe000efff) ||
|
||||
(address >= 0xe002e000 && address <= 0xe002efff) ||
|
||||
(address >= 0xe0040000 && address <= 0xe0041fff) ||
|
||||
(address >= 0xe00ff000 && address <= 0xe00fffff);
|
||||
}
|
||||
|
||||
void v8m_security_lookup(CPUARMState *env, uint32_t address,
|
||||
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
||||
V8M_SAttributes *sattrs)
|
||||
{
|
||||
/* Look up the security attributes for this address. Compare the
|
||||
* pseudocode SecurityCheck() function.
|
||||
* We assume the caller has zero-initialized *sattrs.
|
||||
*/
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
int r;
|
||||
bool idau_exempt = false, idau_ns = true, idau_nsc = true;
|
||||
int idau_region = IREGION_NOTVALID;
|
||||
uint32_t addr_page_base = address & TARGET_PAGE_MASK;
|
||||
uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
|
||||
|
||||
if (cpu->idau) {
|
||||
IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
|
||||
IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
|
||||
|
||||
iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
|
||||
&idau_nsc);
|
||||
}
|
||||
|
||||
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
|
||||
/* 0xf0000000..0xffffffff is always S for insn fetches */
|
||||
return;
|
||||
}
|
||||
|
||||
if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
|
||||
sattrs->ns = !regime_is_secure(env, mmu_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (idau_region != IREGION_NOTVALID) {
|
||||
sattrs->irvalid = true;
|
||||
sattrs->iregion = idau_region;
|
||||
}
|
||||
|
||||
switch (env->sau.ctrl & 3) {
|
||||
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
|
||||
break;
|
||||
case 2: /* SAU.ENABLE == 0, SAU.ALLNS == 1 */
|
||||
sattrs->ns = true;
|
||||
break;
|
||||
default: /* SAU.ENABLE == 1 */
|
||||
for (r = 0; r < cpu->sau_sregion; r++) {
|
||||
if (env->sau.rlar[r] & 1) {
|
||||
uint32_t base = env->sau.rbar[r] & ~0x1f;
|
||||
uint32_t limit = env->sau.rlar[r] | 0x1f;
|
||||
|
||||
if (base <= address && limit >= address) {
|
||||
if (base > addr_page_base || limit < addr_page_limit) {
|
||||
sattrs->subpage = true;
|
||||
}
|
||||
if (sattrs->srvalid) {
|
||||
/* If we hit in more than one region then we must report
|
||||
* as Secure, not NS-Callable, with no valid region
|
||||
* number info.
|
||||
*/
|
||||
sattrs->ns = false;
|
||||
sattrs->nsc = false;
|
||||
sattrs->sregion = 0;
|
||||
sattrs->srvalid = false;
|
||||
break;
|
||||
} else {
|
||||
if (env->sau.rlar[r] & 2) {
|
||||
sattrs->nsc = true;
|
||||
} else {
|
||||
sattrs->ns = true;
|
||||
}
|
||||
sattrs->srvalid = true;
|
||||
sattrs->sregion = r;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Address not in this region. We must check whether the
|
||||
* region covers addresses in the same page as our address.
|
||||
* In that case we must not report a size that covers the
|
||||
* whole page for a subsequent hit against a different MPU
|
||||
* region or the background region, because it would result
|
||||
* in incorrect TLB hits for subsequent accesses to
|
||||
* addresses that are in this MPU region.
|
||||
*/
|
||||
if (limit >= base &&
|
||||
ranges_overlap(base, limit - base + 1,
|
||||
addr_page_base,
|
||||
TARGET_PAGE_SIZE)) {
|
||||
sattrs->subpage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IDAU will override the SAU lookup results if it specifies
|
||||
* higher security than the SAU does.
|
||||
*/
|
||||
if (!idau_ns) {
|
||||
if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
|
||||
sattrs->ns = false;
|
||||
sattrs->nsc = idau_nsc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Combine either inner or outer cacheability attributes for normal
|
||||
* memory, according to table D4-42 and pseudocode procedure
|
||||
* CombineS1S2AttrHints() of ARM DDI 0487B.b (the ARMv8 ARM).
|
||||
|
126
target/arm/ptw.c
126
target/arm/ptw.c
@ -11,6 +11,7 @@
|
||||
#include "qemu/range.h"
|
||||
#include "cpu.h"
|
||||
#include "internals.h"
|
||||
#include "idau.h"
|
||||
#include "ptw.h"
|
||||
|
||||
|
||||
@ -766,6 +767,131 @@ bool pmsav8_mpu_lookup(CPUARMState *env, uint32_t address,
|
||||
return !(*prot & (1 << access_type));
|
||||
}
|
||||
|
||||
static bool v8m_is_sau_exempt(CPUARMState *env,
|
||||
uint32_t address, MMUAccessType access_type)
|
||||
{
|
||||
/*
|
||||
* The architecture specifies that certain address ranges are
|
||||
* exempt from v8M SAU/IDAU checks.
|
||||
*/
|
||||
return
|
||||
(access_type == MMU_INST_FETCH && m_is_system_region(env, address)) ||
|
||||
(address >= 0xe0000000 && address <= 0xe0002fff) ||
|
||||
(address >= 0xe000e000 && address <= 0xe000efff) ||
|
||||
(address >= 0xe002e000 && address <= 0xe002efff) ||
|
||||
(address >= 0xe0040000 && address <= 0xe0041fff) ||
|
||||
(address >= 0xe00ff000 && address <= 0xe00fffff);
|
||||
}
|
||||
|
||||
void v8m_security_lookup(CPUARMState *env, uint32_t address,
|
||||
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
||||
V8M_SAttributes *sattrs)
|
||||
{
|
||||
/*
|
||||
* Look up the security attributes for this address. Compare the
|
||||
* pseudocode SecurityCheck() function.
|
||||
* We assume the caller has zero-initialized *sattrs.
|
||||
*/
|
||||
ARMCPU *cpu = env_archcpu(env);
|
||||
int r;
|
||||
bool idau_exempt = false, idau_ns = true, idau_nsc = true;
|
||||
int idau_region = IREGION_NOTVALID;
|
||||
uint32_t addr_page_base = address & TARGET_PAGE_MASK;
|
||||
uint32_t addr_page_limit = addr_page_base + (TARGET_PAGE_SIZE - 1);
|
||||
|
||||
if (cpu->idau) {
|
||||
IDAUInterfaceClass *iic = IDAU_INTERFACE_GET_CLASS(cpu->idau);
|
||||
IDAUInterface *ii = IDAU_INTERFACE(cpu->idau);
|
||||
|
||||
iic->check(ii, address, &idau_region, &idau_exempt, &idau_ns,
|
||||
&idau_nsc);
|
||||
}
|
||||
|
||||
if (access_type == MMU_INST_FETCH && extract32(address, 28, 4) == 0xf) {
|
||||
/* 0xf0000000..0xffffffff is always S for insn fetches */
|
||||
return;
|
||||
}
|
||||
|
||||
if (idau_exempt || v8m_is_sau_exempt(env, address, access_type)) {
|
||||
sattrs->ns = !regime_is_secure(env, mmu_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
if (idau_region != IREGION_NOTVALID) {
|
||||
sattrs->irvalid = true;
|
||||
sattrs->iregion = idau_region;
|
||||
}
|
||||
|
||||
switch (env->sau.ctrl & 3) {
|
||||
case 0: /* SAU.ENABLE == 0, SAU.ALLNS == 0 */
|
||||
break;
|
||||
case 2: /* SAU.ENABLE == 0, SAU.ALLNS == 1 */
|
||||
sattrs->ns = true;
|
||||
break;
|
||||
default: /* SAU.ENABLE == 1 */
|
||||
for (r = 0; r < cpu->sau_sregion; r++) {
|
||||
if (env->sau.rlar[r] & 1) {
|
||||
uint32_t base = env->sau.rbar[r] & ~0x1f;
|
||||
uint32_t limit = env->sau.rlar[r] | 0x1f;
|
||||
|
||||
if (base <= address && limit >= address) {
|
||||
if (base > addr_page_base || limit < addr_page_limit) {
|
||||
sattrs->subpage = true;
|
||||
}
|
||||
if (sattrs->srvalid) {
|
||||
/*
|
||||
* If we hit in more than one region then we must report
|
||||
* as Secure, not NS-Callable, with no valid region
|
||||
* number info.
|
||||
*/
|
||||
sattrs->ns = false;
|
||||
sattrs->nsc = false;
|
||||
sattrs->sregion = 0;
|
||||
sattrs->srvalid = false;
|
||||
break;
|
||||
} else {
|
||||
if (env->sau.rlar[r] & 2) {
|
||||
sattrs->nsc = true;
|
||||
} else {
|
||||
sattrs->ns = true;
|
||||
}
|
||||
sattrs->srvalid = true;
|
||||
sattrs->sregion = r;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Address not in this region. We must check whether the
|
||||
* region covers addresses in the same page as our address.
|
||||
* In that case we must not report a size that covers the
|
||||
* whole page for a subsequent hit against a different MPU
|
||||
* region or the background region, because it would result
|
||||
* in incorrect TLB hits for subsequent accesses to
|
||||
* addresses that are in this MPU region.
|
||||
*/
|
||||
if (limit >= base &&
|
||||
ranges_overlap(base, limit - base + 1,
|
||||
addr_page_base,
|
||||
TARGET_PAGE_SIZE)) {
|
||||
sattrs->subpage = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* The IDAU will override the SAU lookup results if it specifies
|
||||
* higher security than the SAU does.
|
||||
*/
|
||||
if (!idau_ns) {
|
||||
if (sattrs->ns || (!idau_nsc && sattrs->nsc)) {
|
||||
sattrs->ns = false;
|
||||
sattrs->nsc = idau_nsc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool get_phys_addr_pmsav8(CPUARMState *env, uint32_t address,
|
||||
MMUAccessType access_type, ARMMMUIdx mmu_idx,
|
||||
hwaddr *phys_ptr, MemTxAttrs *txattrs,
|
||||
|
Loading…
Reference in New Issue
Block a user