diff --git a/include/lib/xlat_tables/xlat_mmu_helpers.h b/include/lib/xlat_tables/xlat_mmu_helpers.h index b6c53e2..a290a92 100644 --- a/include/lib/xlat_tables/xlat_mmu_helpers.h +++ b/include/lib/xlat_tables/xlat_mmu_helpers.h @@ -41,10 +41,28 @@ */ #define XLAT_TABLE_NC (U(1) << 1) +/* + * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All + * parameters are 64 bits wide. + */ +#define MMU_CFG_MAIR 0 +#define MMU_CFG_TCR 1 +#define MMU_CFG_TTBR0 2 +#define MMU_CFG_PARAM_MAX 3 + #ifndef __ASSEMBLY__ #include +/* + * Return the values that the MMU configuration registers must contain for the + * specified translation context. `params` must be a pointer to array of size + * MMU_CFG_PARAM_MAX. + */ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime); + #ifdef AARCH32 /* AArch32 specific translation table API */ void enable_mmu_secure(unsigned int flags); diff --git a/include/lib/xlat_tables/xlat_tables_defs.h b/include/lib/xlat_tables/xlat_tables_defs.h index 5eb1d30..c9d5417 100644 --- a/include/lib/xlat_tables/xlat_tables_defs.h +++ b/include/lib/xlat_tables/xlat_tables_defs.h @@ -62,7 +62,7 @@ /* * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or - * 64KB. However, TF only supports the 4KB case at the moment. + * 64KB. However, only 4KB are supported at the moment. */ #define PAGE_SIZE_SHIFT FOUR_KB_SHIFT #define PAGE_SIZE (U(1) << PAGE_SIZE_SHIFT) diff --git a/include/lib/xlat_tables/xlat_tables_v2.h b/include/lib/xlat_tables/xlat_tables_v2.h index 20a9ea1..2e5aba5 100644 --- a/include/lib/xlat_tables/xlat_tables_v2.h +++ b/include/lib/xlat_tables/xlat_tables_v2.h @@ -121,10 +121,12 @@ } mmap_region_t; /* - * Translation regimes supported by this library. + * Translation regimes supported by this library. EL_REGIME_INVALID tells the + * library to detect it at runtime. */ #define EL1_EL0_REGIME 1 #define EL3_REGIME 3 +#define EL_REGIME_INVALID -1 /* * Declare the translation context type. @@ -165,8 +167,7 @@ (_xlat_tables_count), \ (_virt_addr_space_size), \ (_phy_addr_space_size), \ - IMAGE_XLAT_DEFAULT_REGIME, \ - "xlat_table") + EL_REGIME_INVALID, "xlat_table") /* * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: diff --git a/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/include/lib/xlat_tables/xlat_tables_v2_helpers.h index 56b9a93..82d96e7 100644 --- a/include/lib/xlat_tables/xlat_tables_v2_helpers.h +++ b/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -16,13 +16,6 @@ #error "Do not include this header file directly. Include xlat_tables_v2.h instead." #endif -/* Offsets into mmu_cfg_params array. All parameters are 32 bits wide. */ -#define MMU_CFG_MAIR0 0 -#define MMU_CFG_TCR 1 -#define MMU_CFG_TTBR0_LO 2 -#define MMU_CFG_TTBR0_HI 3 -#define MMU_CFG_PARAM_MAX 4 - #ifndef __ASSEMBLY__ #include @@ -31,9 +24,6 @@ #include #include -/* Parameters of register values required when enabling MMU */ -extern uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - /* Forward declaration */ struct mmap_region; @@ -172,29 +162,4 @@ #endif /*__ASSEMBLY__*/ -#if AARCH64 - -/* - * This IMAGE_EL macro must not to be used outside the library, and it is only - * used in AArch64. - */ -#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) -# define IMAGE_EL 3 -# define IMAGE_XLAT_DEFAULT_REGIME EL3_REGIME -#else -# define IMAGE_EL 1 -# define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME -#endif - -#else /* if AARCH32 */ - -/* - * 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. - */ -#define IMAGE_XLAT_DEFAULT_REGIME EL1_EL0_REGIME - -#endif /* AARCH64 */ - #endif /* __XLAT_TABLES_V2_HELPERS_H__ */ diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index b42cd68..ce6e341 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -195,6 +195,10 @@ desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0; desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); + /* + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ desc |= LOWER_ATTRS(ACCESS_FLAG); desc |= ap1_mask; @@ -222,9 +226,10 @@ } else { /* Normal memory */ /* * Always map read-write normal memory as execute-never. - * (Trusted Firmware doesn't self-modify its code, therefore - * R/W memory is reserved for data storage, which must not be - * executable.) + * This library assumes that it is used by software that does + * not self-modify its code, therefore R/W memory is reserved + * for data storage, which must not be executable. + * * Note that setting the XN bit here is for consistency only. * The function that enables the MMU sets the SCTLR_ELx.WXN bit, * which makes any writable memory region to be treated as diff --git a/lib/xlat_tables_v2/aarch32/enable_mmu.S b/lib/xlat_tables_v2/aarch32/enable_mmu.S index 97cdde7..99cf088 100644 --- a/lib/xlat_tables_v2/aarch32/enable_mmu.S +++ b/lib/xlat_tables_v2/aarch32/enable_mmu.S @@ -24,17 +24,17 @@ mov r3, r0 ldr r0, =mmu_cfg_params - /* MAIR0 */ - ldr r1, [r0, #(MMU_CFG_MAIR0 << 2)] + /* MAIR0. Only the lower 32 bits are used. */ + ldr r1, [r0, #(MMU_CFG_MAIR << 3)] stcopr r1, MAIR0 - /* TTBCR */ - ldr r2, [r0, #(MMU_CFG_TCR << 2)] + /* TTBCR. Only the lower 32 bits are used. */ + ldr r2, [r0, #(MMU_CFG_TCR << 3)] stcopr r2, TTBCR /* TTBR0 */ - ldr r1, [r0, #(MMU_CFG_TTBR0_LO << 2)] - ldr r2, [r0, #(MMU_CFG_TTBR0_HI << 2)] + ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)] + ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)] stcopr16 r1, r2, TTBR0_64 /* TTBR1 is unused right now; set it to 0. */ diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c index 6e97192..5e3220c 100644 --- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -18,16 +18,14 @@ #error ARMv7 target does not support LPAE MMU descriptors #endif -uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - /* * Returns 1 if the provided granule size is supported, 0 otherwise. */ int xlat_arch_is_granule_size_supported(size_t size) { /* - * The Trusted Firmware uses long descriptor translation table format, - * which supports 4 KiB pages only. + * The library uses the long descriptor translation table format, which + * supports 4 KiB pages only. */ return (size == (4U * 1024U)); } @@ -50,18 +48,12 @@ return (read_sctlr() & SCTLR_M_BIT) != 0; } -void xlat_arch_tlbi_va(uintptr_t va) +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime __unused) { - /* - * Ensure the translation table write has drained into memory before - * invalidating the TLB entry. - */ - dsbishst(); - - tlbimvaais(TLBI_ADDR(va)); + return UPPER_ATTRS(XN); } -void xlat_arch_tlbi_va_regime(uintptr_t va, int xlat_regime __unused) +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime __unused) { /* * Ensure the translation table write has drained into memory before @@ -103,29 +95,32 @@ /* * 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 3; + return 1; } /******************************************************************************* * Function for enabling the MMU in Secure PL1, assuming that the page tables * have already been created. ******************************************************************************/ -void setup_mmu_cfg(unsigned int flags, - const uint64_t *base_table, - unsigned long long max_pa, - uintptr_t max_va) +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) { - u_register_t mair0, ttbcr; - uint64_t ttbr0; + uint64_t mair, ttbr0; + uint32_t ttbcr; assert(IS_IN_SECURE()); /* Set attributes in the right indices of the MAIR */ - mair0 = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); - mair0 |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + mair = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); - mair0 |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, + mair |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); /* @@ -173,17 +168,17 @@ /* 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. - * Mandatory for ARMv8.2 implementations. + * 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 */ - mmu_cfg_params[MMU_CFG_MAIR0] = mair0; - mmu_cfg_params[MMU_CFG_TCR] = ttbcr; - mmu_cfg_params[MMU_CFG_TTBR0_LO] = (uint32_t) ttbr0; - mmu_cfg_params[MMU_CFG_TTBR0_HI] = ttbr0 >> 32; + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = (uint64_t) ttbcr; + params[MMU_CFG_TTBR0] = ttbr0; } diff --git a/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h deleted file mode 100644 index 9b41f4d..0000000 --- a/lib/xlat_tables_v2/aarch32/xlat_tables_arch_private.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__ -#define __XLAT_TABLES_ARCH_PRIVATE_H__ - -#include -#include - -/* - * Return the execute-never mask that will prevent instruction fetch at the - * given translation regime. - */ -static inline uint64_t xlat_arch_regime_get_xn_desc(int regime __unused) -{ - return UPPER_ATTRS(XN); -} - -#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */ diff --git a/lib/xlat_tables_v2/aarch64/enable_mmu.S b/lib/xlat_tables_v2/aarch64/enable_mmu.S index a72c7fa..5c5a2a9 100644 --- a/lib/xlat_tables_v2/aarch64/enable_mmu.S +++ b/lib/xlat_tables_v2/aarch64/enable_mmu.S @@ -43,17 +43,15 @@ ldr x0, =mmu_cfg_params /* MAIR */ - ldr w1, [x0, #(MMU_CFG_MAIR0 << 2)] + ldr x1, [x0, #(MMU_CFG_MAIR << 3)] _msr mair, \el, x1 /* TCR */ - ldr w2, [x0, #(MMU_CFG_TCR << 2)] + ldr x2, [x0, #(MMU_CFG_TCR << 3)] _msr tcr, \el, x2 /* TTBR */ - ldr w3, [x0, #(MMU_CFG_TTBR0_LO << 2)] - ldr w4, [x0, #(MMU_CFG_TTBR0_HI << 2)] - orr x3, x3, x4, lsl #32 + ldr x3, [x0, #(MMU_CFG_TTBR0 << 3)] _msr ttbr0, \el, x3 /* diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c index 4bbbe54..0f289e2 100644 --- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +++ b/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -13,8 +13,6 @@ #include #include "../xlat_tables_private.h" -uint32_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - /* * Returns 1 if the provided granule size is supported, 0 otherwise. */ @@ -113,19 +111,17 @@ } } - -void xlat_arch_tlbi_va(uintptr_t va) +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) { -#if IMAGE_EL == 1 - assert(IS_IN_EL(1)); - xlat_arch_tlbi_va_regime(va, EL1_EL0_REGIME); -#elif IMAGE_EL == 3 - assert(IS_IN_EL(3)); - xlat_arch_tlbi_va_regime(va, EL3_REGIME); -#endif + if (xlat_regime == EL1_EL0_REGIME) { + return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN); + } else { + assert(xlat_regime == EL3_REGIME); + return UPPER_ATTRS(XN); + } } -void xlat_arch_tlbi_va_regime(uintptr_t va, int xlat_regime) +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime) { /* * Ensure the translation table write has drained into memory before @@ -182,12 +178,11 @@ return el; } -void setup_mmu_cfg(unsigned int flags, - const uint64_t *base_table, - unsigned long long max_pa, - uintptr_t max_va) +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime) { - uint64_t mair, ttbr, tcr; + uint64_t mair, ttbr0, tcr; uintptr_t virtual_addr_space_size; /* Set attributes in the right indices of the MAIR. */ @@ -195,8 +190,6 @@ mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); - ttbr = (uint64_t) base_table; - /* * Limit the input address ranges and memory region sizes translated * using TTBR0 to the given virtual address space size. @@ -232,30 +225,29 @@ */ unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa); -#if IMAGE_EL == 1 - assert(IS_IN_EL(1)); - /* - * TCR_EL1.EPD1: Disable translation table walk for addresses that are - * translated using TTBR1_EL1. - */ - tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT); -#elif IMAGE_EL == 3 - assert(IS_IN_EL(3)); - tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT); -#endif - - mmu_cfg_params[MMU_CFG_MAIR0] = (uint32_t) mair; - mmu_cfg_params[MMU_CFG_TCR] = (uint32_t) tcr; - - /* Set TTBR bits as well */ - if (ARM_ARCH_AT_LEAST(8, 2)) { + if (xlat_regime == EL1_EL0_REGIME) { /* - * Enable CnP bit so as to share page tables with all PEs. This - * is mandatory for ARMv8.2 implementations. + * TCR_EL1.EPD1: Disable translation table walk for addresses + * that are translated using TTBR1_EL1. */ - ttbr |= TTBR_CNP_BIT; + tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT); + } else { + assert(xlat_regime == EL3_REGIME); + tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT); } - mmu_cfg_params[MMU_CFG_TTBR0_LO] = (uint32_t) ttbr; - mmu_cfg_params[MMU_CFG_TTBR0_HI] = (uint32_t) (ttbr >> 32); + /* Set TTBR bits as well */ + ttbr0 = (uint64_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 + + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = tcr; + params[MMU_CFG_TTBR0] = ttbr0; } diff --git a/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h b/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h deleted file mode 100644 index 39b0a65..0000000 --- a/lib/xlat_tables_v2/aarch64/xlat_tables_arch_private.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. - * - * SPDX-License-Identifier: BSD-3-Clause - */ - -#ifndef __XLAT_TABLES_ARCH_PRIVATE_H__ -#define __XLAT_TABLES_ARCH_PRIVATE_H__ - -#include -#include -#include - -/* - * Return the execute-never mask that will prevent instruction fetch at all ELs - * that are part of the given translation regime. - */ -static inline uint64_t xlat_arch_regime_get_xn_desc(int regime) -{ - if (regime == EL1_EL0_REGIME) { - return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN); - } else { - assert(regime == EL3_REGIME); - return UPPER_ATTRS(XN); - } -} - -#endif /* __XLAT_TABLES_ARCH_PRIVATE_H__ */ diff --git a/lib/xlat_tables_v2/xlat_tables.mk b/lib/xlat_tables_v2/xlat_tables.mk index b25c805..9507ad7 100644 --- a/lib/xlat_tables_v2/xlat_tables.mk +++ b/lib/xlat_tables_v2/xlat_tables.mk @@ -10,5 +10,3 @@ xlat_tables_context.c \ xlat_tables_core.c \ xlat_tables_utils.c) - -INCLUDES += -Ilib/xlat_tables_v2/${ARCH} diff --git a/lib/xlat_tables_v2/xlat_tables_context.c b/lib/xlat_tables_v2/xlat_tables_context.c index 0964b49..76c429d 100644 --- a/lib/xlat_tables_v2/xlat_tables_context.c +++ b/lib/xlat_tables_v2/xlat_tables_context.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: BSD-3-Clause */ +#include #include #include #include @@ -12,6 +13,12 @@ #include "xlat_tables_private.h" /* + * MMU configuration register values for the active translation context. Used + * from the MMU assembly helpers. + */ +uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* * Each platform can define the size of its physical and virtual address spaces. * If the platform hasn't defined one or both of them, default to * ADDR_SPACE_SIZE. The latter is deprecated, though. @@ -69,6 +76,17 @@ void init_xlat_tables(void) { + assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); + + int current_el = xlat_arch_current_el(); + + if (current_el == 1) { + tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME; + } else { + assert(current_el == 3); + tf_xlat_ctx.xlat_regime = EL3_REGIME; + } + init_xlat_tables_ctx(&tf_xlat_ctx); } @@ -93,8 +111,9 @@ void enable_mmu_secure(unsigned int flags) { - setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR, - tf_xlat_ctx.va_max_address); + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); enable_mmu_direct(flags); } @@ -102,15 +121,17 @@ void enable_mmu_el1(unsigned int flags) { - setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR, - tf_xlat_ctx.va_max_address); + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); enable_mmu_direct_el1(flags); } void enable_mmu_el3(unsigned int flags) { - setup_mmu_cfg(flags, tf_xlat_ctx.base_table, MAX_PHYS_ADDR, - tf_xlat_ctx.va_max_address); + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL3_REGIME); enable_mmu_direct_el3(flags); } diff --git a/lib/xlat_tables_v2/xlat_tables_core.c b/lib/xlat_tables_v2/xlat_tables_core.c index f555524..e3306e6 100644 --- a/lib/xlat_tables_v2/xlat_tables_core.c +++ b/lib/xlat_tables_v2/xlat_tables_core.c @@ -12,7 +12,6 @@ #include #include #include -#include #include #include @@ -104,12 +103,14 @@ */ desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; /* - * Always set the access flag, as TF doesn't manage access flag faults. + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ + desc |= LOWER_ATTRS(ACCESS_FLAG); + /* * Deduce other fields of the descriptor based on the MT_NS and MT_RW * memory region attributes. */ - desc |= LOWER_ATTRS(ACCESS_FLAG); - desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0; desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); @@ -155,9 +156,10 @@ } else { /* Normal memory */ /* * Always map read-write normal memory as execute-never. - * (Trusted Firmware doesn't self-modify its code, therefore - * R/W memory is reserved for data storage, which must not be - * executable.) + * This library assumes that it is used by software that does + * not self-modify its code, therefore R/W memory is reserved + * for data storage, which must not be executable. + * * Note that setting the XN bit here is for consistency only. * The function that enables the MMU sets the SCTLR_ELx.WXN bit, * which makes any writable memory region to be treated as @@ -311,7 +313,7 @@ if (action == ACTION_WRITE_BLOCK_ENTRY) { table_base[table_idx] = INVALID_DESC; - xlat_arch_tlbi_va_regime(table_idx_va, ctx->xlat_regime); + xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); } else if (action == ACTION_RECURSE_INTO_TABLE) { @@ -327,8 +329,8 @@ */ if (xlat_table_is_empty(ctx, subtable)) { table_base[table_idx] = INVALID_DESC; - xlat_arch_tlbi_va_regime(table_idx_va, - ctx->xlat_regime); + xlat_arch_tlbi_va(table_idx_va, + ctx->xlat_regime); } } else { diff --git a/lib/xlat_tables_v2/xlat_tables_private.h b/lib/xlat_tables_v2/xlat_tables_private.h index 4a54ec5..93640dd 100644 --- a/lib/xlat_tables_v2/xlat_tables_private.h +++ b/lib/xlat_tables_v2/xlat_tables_private.h @@ -36,21 +36,23 @@ #endif /* PLAT_XLAT_TABLES_DYNAMIC */ /* + * Return the execute-never mask that will prevent instruction fetch at the + * given translation regime. + */ +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime); + +/* * Invalidate all TLB entries that match the given virtual address. This * operation applies to all PEs in the same Inner Shareable domain as the PE * that executes this function. This functions must be called for every - * translation table entry that is modified. - * - * xlat_arch_tlbi_va() applies the invalidation to the exception level of the - * current translation regime, whereas xlat_arch_tlbi_va_regime() applies it to - * the given translation regime. + * translation table entry that is modified. It only affects the specified + * translation regime. * * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries * pertaining to a higher exception level, e.g. invalidating EL3 entries from * S-EL1. */ -void xlat_arch_tlbi_va(uintptr_t va); -void xlat_arch_tlbi_va_regime(uintptr_t va, int xlat_regime); +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime); /* * This function has to be called at the end of any code that uses the function @@ -86,10 +88,6 @@ */ unsigned long long xlat_arch_get_max_supported_pa(void); -/* Enable MMU and configure it to use the specified translation tables. */ -void setup_mmu_cfg(unsigned int flags, const uint64_t *base_table, - unsigned long long max_pa, uintptr_t max_va); - /* * Return 1 if the MMU of the translation regime managed by the given xlat_ctx_t * is enabled, 0 otherwise. diff --git a/lib/xlat_tables_v2/xlat_tables_utils.c b/lib/xlat_tables_v2/xlat_tables_utils.c index 5a78434..90a0a86 100644 --- a/lib/xlat_tables_v2/xlat_tables_utils.c +++ b/lib/xlat_tables_v2/xlat_tables_utils.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include @@ -544,7 +543,7 @@ *entry = INVALID_DESC; /* Invalidate any cached copy of this mapping in the TLBs. */ - xlat_arch_tlbi_va_regime(base_va, ctx->xlat_regime); + xlat_arch_tlbi_va(base_va, ctx->xlat_regime); /* Ensure completion of the invalidation. */ xlat_arch_tlbi_va_sync(); diff --git a/services/std_svc/spm/sp_setup.c b/services/std_svc/spm/sp_setup.c index b9b67f7..0d61306 100644 --- a/services/std_svc/spm/sp_setup.c +++ b/services/std_svc/spm/sp_setup.c @@ -107,38 +107,22 @@ * MMU-related registers * --------------------- */ + xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; - /* Set attributes in the right indices of the MAIR */ - u_register_t mair_el1 = - MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX) | - MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX) | - MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); + uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; - write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, mair_el1); + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, + xlat_ctx->pa_max_address, xlat_ctx->va_max_address, + EL1_EL0_REGIME); - /* Setup TCR_EL1. */ - u_register_t tcr_ps_bits = tcr_physical_addr_size_bits(PLAT_PHY_ADDR_SPACE_SIZE); + write_ctx_reg(get_sysregs_ctx(ctx), CTX_MAIR_EL1, + mmu_cfg_params[MMU_CFG_MAIR]); - u_register_t tcr_el1 = - /* Size of region addressed by TTBR0_EL1 = 2^(64-T0SZ) bytes. */ - (64 - __builtin_ctzl(PLAT_VIRT_ADDR_SPACE_SIZE)) | - /* Inner and outer WBWA, shareable. */ - TCR_SH_INNER_SHAREABLE | TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA | - /* Set the granularity to 4KB. */ - TCR_TG0_4K | - /* Limit Intermediate Physical Address Size. */ - tcr_ps_bits << TCR_EL1_IPS_SHIFT | - /* Disable translations using TBBR1_EL1. */ - TCR_EPD1_BIT - /* The remaining fields related to TBBR1_EL1 are left as zero. */ - ; + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, + mmu_cfg_params[MMU_CFG_TCR]); - tcr_el1 &= ~( - /* Enable translations using TBBR0_EL1 */ - TCR_EPD0_BIT - ); - - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TCR_EL1, tcr_el1); + write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, + mmu_cfg_params[MMU_CFG_TTBR0]); /* Setup SCTLR_EL1 */ u_register_t sctlr_el1 = read_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1); @@ -174,13 +158,6 @@ write_ctx_reg(get_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); - uint64_t *xlat_base = - ((xlat_ctx_t *)sp_ctx->xlat_ctx_handle)->base_table; - - /* Point TTBR0_EL1 at the tables of the context created for the SP. */ - write_ctx_reg(get_sysregs_ctx(ctx), CTX_TTBR0_EL1, - (u_register_t)xlat_base); - /* * Setup other system registers * ----------------------------