ARM platforms: Move BL31 below BL2 to enable BL2 overlay
authorSoby Mathew <soby.mathew@arm.com>
Fri, 1 Jun 2018 15:53:38 +0000 (16:53 +0100)
committerSoby Mathew <soby.mathew@arm.com>
Thu, 7 Jun 2018 11:26:19 +0000 (12:26 +0100)
The patch changes the layout of BL images in memory to enable
more efficient use of available space. Previously BL31 was loaded
with the expectation that BL2 memory would be reclaimed by BL32
loaded in SRAM. But with increasing memory requirements in the
firmware, we can no longer fit BL32 in SRAM anymore which means the
BL2 memory is not reclaimed by any runtime image. Positioning BL2
below BL1-RW and above BL31 means that the BL31 NOBITS can be
overlaid on BL2 and BL1-RW.

This patch also propogates the same memory layout to BL32 for AArch32
mode. The reset addresses for the following configurations are also
changed :
   * When RESET_TO_SP_MIN=1 for BL32 in AArch32 mode
   * When BL2_AT_EL3=1 for BL2

The restriction on BL31 to be only in DRAM when SPM is enabled
is now removed with this change. The update to the firmware design
guide for the BL memory layout is done in the following patch.

Change-Id: Icca438e257abe3e4f5a8215f945b9c3f9fbf29c9
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
12 files changed:
docs/user-guide.rst
include/plat/arm/board/common/board_arm_def.h
include/plat/arm/common/arm_def.h
include/plat/arm/css/common/css_def.h
plat/arm/board/fvp/platform.mk
plat/arm/board/juno/include/platform_def.h
plat/arm/common/arm_bl2_setup.c
plat/arm/common/arm_bl31_setup.c
plat/arm/common/arm_dyn_cfg.c
plat/arm/common/sp_min/arm_sp_min_setup.c
plat/arm/css/drivers/scp/css_bom_bootloader.c
plat/arm/css/drivers/scp/css_scp.h

index 5f3823dbed537260cc868613e2b41cd95ad48f7e..f6d0c764156a3e8b0e30ea22247578c58297d664 100644 (file)
@@ -1928,7 +1928,7 @@ with 8 CPUs using the AArch32 build of TF-A.
     -C cluster1.cpu1.RVBAR=0x04001000                            \
     -C cluster1.cpu2.RVBAR=0x04001000                            \
     -C cluster1.cpu3.RVBAR=0x04001000                            \
-    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
+    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04002000    \
     --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
     --data cluster0.cpu0="<path-to>/<fdt>"@0x82000000            \
     --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000  \
@@ -1959,7 +1959,7 @@ boot Linux with 8 CPUs using the AArch64 build of TF-A.
     -C cluster1.cpu2.RVBARADDR=0x04020000                        \
     -C cluster1.cpu3.RVBARADDR=0x04020000                        \
     --data cluster0.cpu0="<path-to>/<bl31-binary>"@0x04020000    \
-    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000    \
+    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04002000    \
     --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000    \
     --data cluster0.cpu0="<path-to>/<fdt>"@0x82000000            \
     --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000  \
@@ -1982,7 +1982,7 @@ boot Linux with 4 CPUs using the AArch32 build of TF-A.
     -C cluster0.cpu1.RVBARADDR=0x04001000                       \
     -C cluster0.cpu2.RVBARADDR=0x04001000                       \
     -C cluster0.cpu3.RVBARADDR=0x04001000                       \
-    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04001000   \
+    --data cluster0.cpu0="<path-to>/<bl32-binary>"@0x04002000   \
     --data cluster0.cpu0="<path-to>/<bl33-binary>"@0x88000000   \
     --data cluster0.cpu0="<path-to>/<fdt>"@0x82000000           \
     --data cluster0.cpu0="<path-to>/<kernel-binary>"@0x80080000 \
index 21ceae30a541f19e5cfb9c3acf1299fa5d3010cc..2d8e4c139f2b117dd41487014c82e8f357ca77ad 100644 (file)
 #endif
 
 /*
- * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
- * little space for growth.
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
  */
-#if ENABLE_SPM
-# define PLAT_ARM_MAX_BL31_SIZE                0x40000
-#else
-# define PLAT_ARM_MAX_BL31_SIZE                0x20000
-#endif
+#define PLAT_ARM_MAX_BL31_SIZE         0x3B000
 
 #ifdef AARCH32
 /*
- * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
- * Payload.
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current SP_MIN PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW
  */
-# define PLAT_ARM_MAX_BL32_SIZE                0x1D000
+# define PLAT_ARM_MAX_BL32_SIZE                0x3B000
 #endif
 
 #endif /* ARM_BOARD_OPTIMISE_MEM */
index 18390d6a7636dc43ab797201869b438d1266e753..1f62ebe7dba901cd19340655c7c69c383860ade5 100644 (file)
  * and limit. Leave enough space of BL2 meminfo.
  */
 #define ARM_TB_FW_CONFIG_BASE          ARM_BL_RAM_BASE + sizeof(meminfo_t)
-#define ARM_TB_FW_CONFIG_LIMIT         BL2_BASE
+#define ARM_TB_FW_CONFIG_LIMIT         ARM_BL_RAM_BASE + PAGE_SIZE
 
 /*******************************************************************************
  * BL1 specific defines.
 /*******************************************************************************
  * BL2 specific defines.
  ******************************************************************************/
-#if ARM_BL31_IN_DRAM
-/*
- * For AArch64 BL31 is loaded in the DRAM.
- * Put BL2 just below BL1.
- */
-#define BL2_BASE                       (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
-#define BL2_LIMIT                      BL1_RW_BASE
-
-#elif BL2_AT_EL3
-
-#define BL2_BASE                       ARM_BL_RAM_BASE
+#if BL2_AT_EL3
+/* Put BL2 in the middle of the Trusted SRAM */
+#define BL2_BASE                       (ARM_TRUSTED_SRAM_BASE + \
+                                               (PLAT_ARM_TRUSTED_SRAM_SIZE >> 1))
 #define BL2_LIMIT                      (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 
-#elif defined(AARCH32) || JUNO_AARCH32_EL3_RUNTIME
-/*
- * Put BL2 just below BL32.
- */
-#define BL2_BASE                       (BL32_BASE - PLAT_ARM_MAX_BL2_SIZE)
-#define BL2_LIMIT                      BL32_BASE
-
 #else
 /*
- * Put BL2 just below BL31.
+ * Put BL2 just below BL1.
  */
-#define BL2_BASE                       (BL31_BASE - PLAT_ARM_MAX_BL2_SIZE)
-#define BL2_LIMIT                      BL31_BASE
+#define BL2_BASE                       (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE)
+#define BL2_LIMIT                      BL1_RW_BASE
 #endif
 
 /*******************************************************************************
                                                (PLAT_ARM_TRUSTED_SRAM_SIZE >> 1))
 #define BL31_LIMIT                     (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #else
-/*
- * Put BL31 at the top of the Trusted SRAM.
- */
-#define BL31_BASE                      (ARM_BL_RAM_BASE +              \
-                                               ARM_BL_RAM_SIZE -       \
-                                               PLAT_ARM_MAX_BL31_SIZE)
-#define BL31_PROGBITS_LIMIT            BL1_RW_BASE
+/* Put BL31 below BL2 in the Trusted SRAM.*/
+#define BL31_BASE                      ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
+                                               - PLAT_ARM_MAX_BL31_SIZE)
+#define BL31_PROGBITS_LIMIT            BL2_BASE
 #define BL31_LIMIT                     (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 #endif
 
  * BL32 specific defines for EL3 runtime in AArch32 mode
  ******************************************************************************/
 # if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME
-/* SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM to BL32 */
-#  define BL32_BASE                    ARM_BL_RAM_BASE
+/*
+ * SP_MIN is the only BL image in SRAM. Allocate the whole of SRAM (excluding
+ * the page reserved for fw_configs) to BL32
+ */
+#  define BL32_BASE                    ARM_TB_FW_CONFIG_LIMIT
 #  define BL32_LIMIT                   (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 # else
-/* Put BL32 at the top of the Trusted SRAM.*/
-#  define BL32_BASE                    (ARM_BL_RAM_BASE +              \
-                                               ARM_BL_RAM_SIZE -       \
-                                               PLAT_ARM_MAX_BL32_SIZE)
-#  define BL32_PROGBITS_LIMIT          BL1_RW_BASE
+/* Put BL32 below BL2 in the Trusted SRAM.*/
+#  define BL32_BASE                    ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\
+                                               - PLAT_ARM_MAX_BL32_SIZE)
+#  define BL32_PROGBITS_LIMIT          BL2_BASE
 #  define BL32_LIMIT                   (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)
 # endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */
 
 # elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID
 #  define TSP_SEC_MEM_BASE             ARM_BL_RAM_BASE
 #  define TSP_SEC_MEM_SIZE             ARM_BL_RAM_SIZE
-#  define TSP_PROGBITS_LIMIT           BL2_BASE
-#  define BL32_BASE                    ARM_BL_RAM_BASE
+#  define TSP_PROGBITS_LIMIT           BL31_BASE
+#  define BL32_BASE                    ARM_TB_FW_CONFIG_LIMIT
 #  define BL32_LIMIT                   BL31_BASE
 # elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID
 #  define TSP_SEC_MEM_BASE             PLAT_ARM_TRUSTED_DRAM_BASE
index 6d68b4406ddbc7fb57f6296115f77d93e0970277..725c27cbcff9e7beae8cd328123b3c40526f07fb 100644 (file)
 /*
  * Load address of SCP_BL2 in CSS platform ports
  * SCP_BL2 is loaded to the same place as BL31 but it shouldn't overwrite BL1
- * rw data.  Once SCP_BL2 is transferred to the SCP, it is discarded and BL31
- * is loaded over the top.
+ * rw data or BL2.  Once SCP_BL2 is transferred to the SCP, it is discarded and
+ * BL31 is loaded over the top.
  */
-#define SCP_BL2_BASE                   (BL1_RW_BASE - PLAT_CSS_MAX_SCP_BL2_SIZE)
-#define SCP_BL2_LIMIT                  BL1_RW_BASE
+#define SCP_BL2_BASE                   (BL2_BASE - PLAT_CSS_MAX_SCP_BL2_SIZE)
+#define SCP_BL2_LIMIT                  BL2_BASE
 
-#define SCP_BL2U_BASE                  (BL1_RW_BASE - PLAT_CSS_MAX_SCP_BL2U_SIZE)
-#define SCP_BL2U_LIMIT                 BL1_RW_BASE
+#define SCP_BL2U_BASE                  (BL2_BASE - PLAT_CSS_MAX_SCP_BL2U_SIZE)
+#define SCP_BL2U_LIMIT                 BL2_BASE
 #endif /* CSS_LOAD_SCP_IMAGES */
 
 /* Load address of Non-Secure Image for CSS platform ports */
index c02831ac3f894b6fb27c30f6744f6c2e11fc7f59..f807dc6e497ef57725638ea092b23b7e43176402 100644 (file)
@@ -225,12 +225,6 @@ ifneq (${BL2_AT_EL3}, 0)
     override BL1_SOURCES =
 endif
 
-ifeq (${ENABLE_SPM},1)
-ifneq (${ARM_BL31_IN_DRAM},1)
-        $(error "Error: SPM needs BL31 to be located in DRAM.")
-endif
-endif
-
 include plat/arm/board/common/board_common.mk
 include plat/arm/common/arm_common.mk
 
index e616e1fcfecc244bd147a4d3d33b572263c4d80c..75ee991ca0b779184f2d3065cd3ad8a00761d8ab 100644 (file)
 #endif
 
 /*
- * PLAT_ARM_MAX_BL31_SIZE is calculated using the current BL31 debug size plus a
- * little space for growth.
- * SCP_BL2 image is loaded into the space BL31 -> BL1_RW_BASE.
- * For TBB use case, PLAT_ARM_MAX_BL1_RW_SIZE has been increased and therefore
- * PLAT_ARM_MAX_BL31_SIZE has been increased to ensure SCP_BL2 has the same
- * space available.
+ * Since BL31 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL31_SIZE is
+ * calculated using the current BL31 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW.  SCP_BL2 image is loaded into the space BL31 -> BL2_BASE.
+ * Hence the BL31 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
  */
-#define PLAT_ARM_MAX_BL31_SIZE         0x1E000
+#define PLAT_ARM_MAX_BL31_SIZE         0x3E000
 
 #if JUNO_AARCH32_EL3_RUNTIME
 /*
- * PLAT_ARM_MAX_BL32_SIZE is calculated for SP_MIN as the AArch32 Secure
- * Payload. We also need to take care of SCP_BL2 size as well, as the SCP_BL2
- * is loaded into the space BL32 -> BL1_RW_BASE
+ * Since BL32 NOBITS overlays BL2 and BL1-RW, PLAT_ARM_MAX_BL32_SIZE is
+ * calculated using the current BL32 PROGBITS debug size plus the sizes of
+ * BL2 and BL1-RW.  SCP_BL2 image is loaded into the space BL32 -> BL2_BASE.
+ * Hence the BL32 PROGBITS size should be >= PLAT_CSS_MAX_SCP_BL2_SIZE.
  */
-# define PLAT_ARM_MAX_BL32_SIZE                0x1E000
+#define PLAT_ARM_MAX_BL32_SIZE         0x3E000
 #endif
 
 /*
index d490f83c82a72c93278daccdc113be51b603f3f0..4ef3a9b0ffb9ec483c0a759a99a882a7bf18eb2d 100644 (file)
 static meminfo_t bl2_tzram_layout __aligned(CACHE_WRITEBACK_GRANULE);
 
 /*
- * Check that BL2_BASE is atleast a page over ARM_BL_RAM_BASE. The page is for
- * `meminfo_t` data structure and TB_FW_CONFIG passed from BL1. Not needed
- * when BL2 is compiled for BL_AT_EL3 as BL2 doesn't need any info from BL1 and
- * BL2 is loaded at base of usable SRAM.
+ * Check that BL2_BASE is above ARM_TB_FW_CONFIG_LIMIT. This reserved page is
+ * for `meminfo_t` data structure and fw_configs passed from BL1.
  */
-#if BL2_AT_EL3
-#define BL1_MEMINFO_OFFSET     0x0
-#else
-#define BL1_MEMINFO_OFFSET     PAGE_SIZE
-#endif
-
-CASSERT(BL2_BASE >= (ARM_BL_RAM_BASE + BL1_MEMINFO_OFFSET), assert_bl2_base_overflows);
+CASSERT(BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl2_base_overflows);
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl2_early_platform_setup2
index 551e7002f253fe1506583eee376efef8529a101e..46f7ae0e5e1432499cbbbca3667806a64952265a 100644 (file)
 static entry_point_info_t bl32_image_ep_info;
 static entry_point_info_t bl33_image_ep_info;
 
+/*
+ * Check that BL31_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
+ */
+CASSERT(BL31_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl31_base_overflows);
 
 /* Weak definitions may be overridden in specific ARM standard platform */
 #pragma weak bl31_early_platform_setup2
index 3f0a9b4cfbbc8fedc22f129dde0805a1b2948204..32a515b5662e027357bd3964b7d0ab913a6c0bc3 100644 (file)
@@ -143,8 +143,8 @@ void arm_bl2_dyn_cfg_init(void)
                        if (check_uptr_overflow(image_base, image_size) != 0)
                                continue;
 
-                       /* Ensure the configs don't overlap with BL2 */
-                       if ((image_base > BL2_BASE) || ((image_base + image_size) > BL2_BASE))
+                       /* Ensure the configs don't overlap with BL31 */
+                       if ((image_base > BL31_BASE) || ((image_base + image_size) > BL31_BASE))
                                continue;
 
                        /* Ensure the configs are loaded in a valid address */
index 9a6c0740bdb22ce5bad02c326c4c166668029f7c..b42e35f3a33a1f33aa12b67f292e9b794e877184 100644 (file)
@@ -22,6 +22,11 @@ static entry_point_info_t bl33_image_ep_info;
 #pragma weak sp_min_plat_arch_setup
 #pragma weak plat_arm_sp_min_early_platform_setup
 
+/*
+ * Check that BL32_BASE is above ARM_TB_FW_CONFIG_LIMIT. The reserved page
+ * is required for SOC_FW_CONFIG/TOS_FW_CONFIG passed from BL2.
+ */
+CASSERT(BL32_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_bl32_base_overflows);
 
 /*******************************************************************************
  * Return a pointer to the 'entry_point_info' structure of the next image for the
index 42ed30d3d6130e6fc6484072deee14608cae2e28..5268510dbd0708c316f83260ede9b26471963821 100644 (file)
@@ -47,16 +47,16 @@ typedef struct {
 } cmd_data_payload_t;
 
 /*
- * All CSS platforms load SCP_BL2/SCP_BL2U just below BL rw-data and above
- * BL2/BL2U (this is where BL31 usually resides except when ARM_BL31_IN_DRAM is
- * set. Ensure that SCP_BL2/SCP_BL2U do not overflow into BL1 rw-data nor
- * BL2/BL2U.
+ * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
+ * usually resides except when ARM_BL31_IN_DRAM is
+ * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into shared RAM and
+ * the tb_fw_config.
  */
-CASSERT(SCP_BL2_LIMIT <= BL1_RW_BASE, assert_scp_bl2_overwrite_bl1);
-CASSERT(SCP_BL2U_LIMIT <= BL1_RW_BASE, assert_scp_bl2u_overwrite_bl1);
+CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
+CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
 
-CASSERT(SCP_BL2_BASE >= BL2_LIMIT, assert_scp_bl2_overwrite_bl2);
-CASSERT(SCP_BL2U_BASE >= BL2U_LIMIT, assert_scp_bl2u_overwrite_bl2u);
+CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
 
 static void scp_boot_message_start(void)
 {
index 1f0cf8e24adfc1f79b6fa36e5c2d2388d728300c..671612a80533ee3177239c9228b289bef8b41942 100644 (file)
@@ -34,17 +34,17 @@ int css_scp_boot_image_xfer(void *image, unsigned int image_size);
 int css_scp_boot_ready(void);
 
 #if CSS_LOAD_SCP_IMAGES
+
 /*
- * All CSS platforms load SCP_BL2/SCP_BL2U just below BL rw-data and above
- * BL2/BL2U (this is where BL31 usually resides except when ARM_BL31_IN_DRAM is
- * set. Ensure that SCP_BL2/SCP_BL2U do not overflow into BL1 rw-data nor
- * BL2/BL2U.
+ * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31
+ * usually resides except when ARM_BL31_IN_DRAM is
+ * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into tb_fw_config.
  */
-CASSERT(SCP_BL2_LIMIT <= BL1_RW_BASE, assert_scp_bl2_limit_overwrite_bl1);
-CASSERT(SCP_BL2U_LIMIT <= BL1_RW_BASE, assert_scp_bl2u_limit_overwrite_bl1);
+CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2);
+CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2);
 
-CASSERT(SCP_BL2_BASE >= BL2_LIMIT, assert_scp_bl2_overwrite_bl2);
-CASSERT(SCP_BL2U_BASE >= BL2U_LIMIT, assert_scp_bl2u_overwrite_bl2u);
+CASSERT(SCP_BL2_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2_overflow);
+CASSERT(SCP_BL2U_BASE >= ARM_TB_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow);
 #endif
 
 #endif /* __CSS_SCP_H__ */