From b5fa6563e68b909dc5a364163dd745a9427eb9f4 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Wed, 18 May 2016 16:11:47 +0100 Subject: Introduce arm_setup_page_tables() function This patch introduces the arm_setup_page_tables() function to set up page tables on ARM platforms. It replaces the arm_configure_mmu_elx() functions and does the same thing except that it doesn't enable the MMU at the end. The idea is to reduce the amount of per-EL code that is generated by the C preprocessor by splitting the memory regions definitions and page tables creation (which is generic) from the MMU enablement (which is the only per-EL configuration). As a consequence, the call to the enable_mmu_elx() function has been moved up into the plat_arch_setup() hook. Any other ARM standard platforms that use the functions `arm_configure_mmu_elx()` must be updated. Change-Id: I6f12a20ce4e5187b3849a8574aac841a136de83d --- include/plat/arm/common/plat_arm.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) (limited to 'include') diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 2fe0a690..3cee6ff0 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -45,17 +45,7 @@ /* * Utility functions common to ARM standard platforms */ - -void arm_configure_mmu_el1(unsigned long total_base, - unsigned long total_size, - unsigned long ro_start, - unsigned long ro_limit -#if USE_COHERENT_MEM - , unsigned long coh_start, - unsigned long coh_limit -#endif -); -void arm_configure_mmu_el3(unsigned long total_base, +void arm_setup_page_tables(unsigned long total_base, unsigned long total_size, unsigned long ro_start, unsigned long ro_limit -- cgit From b9161469fa95d290ba448d65e1d886ec1ff091e5 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Tue, 14 Jun 2016 16:31:09 +0100 Subject: xlat lib: Introduce MT_EXECUTE/MT_EXECUTE_NEVER attributes This patch introduces the MT_EXECUTE/MT_EXECUTE_NEVER memory mapping attributes in the translation table library to specify the access permissions for instruction execution of a memory region. These new attributes should be used only for normal, read-only memory regions. For other types of memory, the translation table library still enforces the following rules, regardless of the MT_EXECUTE/MT_EXECUTE_NEVER attribute: - Device memory is always marked as execute-never. - Read-write normal memory is always marked as execute-never. Change-Id: I8bd27800a8c1d8ac1559910caf4a4840cf25b8b0 --- include/lib/xlat_tables.h | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'include') diff --git a/include/lib/xlat_tables.h b/include/lib/xlat_tables.h index 7d57521b..b51a1de5 100644 --- a/include/lib/xlat_tables.h +++ b/include/lib/xlat_tables.h @@ -134,6 +134,8 @@ #define MT_PERM_SHIFT 3 /* Security state (SECURE/NS) */ #define MT_SEC_SHIFT 4 +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT 5 /* * Memory mapping attributes @@ -155,8 +157,21 @@ typedef enum { MT_SECURE = 0 << MT_SEC_SHIFT, MT_NS = 1 << MT_SEC_SHIFT, + + /* + * Access permissions for instruction execution are only relevant for + * normal read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored + * (and potentially overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ + MT_EXECUTE = 0 << MT_EXECUTE_SHIFT, + MT_EXECUTE_NEVER = 1 << MT_EXECUTE_SHIFT, } mmap_attr_t; +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) + /* * Structure for specifying a single region of memory. */ -- cgit From ed81f3ebbfb5abc7d0d250fbc71f297a904d71ae Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Tue, 5 Jul 2016 09:55:03 +0100 Subject: Introduce utils.h header file This patch introduces a new header file: include/lib/utils.h. Its purpose is to provide generic macros and helper functions that are independent of any BL image, architecture, platform and even not specific to Trusted Firmware. For now, it contains only 2 macros: ARRAY_SIZE() and IS_POWER_OF_TWO(). These were previously defined in bl_common.h and xlat_tables.c respectively. bl_common.h includes utils.h to retain compatibility for platforms that relied on bl_common.h for the ARRAY_SIZE() macro. Upstream platform ports that use this macro have been updated to include utils.h. Change-Id: I960450f54134f25d1710bfbdc4184f12c049a9a9 --- include/common/bl_common.h | 3 +-- include/lib/utils.h | 41 ++++++++++++++++++++++++++++++++++++++ include/plat/arm/common/plat_arm.h | 2 +- 3 files changed, 43 insertions(+), 3 deletions(-) create mode 100644 include/lib/utils.h (limited to 'include') diff --git a/include/common/bl_common.h b/include/common/bl_common.h index f13dc316..c43ad5ef 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -137,8 +137,7 @@ #include #include #include - -#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) +#include /* To retain compatibility */ /* * Declarations of linker defined symbols to help determine memory layout of diff --git a/include/lib/utils.h b/include/lib/utils.h new file mode 100644 index 00000000..d45dff34 --- /dev/null +++ b/include/lib/utils.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __UTILS_H__ +#define __UTILS_H__ + +/* Compute the number of elements in the given array */ +#define ARRAY_SIZE(a) \ + (sizeof(a) / sizeof((a)[0])) + +#define IS_POWER_OF_TWO(x) \ + (((x) & ((x) - 1)) == 0) + +#endif /* __UTILS_H__ */ diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 3cee6ff0..2a32e419 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -31,10 +31,10 @@ #define __PLAT_ARM_H__ #include -#include #include #include #include +#include #include #define ARM_CASSERT_MMAP \ -- cgit From 0146ae64c006956a281865f5688858d4846c781e Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Thu, 16 Jun 2016 15:05:39 +0100 Subject: Introduce round_up/down() macros This patch introduces the round_up() and round_down() macros, which round up (respectively down) a value to a given boundary. The boundary must be a power of two. Change-Id: I589dd1074aeb5ec730dd523b4ebf098d55a7e967 --- include/lib/utils.h | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'include') diff --git a/include/lib/utils.h b/include/lib/utils.h index d45dff34..9cc5468b 100644 --- a/include/lib/utils.h +++ b/include/lib/utils.h @@ -38,4 +38,21 @@ #define IS_POWER_OF_TWO(x) \ (((x) & ((x) - 1)) == 0) +/* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. + * In other words, it computes the smallest multiple of boundary which is + * greater than or equal to value. + * + * round_down() is similar but rounds the value down instead. + */ +#define round_boundary(value, boundary) \ + ((__typeof__(value))((boundary) - 1)) + +#define round_up(value, boundary) \ + ((((value) - 1) | round_boundary(value, boundary)) + 1) + +#define round_down(value, boundary) \ + ((value) & ~round_boundary(value, boundary)) + #endif /* __UTILS_H__ */ -- cgit From 5d1c104f9aa7e1f52607679db96e5695cac266e7 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Fri, 8 Jul 2016 14:37:40 +0100 Subject: Introduce SEPARATE_CODE_AND_RODATA build flag At the moment, all BL images share a similar memory layout: they start with their code section, followed by their read-only data section. The two sections are contiguous in memory. Therefore, the end of the code section and the beginning of the read-only data one might share a memory page. This forces both to be mapped with the same memory attributes. As the code needs to be executable, this means that the read-only data stored on the same memory page as the code are executable as well. This could potentially be exploited as part of a security attack. This patch introduces a new build flag called SEPARATE_CODE_AND_RODATA, which isolates the code and read-only data on separate memory pages. This in turn allows independent control of the access permissions for the code and read-only data. This has an impact on memory footprint, as padding bytes need to be introduced between the code and read-only data to ensure the segragation of the two. To limit the memory cost, the memory layout of the read-only section has been changed in this case. - When SEPARATE_CODE_AND_RODATA=0, the layout is unchanged, i.e. the read-only section still looks like this (padding omitted): | ... | +-------------------+ | Exception vectors | +-------------------+ | Read-only data | +-------------------+ | Code | +-------------------+ BLx_BASE In this case, the linker script provides the limits of the whole read-only section. - When SEPARATE_CODE_AND_RODATA=1, the exception vectors and read-only data are swapped, such that the code and exception vectors are contiguous, followed by the read-only data. This gives the following new layout (padding omitted): | ... | +-------------------+ | Read-only data | +-------------------+ | Exception vectors | +-------------------+ | Code | +-------------------+ BLx_BASE In this case, the linker script now exports 2 sets of addresses instead: the limits of the code and the limits of the read-only data. Refer to the Firmware Design guide for more details. This provides platform code with a finer-grained view of the image layout and allows it to map these 2 regions with the appropriate access permissions. Note that SEPARATE_CODE_AND_RODATA applies to all BL images. Change-Id: I936cf80164f6b66b6ad52b8edacadc532c935a49 --- include/common/bl_common.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include') diff --git a/include/common/bl_common.h b/include/common/bl_common.h index c43ad5ef..646a8172 100644 --- a/include/common/bl_common.h +++ b/include/common/bl_common.h @@ -143,8 +143,16 @@ * Declarations of linker defined symbols to help determine memory layout of * BL images */ +#if SEPARATE_CODE_AND_RODATA +extern unsigned long __TEXT_START__; +extern unsigned long __TEXT_END__; +extern unsigned long __RODATA_START__; +extern unsigned long __RODATA_END__; +#else extern unsigned long __RO_START__; extern unsigned long __RO_END__; +#endif + #if IMAGE_BL2 extern unsigned long __BL2_END__; #elif IMAGE_BL2U -- cgit From 0af559a833e9cb1be1e1295d00e22ecab1d3f5be Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Fri, 8 Jul 2016 14:38:16 +0100 Subject: ARM platforms: Add support for SEPARATE_CODE_AND_RODATA The arm_setup_page_tables() function used to expect a single set of addresses defining the extents of the whole read-only section, code and read-only data mixed up, which was mapped as executable. This patch changes this behaviour. arm_setup_page_tables() now expects 2 separate sets of addresses: - the extents of the code section; - the extents of the read-only data section. The code is mapped as executable, whereas the data is mapped as execute-never. New #defines have been introduced to identify the extents of the code and the read-only data section. Given that all BL images except BL1 share the same memory layout and linker script structure, these #defines are common across these images. The slight memory layout differences in BL1 have been handled by providing values specific to BL1. Note that this patch also affects the Xilinx platform port, which uses the arm_setup_page_tables() function. It has been updated accordingly, such that the memory mappings on this platform are unchanged. This is achieved by passing null values as the extents of the read-only data section so that it is ignored. As a result, the whole read-only section is still mapped as executable. Fixes ARM-software/tf-issues#85 Change-Id: I1f95865c53ce6e253a01286ff56e0aa1161abac5 --- include/plat/arm/common/plat_arm.h | 6 ++++-- include/plat/common/common_def.h | 41 +++++++++++++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 3 deletions(-) (limited to 'include') diff --git a/include/plat/arm/common/plat_arm.h b/include/plat/arm/common/plat_arm.h index 2a32e419..06912eba 100644 --- a/include/plat/arm/common/plat_arm.h +++ b/include/plat/arm/common/plat_arm.h @@ -47,8 +47,10 @@ */ void arm_setup_page_tables(unsigned long total_base, unsigned long total_size, - unsigned long ro_start, - unsigned long ro_limit + unsigned long code_start, + unsigned long code_limit, + unsigned long rodata_start, + unsigned long rodata_limit #if USE_COHERENT_MEM , unsigned long coh_start, unsigned long coh_limit diff --git a/include/plat/common/common_def.h b/include/plat/common/common_def.h index 9fac9fa2..d6b77727 100644 --- a/include/plat/common/common_def.h +++ b/include/plat/common/common_def.h @@ -80,5 +80,44 @@ .ep_info.pc = BL2_BASE, \ } -#endif /* __COMMON_DEF_H__ */ +/* + * The following constants identify the extents of the code & read-only data + * regions. These addresses are used by the MMU setup code and therefore they + * must be page-aligned. + * + * When the code and read-only data are mapped as a single atomic section + * (i.e. when SEPARATE_CODE_AND_RODATA=0) then we treat the whole section as + * code by specifying the read-only data section as empty. + * + * BL1 is different than the other images in the sense that its read-write data + * originally lives in Trusted ROM and needs to be relocated in Trusted SRAM at + * run-time. Therefore, the read-write data in ROM can be mapped with the same + * memory attributes as the read-only data region. For this reason, BL1 uses + * different macros. + * + * Note that BL1_ROM_END is not necessarily aligned on a page boundary as it + * just points to the end of BL1's actual content in Trusted ROM. Therefore it + * needs to be rounded up to the next page size in order to map the whole last + * page of it with the right memory attributes. + */ +#if SEPARATE_CODE_AND_RODATA +#define BL_CODE_BASE (unsigned long)(&__TEXT_START__) +#define BL_CODE_LIMIT (unsigned long)(&__TEXT_END__) +#define BL_RO_DATA_BASE (unsigned long)(&__RODATA_START__) +#define BL_RO_DATA_LIMIT (unsigned long)(&__RODATA_END__) + +#define BL1_CODE_LIMIT BL_CODE_LIMIT +#define BL1_RO_DATA_BASE (unsigned long)(&__RODATA_START__) +#define BL1_RO_DATA_LIMIT round_up(BL1_ROM_END, PAGE_SIZE) +#else +#define BL_CODE_BASE (unsigned long)(&__RO_START__) +#define BL_CODE_LIMIT (unsigned long)(&__RO_END__) +#define BL_RO_DATA_BASE 0 +#define BL_RO_DATA_LIMIT 0 +#define BL1_CODE_LIMIT round_up(BL1_ROM_END, PAGE_SIZE) +#define BL1_RO_DATA_BASE 0 +#define BL1_RO_DATA_LIMIT 0 +#endif /* SEPARATE_CODE_AND_RODATA */ + +#endif /* __COMMON_DEF_H__ */ -- cgit From 91fad6551ee3e5529f9b442cd4a084251cdebe1d Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Tue, 14 Jun 2016 17:01:00 +0100 Subject: ARM CSS platforms: Map flash as execute-never by default On ARM CSS platforms, the whole flash used to be mapped as executable. This is not required, given that the flash is used to store the BL1 and FIP images and: - The FIP is not executed in place, its images are copied to RAM and executed from there. - BL1 is executed in place from flash but only its code needs to be mapped as executable and platform code takes care of re-mapping BL1's read-only section as executable. Therefore, this patch now maps the flash as non-executable by default on these platforms. This increases security by restricting the executable region to what is strictly needed. This patch also adds some comments to clarify the memory mapping attributes on these platforms. Change-Id: I4db3c145508bea1f43fbe0f6dcd551e1aec1ecd3 --- include/plat/arm/board/common/v2m_def.h | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/plat/arm/board/common/v2m_def.h b/include/plat/arm/board/common/v2m_def.h index 888792ed..7cee4e8f 100644 --- a/include/plat/arm/board/common/v2m_def.h +++ b/include/plat/arm/board/common/v2m_def.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: @@ -119,13 +119,26 @@ #define V2M_SP810_CTRL_TIM2_SEL (1 << 19) #define V2M_SP810_CTRL_TIM3_SEL (1 << 21) +/* + * The flash can be mapped either as read-only or read-write. + * + * If it is read-write then it should also be mapped as device memory because + * NOR flash programming involves sending a fixed, ordered sequence of commands. + * + * If it is read-only then it should also be mapped as: + * - Normal memory, because reading from NOR flash is transparent, it is like + * reading from RAM. + * - Non-executable by default. If some parts of the flash need to be executable + * then platform code is responsible for re-mapping the appropriate portion + * of it as executable. + */ #define V2M_MAP_FLASH0_RW MAP_REGION_FLAT(V2M_FLASH0_BASE,\ V2M_FLASH0_SIZE, \ MT_DEVICE | MT_RW | MT_SECURE) #define V2M_MAP_FLASH0_RO MAP_REGION_FLAT(V2M_FLASH0_BASE,\ V2M_FLASH0_SIZE, \ - MT_MEMORY | MT_RO | MT_SECURE) + MT_RO_DATA | MT_SECURE) #define V2M_MAP_IOFPGA MAP_REGION_FLAT(V2M_IOFPGA_BASE,\ V2M_IOFPGA_SIZE, \ -- cgit