tee: optee: sync cache on pre-reloc OP-TEE invocation
authorEtienne Carriere <etienne.carriere@linaro.org>
Wed, 19 May 2021 14:27:41 +0000 (16:27 +0200)
committerTom Rini <trini@konsulko.com>
Fri, 23 Jul 2021 11:13:25 +0000 (07:13 -0400)
This change ensures both U-Boot and OP-TEE see the same content
from shared memory when OP-TEE is invoked prior U-Boot relocation.

This change is required since U-Boot may execute with data cache off
while OP-TEE always enables cache on memory shared with U-Boot.

Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Reviewed-by: Jens Wiklander <jens.wiklander@linaro.org>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
drivers/tee/optee/core.c
drivers/tee/tee-uclass.c
include/tee.h

index 73dbb22..dad46aa 100644 (file)
@@ -1,9 +1,10 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (c) 2018 Linaro Limited
+ * Copyright (c) 2018-2020 Linaro Limited
  */
 
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
 #include <dm/device_compat.h>
 #include <log.h>
@@ -295,6 +296,16 @@ static u32 call_err_to_res(u32 call_err)
        }
 }
 
+static void flush_shm_dcache(struct udevice *dev, struct optee_msg_arg *arg)
+{
+       size_t sz = OPTEE_MSG_GET_ARG_SIZE(arg->num_params);
+
+       flush_dcache_range(rounddown((ulong)arg, CONFIG_SYS_CACHELINE_SIZE),
+                          roundup((ulong)arg + sz, CONFIG_SYS_CACHELINE_SIZE));
+
+       tee_flush_all_shm_dcache(dev);
+}
+
 static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
 {
        struct optee_pdata *pdata = dev_get_plat(dev);
@@ -305,9 +316,17 @@ static u32 do_call_with_arg(struct udevice *dev, struct optee_msg_arg *arg)
        while (true) {
                struct arm_smccc_res res;
 
+               /* If cache are off from U-Boot, sync the cache shared with OP-TEE */
+               if (!dcache_status())
+                       flush_shm_dcache(dev, arg);
+
                pdata->invoke_fn(param.a0, param.a1, param.a2, param.a3,
                                 param.a4, param.a5, param.a6, param.a7, &res);
 
+               /* If cache are off from U-Boot, sync the cache shared with OP-TEE */
+               if (!dcache_status())
+                       flush_shm_dcache(dev, arg);
+
                free(page_list);
                page_list = NULL;
 
index cb1b28e..52412a4 100644 (file)
@@ -1,15 +1,17 @@
 // SPDX-License-Identifier: GPL-2.0+
 /*
- * Copyright (c) 2018 Linaro Limited
+ * Copyright (c) 2018-2020 Linaro Limited
  */
 
 #define LOG_CATEGORY UCLASS_TEE
 
 #include <common.h>
+#include <cpu_func.h>
 #include <dm.h>
 #include <log.h>
 #include <malloc.h>
 #include <tee.h>
+#include <asm/cache.h>
 #include <dm/device-internal.h>
 #include <dm/uclass-internal.h>
 
@@ -235,3 +237,18 @@ void tee_optee_ta_uuid_to_octets(u8 d[TEE_UUID_LEN],
        d[7] = s->time_hi_and_version;
        memcpy(d + 8, s->clock_seq_and_node, sizeof(s->clock_seq_and_node));
 }
+
+void tee_flush_all_shm_dcache(struct udevice *dev)
+{
+       struct tee_uclass_priv *priv = dev_get_uclass_priv(dev);
+       struct tee_shm *s;
+
+       list_for_each_entry(s, &priv->list_shm, link) {
+               ulong start = rounddown((ulong)s->addr,
+                                       CONFIG_SYS_CACHELINE_SIZE);
+               ulong end = roundup((ulong)s->addr + s->size,
+                                   CONFIG_SYS_CACHELINE_SIZE);
+
+               flush_dcache_range(start, end);
+       }
+}
index 99367b2..2ef29bf 100644 (file)
@@ -377,4 +377,10 @@ void tee_optee_ta_uuid_from_octets(struct tee_optee_ta_uuid *d,
 void tee_optee_ta_uuid_to_octets(u8 d[TEE_UUID_LEN],
                                 const struct tee_optee_ta_uuid *s);
 
+/**
+ * tee_flush_all_shm_dcache() - Flush data cache for all shared memories
+ * @dev:       The TEE device
+ */
+void tee_flush_all_shm_dcache(struct udevice *dev);
+
 #endif /* __TEE_H */