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:
Richard Henderson 2022-06-08 19:38:50 +01:00 committed by Peter Maydell
parent c8e436c9f7
commit 2c1f429df3
2 changed files with 126 additions and 123 deletions

View File

@ -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).

View File

@ -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,