feat(lib/granule): Clean and invalidate granules to PoE

A granule in GPT_REALM can transition between DELEGATED and other states
several times, and be accessed in different MEC contexts. When
transitioning back to DELEGATED, flush the caches to the point of
encryption in order to avoid MECID mismatches.

TF-A's clean+invalidate to PoPA when delegating/undelegating already
deals with transitions that change the granule's GPT entry. So we could
optimize this by marking the granule dirty when transitioning back to
DELEGATED, then doing the flush only if the granule is reused without
going through an undelegate operation.

Change-Id: I12e9f93f49462e55025b0d5dd16dc78f8a3b3637
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.org>
diff --git a/lib/arch/src/aarch64/cache_helpers.S b/lib/arch/src/aarch64/cache_helpers.S
index 195cf61..bd7a6c4 100644
--- a/lib/arch/src/aarch64/cache_helpers.S
+++ b/lib/arch/src/aarch64/cache_helpers.S
@@ -9,6 +9,13 @@
 	.globl	flush_dcache_range
 	.globl	clean_dcache_range
 	.globl	inv_dcache_range
+	.globl	flush_dcache_range_to_poe
+
+/*
+ * sys  #4, c7, c14, #0, x0
+ * DC CIPAE, X0
+ */
+#define dc_cipae_x0    0xd50c7e00
 
 /*
  * This macro can be used for implementing various data cache operations `op`
@@ -29,6 +36,25 @@
 exit_loop_\op:
 	ret
 .endm
+
+/* op: the hexadecimal instruction opcode for the cache operation */
+.macro do_dcache_maintenance_instr op
+	/* Exit early if size is zero */
+	cbz	x1, exit_loop_\op
+	dcache_line_size x2, x3
+	add	x1, x0, x1
+	sub	x3, x2, #1
+	bic	x0, x0, x3
+loop_\op:
+	.inst	\op
+	add	x0, x0, x2
+	cmp	x0, x1
+	b.lo	loop_\op
+	dsb	sy
+exit_loop_\op:
+	ret
+.endm
+
 	/* ------------------------------------------
 	 * Clean+Invalidate from base address till
 	 * size. 'x0' = addr, 'x1' = size
@@ -55,3 +81,13 @@
 func inv_dcache_range
 	do_dcache_maintenance_by_mva ivac
 endfunc inv_dcache_range
+
+	/* ------------------------------------------
+	 * Clean and invalidate to point of
+	 * encryption from base address till size.
+	 * 'x0' = physical addr, 'x1' = size
+	 * ------------------------------------------
+	 */
+func flush_dcache_range_to_poe
+	do_dcache_maintenance_instr dc_cipae_x0
+endfunc flush_dcache_range_to_poe