arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c
Antonio Nino Diaz 09d40e0e08 Sanitise includes across codebase
Enforce full include path for includes. Deprecate old paths.

The following folders inside include/lib have been left unchanged:

- include/lib/cpus/${ARCH}
- include/lib/el3_runtime/${ARCH}

The reason for this change is that having a global namespace for
includes isn't a good idea. It defeats one of the advantages of having
folders and it introduces problems that are sometimes subtle (because
you may not know the header you are actually including if there are two
of them).

For example, this patch had to be created because two headers were
called the same way: e0ea0928d5 ("Fix gpio includes of mt8173 platform
to avoid collision."). More recently, this patch has had similar
problems: 46f9b2c3a2 ("drivers: add tzc380 support").

This problem was introduced in commit 4ecca33988 ("Move include and
source files to logical locations"). At that time, there weren't too
many headers so it wasn't a real issue. However, time has shown that
this creates problems.

Platforms that want to preserve the way they include headers may add the
removed paths to PLAT_INCLUDES, but this is discouraged.

Change-Id: I39dc53ed98f9e297a5966e723d1936d6ccf2fc8f
Signed-off-by: Antonio Nino Diaz <antonio.ninodiaz@arm.com>
2019-01-04 10:43:17 +00:00

235 lines
6.2 KiB
C

/*
* Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <assert.h>
#include <stdbool.h>
#include <platform_def.h>
#include <arch.h>
#include <arch_helpers.h>
#include <lib/cassert.h>
#include <lib/utils_def.h>
#include <lib/xlat_tables/xlat_tables_v2.h>
#include "../xlat_tables_private.h"
#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING)
#error ARMv7 target does not support LPAE MMU descriptors
#endif
/*
* Returns true if the provided granule size is supported, false otherwise.
*/
bool xlat_arch_is_granule_size_supported(size_t size)
{
/*
* The library uses the long descriptor translation table format, which
* supports 4 KiB pages only.
*/
return size == PAGE_SIZE_4KB;
}
size_t xlat_arch_get_max_supported_granule_size(void)
{
return PAGE_SIZE_4KB;
}
#if ENABLE_ASSERTIONS
unsigned long long xlat_arch_get_max_supported_pa(void)
{
/* Physical address space size for long descriptor format. */
return (1ULL << 40) - 1ULL;
}
#endif /* ENABLE_ASSERTIONS*/
bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx)
{
if (ctx->xlat_regime == EL1_EL0_REGIME) {
assert(xlat_arch_current_el() == 1U);
return (read_sctlr() & SCTLR_M_BIT) != 0U;
} else {
assert(ctx->xlat_regime == EL2_REGIME);
assert(xlat_arch_current_el() == 2U);
return (read_hsctlr() & HSCTLR_M_BIT) != 0U;
}
}
bool is_dcache_enabled(void)
{
if (IS_IN_EL2()) {
return (read_hsctlr() & HSCTLR_C_BIT) != 0U;
} else {
return (read_sctlr() & SCTLR_C_BIT) != 0U;
}
}
uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime)
{
if (xlat_regime == EL1_EL0_REGIME) {
return UPPER_ATTRS(XN) | UPPER_ATTRS(PXN);
} else {
assert(xlat_regime == EL2_REGIME);
return UPPER_ATTRS(XN);
}
}
void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime)
{
/*
* Ensure the translation table write has drained into memory before
* invalidating the TLB entry.
*/
dsbishst();
if (xlat_regime == EL1_EL0_REGIME) {
tlbimvaais(TLBI_ADDR(va));
} else {
assert(xlat_regime == EL2_REGIME);
tlbimvahis(TLBI_ADDR(va));
}
}
void xlat_arch_tlbi_va_sync(void)
{
/* Invalidate all entries from branch predictors. */
bpiallis();
/*
* A TLB maintenance instruction can complete at any time after
* it is issued, but is only guaranteed to be complete after the
* execution of DSB by the PE that executed the TLB maintenance
* instruction. After the TLB invalidate instruction is
* complete, no new memory accesses using the invalidated TLB
* entries will be observed by any observer of the system
* domain. See section D4.8.2 of the ARMv8 (issue k), paragraph
* "Ordering and completion of TLB maintenance instructions".
*/
dsbish();
/*
* The effects of a completed TLB maintenance instruction are
* only guaranteed to be visible on the PE that executed the
* instruction after the execution of an ISB instruction by the
* PE that executed the TLB maintenance instruction.
*/
isb();
}
unsigned int xlat_arch_current_el(void)
{
if (IS_IN_HYP()) {
return 2U;
} else {
assert(IS_IN_SVC() || IS_IN_MON());
/*
* If EL3 is in AArch32 mode, all secure PL1 modes (Monitor,
* System, SVC, Abort, UND, IRQ and FIQ modes) execute at EL3.
*
* The PL1&0 translation regime in AArch32 behaves like the
* EL1&0 regime in AArch64 except for the XN bits, but we set
* and unset them at the same time, so there's no difference in
* practice.
*/
return 1U;
}
}
/*******************************************************************************
* Function for enabling the MMU in PL1 or PL2, assuming that the page tables
* have already been created.
******************************************************************************/
void setup_mmu_cfg(uint64_t *params, unsigned int flags,
const uint64_t *base_table, unsigned long long max_pa,
uintptr_t max_va, __unused int xlat_regime)
{
uint64_t mair, ttbr0;
uint32_t ttbcr;
/* Set attributes in the right indices of the MAIR */
mair = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX);
mair |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR,
ATTR_IWBWA_OWBWA_NTR_INDEX);
mair |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE,
ATTR_NON_CACHEABLE_INDEX);
/*
* Configure the control register for stage 1 of the PL1&0 or EL2
* translation regimes.
*/
/* Use the Long-descriptor translation table format. */
ttbcr = TTBCR_EAE_BIT;
if (xlat_regime == EL1_EL0_REGIME) {
assert(IS_IN_SVC() || IS_IN_MON());
/*
* Disable translation table walk for addresses that are
* translated using TTBR1. Therefore, only TTBR0 is used.
*/
ttbcr |= TTBCR_EPD1_BIT;
} else {
assert(xlat_regime == EL2_REGIME);
assert(IS_IN_HYP());
/*
* Set HTCR bits as well. Set HTTBR table properties
* as Inner & outer WBWA & shareable.
*/
ttbcr |= HTCR_RES1 |
HTCR_SH0_INNER_SHAREABLE | HTCR_RGN0_OUTER_WBA |
HTCR_RGN0_INNER_WBA;
}
/*
* Limit the input address ranges and memory region sizes translated
* using TTBR0 to the given virtual address space size, if smaller than
* 32 bits.
*/
if (max_va != UINT32_MAX) {
uintptr_t virtual_addr_space_size = max_va + 1U;
assert(CHECK_VIRT_ADDR_SPACE_SIZE(virtual_addr_space_size));
/*
* __builtin_ctzll(0) is undefined but here we are guaranteed
* that virtual_addr_space_size is in the range [1, UINT32_MAX].
*/
int t0sz = 32 - __builtin_ctzll(virtual_addr_space_size);
ttbcr |= (uint32_t) t0sz;
}
/*
* Set the cacheability and shareability attributes for memory
* associated with translation table walks using TTBR0.
*/
if ((flags & XLAT_TABLE_NC) != 0U) {
/* Inner & outer non-cacheable non-shareable. */
ttbcr |= TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC |
TTBCR_RGN0_INNER_NC;
} else {
/* Inner & outer WBWA & shareable. */
ttbcr |= TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA |
TTBCR_RGN0_INNER_WBA;
}
/* Set TTBR0 bits as well */
ttbr0 = (uint64_t)(uintptr_t) base_table;
#if ARM_ARCH_AT_LEAST(8, 2)
/*
* Enable CnP bit so as to share page tables with all PEs. This
* is mandatory for ARMv8.2 implementations.
*/
ttbr0 |= TTBR_CNP_BIT;
#endif
/* Now populate MMU configuration */
params[MMU_CFG_MAIR] = mair;
params[MMU_CFG_TCR] = (uint64_t) ttbcr;
params[MMU_CFG_TTBR0] = ttbr0;
}