tee_shm.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (c) 2015-2017, 2019-2021 Linaro Limited
  4. */
  5. #include <linux/anon_inodes.h>
  6. #include <linux/device.h>
  7. #include <linux/dma-buf.h>
  8. #include <linux/dma-mapping.h>
  9. #include <linux/highmem.h>
  10. #include <linux/idr.h>
  11. #include <linux/io.h>
  12. #include <linux/mm.h>
  13. #include <linux/sched.h>
  14. #include <linux/slab.h>
  15. #include <linux/tee_core.h>
  16. #include <linux/uaccess.h>
  17. #include <linux/uio.h>
  18. #include "tee_private.h"
  19. struct tee_shm_dma_mem {
  20. struct tee_shm shm;
  21. dma_addr_t dma_addr;
  22. struct page *page;
  23. };
  24. static void release_registered_pages(struct tee_shm *shm)
  25. {
  26. if (shm->pages) {
  27. if (shm->flags & TEE_SHM_USER_MAPPED)
  28. unpin_user_pages(shm->pages, shm->num_pages);
  29. kfree(shm->pages);
  30. }
  31. }
  32. static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
  33. {
  34. void *p = shm;
  35. if (shm->flags & TEE_SHM_DMA_MEM) {
  36. #if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS)
  37. struct tee_shm_dma_mem *dma_mem;
  38. dma_mem = container_of(shm, struct tee_shm_dma_mem, shm);
  39. p = dma_mem;
  40. dma_free_pages(&teedev->dev, shm->size, dma_mem->page,
  41. dma_mem->dma_addr, DMA_BIDIRECTIONAL);
  42. #endif
  43. } else if (shm->flags & TEE_SHM_DMA_BUF) {
  44. struct tee_shm_dmabuf_ref *ref;
  45. ref = container_of(shm, struct tee_shm_dmabuf_ref, shm);
  46. p = ref;
  47. dma_buf_put(ref->dmabuf);
  48. } else if (shm->flags & TEE_SHM_POOL) {
  49. teedev->pool->ops->free(teedev->pool, shm);
  50. } else if (shm->flags & TEE_SHM_DYNAMIC) {
  51. int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm);
  52. if (rc)
  53. dev_err(teedev->dev.parent,
  54. "unregister shm %p failed: %d", shm, rc);
  55. release_registered_pages(shm);
  56. }
  57. teedev_ctx_put(shm->ctx);
  58. kfree(p);
  59. tee_device_put(teedev);
  60. }
  61. static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
  62. size_t align, u32 flags, int id)
  63. {
  64. struct tee_device *teedev = ctx->teedev;
  65. struct tee_shm *shm;
  66. void *ret;
  67. int rc;
  68. if (!tee_device_get(teedev))
  69. return ERR_PTR(-EINVAL);
  70. if (!teedev->pool) {
  71. /* teedev has been detached from driver */
  72. ret = ERR_PTR(-EINVAL);
  73. goto err_dev_put;
  74. }
  75. shm = kzalloc_obj(*shm);
  76. if (!shm) {
  77. ret = ERR_PTR(-ENOMEM);
  78. goto err_dev_put;
  79. }
  80. refcount_set(&shm->refcount, 1);
  81. shm->flags = flags;
  82. shm->id = id;
  83. /*
  84. * We're assigning this as it is needed if the shm is to be
  85. * registered. If this function returns OK then the caller expected
  86. * to call teedev_ctx_get() or clear shm->ctx in case it's not
  87. * needed any longer.
  88. */
  89. shm->ctx = ctx;
  90. rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
  91. if (rc) {
  92. ret = ERR_PTR(rc);
  93. goto err_kfree;
  94. }
  95. teedev_ctx_get(ctx);
  96. return shm;
  97. err_kfree:
  98. kfree(shm);
  99. err_dev_put:
  100. tee_device_put(teedev);
  101. return ret;
  102. }
  103. /**
  104. * tee_shm_alloc_user_buf() - Allocate shared memory for user space
  105. * @ctx: Context that allocates the shared memory
  106. * @size: Requested size of shared memory
  107. *
  108. * Memory allocated as user space shared memory is automatically freed when
  109. * the TEE file pointer is closed. The primary usage of this function is
  110. * when the TEE driver doesn't support registering ordinary user space
  111. * memory.
  112. *
  113. * @returns a pointer to 'struct tee_shm'
  114. */
  115. struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
  116. {
  117. u32 flags = TEE_SHM_DYNAMIC | TEE_SHM_POOL;
  118. struct tee_device *teedev = ctx->teedev;
  119. struct tee_shm *shm;
  120. void *ret;
  121. int id;
  122. mutex_lock(&teedev->mutex);
  123. id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
  124. mutex_unlock(&teedev->mutex);
  125. if (id < 0)
  126. return ERR_PTR(id);
  127. shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id);
  128. if (IS_ERR(shm)) {
  129. mutex_lock(&teedev->mutex);
  130. idr_remove(&teedev->idr, id);
  131. mutex_unlock(&teedev->mutex);
  132. return shm;
  133. }
  134. mutex_lock(&teedev->mutex);
  135. ret = idr_replace(&teedev->idr, shm, id);
  136. mutex_unlock(&teedev->mutex);
  137. if (IS_ERR(ret)) {
  138. tee_shm_free(shm);
  139. return ret;
  140. }
  141. return shm;
  142. }
  143. /**
  144. * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer
  145. * @ctx: Context that allocates the shared memory
  146. * @size: Requested size of shared memory
  147. *
  148. * The returned memory registered in secure world and is suitable to be
  149. * passed as a memory buffer in parameter argument to
  150. * tee_client_invoke_func(). The memory allocated is later freed with a
  151. * call to tee_shm_free().
  152. *
  153. * @returns a pointer to 'struct tee_shm' on success, and ERR_PTR on failure
  154. */
  155. struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
  156. {
  157. u32 flags = TEE_SHM_DYNAMIC | TEE_SHM_POOL;
  158. return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
  159. }
  160. EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
  161. struct tee_shm *tee_shm_register_fd(struct tee_context *ctx, int fd)
  162. {
  163. struct tee_shm_dmabuf_ref *ref;
  164. int rc;
  165. if (!tee_device_get(ctx->teedev))
  166. return ERR_PTR(-EINVAL);
  167. teedev_ctx_get(ctx);
  168. ref = kzalloc_obj(*ref);
  169. if (!ref) {
  170. rc = -ENOMEM;
  171. goto err_put_tee;
  172. }
  173. refcount_set(&ref->shm.refcount, 1);
  174. ref->shm.ctx = ctx;
  175. ref->shm.id = -1;
  176. ref->shm.flags = TEE_SHM_DMA_BUF;
  177. ref->dmabuf = dma_buf_get(fd);
  178. if (IS_ERR(ref->dmabuf)) {
  179. rc = PTR_ERR(ref->dmabuf);
  180. goto err_kfree_ref;
  181. }
  182. rc = tee_heap_update_from_dma_buf(ctx->teedev, ref->dmabuf,
  183. &ref->offset, &ref->shm,
  184. &ref->parent_shm);
  185. if (rc)
  186. goto err_put_dmabuf;
  187. mutex_lock(&ref->shm.ctx->teedev->mutex);
  188. ref->shm.id = idr_alloc(&ref->shm.ctx->teedev->idr, &ref->shm,
  189. 1, 0, GFP_KERNEL);
  190. mutex_unlock(&ref->shm.ctx->teedev->mutex);
  191. if (ref->shm.id < 0) {
  192. rc = ref->shm.id;
  193. goto err_put_dmabuf;
  194. }
  195. return &ref->shm;
  196. err_put_dmabuf:
  197. dma_buf_put(ref->dmabuf);
  198. err_kfree_ref:
  199. kfree(ref);
  200. err_put_tee:
  201. teedev_ctx_put(ctx);
  202. tee_device_put(ctx->teedev);
  203. return ERR_PTR(rc);
  204. }
  205. EXPORT_SYMBOL_GPL(tee_shm_register_fd);
  206. /**
  207. * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared
  208. * kernel buffer
  209. * @ctx: Context that allocates the shared memory
  210. * @size: Requested size of shared memory
  211. *
  212. * This function returns similar shared memory as
  213. * tee_shm_alloc_kernel_buf(), but with the difference that the memory
  214. * might not be registered in secure world in case the driver supports
  215. * passing memory not registered in advance.
  216. *
  217. * This function should normally only be used internally in the TEE
  218. * drivers.
  219. *
  220. * @returns a pointer to 'struct tee_shm'
  221. */
  222. struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size)
  223. {
  224. u32 flags = TEE_SHM_PRIV | TEE_SHM_POOL;
  225. return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
  226. }
  227. EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf);
  228. #if IS_ENABLED(CONFIG_TEE_DMABUF_HEAPS)
  229. /**
  230. * tee_shm_alloc_dma_mem() - Allocate DMA memory as shared memory object
  231. * @ctx: Context that allocates the shared memory
  232. * @page_count: Number of pages
  233. *
  234. * The allocated memory is expected to be lent (made inaccessible to the
  235. * kernel) to the TEE while it's used and returned (accessible to the
  236. * kernel again) before it's freed.
  237. *
  238. * This function should normally only be used internally in the TEE
  239. * drivers.
  240. *
  241. * @returns a pointer to 'struct tee_shm'
  242. */
  243. struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx,
  244. size_t page_count)
  245. {
  246. struct tee_device *teedev = ctx->teedev;
  247. struct tee_shm_dma_mem *dma_mem;
  248. dma_addr_t dma_addr;
  249. struct page *page;
  250. if (!tee_device_get(teedev))
  251. return ERR_PTR(-EINVAL);
  252. page = dma_alloc_pages(&teedev->dev, page_count * PAGE_SIZE,
  253. &dma_addr, DMA_BIDIRECTIONAL, GFP_KERNEL);
  254. if (!page)
  255. goto err_put_teedev;
  256. dma_mem = kzalloc_obj(*dma_mem);
  257. if (!dma_mem)
  258. goto err_free_pages;
  259. refcount_set(&dma_mem->shm.refcount, 1);
  260. dma_mem->shm.ctx = ctx;
  261. dma_mem->shm.paddr = page_to_phys(page);
  262. dma_mem->dma_addr = dma_addr;
  263. dma_mem->page = page;
  264. dma_mem->shm.size = page_count * PAGE_SIZE;
  265. dma_mem->shm.flags = TEE_SHM_DMA_MEM;
  266. teedev_ctx_get(ctx);
  267. return &dma_mem->shm;
  268. err_free_pages:
  269. dma_free_pages(&teedev->dev, page_count * PAGE_SIZE, page, dma_addr,
  270. DMA_BIDIRECTIONAL);
  271. err_put_teedev:
  272. tee_device_put(teedev);
  273. return ERR_PTR(-ENOMEM);
  274. }
  275. EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem);
  276. #else
  277. struct tee_shm *tee_shm_alloc_dma_mem(struct tee_context *ctx,
  278. size_t page_count)
  279. {
  280. return ERR_PTR(-EINVAL);
  281. }
  282. EXPORT_SYMBOL_GPL(tee_shm_alloc_dma_mem);
  283. #endif
  284. int tee_dyn_shm_alloc_helper(struct tee_shm *shm, size_t size, size_t align,
  285. int (*shm_register)(struct tee_context *ctx,
  286. struct tee_shm *shm,
  287. struct page **pages,
  288. size_t num_pages,
  289. unsigned long start))
  290. {
  291. size_t nr_pages = roundup(size, PAGE_SIZE) / PAGE_SIZE;
  292. struct page **pages;
  293. unsigned int i;
  294. int rc = 0;
  295. /*
  296. * Ignore alignment since this is already going to be page aligned
  297. * and there's no need for any larger alignment.
  298. */
  299. shm->kaddr = alloc_pages_exact(nr_pages * PAGE_SIZE,
  300. GFP_KERNEL | __GFP_ZERO);
  301. if (!shm->kaddr)
  302. return -ENOMEM;
  303. shm->paddr = virt_to_phys(shm->kaddr);
  304. shm->size = nr_pages * PAGE_SIZE;
  305. pages = kzalloc_objs(*pages, nr_pages);
  306. if (!pages) {
  307. rc = -ENOMEM;
  308. goto err_pages;
  309. }
  310. for (i = 0; i < nr_pages; i++)
  311. pages[i] = virt_to_page((u8 *)shm->kaddr + i * PAGE_SIZE);
  312. shm->pages = pages;
  313. shm->num_pages = nr_pages;
  314. if (shm_register) {
  315. rc = shm_register(shm->ctx, shm, pages, nr_pages,
  316. (unsigned long)shm->kaddr);
  317. if (rc)
  318. goto err_kfree;
  319. }
  320. return 0;
  321. err_kfree:
  322. kfree(pages);
  323. err_pages:
  324. free_pages_exact(shm->kaddr, shm->size);
  325. shm->kaddr = NULL;
  326. return rc;
  327. }
  328. EXPORT_SYMBOL_GPL(tee_dyn_shm_alloc_helper);
  329. void tee_dyn_shm_free_helper(struct tee_shm *shm,
  330. int (*shm_unregister)(struct tee_context *ctx,
  331. struct tee_shm *shm))
  332. {
  333. if (shm_unregister)
  334. shm_unregister(shm->ctx, shm);
  335. free_pages_exact(shm->kaddr, shm->size);
  336. shm->kaddr = NULL;
  337. kfree(shm->pages);
  338. shm->pages = NULL;
  339. }
  340. EXPORT_SYMBOL_GPL(tee_dyn_shm_free_helper);
  341. static struct tee_shm *
  342. register_shm_helper(struct tee_context *ctx, struct iov_iter *iter, u32 flags,
  343. int id)
  344. {
  345. struct tee_device *teedev = ctx->teedev;
  346. struct tee_shm *shm;
  347. unsigned long start, addr;
  348. size_t num_pages, off;
  349. ssize_t len;
  350. void *ret;
  351. int rc;
  352. if (!tee_device_get(teedev))
  353. return ERR_PTR(-EINVAL);
  354. if (!teedev->desc->ops->shm_register ||
  355. !teedev->desc->ops->shm_unregister) {
  356. ret = ERR_PTR(-ENOTSUPP);
  357. goto err_dev_put;
  358. }
  359. teedev_ctx_get(ctx);
  360. shm = kzalloc_obj(*shm);
  361. if (!shm) {
  362. ret = ERR_PTR(-ENOMEM);
  363. goto err_ctx_put;
  364. }
  365. refcount_set(&shm->refcount, 1);
  366. shm->flags = flags;
  367. shm->ctx = ctx;
  368. shm->id = id;
  369. addr = untagged_addr((unsigned long)iter_iov_addr(iter));
  370. start = rounddown(addr, PAGE_SIZE);
  371. num_pages = iov_iter_npages(iter, INT_MAX);
  372. if (!num_pages) {
  373. ret = ERR_PTR(-ENOMEM);
  374. goto err_ctx_put;
  375. }
  376. shm->pages = kzalloc_objs(*shm->pages, num_pages);
  377. if (!shm->pages) {
  378. ret = ERR_PTR(-ENOMEM);
  379. goto err_free_shm;
  380. }
  381. len = iov_iter_extract_pages(iter, &shm->pages, LONG_MAX, num_pages, 0,
  382. &off);
  383. if (unlikely(len <= 0)) {
  384. ret = len ? ERR_PTR(len) : ERR_PTR(-ENOMEM);
  385. goto err_free_shm_pages;
  386. } else if (DIV_ROUND_UP(len + off, PAGE_SIZE) != num_pages) {
  387. /*
  388. * If we only got a few pages, update to release the
  389. * correct amount below.
  390. */
  391. shm->num_pages = len / PAGE_SIZE;
  392. ret = ERR_PTR(-ENOMEM);
  393. goto err_put_shm_pages;
  394. }
  395. shm->offset = off;
  396. shm->size = len;
  397. shm->num_pages = num_pages;
  398. rc = teedev->desc->ops->shm_register(ctx, shm, shm->pages,
  399. shm->num_pages, start);
  400. if (rc) {
  401. ret = ERR_PTR(rc);
  402. goto err_put_shm_pages;
  403. }
  404. return shm;
  405. err_put_shm_pages:
  406. if (!iov_iter_is_kvec(iter))
  407. unpin_user_pages(shm->pages, shm->num_pages);
  408. err_free_shm_pages:
  409. kfree(shm->pages);
  410. err_free_shm:
  411. kfree(shm);
  412. err_ctx_put:
  413. teedev_ctx_put(ctx);
  414. err_dev_put:
  415. tee_device_put(teedev);
  416. return ret;
  417. }
  418. /**
  419. * tee_shm_register_user_buf() - Register a userspace shared memory buffer
  420. * @ctx: Context that registers the shared memory
  421. * @addr: The userspace address of the shared buffer
  422. * @length: Length of the shared buffer
  423. *
  424. * @returns a pointer to 'struct tee_shm'
  425. */
  426. struct tee_shm *tee_shm_register_user_buf(struct tee_context *ctx,
  427. unsigned long addr, size_t length)
  428. {
  429. u32 flags = TEE_SHM_USER_MAPPED | TEE_SHM_DYNAMIC;
  430. struct tee_device *teedev = ctx->teedev;
  431. struct tee_shm *shm;
  432. struct iov_iter iter;
  433. void *ret;
  434. int id;
  435. if (!access_ok((void __user *)addr, length))
  436. return ERR_PTR(-EFAULT);
  437. mutex_lock(&teedev->mutex);
  438. id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
  439. mutex_unlock(&teedev->mutex);
  440. if (id < 0)
  441. return ERR_PTR(id);
  442. iov_iter_ubuf(&iter, ITER_DEST, (void __user *)addr, length);
  443. shm = register_shm_helper(ctx, &iter, flags, id);
  444. if (IS_ERR(shm)) {
  445. mutex_lock(&teedev->mutex);
  446. idr_remove(&teedev->idr, id);
  447. mutex_unlock(&teedev->mutex);
  448. return shm;
  449. }
  450. mutex_lock(&teedev->mutex);
  451. ret = idr_replace(&teedev->idr, shm, id);
  452. mutex_unlock(&teedev->mutex);
  453. if (IS_ERR(ret)) {
  454. tee_shm_free(shm);
  455. return ret;
  456. }
  457. return shm;
  458. }
  459. /**
  460. * tee_shm_register_kernel_buf() - Register kernel memory to be shared with
  461. * secure world
  462. * @ctx: Context that registers the shared memory
  463. * @addr: The buffer
  464. * @length: Length of the buffer
  465. *
  466. * @returns a pointer to 'struct tee_shm'
  467. */
  468. struct tee_shm *tee_shm_register_kernel_buf(struct tee_context *ctx,
  469. void *addr, size_t length)
  470. {
  471. u32 flags = TEE_SHM_DYNAMIC;
  472. struct kvec kvec;
  473. struct iov_iter iter;
  474. kvec.iov_base = addr;
  475. kvec.iov_len = length;
  476. iov_iter_kvec(&iter, ITER_DEST, &kvec, 1, length);
  477. return register_shm_helper(ctx, &iter, flags, -1);
  478. }
  479. EXPORT_SYMBOL_GPL(tee_shm_register_kernel_buf);
  480. static int tee_shm_fop_release(struct inode *inode, struct file *filp)
  481. {
  482. tee_shm_put(filp->private_data);
  483. return 0;
  484. }
  485. static int tee_shm_fop_mmap(struct file *filp, struct vm_area_struct *vma)
  486. {
  487. struct tee_shm *shm = filp->private_data;
  488. size_t size = vma->vm_end - vma->vm_start;
  489. /* Refuse sharing shared memory provided by application */
  490. if (shm->flags & TEE_SHM_USER_MAPPED)
  491. return -EINVAL;
  492. /* Refuse sharing registered DMA_bufs with the application */
  493. if (shm->flags & TEE_SHM_DMA_BUF)
  494. return -EINVAL;
  495. /* check for overflowing the buffer's size */
  496. if (vma->vm_pgoff + vma_pages(vma) > shm->size >> PAGE_SHIFT)
  497. return -EINVAL;
  498. return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
  499. size, vma->vm_page_prot);
  500. }
  501. static const struct file_operations tee_shm_fops = {
  502. .owner = THIS_MODULE,
  503. .release = tee_shm_fop_release,
  504. .mmap = tee_shm_fop_mmap,
  505. };
  506. /**
  507. * tee_shm_get_fd() - Increase reference count and return file descriptor
  508. * @shm: Shared memory handle
  509. * @returns user space file descriptor to shared memory
  510. */
  511. int tee_shm_get_fd(struct tee_shm *shm)
  512. {
  513. int fd;
  514. if (shm->id < 0)
  515. return -EINVAL;
  516. /* matched by tee_shm_put() in tee_shm_op_release() */
  517. refcount_inc(&shm->refcount);
  518. fd = anon_inode_getfd("tee_shm", &tee_shm_fops, shm, O_RDWR);
  519. if (fd < 0)
  520. tee_shm_put(shm);
  521. return fd;
  522. }
  523. /**
  524. * tee_shm_free() - Free shared memory
  525. * @shm: Handle to shared memory to free
  526. */
  527. void tee_shm_free(struct tee_shm *shm)
  528. {
  529. tee_shm_put(shm);
  530. }
  531. EXPORT_SYMBOL_GPL(tee_shm_free);
  532. /**
  533. * tee_shm_get_va() - Get virtual address of a shared memory plus an offset
  534. * @shm: Shared memory handle
  535. * @offs: Offset from start of this shared memory
  536. * @returns virtual address of the shared memory + offs if offs is within
  537. * the bounds of this shared memory, else an ERR_PTR
  538. */
  539. void *tee_shm_get_va(struct tee_shm *shm, size_t offs)
  540. {
  541. if (!shm->kaddr)
  542. return ERR_PTR(-EINVAL);
  543. if (offs >= shm->size)
  544. return ERR_PTR(-EINVAL);
  545. return (char *)shm->kaddr + offs;
  546. }
  547. EXPORT_SYMBOL_GPL(tee_shm_get_va);
  548. /**
  549. * tee_shm_get_pa() - Get physical address of a shared memory plus an offset
  550. * @shm: Shared memory handle
  551. * @offs: Offset from start of this shared memory
  552. * @pa: Physical address to return
  553. * @returns 0 if offs is within the bounds of this shared memory, else an
  554. * error code.
  555. */
  556. int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa)
  557. {
  558. if (offs >= shm->size)
  559. return -EINVAL;
  560. if (pa)
  561. *pa = shm->paddr + offs;
  562. return 0;
  563. }
  564. EXPORT_SYMBOL_GPL(tee_shm_get_pa);
  565. /**
  566. * tee_shm_get_from_id() - Find shared memory object and increase reference
  567. * count
  568. * @ctx: Context owning the shared memory
  569. * @id: Id of shared memory object
  570. * @returns a pointer to 'struct tee_shm' on success or an ERR_PTR on failure
  571. */
  572. struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id)
  573. {
  574. struct tee_device *teedev;
  575. struct tee_shm *shm;
  576. if (!ctx)
  577. return ERR_PTR(-EINVAL);
  578. teedev = ctx->teedev;
  579. mutex_lock(&teedev->mutex);
  580. shm = idr_find(&teedev->idr, id);
  581. /*
  582. * If the tee_shm was found in the IDR it must have a refcount
  583. * larger than 0 due to the guarantee in tee_shm_put() below. So
  584. * it's safe to use refcount_inc().
  585. */
  586. if (!shm || shm->ctx != ctx)
  587. shm = ERR_PTR(-EINVAL);
  588. else
  589. refcount_inc(&shm->refcount);
  590. mutex_unlock(&teedev->mutex);
  591. return shm;
  592. }
  593. EXPORT_SYMBOL_GPL(tee_shm_get_from_id);
  594. /**
  595. * tee_shm_put() - Decrease reference count on a shared memory handle
  596. * @shm: Shared memory handle
  597. */
  598. void tee_shm_put(struct tee_shm *shm)
  599. {
  600. struct tee_device *teedev;
  601. bool do_release = false;
  602. if (!shm || !shm->ctx || !shm->ctx->teedev)
  603. return;
  604. teedev = shm->ctx->teedev;
  605. mutex_lock(&teedev->mutex);
  606. if (refcount_dec_and_test(&shm->refcount)) {
  607. /*
  608. * refcount has reached 0, we must now remove it from the
  609. * IDR before releasing the mutex. This will guarantee that
  610. * the refcount_inc() in tee_shm_get_from_id() never starts
  611. * from 0.
  612. */
  613. if (shm->id >= 0)
  614. idr_remove(&teedev->idr, shm->id);
  615. do_release = true;
  616. }
  617. mutex_unlock(&teedev->mutex);
  618. if (do_release)
  619. tee_shm_release(teedev, shm);
  620. }
  621. EXPORT_SYMBOL_GPL(tee_shm_put);