feat(cpus): make cache ops conditional

When a core is in debug recovery mode its caches are not invalidated
upon reset, so the L1 and L2 cache contents from before reset are
observable after reset. Similarly, debug recovery mode of DynamIQ
cluster ensures that contents of the shared L3 cache are also not
invalidated upon transition to On mode.

Booting cores in debug recovery mode means booting with caches disabled
and preserving the caches until a point where software can dump the
caches and retrieve their contents. TF-A however unconditionally cleans
and invalidates caches at multiple points during boot. This can lead to
memory corruption as well as loss of cache contents to be used for
debugging.

This patch fixes this by calling a platform hook before performing CMOs
in helper routines in cache_helpers.S. The platform hook plat_can_cmo is
an assembly routine which must not clobber x2 and x3, and avoid using
stack. The whole checking is conditional upon `CONDITIONAL_CMO` which
can be set at compile time.

Signed-off-by: Okash Khawaja <okash@google.com>
Change-Id: I172e999e4acd0f872c24056e647cc947ee54b193
diff --git a/lib/aarch32/cache_helpers.S b/lib/aarch32/cache_helpers.S
index 13d1872..fd9b33f 100644
--- a/lib/aarch32/cache_helpers.S
+++ b/lib/aarch32/cache_helpers.S
@@ -37,12 +37,27 @@
 	bx	lr
 .endm
 
+.macro check_plat_can_cmo
+#if CONDITIONAL_CMO
+	mov	r3, lr
+	mov	r2, r0
+	bl	plat_can_cmo
+	mov	lr, r3
+	cmp	r0, #0
+	bne	1f
+	bx	lr
+1:
+	mov	r0, r2
+#endif
+.endm
+
 	/* ------------------------------------------
 	 * Clean+Invalidate from base address till
 	 * size. 'r0' = addr, 'r1' = size
 	 * ------------------------------------------
 	 */
 func flush_dcache_range
+	check_plat_can_cmo
 	do_dcache_maintenance_by_mva cimvac, DCCIMVAC
 endfunc flush_dcache_range
 
@@ -52,6 +67,7 @@
 	 * ------------------------------------------
 	 */
 func clean_dcache_range
+	check_plat_can_cmo
 	do_dcache_maintenance_by_mva cmvac, DCCMVAC
 endfunc clean_dcache_range
 
@@ -61,6 +77,7 @@
 	 * ------------------------------------------
 	 */
 func inv_dcache_range
+	check_plat_can_cmo
 	do_dcache_maintenance_by_mva imvac, DCIMVAC
 endfunc inv_dcache_range
 
@@ -168,6 +185,7 @@
 	 * ---------------------------------------------------------------
 	 */
 func dcsw_op_louis
+	check_plat_can_cmo
 	dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
 endfunc	dcsw_op_louis
 
@@ -180,6 +198,7 @@
 	 * ---------------------------------------------------------------
 	 */
 func dcsw_op_all
+	check_plat_can_cmo
 	dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT
 endfunc	dcsw_op_all
 
@@ -205,6 +224,7 @@
 	 * ---------------------------------------------------------------
 	 */
 func dcsw_op_level1
+	check_plat_can_cmo
 	dcsw_op_level #(1 << LEVEL_SHIFT)
 endfunc dcsw_op_level1
 
@@ -217,6 +237,7 @@
 	 * ---------------------------------------------------------------
 	 */
 func dcsw_op_level2
+	check_plat_can_cmo
 	dcsw_op_level #(2 << LEVEL_SHIFT)
 endfunc dcsw_op_level2
 
@@ -229,5 +250,6 @@
 	 * ---------------------------------------------------------------
 	 */
 func dcsw_op_level3
+	check_plat_can_cmo
 	dcsw_op_level #(3 << LEVEL_SHIFT)
 endfunc dcsw_op_level3