ARM platforms: Add support for SEPARATE_CODE_AND_RODATA
authorSandrine Bailleux <sandrine.bailleux@arm.com>
Fri, 8 Jul 2016 13:38:16 +0000 (14:38 +0100)
committerSandrine Bailleux <sandrine.bailleux@arm.com>
Fri, 8 Jul 2016 13:55:11 +0000 (14:55 +0100)
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
include/plat/common/common_def.h
plat/arm/common/aarch64/arm_common.c
plat/arm/common/arm_bl1_setup.c
plat/arm/common/arm_bl2_setup.c
plat/arm/common/arm_bl2u_setup.c
plat/arm/common/arm_bl31_setup.c
plat/arm/common/arm_common.mk
plat/arm/common/tsp/arm_tsp_setup.c
plat/xilinx/zynqmp/bl31_zynqmp_setup.c
plat/xilinx/zynqmp/tsp/tsp_plat_setup.c

index 2a32e419b0f132ee9304fcda43b95e4f30be7c6c..06912eba7ceb0f79d956f17ddd26dd52bff17247 100644 (file)
  */
 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
index 9fac9fa22131c648f82f4251985ad5eee05ac758..d6b777278f11342ee2769db407959dd668337c8f 100644 (file)
        .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__ */
index c0a7e6b47ad58c7d37a785b9d4ca519f4f2477e2..36ba4c18bab68d03c9d7b89e48871b86bcc20323 100644 (file)
@@ -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());
 
index 34996604b4f7e27e6ef44c4bb84d5c102fb9a77f..c94f0cd773a99d50852116e9dcd68219197bcb38 100644 (file)
@@ -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
index e8e7928c02d5af5b833a1fdfed38d17716e57359..b6afaa7f519844f63df910e091b6956310c6046e 100644 (file)
 #include <plat_arm.h>
 #include <string.h>
 
-
-/*
- * 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
index 8185f9f5174c598ab4a22c098776cfabdcfabedd..de7d0c2f9e582d3a3cb102b3efbac875f1ff92c3 100644 (file)
 #include <plat_arm.h>
 #include <string.h>
 
-
-/*
- * 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,
index 9cfa3b8b7d1ead6e3b2672f5945fb6e8dc5091b4..87cafced8501f326aceaa2f70231a5ffe35a2c05 100644 (file)
 #include <plat_arm.h>
 #include <platform.h>
 
-
-/*
- * 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
index bcb3f6f6ece98cff6ca8b309081c9f4233a409f2..9e5ddea7703c68d748e6dd108793262ab7f96699 100644 (file)
@@ -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
index 6c6ceea0816e4798720feacf03d916c81b1d2858..09029f4c2a1b5a7c7494c417b816de976c935be0 100644 (file)
 #include <platform_tsp.h>
 #include <plat_arm.h>
 
-
-/*
- * 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
index 2ea8b1c982dad835c1f2ab211bcbd51e913733d2..ffed591cf9aa04e5040e8613f3006571f1d8d44c 100644 (file)
@@ -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);
index 19e2c12987a304c7b21f708e23e4f60bc4ee6260..ae66fa4157c5901c410d688a5c68ae5b7b347682 100644 (file)
@@ -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