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 +---- plat/arm/board/common/board_css_common.c | 8 +-- plat/arm/board/fvp/fvp_common.c | 6 +-- plat/arm/common/aarch64/arm_common.c | 87 ++++++++++++++------------------ plat/arm/common/arm_bl1_setup.c | 3 +- plat/arm/common/arm_bl2_setup.c | 3 +- plat/arm/common/arm_bl2u_setup.c | 5 +- plat/arm/common/arm_bl31_setup.c | 9 ++-- plat/arm/common/tsp/arm_tsp_setup.c | 5 +- plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 6 +-- plat/xilinx/zynqmp/tsp/tsp_plat_setup.c | 5 +- 11 files changed, 69 insertions(+), 80 deletions(-) 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 diff --git a/plat/arm/board/common/board_css_common.c b/plat/arm/board/common/board_css_common.c index 62253f8c..69b744d9 100644 --- a/plat/arm/board/common/board_css_common.c +++ b/plat/arm/board/common/board_css_common.c @@ -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: @@ -31,9 +31,9 @@ #include /* - * Table of regions for different BL stages to map using the MMU. - * This doesn't include Trusted RAM as the 'mem_layout' argument passed to - * arm_configure_mmu_elx() will give the available subset of that, + * Table of memory regions for different BL stages to map using the MMU. + * This doesn't include Trusted SRAM as arm_setup_page_tables() already + * takes care of mapping it. */ #if IMAGE_BL1 const mmap_region_t plat_arm_mmap[] = { diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index 0f557af2..affd0b82 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -66,9 +66,9 @@ arm_config_t arm_config; /* - * Table of regions for various BL stages to map using the MMU. - * This doesn't include TZRAM as the 'mem_layout' argument passed to - * arm_configure_mmu_elx() will give the available subset of that, + * Table of memory regions for various BL stages to map using the MMU. + * This doesn't include Trusted SRAM as arm_setup_page_tables() already + * takes care of mapping it. */ #if IMAGE_BL1 const mmap_region_t plat_arm_mmap[] = { diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c index c4cc80e6..c0a7e6b4 100644 --- a/plat/arm/common/aarch64/arm_common.c +++ b/plat/arm/common/aarch64/arm_common.c @@ -50,57 +50,48 @@ extern const mmap_region_t plat_arm_mmap[]; #pragma weak plat_get_syscnt_freq #endif -/******************************************************************************* - * Macro generating the code for the function setting up the pagetables as per - * the platform memory map & initialize the mmu, for the given exception level - ******************************************************************************/ +/* + * Set up the page tables for the generic and platform-specific memory regions. + * The extents of the generic memory regions are specified by the function + * arguments and consist of: + * - Trusted SRAM seen by the BL image; + * - Read-only section (code and read-only data); + * - Coherent memory region, if applicable. + */ +void arm_setup_page_tables(unsigned long total_base, + unsigned long total_size, + unsigned long ro_start, + unsigned long ro_limit #if USE_COHERENT_MEM -#define DEFINE_CONFIGURE_MMU_EL(_el) \ - void arm_configure_mmu_el##_el(unsigned long total_base, \ - unsigned long total_size, \ - unsigned long ro_start, \ - unsigned long ro_limit, \ - unsigned long coh_start, \ - unsigned long coh_limit) \ - { \ - mmap_add_region(total_base, total_base, \ - total_size, \ - MT_MEMORY | MT_RW | MT_SECURE); \ - mmap_add_region(ro_start, ro_start, \ - ro_limit - ro_start, \ - MT_MEMORY | MT_RO | MT_SECURE); \ - mmap_add_region(coh_start, coh_start, \ - coh_limit - coh_start, \ - MT_DEVICE | MT_RW | MT_SECURE); \ - mmap_add(plat_arm_get_mmap()); \ - init_xlat_tables(); \ - \ - enable_mmu_el##_el(0); \ - } -#else -#define DEFINE_CONFIGURE_MMU_EL(_el) \ - void arm_configure_mmu_el##_el(unsigned long total_base, \ - unsigned long total_size, \ - unsigned long ro_start, \ - unsigned long ro_limit) \ - { \ - mmap_add_region(total_base, total_base, \ - total_size, \ - MT_MEMORY | MT_RW | MT_SECURE); \ - mmap_add_region(ro_start, ro_start, \ - ro_limit - ro_start, \ - MT_MEMORY | MT_RO | MT_SECURE); \ - mmap_add(plat_arm_get_mmap()); \ - init_xlat_tables(); \ - \ - enable_mmu_el##_el(0); \ - } + , + unsigned long coh_start, + unsigned long coh_limit #endif + ) +{ + /* + * Map the Trusted SRAM with appropriate memory attributes. + * Subsequent mappings will adjust the attributes for specific regions. + */ + mmap_add_region(total_base, total_base, + total_size, + MT_MEMORY | MT_RW | MT_SECURE); + /* Re-map the read-only section */ + mmap_add_region(ro_start, ro_start, + ro_limit - ro_start, + MT_MEMORY | MT_RO | MT_SECURE); +#if USE_COHERENT_MEM + /* Re-map the coherent memory region */ + mmap_add_region(coh_start, coh_start, + coh_limit - coh_start, + MT_DEVICE | MT_RW | MT_SECURE); +#endif + /* Now (re-)map the platform-specific memory regions */ + mmap_add(plat_arm_get_mmap()); -/* Define EL1 and EL3 variants of the function initialising the MMU */ -DEFINE_CONFIGURE_MMU_EL(1) -DEFINE_CONFIGURE_MMU_EL(3) - + /* Create the page tables to reflect the above mappings */ + init_xlat_tables(); +} uintptr_t plat_get_ns_image_entrypoint(void) { diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 951f48a5..1ffd7ee2 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -118,7 +118,7 @@ void bl1_early_platform_setup(void) *****************************************************************************/ void arm_bl1_plat_arch_setup(void) { - arm_configure_mmu_el3(bl1_tzram_layout.total_base, + arm_setup_page_tables(bl1_tzram_layout.total_base, bl1_tzram_layout.total_size, BL1_RO_BASE, BL1_RO_LIMIT @@ -127,6 +127,7 @@ void arm_bl1_plat_arch_setup(void) BL1_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el3(0); } void bl1_plat_arch_setup(void) diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index 681dc8ad..e8e7928c 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -234,7 +234,7 @@ void bl2_platform_setup(void) ******************************************************************************/ void arm_bl2_plat_arch_setup(void) { - arm_configure_mmu_el1(bl2_tzram_layout.total_base, + arm_setup_page_tables(bl2_tzram_layout.total_base, bl2_tzram_layout.total_size, BL2_RO_BASE, BL2_RO_LIMIT @@ -243,6 +243,7 @@ void arm_bl2_plat_arch_setup(void) BL2_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el1(0); } void bl2_plat_arch_setup(void) diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index 5b7354b3..5f2634a2 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -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: @@ -102,7 +102,7 @@ void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) ******************************************************************************/ void arm_bl2u_plat_arch_setup(void) { - arm_configure_mmu_el1(BL2U_RO_LIMIT, + arm_setup_page_tables(BL2U_RO_LIMIT, BL31_LIMIT, BL2U_RO_BASE, BL2U_RO_LIMIT @@ -112,6 +112,7 @@ void arm_bl2u_plat_arch_setup(void) BL2U_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el1(0); } void bl2u_plat_arch_setup(void) diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 8eb68180..9cfa3b8b 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -246,12 +246,14 @@ void bl31_plat_runtime_setup(void) } /******************************************************************************* - * Perform the very early platform specific architectural setup here. At the - * moment this is only intializes the mmu in a quick and dirty way. + * Perform the very early platform specific architectural setup shared between + * ARM standard platforms. This only does basic initialization. Later + * architectural setup (bl31_arch_setup()) does not do anything platform + * specific. ******************************************************************************/ void arm_bl31_plat_arch_setup(void) { - arm_configure_mmu_el3(BL31_RO_BASE, + arm_setup_page_tables(BL31_RO_BASE, (BL31_END - BL31_RO_BASE), BL31_RO_BASE, BL31_RO_LIMIT @@ -260,6 +262,7 @@ void arm_bl31_plat_arch_setup(void) BL31_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el3(0); } void bl31_plat_arch_setup(void) diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c index 2a67fd10..6c6ceea0 100644 --- a/plat/arm/common/tsp/arm_tsp_setup.c +++ b/plat/arm/common/tsp/arm_tsp_setup.c @@ -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: @@ -98,7 +98,7 @@ void tsp_platform_setup(void) ******************************************************************************/ void tsp_plat_arch_setup(void) { - arm_configure_mmu_el1(BL32_RO_BASE, + arm_setup_page_tables(BL32_RO_BASE, (BL32_END - BL32_RO_BASE), BL32_RO_BASE, BL32_RO_LIMIT @@ -107,4 +107,5 @@ void tsp_plat_arch_setup(void) BL32_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el1(0); } diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index 6f1a18b1..2ea8b1c9 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -147,18 +147,18 @@ void bl31_plat_runtime_setup(void) } /* - * Perform the very early platform specific architectural setup here. At the - * moment this is only intializes the MMU in a quick and dirty way. + * Perform the very early platform specific architectural setup here. */ void bl31_plat_arch_setup(void) { plat_arm_interconnect_init(); plat_arm_interconnect_enter_coherency(); - arm_configure_mmu_el3(BL31_RO_BASE, + arm_setup_page_tables(BL31_RO_BASE, BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE, BL31_RO_BASE, BL31_RO_LIMIT, BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT); + enable_mmu_el3(0); } diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c index 58a3e2a1..19e2c129 100644 --- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2014-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: @@ -90,7 +90,7 @@ void tsp_platform_setup(void) ******************************************************************************/ void tsp_plat_arch_setup(void) { - arm_configure_mmu_el1(BL32_RO_BASE, + arm_setup_page_tables(BL32_RO_BASE, (BL32_END - BL32_RO_BASE), BL32_RO_BASE, BL32_RO_LIMIT @@ -99,4 +99,5 @@ void tsp_plat_arch_setup(void) BL32_COHERENT_RAM_LIMIT #endif ); + enable_mmu_el1(0); } -- cgit From bcbe19afaa7a19083164dd1be80c741d23ee9caf Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Tue, 14 Jun 2016 16:29:04 +0100 Subject: xlat lib: Refactor mmap_desc() function This patch clarifies the mmap_desc() function by adding some comments and reorganising its code. No functional change has been introduced. Change-Id: I873493be17b4e60a89c1dc087dd908b425065401 --- lib/xlat_tables/xlat_tables_common.c | 60 ++++++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index fd100846..a8401894 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -194,30 +194,56 @@ void mmap_add(const mmap_region_t *mm) static uint64_t mmap_desc(unsigned attr, unsigned long long addr_pa, int level) { - uint64_t desc = addr_pa; + uint64_t desc; int mem_type; - desc |= level == 3 ? TABLE_DESC : BLOCK_DESC; - - desc |= attr & MT_NS ? LOWER_ATTRS(NS) : 0; - - desc |= attr & MT_RW ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); - + desc = addr_pa; + desc |= (level == 3) ? TABLE_DESC : BLOCK_DESC; + desc |= (attr & MT_NS) ? LOWER_ATTRS(NS) : 0; + desc |= (attr & MT_RW) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); desc |= LOWER_ATTRS(ACCESS_FLAG); + /* + * Deduce shareability domain and executability of the memory region + * from the memory type. + * + * Data accesses to device memory and non-cacheable normal memory are + * coherent for all observers in the system, and correspondingly are + * always treated as being Outer Shareable. Therefore, for these 2 types + * of memory, it is not strictly needed to set the shareability field + * in the translation tables. + */ mem_type = MT_TYPE(attr); - if (mem_type == MT_MEMORY) { - desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); - if (attr & MT_RW) - desc |= UPPER_ATTRS(XN); - } else if (mem_type == MT_NON_CACHEABLE) { - desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); - if (attr & MT_RW) - desc |= UPPER_ATTRS(XN); - } else { - assert(mem_type == MT_DEVICE); + if (mem_type == MT_DEVICE) { desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH); + /* + * Always map device memory as execute-never. + * This is to avoid the possibility of a speculative instruction + * fetch, which could be an issue if this memory region + * corresponds to a read-sensitive peripheral. + */ desc |= UPPER_ATTRS(XN); + } 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.) + * Note that setting the XN bit here is for consistency only. + * The enable_mmu_elx() function sets the SCTLR_EL3.WXN bit, + * which makes any writable memory region to be treated as + * execute-never, regardless of the value of the XN bit in the + * translation table. + */ + if (attr & MT_RW) + desc |= UPPER_ATTRS(XN); + + if (mem_type == MT_MEMORY) { + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); + } else { + assert(mem_type == MT_NON_CACHEABLE); + desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); + } } debug_print((mem_type == MT_MEMORY) ? "MEM" : -- 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 +++++++++++++++ lib/xlat_tables/xlat_tables_common.c | 7 +++++-- 2 files changed, 20 insertions(+), 2 deletions(-) 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. */ diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index a8401894..e1448b94 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -234,8 +234,11 @@ static uint64_t mmap_desc(unsigned attr, unsigned long long addr_pa, * which makes any writable memory region to be treated as * execute-never, regardless of the value of the XN bit in the * translation table. + * + * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER + * attribute to figure out the value of the XN bit. */ - if (attr & MT_RW) + if ((attr & MT_RW) || (attr & MT_EXECUTE_NEVER)) desc |= UPPER_ATTRS(XN); if (mem_type == MT_MEMORY) { @@ -250,7 +253,7 @@ static uint64_t mmap_desc(unsigned attr, unsigned long long addr_pa, ((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV")); debug_print(attr & MT_RW ? "-RW" : "-RO"); debug_print(attr & MT_NS ? "-NS" : "-S"); - + debug_print(attr & MT_EXECUTE_NEVER ? "-XN" : "-EXEC"); return desc; } -- cgit From c02fcc4a3849af4e534c8cf726562694f69b9a04 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Wed, 15 Jun 2016 13:53:50 +0100 Subject: BL1: Add linker symbol identifying end of ROM content This patch adds a new linker symbol in BL1's linker script named '__BL1_ROM_END__', which marks the end of BL1's ROM content. This covers BL1's code, read-only data and read-write data to relocate in Trusted SRAM. The address of this new linker symbol is exported to C code through the 'BL1_ROM_END' macro. The section related to linker symbols in the Firmware Design guide has been updated and improved. Change-Id: I5c442ff497c78d865ffba1d7d044511c134e11c7 --- bl1/bl1.ld.S | 10 +++++--- bl1/bl1_private.h | 7 ++++-- docs/firmware-design.md | 67 +++++++++++++++++++++++-------------------------- 3 files changed, 42 insertions(+), 42 deletions(-) diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index df9a7994..be36b4ee 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-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: @@ -139,12 +139,14 @@ SECTIONS __DATA_ROM_START__ = LOADADDR(.data); __DATA_SIZE__ = SIZEOF(.data); + /* * The .data section is the last PROGBITS section so its end marks the end - * of the read-only part of BL1's binary. + * of BL1's actual content in Trusted ROM. */ - ASSERT(__DATA_ROM_START__ + __DATA_SIZE__ <= BL1_RO_LIMIT, - "BL1's RO section has exceeded its limit.") + __BL1_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL1_ROM_END__ <= BL1_RO_LIMIT, + "BL1's ROM content has exceeded its limit.") __BSS_SIZE__ = SIZEOF(.bss); diff --git a/bl1/bl1_private.h b/bl1/bl1_private.h index 283bbb97..79dde738 100644 --- a/bl1/bl1_private.h +++ b/bl1/bl1_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-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: @@ -35,8 +35,11 @@ /******************************************************************************* * Declarations of linker defined symbols which will tell us where BL1 lives - * in Trusted RAM + * in Trusted ROM and RAM ******************************************************************************/ +extern uint64_t __BL1_ROM_END__; +#define BL1_ROM_END (uint64_t)(&__BL1_ROM_END__) + extern uint64_t __BL1_RAM_START__; extern uint64_t __BL1_RAM_END__; #define BL1_RAM_BASE (uint64_t)(&__BL1_RAM_START__) diff --git a/docs/firmware-design.md b/docs/firmware-design.md index 294349d9..575a822a 100644 --- a/docs/firmware-design.md +++ b/docs/firmware-design.md @@ -1052,10 +1052,10 @@ Each bootloader image can be divided in 2 parts: All PROGBITS sections are grouped together at the beginning of the image, followed by all NOBITS sections. This is true for all Trusted Firmware images and it is governed by the linker scripts. This ensures that the raw binary -images are as small as possible. If a NOBITS section would sneak in between -PROGBITS sections then the resulting binary file would contain a bunch of zero -bytes at the location of this NOBITS section, making the image unnecessarily -bigger. Smaller images allow faster loading from the FIP to the main memory. +images are as small as possible. If a NOBITS section was inserted in between +PROGBITS sections then the resulting binary file would contain zero bytes in +place of this NOBITS section, making the image unnecessarily bigger. Smaller +images allow faster loading from the FIP to the main memory. ### Linker scripts and symbols @@ -1110,47 +1110,42 @@ layout as they are easy to spot in the link map files. #### Common linker symbols -Early setup code needs to know the extents of the BSS section to zero-initialise -it before executing any C code. The following linker symbols are defined for -this purpose: +All BL images share the following requirements: -* `__BSS_START__` This address must be aligned on a 16-byte boundary. -* `__BSS_SIZE__` +* The BSS section must be zero-initialised before executing any C code. +* The coherent memory section (if enabled) must be zero-initialised as well. +* The MMU setup code needs to know the extents of the coherent and read-only + memory regions to set the right memory attributes. -Similarly, the coherent memory section (if enabled) must be zero-initialised. -Also, the MMU setup code needs to know the extents of this section to set the -right memory attributes for it. The following linker symbols are defined for -this purpose: +The following linker symbols are defined for this purpose: -* `__COHERENT_RAM_START__` This address must be aligned on a page-size boundary. -* `__COHERENT_RAM_END__` This address must be aligned on a page-size boundary. -* `__COHERENT_RAM_UNALIGNED_SIZE__` +* `__BSS_START__` Must be aligned on a 16-byte boundary. +* `__BSS_SIZE__` +* `__COHERENT_RAM_START__` Must be aligned on a page-size boundary. +* `__COHERENT_RAM_END__` Must be aligned on a page-size boundary. +* `__COHERENT_RAM_UNALIGNED_SIZE__` +* `__RO_START__` +* `__RO_END__` #### BL1's linker symbols -BL1's early setup code needs to know the extents of the .data section to -relocate it from ROM to RAM before executing any C code. The following linker -symbols are defined for this purpose: +BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and +it is entirely executed in place but it needs some read-write memory for its +mutable data. Its `.data` section (i.e. its allocated read-write data) must be +relocated from ROM to RAM before executing any C code. -* `__DATA_ROM_START__` This address must be aligned on a 16-byte boundary. -* `__DATA_RAM_START__` This address must be aligned on a 16-byte boundary. -* `__DATA_SIZE__` +The following additional linker symbols are defined for BL1: -BL1's platform setup code needs to know the extents of its read-write data -region to figure out its memory layout. The following linker symbols are defined -for this purpose: +* `__BL1_ROM_END__` End address of BL1's ROM contents, covering its code + and `.data` section in ROM. +* `__DATA_ROM_START__` Start address of the `.data` section in ROM. Must be + aligned on a 16-byte boundary. +* `__DATA_RAM_START__` Address in RAM where the `.data` section should be + copied over. Must be aligned on a 16-byte boundary. +* `__DATA_SIZE__` Size of the `.data` section (in ROM or RAM). +* `__BL1_RAM_START__` Start address of BL1 read-write data. +* `__BL1_RAM_END__` End address of BL1 read-write data. -* `__BL1_RAM_START__` This is the start address of BL1 RW data. -* `__BL1_RAM_END__` This is the end address of BL1 RW data. - -#### BL2's, BL31's and TSP's linker symbols - -BL2, BL31 and TSP need to know the extents of their read-only section to set -the right memory attributes for this memory region in their MMU setup code. The -following linker symbols are defined for this purpose: - -* `__RO_START__` -* `__RO_END__` ### How to choose the right base addresses for each bootloader stage image -- 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 +- lib/xlat_tables/aarch64/xlat_tables.c | 3 +- lib/xlat_tables/xlat_tables_common.c | 2 +- plat/arm/common/arm_cci.c | 1 + plat/arm/common/arm_io_storage.c | 4 +-- plat/mediatek/mt8173/aarch64/platform_common.c | 3 +- plat/mediatek/mt8173/plat_mt_gic.c | 3 +- plat/rockchip/common/aarch64/platform_common.c | 1 + plat/rockchip/common/rockchip_gicv2.c | 1 + plat/rockchip/common/rockchip_gicv3.c | 1 + plat/xilinx/zynqmp/pm_service/pm_client.c | 3 +- 13 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 include/lib/utils.h 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 \ diff --git a/lib/xlat_tables/aarch64/xlat_tables.c b/lib/xlat_tables/aarch64/xlat_tables.c index 051e46a2..19eb7d5d 100644 --- a/lib/xlat_tables/aarch64/xlat_tables.c +++ b/lib/xlat_tables/aarch64/xlat_tables.c @@ -33,11 +33,10 @@ #include #include #include +#include #include #include "../xlat_tables_private.h" -#define IS_POWER_OF_TWO(x) (((x) & ((x) - 1)) == 0) - /* * The virtual address space size must be a power of two (as set in TCR.T0SZ). * As we start the initial lookup at level 1, it must also be between 2 GB and diff --git a/lib/xlat_tables/xlat_tables_common.c b/lib/xlat_tables/xlat_tables_common.c index e1448b94..71e3efca 100644 --- a/lib/xlat_tables/xlat_tables_common.c +++ b/lib/xlat_tables/xlat_tables_common.c @@ -31,11 +31,11 @@ #include #include #include -#include #include #include #include #include +#include #include #if LOG_LEVEL >= LOG_LEVEL_VERBOSE diff --git a/plat/arm/common/arm_cci.c b/plat/arm/common/arm_cci.c index 41054c24..40cfb480 100644 --- a/plat/arm/common/arm_cci.c +++ b/plat/arm/common/arm_cci.c @@ -32,6 +32,7 @@ #include #include #include +#include static const int cci_map[] = { PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX, diff --git a/plat/arm/common/arm_io_storage.c b/plat/arm/common/arm_io_storage.c index 153fdfe8..42435a74 100644 --- a/plat/arm/common/arm_io_storage.c +++ b/plat/arm/common/arm_io_storage.c @@ -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: @@ -28,7 +28,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include -#include /* For ARRAY_SIZE */ #include #include #include @@ -37,6 +36,7 @@ #include #include #include +#include /* IO devices */ static const io_dev_connector_t *fip_dev_con; diff --git a/plat/mediatek/mt8173/aarch64/platform_common.c b/plat/mediatek/mt8173/aarch64/platform_common.c index 365df1b0..70639edb 100644 --- a/plat/mediatek/mt8173/aarch64/platform_common.c +++ b/plat/mediatek/mt8173/aarch64/platform_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-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: @@ -34,6 +34,7 @@ #include #include #include +#include #include static const int cci_map[] = { diff --git a/plat/mediatek/mt8173/plat_mt_gic.c b/plat/mediatek/mt8173/plat_mt_gic.c index c9bdaa90..402a0f4b 100644 --- a/plat/mediatek/mt8173/plat_mt_gic.c +++ b/plat/mediatek/mt8173/plat_mt_gic.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-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: @@ -30,6 +30,7 @@ #include #include #include +#include const unsigned int mt_irq_sec_array[] = { MT_IRQ_SEC_SGI_0, diff --git a/plat/rockchip/common/aarch64/platform_common.c b/plat/rockchip/common/aarch64/platform_common.c index 6e9dab79..40cd29e3 100644 --- a/plat/rockchip/common/aarch64/platform_common.c +++ b/plat/rockchip/common/aarch64/platform_common.c @@ -37,6 +37,7 @@ #include #include #include +#include #ifdef PLAT_RK_CCI_BASE static const int cci_map[] = { diff --git a/plat/rockchip/common/rockchip_gicv2.c b/plat/rockchip/common/rockchip_gicv2.c index 3e1fa912..c2dca1fc 100644 --- a/plat/rockchip/common/rockchip_gicv2.c +++ b/plat/rockchip/common/rockchip_gicv2.c @@ -31,6 +31,7 @@ #include #include #include +#include /****************************************************************************** * The following functions are defined as weak to allow a platform to override diff --git a/plat/rockchip/common/rockchip_gicv3.c b/plat/rockchip/common/rockchip_gicv3.c index d197aba5..77308965 100644 --- a/plat/rockchip/common/rockchip_gicv3.c +++ b/plat/rockchip/common/rockchip_gicv3.c @@ -32,6 +32,7 @@ #include #include #include +#include /****************************************************************************** * The following functions are defined as weak to allow a platform to override diff --git a/plat/xilinx/zynqmp/pm_service/pm_client.c b/plat/xilinx/zynqmp/pm_service/pm_client.c index d3396dfa..cf0d5f08 100644 --- a/plat/xilinx/zynqmp/pm_service/pm_client.c +++ b/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2013-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: @@ -37,6 +37,7 @@ #include #include #include +#include #include "pm_api_sys.h" #include "pm_client.h" #include "pm_ipi.h" -- 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(+) 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 --- Makefile | 6 ++++++ bl1/bl1.ld.S | 38 ++++++++++++++++++++++++++++++++++++++ bl2/bl2.ld.S | 25 +++++++++++++++++++++++++ bl2u/bl2u.ld.S | 18 ++++++++++++++++++ bl31/bl31.ld.S | 42 ++++++++++++++++++++++++++++++++++++++++++ bl32/tsp/tsp.ld.S | 18 ++++++++++++++++++ docs/firmware-design.md | 8 +++++++- include/common/bl_common.h | 8 ++++++++ 8 files changed, 162 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5f4a93c9..800312c9 100644 --- a/Makefile +++ b/Makefile @@ -108,6 +108,10 @@ PL011_GENERIC_UART := 0 ENABLE_PMF := 0 # Flag to enable PSCI STATs functionality ENABLE_PSCI_STAT := 0 +# Whether code and read-only data should be put on separate memory pages. +# The platform Makefile is free to override this value. +SEPARATE_CODE_AND_RODATA := 0 + ################################################################################ # Checkpatch script options @@ -419,6 +423,7 @@ $(eval $(call assert_boolean,SPIN_ON_BL1_EXIT)) $(eval $(call assert_boolean,PL011_GENERIC_UART)) $(eval $(call assert_boolean,ENABLE_PMF)) $(eval $(call assert_boolean,ENABLE_PSCI_STAT)) +$(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA)) ################################################################################ @@ -448,6 +453,7 @@ $(eval $(call add_define,SPIN_ON_BL1_EXIT)) $(eval $(call add_define,PL011_GENERIC_UART)) $(eval $(call add_define,ENABLE_PMF)) $(eval $(call add_define,ENABLE_PSCI_STAT)) +$(eval $(call add_define,SEPARATE_CODE_AND_RODATA)) # Define the EL3_PAYLOAD_BASE flag only if it is provided. ifdef EL3_PAYLOAD_BASE $(eval $(call add_define,EL3_PAYLOAD_BASE)) diff --git a/bl1/bl1.ld.S b/bl1/bl1.ld.S index be36b4ee..b9554d15 100644 --- a/bl1/bl1.ld.S +++ b/bl1/bl1.ld.S @@ -45,6 +45,43 @@ SECTIONS ASSERT(. == ALIGN(4096), "BL1_RO_BASE address is not aligned on a page boundary.") +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl1_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(4096); + __TEXT_END__ = .; + } >ROM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + /* + * No need to pad out the .rodata section to a page boundary. Next is + * the .data section, which can mapped in ROM with the same memory + * attributes as the .rodata section. + */ + __RODATA_END__ = .; + } >ROM +#else ro . : { __RO_START__ = .; *bl1_entrypoint.o(.text*) @@ -69,6 +106,7 @@ SECTIONS *(.vectors) __RO_END__ = .; } >ROM +#endif ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, "cpu_ops not defined for this platform.") diff --git a/bl2/bl2.ld.S b/bl2/bl2.ld.S index a660bda6..fa694de2 100644 --- a/bl2/bl2.ld.S +++ b/bl2/bl2.ld.S @@ -45,6 +45,30 @@ SECTIONS ASSERT(. == ALIGN(4096), "BL2_BASE address is not aligned on a page boundary.") +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(4096); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PARSER_LIB_DESCS_START__ = .; + KEEP(*(.img_parser_lib_descs)) + __PARSER_LIB_DESCS_END__ = .; + + . = NEXT(4096); + __RODATA_END__ = .; + } >RAM +#else ro . : { __RO_START__ = .; *bl2_entrypoint.o(.text*) @@ -67,6 +91,7 @@ SECTIONS . = NEXT(4096); __RO_END__ = .; } >RAM +#endif /* * Define a linker symbol to mark start of the RW memory area for this diff --git a/bl2u/bl2u.ld.S b/bl2u/bl2u.ld.S index ec120779..d72589fc 100644 --- a/bl2u/bl2u.ld.S +++ b/bl2u/bl2u.ld.S @@ -45,6 +45,23 @@ SECTIONS ASSERT(. == ALIGN(4096), "BL2U_BASE address is not aligned on a page boundary.") +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2u_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(4096); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + . = NEXT(4096); + __RODATA_END__ = .; + } >RAM +#else ro . : { __RO_START__ = .; *bl2u_entrypoint.o(.text*) @@ -61,6 +78,7 @@ SECTIONS . = NEXT(4096); __RO_END__ = .; } >RAM +#endif /* * Define a linker symbol to mark start of the RW memory area for this diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index 33cbe4b7..743e65c4 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -46,6 +46,47 @@ SECTIONS ASSERT(. == ALIGN(4096), "BL31_BASE address is not aligned on a page boundary.") +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl31_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(4096); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __RT_SVC_DESCS_START__ = .; + KEEP(*(rt_svc_descs)) + __RT_SVC_DESCS_END__ = .; + +#if ENABLE_PMF + /* Ensure 8-byte alignment for descriptors and ensure inclusion */ + . = ALIGN(8); + __PMF_SVC_DESCS_START__ = .; + KEEP(*(pmf_svc_descs)) + __PMF_SVC_DESCS_END__ = .; +#endif /* ENABLE_PMF */ + + /* + * Ensure 8-byte alignment for cpu_ops so that its fields are also + * aligned. Also ensure cpu_ops inclusion. + */ + . = ALIGN(8); + __CPU_OPS_START__ = .; + KEEP(*(cpu_ops)) + __CPU_OPS_END__ = .; + + . = NEXT(4096); + __RODATA_END__ = .; + } >RAM +#else ro . : { __RO_START__ = .; *bl31_entrypoint.o(.text*) @@ -85,6 +126,7 @@ SECTIONS . = NEXT(4096); __RO_END__ = .; } >RAM +#endif ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, "cpu_ops not defined for this platform.") diff --git a/bl32/tsp/tsp.ld.S b/bl32/tsp/tsp.ld.S index 9c7ed381..7e24f66d 100644 --- a/bl32/tsp/tsp.ld.S +++ b/bl32/tsp/tsp.ld.S @@ -46,6 +46,23 @@ SECTIONS ASSERT(. == ALIGN(4096), "BL32_BASE address is not aligned on a page boundary.") +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *tsp_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = NEXT(4096); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + . = NEXT(4096); + __RODATA_END__ = .; + } >RAM +#else ro . : { __RO_START__ = .; *tsp_entrypoint.o(.text*) @@ -61,6 +78,7 @@ SECTIONS . = NEXT(4096); __RO_END__ = .; } >RAM +#endif /* * Define a linker symbol to mark start of the RW memory area for this diff --git a/docs/firmware-design.md b/docs/firmware-design.md index 575a822a..b99a2838 100644 --- a/docs/firmware-design.md +++ b/docs/firmware-design.md @@ -1115,7 +1115,9 @@ All BL images share the following requirements: * The BSS section must be zero-initialised before executing any C code. * The coherent memory section (if enabled) must be zero-initialised as well. * The MMU setup code needs to know the extents of the coherent and read-only - memory regions to set the right memory attributes. + memory regions to set the right memory attributes. When + `SEPARATE_CODE_AND_RODATA=1`, it needs to know more specifically how the + read-only memory region is divided between code and data. The following linker symbols are defined for this purpose: @@ -1126,6 +1128,10 @@ The following linker symbols are defined for this purpose: * `__COHERENT_RAM_UNALIGNED_SIZE__` * `__RO_START__` * `__RO_END__` +* `__TEXT_START__` +* `__TEXT_END__` +* `__RODATA_START__` +* `__RODATA_END__` #### BL1's linker symbols 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 a604623c718bf9dc028cb920db184219c6046454 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Thu, 16 Jun 2016 14:24:26 +0100 Subject: TSP: Print BL32_BASE rather than __RO_START__ In debug builds, the TSP prints its image base address and size. The base address displayed corresponds to the start address of the read-only section, as defined in the linker script. This patch changes this to use the BL32_BASE address instead, which is the same address as __RO_START__ at the moment but has the advantage to be independent of the linker symbols defined in the linker script as well as the layout and order of the sections. Change-Id: I032d8d50df712c014cbbcaa84a9615796ec902cc --- bl32/tsp/tsp_main.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/bl32/tsp/tsp_main.c b/bl32/tsp/tsp_main.c index 359b9e16..d03f7e22 100644 --- a/bl32/tsp/tsp_main.c +++ b/bl32/tsp/tsp_main.c @@ -56,12 +56,12 @@ static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT]; work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; /******************************************************************************* - * The BL32 memory footprint starts with an RO sections and ends - * with the linker symbol __BL32_END__. Use it to find the memory size + * The TSP memory footprint starts at address BL32_BASE and ends with the + * linker symbol __BL32_END__. Use these addresses to compute the TSP image + * size. ******************************************************************************/ -#define BL32_TOTAL_BASE (unsigned long)(&__RO_START__) - #define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__) +#define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE) static tsp_args_t *set_smc_args(uint64_t arg0, uint64_t arg1, @@ -102,9 +102,8 @@ uint64_t tsp_main(void) { NOTICE("TSP: %s\n", version_string); NOTICE("TSP: %s\n", build_message); - INFO("TSP: Total memory base : 0x%lx\n", BL32_TOTAL_BASE); - INFO("TSP: Total memory size : 0x%lx bytes\n", - BL32_TOTAL_LIMIT - BL32_TOTAL_BASE); + INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); + INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); uint32_t linear_id = plat_my_core_pos(); -- cgit From af419dd63706ea3f5f280675b8559beec7245ff5 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Wed, 15 Jun 2016 15:44:27 +0100 Subject: ARM platforms: Restrict mapping of Trusted ROM in BL1 At the moment, on ARM platforms, BL1 maps everything from BL1_RO_BASE to BL1_RO_LIMIT. BL1_RO_LIMIT, as defined in the porting guide, is the maximum address in Trusted ROM that BL1's actual content _can_ occupy. The actual portion of ROM occupied by BL1 can be less than that, which means that BL1 might map more Trusted ROM than it actually needs to. This patch changes BL1's memory mappings on ARM platforms to restrict the region of Trusted ROM it maps. It uses the symbols exported by the linker to figure out the actual extents of BL1's ROM footprint. This change increases the number of page tables used on FVP by 1. On FVP, we used to map the whole Trusted ROM. As it is 64MB large, we used to map it as blocks of 2MB using level-2 translation table entries. We now need a finer-grained mapping, which requires an additional level-3 translation table. On ARM CSS platforms, the number of translation tables is unchanged. The BL1 image resides in flash at address 0x0BEC0000. This address is not aligned on a 2MB-boundary so a level-3 translation table was already required to map this memory. Change-Id: I317a93fd99c40e70d0f13cc3d7a570f05c6c61eb --- plat/arm/common/arm_bl1_setup.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 1ffd7ee2..34996604 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -35,6 +35,8 @@ #include #include #include +#include +#include #include "../../../bl1/bl1_private.h" @@ -118,10 +120,16 @@ void bl1_early_platform_setup(void) *****************************************************************************/ void arm_bl1_plat_arch_setup(void) { + /* + * 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. + */ arm_setup_page_tables(bl1_tzram_layout.total_base, bl1_tzram_layout.total_size, BL1_RO_BASE, - BL1_RO_LIMIT + round_up(BL1_ROM_END, PAGE_SIZE) #if USE_COHERENT_MEM , BL1_COHERENT_RAM_BASE, BL1_COHERENT_RAM_LIMIT -- cgit From b2c96eed562b221f32f56976c7283d0e5e8503d0 Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Mon, 20 Jun 2016 10:10:40 +0100 Subject: ARM platforms: Include BL2U's RO section in total memory region This patch changes the base address of the "total" Trusted SRAM region seen by the BL2U image. It used to start just after BL2U's read-only section (i.e. at address BL2U_RO_LIMIT), it now starts from the base address of the BL2U image (i.e. at address BL2U_BASE). In other words, the "total" memory region now includes BL2U's own read-only section. This does not change BL2U's resulting memory mappings because the read-only section was already mapped in BL2U, it just wasn't part of this total memory region. Change-Id: I2da16ac842469023b41904eaa8d13ed678d65671 --- plat/arm/common/arm_bl2u_setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index 5f2634a2..8185f9f5 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -102,7 +102,7 @@ void bl2u_early_platform_setup(meminfo_t *mem_layout, void *plat_info) ******************************************************************************/ void arm_bl2u_plat_arch_setup(void) { - arm_setup_page_tables(BL2U_RO_LIMIT, + arm_setup_page_tables(BL2U_BASE, BL31_LIMIT, BL2U_RO_BASE, BL2U_RO_LIMIT -- 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 ++++++++++++++++++++++++++++++++- plat/arm/common/aarch64/arm_common.c | 25 ++++++++++++++------ plat/arm/common/arm_bl1_setup.c | 12 ++++------ plat/arm/common/arm_bl2_setup.c | 16 ++++--------- plat/arm/common/arm_bl2u_setup.c | 16 ++++--------- plat/arm/common/arm_bl31_setup.c | 20 +++++----------- plat/arm/common/arm_common.mk | 5 ++++ plat/arm/common/tsp/arm_tsp_setup.c | 20 +++++----------- plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 2 ++ plat/xilinx/zynqmp/tsp/tsp_plat_setup.c | 4 +++- 11 files changed, 96 insertions(+), 71 deletions(-) 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__ */ diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c index c0a7e6b4..36ba4c18 100644 --- a/plat/arm/common/aarch64/arm_common.c +++ b/plat/arm/common/aarch64/arm_common.c @@ -55,13 +55,16 @@ extern const mmap_region_t plat_arm_mmap[]; * The extents of the generic memory regions are specified by the function * arguments and consist of: * - Trusted SRAM seen by the BL image; - * - Read-only section (code and read-only data); + * - Code section; + * - Read-only data section; * - Coherent memory region, if applicable. */ 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, @@ -76,16 +79,24 @@ void arm_setup_page_tables(unsigned long total_base, mmap_add_region(total_base, total_base, total_size, MT_MEMORY | MT_RW | MT_SECURE); - /* Re-map the read-only section */ - mmap_add_region(ro_start, ro_start, - ro_limit - ro_start, - MT_MEMORY | MT_RO | MT_SECURE); + + /* Re-map the code section */ + mmap_add_region(code_start, code_start, + code_limit - code_start, + MT_CODE | MT_SECURE); + + /* Re-map the read-only data section */ + mmap_add_region(rodata_start, rodata_start, + rodata_limit - rodata_start, + MT_RO_DATA | MT_SECURE); + #if USE_COHERENT_MEM /* Re-map the coherent memory region */ mmap_add_region(coh_start, coh_start, coh_limit - coh_start, MT_DEVICE | MT_RW | MT_SECURE); #endif + /* Now (re-)map the platform-specific memory regions */ mmap_add(plat_arm_get_mmap()); diff --git a/plat/arm/common/arm_bl1_setup.c b/plat/arm/common/arm_bl1_setup.c index 34996604..c94f0cd7 100644 --- a/plat/arm/common/arm_bl1_setup.c +++ b/plat/arm/common/arm_bl1_setup.c @@ -120,16 +120,12 @@ void bl1_early_platform_setup(void) *****************************************************************************/ void arm_bl1_plat_arch_setup(void) { - /* - * 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. - */ arm_setup_page_tables(bl1_tzram_layout.total_base, bl1_tzram_layout.total_size, - BL1_RO_BASE, - round_up(BL1_ROM_END, PAGE_SIZE) + BL_CODE_BASE, + BL1_CODE_LIMIT, + BL1_RO_DATA_BASE, + BL1_RO_DATA_LIMIT #if USE_COHERENT_MEM , BL1_COHERENT_RAM_BASE, BL1_COHERENT_RAM_LIMIT diff --git a/plat/arm/common/arm_bl2_setup.c b/plat/arm/common/arm_bl2_setup.c index e8e7928c..b6afaa7f 100644 --- a/plat/arm/common/arm_bl2_setup.c +++ b/plat/arm/common/arm_bl2_setup.c @@ -36,16 +36,6 @@ #include #include - -/* - * The next 2 constants identify the extents of the code & RO data region. - * These addresses are used by the MMU setup code and therefore they must be - * page-aligned. It is the responsibility of the linker script to ensure that - * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. - */ -#define BL2_RO_BASE (unsigned long)(&__RO_START__) -#define BL2_RO_LIMIT (unsigned long)(&__RO_END__) - #if USE_COHERENT_MEM /* * The next 2 constants identify the extents of the coherent memory region. @@ -236,8 +226,10 @@ void arm_bl2_plat_arch_setup(void) { arm_setup_page_tables(bl2_tzram_layout.total_base, bl2_tzram_layout.total_size, - BL2_RO_BASE, - BL2_RO_LIMIT + BL_CODE_BASE, + BL_CODE_LIMIT, + BL_RO_DATA_BASE, + BL_RO_DATA_LIMIT #if USE_COHERENT_MEM , BL2_COHERENT_RAM_BASE, BL2_COHERENT_RAM_LIMIT diff --git a/plat/arm/common/arm_bl2u_setup.c b/plat/arm/common/arm_bl2u_setup.c index 8185f9f5..de7d0c2f 100644 --- a/plat/arm/common/arm_bl2u_setup.c +++ b/plat/arm/common/arm_bl2u_setup.c @@ -36,16 +36,6 @@ #include #include - -/* - * The next 2 constants identify the extents of the code & RO data region. - * These addresses are used by the MMU setup code and therefore they must be - * page-aligned. It is the responsibility of the linker script to ensure that - * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. - */ -#define BL2U_RO_BASE (unsigned long)(&__RO_START__) -#define BL2U_RO_LIMIT (unsigned long)(&__RO_END__) - #if USE_COHERENT_MEM /* * The next 2 constants identify the extents of the coherent memory region. @@ -104,8 +94,10 @@ void arm_bl2u_plat_arch_setup(void) { arm_setup_page_tables(BL2U_BASE, BL31_LIMIT, - BL2U_RO_BASE, - BL2U_RO_LIMIT + BL_CODE_BASE, + BL_CODE_LIMIT, + BL_RO_DATA_BASE, + BL_RO_DATA_LIMIT #if USE_COHERENT_MEM , BL2U_COHERENT_RAM_BASE, diff --git a/plat/arm/common/arm_bl31_setup.c b/plat/arm/common/arm_bl31_setup.c index 9cfa3b8b..87cafced 100644 --- a/plat/arm/common/arm_bl31_setup.c +++ b/plat/arm/common/arm_bl31_setup.c @@ -38,16 +38,6 @@ #include #include - -/* - * The next 3 constants identify the extents of the code, RO data region and the - * limit of the BL31 image. These addresses are used by the MMU setup code and - * therefore they must be page-aligned. It is the responsibility of the linker - * script to ensure that __RO_START__, __RO_END__ & __BL31_END__ linker symbols - * refer to page-aligned addresses. - */ -#define BL31_RO_BASE (unsigned long)(&__RO_START__) -#define BL31_RO_LIMIT (unsigned long)(&__RO_END__) #define BL31_END (unsigned long)(&__BL31_END__) #if USE_COHERENT_MEM @@ -253,10 +243,12 @@ void bl31_plat_runtime_setup(void) ******************************************************************************/ void arm_bl31_plat_arch_setup(void) { - arm_setup_page_tables(BL31_RO_BASE, - (BL31_END - BL31_RO_BASE), - BL31_RO_BASE, - BL31_RO_LIMIT + arm_setup_page_tables(BL31_BASE, + BL31_END - BL31_BASE, + BL_CODE_BASE, + BL_CODE_LIMIT, + BL_RO_DATA_BASE, + BL_RO_DATA_LIMIT #if USE_COHERENT_MEM , BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT diff --git a/plat/arm/common/arm_common.mk b/plat/arm/common/arm_common.mk index bcb3f6f6..9e5ddea7 100644 --- a/plat/arm/common/arm_common.mk +++ b/plat/arm/common/arm_common.mk @@ -85,6 +85,11 @@ $(eval $(call add_define,ARM_BL31_IN_DRAM)) # Enable PSCI_STAT_COUNT/RESIDENCY APIs on ARM platforms ENABLE_PSCI_STAT = 1 +# On ARM platforms, separate the code and read-only data sections to allow +# mapping the former as executable and the latter as execute-never. +SEPARATE_CODE_AND_RODATA := 1 + + PLAT_INCLUDES += -Iinclude/common/tbbr \ -Iinclude/plat/arm/common \ -Iinclude/plat/arm/common/aarch64 diff --git a/plat/arm/common/tsp/arm_tsp_setup.c b/plat/arm/common/tsp/arm_tsp_setup.c index 6c6ceea0..09029f4c 100644 --- a/plat/arm/common/tsp/arm_tsp_setup.c +++ b/plat/arm/common/tsp/arm_tsp_setup.c @@ -35,16 +35,6 @@ #include #include - -/* - * The next 3 constants identify the extents of the code & RO data region and - * the limit of the BL32 image. These addresses are used by the MMU setup code - * and therefore they must be page-aligned. It is the responsibility of the - * linker script to ensure that __RO_START__, __RO_END__ & & __BL32_END__ - * linker symbols refer to page-aligned addresses. - */ -#define BL32_RO_BASE (unsigned long)(&__RO_START__) -#define BL32_RO_LIMIT (unsigned long)(&__RO_END__) #define BL32_END (unsigned long)(&__BL32_END__) #if USE_COHERENT_MEM @@ -98,10 +88,12 @@ void tsp_platform_setup(void) ******************************************************************************/ void tsp_plat_arch_setup(void) { - arm_setup_page_tables(BL32_RO_BASE, - (BL32_END - BL32_RO_BASE), - BL32_RO_BASE, - BL32_RO_LIMIT + arm_setup_page_tables(BL32_BASE, + (BL32_END - BL32_BASE), + BL_CODE_BASE, + BL_CODE_LIMIT, + BL_RO_DATA_BASE, + BL_RO_DATA_LIMIT #if USE_COHERENT_MEM , BL32_COHERENT_RAM_BASE, BL32_COHERENT_RAM_LIMIT diff --git a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c index 2ea8b1c9..ffed591c 100644 --- a/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +++ b/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -158,6 +158,8 @@ void bl31_plat_arch_setup(void) BL31_COHERENT_RAM_LIMIT - BL31_RO_BASE, BL31_RO_BASE, BL31_RO_LIMIT, + 0, + 0, BL31_COHERENT_RAM_BASE, BL31_COHERENT_RAM_LIMIT); enable_mmu_el3(0); diff --git a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c index 19e2c129..ae66fa41 100644 --- a/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +++ b/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c @@ -93,7 +93,9 @@ void tsp_plat_arch_setup(void) arm_setup_page_tables(BL32_RO_BASE, (BL32_END - BL32_RO_BASE), BL32_RO_BASE, - BL32_RO_LIMIT + BL32_RO_LIMIT, + 0, + 0 #if USE_COHERENT_MEM , BL32_COHERENT_RAM_BASE, BL32_COHERENT_RAM_LIMIT -- cgit From 84aaf559618f7323e4e053215ab558bb540beffc Mon Sep 17 00:00:00 2001 From: Sandrine Bailleux Date: Mon, 20 Jun 2016 13:57:10 +0100 Subject: Add some verbose traces in arm_setup_page_tables() This patch adds some verbose traces in the arm_setup_page_tables() function to print the extents of the different memory regions it maps. Change-Id: Ia3ae1053e7ebf3579601ff9238b0e3791eb1e9e4 --- plat/arm/common/aarch64/arm_common.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/plat/arm/common/aarch64/arm_common.c b/plat/arm/common/aarch64/arm_common.c index 36ba4c18..7c0b93db 100644 --- a/plat/arm/common/aarch64/arm_common.c +++ b/plat/arm/common/aarch64/arm_common.c @@ -76,22 +76,30 @@ void arm_setup_page_tables(unsigned long total_base, * Map the Trusted SRAM with appropriate memory attributes. * Subsequent mappings will adjust the attributes for specific regions. */ + VERBOSE("Trusted SRAM seen by this BL image: %p - %p\n", + (void *) total_base, (void *) (total_base + total_size)); mmap_add_region(total_base, total_base, total_size, MT_MEMORY | MT_RW | MT_SECURE); /* Re-map the code section */ + VERBOSE("Code region: %p - %p\n", + (void *) code_start, (void *) code_limit); mmap_add_region(code_start, code_start, code_limit - code_start, MT_CODE | MT_SECURE); /* Re-map the read-only data section */ + VERBOSE("Read-only data region: %p - %p\n", + (void *) rodata_start, (void *) rodata_limit); mmap_add_region(rodata_start, rodata_start, rodata_limit - rodata_start, MT_RO_DATA | MT_SECURE); #if USE_COHERENT_MEM /* Re-map the coherent memory region */ + VERBOSE("Coherent region: %p - %p\n", + (void *) coh_start, (void *) coh_limit); mmap_add_region(coh_start, coh_start, coh_limit - coh_start, MT_DEVICE | MT_RW | MT_SECURE); -- 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 +++++++++++++++-- plat/arm/board/fvp/fvp_common.c | 3 +++ 2 files changed, 18 insertions(+), 2 deletions(-) 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, \ diff --git a/plat/arm/board/fvp/fvp_common.c b/plat/arm/board/fvp/fvp_common.c index affd0b82..002cff67 100644 --- a/plat/arm/board/fvp/fvp_common.c +++ b/plat/arm/board/fvp/fvp_common.c @@ -69,6 +69,9 @@ arm_config_t arm_config; * Table of memory regions for various BL stages to map using the MMU. * This doesn't include Trusted SRAM as arm_setup_page_tables() already * takes care of mapping it. + * + * The flash needs to be mapped as writable in order to erase the FIP's Table of + * Contents in case of unrecoverable error (see plat_error_handler()). */ #if IMAGE_BL1 const mmap_region_t plat_arm_mmap[] = { -- cgit