PSCI: Build option to enable D-Caches early in warmboot

This patch introduces a build option to enable D-cache early on the CPU
after warm boot. This is applicable for platforms which do not require
interconnect programming to enable cache coherency (eg: single cluster
platforms). If this option is enabled, then warm boot path enables
D-caches immediately after enabling MMU.

Fixes ARM-Software/tf-issues#456

Change-Id: I44c8787d116d7217837ced3bcf0b1d3441c8d80e
Signed-off-by: Soby Mathew <soby.mathew@arm.com>
diff --git a/Makefile b/Makefile
index 9f9061c..1c2dcb9 100644
--- a/Makefile
+++ b/Makefile
@@ -459,6 +459,7 @@
 $(eval $(call assert_boolean,SPIN_ON_BL1_EXIT))
 $(eval $(call assert_boolean,TRUSTED_BOARD_BOOT))
 $(eval $(call assert_boolean,USE_COHERENT_MEM))
+$(eval $(call assert_boolean,WARMBOOT_ENABLE_DCACHE_EARLY))
 
 $(eval $(call assert_numeric,ARM_ARCH_MAJOR))
 $(eval $(call assert_numeric,ARM_ARCH_MINOR))
@@ -496,6 +497,7 @@
 $(eval $(call add_define,SPIN_ON_BL1_EXIT))
 $(eval $(call add_define,TRUSTED_BOARD_BOOT))
 $(eval $(call add_define,USE_COHERENT_MEM))
+$(eval $(call add_define,WARMBOOT_ENABLE_DCACHE_EARLY))
 
 # Define the EL3_PAYLOAD_BASE flag only if it is provided.
 ifdef EL3_PAYLOAD_BASE
diff --git a/bl31/aarch64/bl31_entrypoint.S b/bl31/aarch64/bl31_entrypoint.S
index 6238329..a847ae3 100644
--- a/bl31/aarch64/bl31_entrypoint.S
+++ b/bl31/aarch64/bl31_entrypoint.S
@@ -185,26 +185,27 @@
 	 *
 	 * The PSCI implementation invokes platform routines that enable CPUs to
 	 * participate in coherency. On a system where CPUs are not
-	 * cache-coherent out of reset, having caches enabled until such time
-	 * might lead to coherency issues (resulting from stale data getting
-	 * speculatively fetched, among others). Therefore we keep data caches
-	 * disabled while enabling the MMU, thereby forcing data accesses to
-	 * have non-cacheable, nGnRnE attributes (these will always be coherent
-	 * with main memory).
+	 * cache-coherent without appropriate platform specific programming,
+	 * having caches enabled until such time might lead to coherency issues
+	 * (resulting from stale data getting speculatively fetched, among
+	 * others). Therefore we keep data caches disabled even after enabling
+	 * the MMU for such platforms.
 	 *
-	 * On systems with hardware-assisted coherency, where CPUs are expected
-	 * to be cache-coherent out of reset without needing explicit software
-	 * intervention, PSCI need not invoke platform routines to enter
-	 * coherency (as CPUs already are); and there's no reason to have caches
-	 * disabled either.
+	 * On systems with hardware-assisted coherency, or on single cluster
+	 * platforms, such platform specific programming is not required to
+	 * enter coherency (as CPUs already are); and there's no reason to have
+	 * caches disabled either.
 	 */
-#if HW_ASSISTED_COHERENCY
-	mov	x0, #0
-#else
 	mov	x0, #DISABLE_DCACHE
-#endif
 	bl	bl31_plat_enable_mmu
 
+#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY
+	mrs	x0, sctlr_el3
+	orr	x0, x0, #SCTLR_C_BIT
+	msr	sctlr_el3, x0
+	isb
+#endif
+
 	bl	psci_warmboot_entrypoint
 
 #if ENABLE_RUNTIME_INSTRUMENTATION
diff --git a/bl32/sp_min/aarch32/entrypoint.S b/bl32/sp_min/aarch32/entrypoint.S
index c7f60b5..477b55b 100644
--- a/bl32/sp_min/aarch32/entrypoint.S
+++ b/bl32/sp_min/aarch32/entrypoint.S
@@ -236,24 +236,27 @@
 	 *
 	 * The PSCI implementation invokes platform routines that enable CPUs to
 	 * participate in coherency. On a system where CPUs are not
-	 * cache-coherent out of reset, having caches enabled until such time
-	 * might lead to coherency issues (resulting from stale data getting
-	 * speculatively fetched, among others). Therefore we keep data caches
-	 * disabled while enabling the MMU, thereby forcing data accesses to
-	 * have non-cacheable, nGnRnE attributes (these will always be coherent
-	 * with main memory).
+	 * cache-coherent without appropriate platform specific programming,
+	 * having caches enabled until such time might lead to coherency issues
+	 * (resulting from stale data getting speculatively fetched, among
+	 * others). Therefore we keep data caches disabled even after enabling
+	 * the MMU for such platforms.
 	 *
-	 * On systems where CPUs are cache-coherent out of reset, however, PSCI
-	 * need not invoke platform routines to enter coherency (as CPUs already
-	 * are), and there's no reason to have caches disabled either.
+	 * On systems with hardware-assisted coherency, or on single cluster
+	 * platforms, such platform specific programming is not required to
+	 * enter coherency (as CPUs already are); and there's no reason to have
+	 * caches disabled either.
 	 */
-#if HW_ASSISTED_COHERENCY
-	mov	r0, #0
-#else
 	mov	r0, #DISABLE_DCACHE
-#endif
 	bl	bl32_plat_enable_mmu
 
+#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY
+	ldcopr	r0, SCTLR
+	orr	r0, r0, #SCTLR_C_BIT
+	stcopr	r0, SCTLR
+	isb
+#endif
+
 	bl	sp_min_warm_boot
 
 	/* Program the registers in cpu_context and exit monitor mode */
diff --git a/docs/user-guide.md b/docs/user-guide.md
index a1df965..af7741e 100644
--- a/docs/user-guide.md
+++ b/docs/user-guide.md
@@ -349,7 +349,8 @@
     initiate the operations, and the rest is managed in hardware, minimizing
     active software management. In such systems, this boolean option enables ARM
     Trusted Firmware to carry out build and run-time optimizations during boot
-    and power management operations. This option defaults to 0.
+    and power management operations. This option defaults to 0 and if it is
+    enabled, then it implies `WARMBOOT_ENABLE_DCACHE_EARLY` is also enabled.
 
 *   `LOAD_IMAGE_V2`: Boolean option to enable support for new version (v2) of
     image loading, which provides more flexibility and scalability around what
@@ -508,6 +509,12 @@
     to a string formed by concatenating the version number, build type and build
     string.
 
+*   `WARMBOOT_ENABLE_DCACHE_EARLY` : Boolean option to enable D-cache early on
+    the CPU after warm boot. This is applicable for platforms which do not
+    require interconnect programming to enable cache coherency (eg: single
+    cluster platforms). If this option is enabled, then warm boot path
+    enables D-caches immediately after enabling MMU. This option defaults to 0.
+
 #### ARM development platform specific build options
 
 *   `ARM_BL31_IN_DRAM`: Boolean option to select loading of BL31 in TZC secured
diff --git a/lib/psci/psci_on.c b/lib/psci/psci_on.c
index 675ed66..76e67a3 100644
--- a/lib/psci/psci_on.c
+++ b/lib/psci/psci_on.c
@@ -165,7 +165,7 @@
 	 */
 	psci_plat_pm_ops->pwr_domain_on_finish(state_info);
 
-#if !HW_ASSISTED_COHERENCY
+#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
 	/*
 	 * Arch. management: Enable data cache and manage stack memory
 	 */
diff --git a/lib/psci/psci_suspend.c b/lib/psci/psci_suspend.c
index 08c8fd6..bf95df2 100644
--- a/lib/psci/psci_suspend.c
+++ b/lib/psci/psci_suspend.c
@@ -302,7 +302,7 @@
 	 */
 	psci_plat_pm_ops->pwr_domain_suspend_finish(state_info);
 
-#if !HW_ASSISTED_COHERENCY
+#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY)
 	/* Arch. management: Enable the data cache, stack memory maintenance. */
 	psci_do_pwrup_cache_maintenance();
 #endif
diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk
index e66f511..903363a 100644
--- a/make_helpers/defaults.mk
+++ b/make_helpers/defaults.mk
@@ -154,3 +154,9 @@
 
 # Build verbosity
 V				:= 0
+
+# Whether to enable D-Cache early during warm boot. This is usually
+# applicable for platforms wherein interconnect programming is not
+# required to enable cache coherency after warm reset (eg: single cluster
+# platforms).
+WARMBOOT_ENABLE_DCACHE_EARLY	:= 0