diff --git a/Makefile b/Makefile index 6bbca3bfd..465e1154b 100644 --- a/Makefile +++ b/Makefile @@ -1189,6 +1189,7 @@ $(eval $(call assert_booleans,\ SEPARATE_CODE_AND_RODATA \ SEPARATE_BL2_NOLOAD_REGION \ SEPARATE_NOBITS_REGION \ + SEPARATE_RWDATA_REGION \ SEPARATE_SIMD_SECTION \ SPIN_ON_BL1_EXIT \ SPM_MM \ @@ -1368,6 +1369,7 @@ $(eval $(call add_defines,\ SEPARATE_CODE_AND_RODATA \ SEPARATE_BL2_NOLOAD_REGION \ SEPARATE_NOBITS_REGION \ + SEPARATE_RWDATA_REGION \ SEPARATE_SIMD_SECTION \ RECLAIM_INIT_CODE \ SPD_${SPD} \ diff --git a/bl31/bl31.ld.S b/bl31/bl31.ld.S index 8698dffd4..867dedb99 100644 --- a/bl31/bl31.ld.S +++ b/bl31/bl31.ld.S @@ -19,6 +19,12 @@ MEMORY { #else /* SEPARATE_NOBITS_REGION */ # define NOBITS RAM #endif /* SEPARATE_NOBITS_REGION */ + +#if SEPARATE_RWDATA_REGION + RAM_RW (rw): ORIGIN = BL31_RWDATA_BASE, LENGTH = BL31_RWDATA_LIMIT - BL31_RWDATA_BASE +#else /* SEPARATE_RWDATA_REGION */ +#define RAM_RW RAM +#endif /* SEPARATE_RWDATA_REGION */ } #ifdef PLAT_EXTRA_LD_SCRIPT @@ -136,10 +142,36 @@ SECTIONS { . = LOADADDR(.spm_shim_exceptions) + SIZEOF(.spm_shim_exceptions); #endif /* SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) */ - __RW_START__ = .; +#if SEPARATE_RWDATA_REGION + . = BL31_RWDATA_BASE; + ASSERT(BL31_RWDATA_BASE == ALIGN(PAGE_SIZE), + "BL31_RWDATA_BASE address is not aligned on a page boundary.") + + /* + * Define a linker symbol to mark the start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM_RW AT>RAM + __DATA_RAM_START__ = __DATA_START__; + __DATA_RAM_END__ = __DATA_END__; + __DATA_ROM_START__ = LOADADDR(.data); + + . = ALIGN(PAGE_SIZE); + __RW_END__ = .; + + RELA_SECTION >RAM +#else /* SEPARATE_RWDATA_REGION */ + /* + * Define a linker symbol to mark the start of the RW memory area for this + * image. + */ + __RW_START__ = . ; DATA_SECTION >RAM RELA_SECTION >RAM +#endif /* SEPARATE_RWDATA_REGION */ #ifdef BL31_PROGBITS_LIMIT ASSERT( @@ -151,7 +183,9 @@ SECTIONS { #if SEPARATE_NOBITS_REGION . = ALIGN(PAGE_SIZE); +#if !SEPARATE_RWDATA_REGION __RW_END__ = .; +#endif /* SEPARATE_RWDATA_REGION */ __BL31_END__ = .; ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") @@ -203,7 +237,13 @@ SECTIONS { ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.") #else /* SEPARATE_NOBITS_REGION */ + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ +#if !SEPARATE_RWDATA_REGION __RW_END__ = .; +#endif /* SEPARATE_RWDATA_REGION */ __BL31_END__ = .; ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") diff --git a/include/arch/aarch64/el3_common_macros.S b/include/arch/aarch64/el3_common_macros.S index 1666e3bfe..204625cee 100644 --- a/include/arch/aarch64/el3_common_macros.S +++ b/include/arch/aarch64/el3_common_macros.S @@ -340,7 +340,9 @@ #endif #if defined(IMAGE_BL1) || \ - (defined(IMAGE_BL2) && RESET_TO_BL2 && BL2_IN_XIP_MEM) + (defined(IMAGE_BL2) && RESET_TO_BL2 && BL2_IN_XIP_MEM) || \ + (defined(IMAGE_BL31) && SEPARATE_RWDATA_REGION) + adrp x0, __DATA_RAM_START__ add x0, x0, :lo12:__DATA_RAM_START__ adrp x1, __DATA_ROM_START__ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 584542c30..d6c09de66 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -240,6 +240,10 @@ SEPARATE_NOBITS_REGION := 0 # region, platform Makefile is free to override this value. SEPARATE_BL2_NOLOAD_REGION := 0 +# Put RW DATA sections (.rwdata) in a separate memory region, which may be +# discontiguous from the rest of BL31. +SEPARATE_RWDATA_REGION := 0 + # Put SIMD context data structures in a separate memory region. Platforms # have the choice to put it outside of default BSS region of EL3 firmware. SEPARATE_SIMD_SECTION := 0