[PATCH 12/12] efi_loader: align FF-A cache maintenance with runtime path

Harsimran Singh Tungal harsimransingh.tungal at arm.com
Fri Apr 24 19:31:51 CEST 2026


Match boot-time FF-A cache handling to runtime behavior

The boot-time FF-A MM communication path used invalidate_dcache_all()
after copying the message into the shared buffer. This differs from the
runtime path, which performs range-based maintenance to avoid global cache
operations.

Update ffa_mm_communicate() to use the same pattern as the runtime helper:
clean the shared buffer range before the SMC and invalidate the same range
after the response. This keeps boot-time and runtime behavior consistent
and avoids whole-cache invalidation.

Signed-off-by: Abdellatif El Khlifi <abdellatif.elkhlifi at arm.com>
Signed-off-by: Harsimran Singh Tungal <harsimransingh.tungal at arm.com>
---
 lib/efi_loader/efi_variable_tee.c | 33 ++++++++++++++++++++++++-------
 1 file changed, 26 insertions(+), 7 deletions(-)

diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c
index 30687c21b8e..df509a435b1 100644
--- a/lib/efi_loader/efi_variable_tee.c
+++ b/lib/efi_loader/efi_variable_tee.c
@@ -389,19 +389,38 @@ static efi_status_t ffa_mm_communicate(void *comm_buf, ulong comm_buf_size)
 	memcpy(virt_shared_buf, comm_buf, tx_data_size);
 
 	/*
-	 * The secure world might have cache disabled for
-	 * the device region used for shared buffer (which is the case for Optee).
-	 * In this case, the secure world reads the data from DRAM.
-	 * Let's flush the cache so the DRAM is updated with the latest data.
+	 * Shared buffer cache maintenance for FF-A / OP-TEE communication:
+	 *
+	 * NS -> S (request path):
+	 *
+	 * The non-secure side populates the shared buffer. If the buffer is cached
+	 * in NS, the updated bytes may reside in dirty D-cache lines and not yet be
+	 * visible in DDR. Since the secure world typically reads the shared buffer
+	 * directly from DDR (e.g. with caches disabled / non-coherent mapping), we
+	 * must clean the corresponding cache lines to the Point of Coherency (PoC)
+	 * before entering secure world.
+	 *
+	 * S -> NS (response path):
+	 *
+	 * The secure world may update the same shared buffer in DDR. After returning
+	 * to non-secure, any cached copies of that region in NS may be stale. We
+	 * therefore invalidate the shared buffer range after the FF-A call to drop
+	 * those lines and force subsequent reads to fetch the latest data from DDR.
 	 */
-#ifdef CONFIG_ARM64
-	invalidate_dcache_all();
-#endif
+	if (IS_ENABLED(CONFIG_ARM64))
+		flush_dcache_range((unsigned long)virt_shared_buf,
+				   (unsigned long)virt_shared_buf +
+				   CONFIG_FFA_SHARED_MM_BUF_SIZE);
 
 	/* Announce there is data in the shared buffer */
 
 	ffa_ret = ffa_notify_mm_sp();
 
+	if (IS_ENABLED(CONFIG_ARM64))
+		invalidate_dcache_range((unsigned long)virt_shared_buf,
+					(unsigned long)virt_shared_buf +
+					CONFIG_FFA_SHARED_MM_BUF_SIZE);
+
 	switch (ffa_ret) {
 	case 0: {
 		ulong rx_data_size;
-- 
2.34.1



More information about the U-Boot mailing list