tee_heap.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2025, Linaro Limited
  4. */
  5. #include <linux/dma-buf.h>
  6. #include <linux/dma-heap.h>
  7. #include <linux/genalloc.h>
  8. #include <linux/module.h>
  9. #include <linux/scatterlist.h>
  10. #include <linux/slab.h>
  11. #include <linux/tee_core.h>
  12. #include <linux/xarray.h>
  13. #include "tee_private.h"
  14. struct tee_dma_heap {
  15. struct dma_heap *heap;
  16. enum tee_dma_heap_id id;
  17. struct kref kref;
  18. struct tee_protmem_pool *pool;
  19. struct tee_device *teedev;
  20. bool shutting_down;
  21. /* Protects pool, teedev, and shutting_down above */
  22. struct mutex mu;
  23. };
  24. struct tee_heap_buffer {
  25. struct tee_dma_heap *heap;
  26. size_t size;
  27. size_t offs;
  28. struct sg_table table;
  29. };
  30. struct tee_heap_attachment {
  31. struct sg_table table;
  32. struct device *dev;
  33. };
  34. struct tee_protmem_static_pool {
  35. struct tee_protmem_pool pool;
  36. struct gen_pool *gen_pool;
  37. phys_addr_t pa_base;
  38. };
  39. #if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS)
  40. static DEFINE_XARRAY_ALLOC(tee_dma_heap);
  41. static void tee_heap_release(struct kref *kref)
  42. {
  43. struct tee_dma_heap *h = container_of(kref, struct tee_dma_heap, kref);
  44. h->pool->ops->destroy_pool(h->pool);
  45. tee_device_put(h->teedev);
  46. h->pool = NULL;
  47. h->teedev = NULL;
  48. }
  49. static void put_tee_heap(struct tee_dma_heap *h)
  50. {
  51. kref_put(&h->kref, tee_heap_release);
  52. }
  53. static void get_tee_heap(struct tee_dma_heap *h)
  54. {
  55. kref_get(&h->kref);
  56. }
  57. static int copy_sg_table(struct sg_table *dst, struct sg_table *src)
  58. {
  59. struct scatterlist *dst_sg;
  60. struct scatterlist *src_sg;
  61. int ret;
  62. int i;
  63. ret = sg_alloc_table(dst, src->orig_nents, GFP_KERNEL);
  64. if (ret)
  65. return ret;
  66. dst_sg = dst->sgl;
  67. for_each_sgtable_sg(src, src_sg, i) {
  68. sg_set_page(dst_sg, sg_page(src_sg), src_sg->length,
  69. src_sg->offset);
  70. dst_sg = sg_next(dst_sg);
  71. }
  72. return 0;
  73. }
  74. static int tee_heap_attach(struct dma_buf *dmabuf,
  75. struct dma_buf_attachment *attachment)
  76. {
  77. struct tee_heap_buffer *buf = dmabuf->priv;
  78. struct tee_heap_attachment *a;
  79. int ret;
  80. a = kzalloc_obj(*a);
  81. if (!a)
  82. return -ENOMEM;
  83. ret = copy_sg_table(&a->table, &buf->table);
  84. if (ret) {
  85. kfree(a);
  86. return ret;
  87. }
  88. a->dev = attachment->dev;
  89. attachment->priv = a;
  90. return 0;
  91. }
  92. static void tee_heap_detach(struct dma_buf *dmabuf,
  93. struct dma_buf_attachment *attachment)
  94. {
  95. struct tee_heap_attachment *a = attachment->priv;
  96. sg_free_table(&a->table);
  97. kfree(a);
  98. }
  99. static struct sg_table *
  100. tee_heap_map_dma_buf(struct dma_buf_attachment *attachment,
  101. enum dma_data_direction direction)
  102. {
  103. struct tee_heap_attachment *a = attachment->priv;
  104. int ret;
  105. ret = dma_map_sgtable(attachment->dev, &a->table, direction,
  106. DMA_ATTR_SKIP_CPU_SYNC);
  107. if (ret)
  108. return ERR_PTR(ret);
  109. return &a->table;
  110. }
  111. static void tee_heap_unmap_dma_buf(struct dma_buf_attachment *attachment,
  112. struct sg_table *table,
  113. enum dma_data_direction direction)
  114. {
  115. struct tee_heap_attachment *a = attachment->priv;
  116. WARN_ON(&a->table != table);
  117. dma_unmap_sgtable(attachment->dev, table, direction,
  118. DMA_ATTR_SKIP_CPU_SYNC);
  119. }
  120. static void tee_heap_buf_free(struct dma_buf *dmabuf)
  121. {
  122. struct tee_heap_buffer *buf = dmabuf->priv;
  123. buf->heap->pool->ops->free(buf->heap->pool, &buf->table);
  124. mutex_lock(&buf->heap->mu);
  125. put_tee_heap(buf->heap);
  126. mutex_unlock(&buf->heap->mu);
  127. kfree(buf);
  128. }
  129. static const struct dma_buf_ops tee_heap_buf_ops = {
  130. .attach = tee_heap_attach,
  131. .detach = tee_heap_detach,
  132. .map_dma_buf = tee_heap_map_dma_buf,
  133. .unmap_dma_buf = tee_heap_unmap_dma_buf,
  134. .release = tee_heap_buf_free,
  135. };
  136. static struct dma_buf *tee_dma_heap_alloc(struct dma_heap *heap,
  137. unsigned long len, u32 fd_flags,
  138. u64 heap_flags)
  139. {
  140. struct tee_dma_heap *h = dma_heap_get_drvdata(heap);
  141. DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
  142. struct tee_device *teedev = NULL;
  143. struct tee_heap_buffer *buf;
  144. struct tee_protmem_pool *pool;
  145. struct dma_buf *dmabuf;
  146. int rc;
  147. mutex_lock(&h->mu);
  148. if (h->teedev) {
  149. teedev = h->teedev;
  150. pool = h->pool;
  151. get_tee_heap(h);
  152. }
  153. mutex_unlock(&h->mu);
  154. if (!teedev)
  155. return ERR_PTR(-EINVAL);
  156. buf = kzalloc_obj(*buf);
  157. if (!buf) {
  158. dmabuf = ERR_PTR(-ENOMEM);
  159. goto err;
  160. }
  161. buf->size = len;
  162. buf->heap = h;
  163. rc = pool->ops->alloc(pool, &buf->table, len, &buf->offs);
  164. if (rc) {
  165. dmabuf = ERR_PTR(rc);
  166. goto err_kfree;
  167. }
  168. exp_info.ops = &tee_heap_buf_ops;
  169. exp_info.size = len;
  170. exp_info.priv = buf;
  171. exp_info.flags = fd_flags;
  172. dmabuf = dma_buf_export(&exp_info);
  173. if (IS_ERR(dmabuf))
  174. goto err_protmem_free;
  175. return dmabuf;
  176. err_protmem_free:
  177. pool->ops->free(pool, &buf->table);
  178. err_kfree:
  179. kfree(buf);
  180. err:
  181. mutex_lock(&h->mu);
  182. put_tee_heap(h);
  183. mutex_unlock(&h->mu);
  184. return dmabuf;
  185. }
  186. static const struct dma_heap_ops tee_dma_heap_ops = {
  187. .allocate = tee_dma_heap_alloc,
  188. };
  189. static const char *heap_id_2_name(enum tee_dma_heap_id id)
  190. {
  191. switch (id) {
  192. case TEE_DMA_HEAP_SECURE_VIDEO_PLAY:
  193. return "protected,secure-video";
  194. case TEE_DMA_HEAP_TRUSTED_UI:
  195. return "protected,trusted-ui";
  196. case TEE_DMA_HEAP_SECURE_VIDEO_RECORD:
  197. return "protected,secure-video-record";
  198. default:
  199. return NULL;
  200. }
  201. }
  202. static int alloc_dma_heap(struct tee_device *teedev, enum tee_dma_heap_id id,
  203. struct tee_protmem_pool *pool)
  204. {
  205. struct dma_heap_export_info exp_info = {
  206. .ops = &tee_dma_heap_ops,
  207. .name = heap_id_2_name(id),
  208. };
  209. struct tee_dma_heap *h;
  210. int rc;
  211. if (!exp_info.name)
  212. return -EINVAL;
  213. if (xa_reserve(&tee_dma_heap, id, GFP_KERNEL)) {
  214. if (!xa_load(&tee_dma_heap, id))
  215. return -EEXIST;
  216. return -ENOMEM;
  217. }
  218. h = kzalloc_obj(*h);
  219. if (!h)
  220. return -ENOMEM;
  221. h->id = id;
  222. kref_init(&h->kref);
  223. h->teedev = teedev;
  224. h->pool = pool;
  225. mutex_init(&h->mu);
  226. exp_info.priv = h;
  227. h->heap = dma_heap_add(&exp_info);
  228. if (IS_ERR(h->heap)) {
  229. rc = PTR_ERR(h->heap);
  230. kfree(h);
  231. return rc;
  232. }
  233. /* "can't fail" due to the call to xa_reserve() above */
  234. return WARN_ON(xa_is_err(xa_store(&tee_dma_heap, id, h, GFP_KERNEL)));
  235. }
  236. int tee_device_register_dma_heap(struct tee_device *teedev,
  237. enum tee_dma_heap_id id,
  238. struct tee_protmem_pool *pool)
  239. {
  240. struct tee_dma_heap *h;
  241. int rc;
  242. if (!tee_device_get(teedev))
  243. return -EINVAL;
  244. h = xa_load(&tee_dma_heap, id);
  245. if (h) {
  246. mutex_lock(&h->mu);
  247. if (h->teedev) {
  248. rc = -EBUSY;
  249. } else {
  250. kref_init(&h->kref);
  251. h->shutting_down = false;
  252. h->teedev = teedev;
  253. h->pool = pool;
  254. rc = 0;
  255. }
  256. mutex_unlock(&h->mu);
  257. } else {
  258. rc = alloc_dma_heap(teedev, id, pool);
  259. }
  260. if (rc) {
  261. tee_device_put(teedev);
  262. dev_err(&teedev->dev, "can't register DMA heap id %d (%s)\n",
  263. id, heap_id_2_name(id));
  264. }
  265. return rc;
  266. }
  267. EXPORT_SYMBOL_GPL(tee_device_register_dma_heap);
  268. void tee_device_put_all_dma_heaps(struct tee_device *teedev)
  269. {
  270. struct tee_dma_heap *h;
  271. u_long i;
  272. xa_for_each(&tee_dma_heap, i, h) {
  273. if (h) {
  274. mutex_lock(&h->mu);
  275. if (h->teedev == teedev && !h->shutting_down) {
  276. h->shutting_down = true;
  277. put_tee_heap(h);
  278. }
  279. mutex_unlock(&h->mu);
  280. }
  281. }
  282. }
  283. EXPORT_SYMBOL_GPL(tee_device_put_all_dma_heaps);
  284. int tee_heap_update_from_dma_buf(struct tee_device *teedev,
  285. struct dma_buf *dmabuf, size_t *offset,
  286. struct tee_shm *shm,
  287. struct tee_shm **parent_shm)
  288. {
  289. struct tee_heap_buffer *buf;
  290. int rc;
  291. /* The DMA-buf must be from our heap */
  292. if (dmabuf->ops != &tee_heap_buf_ops)
  293. return -EINVAL;
  294. buf = dmabuf->priv;
  295. /* The buffer must be from the same teedev */
  296. if (buf->heap->teedev != teedev)
  297. return -EINVAL;
  298. shm->size = buf->size;
  299. rc = buf->heap->pool->ops->update_shm(buf->heap->pool, &buf->table,
  300. buf->offs, shm, parent_shm);
  301. if (!rc && *parent_shm)
  302. *offset = buf->offs;
  303. return rc;
  304. }
  305. #else
  306. int tee_device_register_dma_heap(struct tee_device *teedev __always_unused,
  307. enum tee_dma_heap_id id __always_unused,
  308. struct tee_protmem_pool *pool __always_unused)
  309. {
  310. return -EINVAL;
  311. }
  312. EXPORT_SYMBOL_GPL(tee_device_register_dma_heap);
  313. void
  314. tee_device_put_all_dma_heaps(struct tee_device *teedev __always_unused)
  315. {
  316. }
  317. EXPORT_SYMBOL_GPL(tee_device_put_all_dma_heaps);
  318. int tee_heap_update_from_dma_buf(struct tee_device *teedev __always_unused,
  319. struct dma_buf *dmabuf __always_unused,
  320. size_t *offset __always_unused,
  321. struct tee_shm *shm __always_unused,
  322. struct tee_shm **parent_shm __always_unused)
  323. {
  324. return -EINVAL;
  325. }
  326. #endif
  327. static struct tee_protmem_static_pool *
  328. to_protmem_static_pool(struct tee_protmem_pool *pool)
  329. {
  330. return container_of(pool, struct tee_protmem_static_pool, pool);
  331. }
  332. static int protmem_pool_op_static_alloc(struct tee_protmem_pool *pool,
  333. struct sg_table *sgt, size_t size,
  334. size_t *offs)
  335. {
  336. struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool);
  337. phys_addr_t pa;
  338. int ret;
  339. pa = gen_pool_alloc(stp->gen_pool, size);
  340. if (!pa)
  341. return -ENOMEM;
  342. ret = sg_alloc_table(sgt, 1, GFP_KERNEL);
  343. if (ret) {
  344. gen_pool_free(stp->gen_pool, pa, size);
  345. return ret;
  346. }
  347. sg_set_page(sgt->sgl, phys_to_page(pa), size, 0);
  348. *offs = pa - stp->pa_base;
  349. return 0;
  350. }
  351. static void protmem_pool_op_static_free(struct tee_protmem_pool *pool,
  352. struct sg_table *sgt)
  353. {
  354. struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool);
  355. struct scatterlist *sg;
  356. int i;
  357. for_each_sgtable_sg(sgt, sg, i)
  358. gen_pool_free(stp->gen_pool, sg_phys(sg), sg->length);
  359. sg_free_table(sgt);
  360. }
  361. static int protmem_pool_op_static_update_shm(struct tee_protmem_pool *pool,
  362. struct sg_table *sgt, size_t offs,
  363. struct tee_shm *shm,
  364. struct tee_shm **parent_shm)
  365. {
  366. struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool);
  367. shm->paddr = stp->pa_base + offs;
  368. *parent_shm = NULL;
  369. return 0;
  370. }
  371. static void protmem_pool_op_static_destroy_pool(struct tee_protmem_pool *pool)
  372. {
  373. struct tee_protmem_static_pool *stp = to_protmem_static_pool(pool);
  374. gen_pool_destroy(stp->gen_pool);
  375. kfree(stp);
  376. }
  377. static struct tee_protmem_pool_ops protmem_pool_ops_static = {
  378. .alloc = protmem_pool_op_static_alloc,
  379. .free = protmem_pool_op_static_free,
  380. .update_shm = protmem_pool_op_static_update_shm,
  381. .destroy_pool = protmem_pool_op_static_destroy_pool,
  382. };
  383. struct tee_protmem_pool *tee_protmem_static_pool_alloc(phys_addr_t paddr,
  384. size_t size)
  385. {
  386. const size_t page_mask = PAGE_SIZE - 1;
  387. struct tee_protmem_static_pool *stp;
  388. int rc;
  389. /* Check it's page aligned */
  390. if ((paddr | size) & page_mask)
  391. return ERR_PTR(-EINVAL);
  392. if (!pfn_valid(PHYS_PFN(paddr)))
  393. return ERR_PTR(-EINVAL);
  394. stp = kzalloc_obj(*stp);
  395. if (!stp)
  396. return ERR_PTR(-ENOMEM);
  397. stp->gen_pool = gen_pool_create(PAGE_SHIFT, -1);
  398. if (!stp->gen_pool) {
  399. rc = -ENOMEM;
  400. goto err_free;
  401. }
  402. rc = gen_pool_add(stp->gen_pool, paddr, size, -1);
  403. if (rc)
  404. goto err_free_pool;
  405. stp->pool.ops = &protmem_pool_ops_static;
  406. stp->pa_base = paddr;
  407. return &stp->pool;
  408. err_free_pool:
  409. gen_pool_destroy(stp->gen_pool);
  410. err_free:
  411. kfree(stp);
  412. return ERR_PTR(rc);
  413. }
  414. EXPORT_SYMBOL_GPL(tee_protmem_static_pool_alloc);