[PATCH v9 10/10] optee: Add support for arm,ffa-lend-pool
Vincent Donnefort
vdonnefort at google.com
Wed Sep 2 03:47:12 PDT 2026
Hook OP-TEE dynamically allocated protected memory pools to the
"arm,ffa-lend-pool" driver. While the SMC transport platform device
resolves the pool through its DT "memory-region" property, the FF-A
transport lacks a device tree node and binds via ffa_lend_pool_attach().
Signed-off-by: Vincent Donnefort <vdonnefort at google.com>
diff --git a/drivers/tee/optee/ffa_abi.c b/drivers/tee/optee/ffa_abi.c
index 633715b98625..4d6555171918 100644
--- a/drivers/tee/optee/ffa_abi.c
+++ b/drivers/tee/optee/ffa_abi.c
@@ -979,6 +979,7 @@ static void optee_ffa_remove(struct ffa_device *ffa_dev)
mutex_destroy(&optee->ffa.mutex);
rhashtable_free_and_destroy(&optee->ffa.global_ids, rh_free_fn, NULL);
+ ffa_lend_pool_detach(&optee->teedev->dev);
kfree(optee);
}
@@ -1042,13 +1043,21 @@ static int optee_ffa_protmem_pool_init(struct optee *optee, u32 sec_caps)
int rc = 0;
if (sec_caps & OPTEE_FFA_SEC_CAP_PROTMEM) {
+ rc = ffa_lend_pool_attach(&optee->teedev->dev);
+ if (rc && rc != -ENODEV)
+ return rc;
+
pool = optee_protmem_alloc_dyn_pool(optee, id);
- if (IS_ERR(pool))
+ if (IS_ERR(pool)) {
+ ffa_lend_pool_detach(&optee->teedev->dev);
return PTR_ERR(pool);
+ }
rc = tee_device_register_dma_heap(optee->teedev, id, pool);
- if (rc)
+ if (rc) {
pool->ops->destroy_pool(pool);
+ ffa_lend_pool_detach(&optee->teedev->dev);
+ }
}
return rc;
diff --git a/drivers/tee/optee/protmem.c b/drivers/tee/optee/protmem.c
index be3abf6e8aa6..9b64db9b4e64 100644
--- a/drivers/tee/optee/protmem.c
+++ b/drivers/tee/optee/protmem.c
@@ -42,14 +42,6 @@ static int init_dyn_protmem(struct optee_protmem_dyn_pool *rp)
goto err_null_protmem;
}
- /*
- * TODO unmap the memory range since the physical memory will
- * become inaccesible after the lend_protmem() call.
- *
- * If the platform supports a hypervisor at EL2, it will unmap the
- * intermediate physical memory for us and stop cache pre-fetch of
- * the memory.
- */
rc = rp->optee->ops->lend_protmem(rp->optee, rp->protmem,
rp->mem_attrs,
rp->mem_attr_count, rp->use_case);
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index b8a2bdac3208..5949aa717cad 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -19,6 +19,7 @@
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_platform.h>
+#include <linux/of_reserved_mem.h>
#include <linux/platform_device.h>
#include <linux/rpmb.h>
#include <linux/sched.h>
@@ -1528,6 +1529,8 @@ static void optee_smc_remove(struct platform_device *pdev)
if (optee->smc.memremaped_shm)
memunmap(optee->smc.memremaped_shm);
+ of_reserved_mem_device_release(&optee->teedev->dev);
+
kfree(optee);
}
@@ -1712,16 +1715,22 @@ static int optee_protmem_pool_init(struct optee *optee)
if (!protm && !dyn_protm)
return 0;
+ of_reserved_mem_device_init_by_idx(&optee->teedev->dev,
+ dev_of_node(optee->teedev->dev.parent), 0);
if (protm)
pool = static_protmem_pool_init(optee);
if (dyn_protm && IS_ERR(pool))
pool = optee_protmem_alloc_dyn_pool(optee, heap_id);
- if (IS_ERR(pool))
+ if (IS_ERR(pool)) {
+ of_reserved_mem_device_release(&optee->teedev->dev);
return PTR_ERR(pool);
+ }
rc = tee_device_register_dma_heap(optee->teedev, heap_id, pool);
- if (rc)
+ if (rc) {
pool->ops->destroy_pool(pool);
+ of_reserved_mem_device_release(&optee->teedev->dev);
+ }
return rc;
}
@@ -1833,14 +1842,14 @@ static int optee_probe(struct platform_device *pdev)
(sec_caps & OPTEE_SMC_SEC_CAP_RPMB_PROBE))
optee->in_kernel_rpmb_routing = true;
- teedev = tee_device_alloc(&optee_clnt_desc, NULL, pool, optee);
+ teedev = tee_device_alloc(&optee_clnt_desc, &pdev->dev, pool, optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
goto err_free_optee;
}
optee->teedev = teedev;
- teedev = tee_device_alloc(&optee_supp_desc, NULL, pool, optee);
+ teedev = tee_device_alloc(&optee_supp_desc, &pdev->dev, pool, optee);
if (IS_ERR(teedev)) {
rc = PTR_ERR(teedev);
goto err_unreg_teedev;
diff --git a/drivers/tee/tee_shm.c b/drivers/tee/tee_shm.c
index 6742b3579c86..49a9b2993c83 100644
--- a/drivers/tee/tee_shm.c
+++ b/drivers/tee/tee_shm.c
@@ -3,6 +3,7 @@
* Copyright (c) 2015-2017, 2019-2021 Linaro Limited
*/
#include <linux/anon_inodes.h>
+#include <linux/arm_ffa.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/dma-mapping.h>
@@ -43,6 +44,7 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
dma_mem = container_of(shm, struct tee_shm_dma_mem, shm);
p = dma_mem;
+ ffa_lend_reclaimed(&teedev->dev, shm->paddr, shm->size);
dma_free_pages(&teedev->dev, shm->size, dma_mem->page,
dma_mem->dma_addr, DMA_BIDIRECTIONAL);
#endif
@@ -288,6 +290,7 @@ struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx,
struct tee_shm_dma_mem *dma_mem;
dma_addr_t dma_addr;
struct page *page;
+ int ret;
if (!tee_device_get(teedev))
return ERR_PTR(-EINVAL);
@@ -297,9 +300,13 @@ struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx,
if (!page)
goto err_put_teedev;
+ ret = ffa_prepare_lend(&teedev->dev, page_to_phys(page), page_count * PAGE_SIZE);
+ if (ret && ret != -ENODEV)
+ goto err_free_pages;
+
dma_mem = kzalloc_obj(*dma_mem);
if (!dma_mem)
- goto err_free_pages;
+ goto err_map_pages;
refcount_set(&dma_mem->shm.refcount, 1);
dma_mem->shm.ctx = ctx;
@@ -313,6 +320,8 @@ struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx,
return &dma_mem->shm;
+err_map_pages:
+ ffa_lend_reclaimed(&teedev->dev, page_to_phys(page), page_count * PAGE_SIZE);
err_free_pages:
dma_free_pages(&teedev->dev, page_count * PAGE_SIZE, page, dma_addr,
DMA_BIDIRECTIONAL);
--
2.55.0.970.g62bdec98f9-goog
More information about the linux-arm-kernel
mailing list