diff --git a/Makefile b/Makefile index 073c2ed3e..42fdb7326 100644 --- a/Makefile +++ b/Makefile @@ -736,6 +736,7 @@ $(eval $(call assert_boolean,RAS_EXTENSION)) $(eval $(call assert_boolean,RESET_TO_BL31)) $(eval $(call assert_boolean,SAVE_KEYS)) $(eval $(call assert_boolean,SEPARATE_CODE_AND_RODATA)) +$(eval $(call assert_boolean,SEPARATE_NOBITS_REGION)) $(eval $(call assert_boolean,SPIN_ON_BL1_EXIT)) $(eval $(call assert_boolean,SPM_MM)) $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT)) @@ -800,6 +801,7 @@ $(eval $(call add_define,PSCI_EXTENDED_STATE_ID)) $(eval $(call add_define,RAS_EXTENSION)) $(eval $(call add_define,RESET_TO_BL31)) $(eval $(call add_define,SEPARATE_CODE_AND_RODATA)) +$(eval $(call add_define,SEPARATE_NOBITS_REGION)) $(eval $(call add_define,RECLAIM_INIT_CODE)) $(eval $(call add_define,SPD_${SPD})) $(eval $(call add_define,SPIN_ON_BL1_EXIT)) diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index a598e59cf..42227f0f3 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -15,6 +15,11 @@ ENTRY(bl31_entrypoint) MEMORY { RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE +#if SEPARATE_NOBITS_REGION + NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE +#else +#define NOBITS RAM +#endif } #ifdef PLAT_EXTRA_LD_SCRIPT @@ -198,11 +203,28 @@ SECTIONS ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.") #endif +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL31_END__ = .; + + ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") + + . = BL31_NOBITS_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31 NOBITS base address is not aligned on a page boundary.") + + __NOBITS_START__ = .; +#endif + stacks (NOLOAD) : { __STACKS_START__ = .; *(tzfw_normal_stacks) __STACKS_END__ = .; - } >RAM + } >NOBITS /* * The .bss section gets initialised to 0 at runtime. @@ -262,7 +284,7 @@ SECTIONS __PMF_TIMESTAMP_END__ = .; #endif /* ENABLE_PMF */ __BSS_END__ = .; - } >RAM + } >NOBITS /* * The xlat_table section is for full, aligned page tables (4K). @@ -272,7 +294,7 @@ SECTIONS */ xlat_table (NOLOAD) : { *(xlat_table) - } >RAM + } >NOBITS #if USE_COHERENT_MEM /* @@ -298,9 +320,18 @@ SECTIONS */ . = ALIGN(PAGE_SIZE); __COHERENT_RAM_END__ = .; - } >RAM + } >NOBITS #endif +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the NOBITS memory area for this + * image. + */ + __NOBITS_END__ = .; + + ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.") +#else /* * Define a linker symbol to mark end of the RW memory area for this * image. @@ -309,4 +340,5 @@ SECTIONS __BL31_END__ = .; ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") +#endif } diff --git a/docs/design/firmware-design.rst b/docs/design/firmware-design.rst index cae94b5d8..5fc1335b3 100644 --- a/docs/design/firmware-design.rst +++ b/docs/design/firmware-design.rst @@ -1500,6 +1500,11 @@ 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. +For BL31, a platform can specify an alternate location for NOBITS sections +(other than immediately following PROGBITS sections) by setting +``SEPARATE_NOBITS_REGION`` to 1 and defining ``BL31_NOBITS_BASE`` and +``BL31_NOBITS_LIMIT``. + Linker scripts and symbols ~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 37c28a5a4..d7bb0449e 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -491,6 +491,13 @@ Common build options pages" section in :ref:`Firmware Design`. This flag is disabled by default and affects all BL images. +- ``SEPARATE_NOBITS_REGION``: Setting this option to ``1`` allows the NOBITS + sections of BL31 (.bss, stacks, page tables, and coherent memory) to be + allocated in RAM discontiguous from the loaded firmware image. When set, the + platform is expected to provide definitons for ``BL31_NOBITS_BASE`` and + ``BL31_NOBITS_LIMIT``. When the option is ``0`` (the default), NOBITS + sections are placed in RAM immediately following the loaded firmware image. + - ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A. This build option is only valid if ``ARCH=aarch64``. The value should be the path to the directory containing the SPD source, relative to diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S index b14b7b66e..156b18a4f 100644 --- a/include/arch/aarch64/el3_common_macros.S +++ b/include/arch/aarch64/el3_common_macros.S @@ -382,6 +382,14 @@ add x1, x1, :lo12:__RW_END__ sub x1, x1, x0 bl inv_dcache_range +#if defined(IMAGE_BL31) && SEPARATE_NOBITS_REGION + adrp x0, __NOBITS_START__ + add x0, x0, :lo12:__NOBITS_START__ + adrp x1, __NOBITS_END__ + add x1, x1, :lo12:__NOBITS_END__ + sub x1, x1, x0 + bl inv_dcache_range +#endif #endif adrp x0, __BSS_START__ add x0, x0, :lo12:__BSS_START__ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index a1f9db9d3..53832c561 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -171,6 +171,10 @@ SDEI_SUPPORT := 0 # platform Makefile is free to override this value. SEPARATE_CODE_AND_RODATA := 0 +# Put NOBITS sections (.bss, stacks, page tables, and coherent memory) in a +# separate memory region, which may be discontiguous from the rest of BL31. +SEPARATE_NOBITS_REGION := 0 + # If the BL31 image initialisation code is recalimed after use for the secondary # cores stack RECLAIM_INIT_CODE := 0