Merge "build(bl31): support separated memory for RW DATA" into integration
diff --git a/Makefile b/Makefile
index 6bbca3b..465e115 100644
--- a/Makefile
+++ b/Makefile
@@ -1189,6 +1189,7 @@
 	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 @@
 	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 8698dff..867dedb 100644
--- a/bl31/bl31.ld.S
+++ b/bl31/bl31.ld.S
@@ -19,6 +19,12 @@
 #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 @@
     . = LOADADDR(.spm_shim_exceptions) + SIZEOF(.spm_shim_exceptions);
 #endif /* SPM_MM || (SPMC_AT_EL3 && SPMC_AT_EL3_SEL0_SP) */
 
+#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__ = .;
+
-    __RW_START__ = .;
+    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 @@
 #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 @@
 
     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 1666e3b..204625c 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 584542c..d6c09de 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -240,6 +240,10 @@
 # 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