tz_mem.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. /* Release secure chunk memory for normal world usage.
  2. *
  3. * For better utilization, part of secure chunk memory (pre-defined size) can
  4. * be used by normal world through memory TA.
  5. * After release, pre-defined secure memory can be read/write by normal world
  6. * through memroy TA, and can not be used by secure world. After append, it
  7. * can be used for secure world again.
  8. * For easy usage at user level, a block device can be registered, and it can
  9. * access released secure chunk memory by memory TA.
  10. *
  11. * How to use secure chunk memory at user level:
  12. * 1) Create a block device node, ex: /dev/tzmem
  13. * 2) Release secure chunk memory by UREE_ReleaseSecurechunkmem.
  14. * After releasing, the pre-defined chunk memory will be used by normal
  15. * world only.
  16. * 3) Open /dev/tzmem for read/write
  17. * 4) If finishing to use, close it.
  18. * 5) Append secure chunk memory back to secure world usage by
  19. * UREE_AppendSecurechunkmem.
  20. * After appending, the pre-defined chunk memory will not be used by normal
  21. * world.
  22. *
  23. * Or simply, using APIs
  24. * 1) UREE_ReleaseTzmem for release secure chunk memory to normal world usage.
  25. * 2) UREE_AppendTzmem for append secure chunk memory back to secure world.
  26. *
  27. */
  28. /* ------------------------------------------------------------------------- */
  29. /* Include files */
  30. /* ------------------------------------------------------------------------- */
  31. #include <trustzone/kree/mem.h>
  32. #include "trustzone/kree/system.h"
  33. #include <tz_cross/ta_mem.h>
  34. #include <linux/init.h>
  35. #include <linux/module.h>
  36. #include <linux/blkdev.h>
  37. #include "trustzone/kree/tz_mem.h"
  38. /* Use this define to enable module for TZMEM
  39. */
  40. /* #define MTEE_TZMEM_ENABLE */
  41. /* enable debug logs
  42. */
  43. #define MTEE_TZMEM_DBG
  44. #define KREE_RELEASECM_MAX_SIZE 4096 /* bytes */
  45. typedef struct {
  46. uint32_t control; /* 0 = not released, 1 = released */
  47. uint32_t size; /* real released pool size in bytes */
  48. uint32_t pool_size;
  49. struct gendisk *disk;
  50. KREE_SESSION_HANDLE session;
  51. KREE_RELEASECM_HANDLE handle;
  52. } tzmem_diskinfo_t;
  53. #ifdef MTEE_TZMEM_ENABLE
  54. static uint32_t tzmem_poolIndex; /* currently, always 0. for future extension */
  55. static tzmem_diskinfo_t _tzmem_diskInfo[IO_NODE_NUMBER_TZMEM];
  56. static DEFINE_MUTEX(tzmem_probe_mutex);
  57. static DEFINE_SPINLOCK(tzmem_blk_lock);
  58. static TZ_RESULT _tzmem_get_poolsize(uint32_t *size)
  59. {
  60. KREE_SESSION_HANDLE session;
  61. int ret = TZ_RESULT_SUCCESS;
  62. ret = KREE_CreateSession(TZ_TA_MEM_UUID, &session);
  63. if (ret != TZ_RESULT_SUCCESS) {
  64. pr_warn("[%s] _tzmem_get_poolsize: KREE_CreateSession Error = 0x%x\n",
  65. MODULE_NAME, ret);
  66. return ret;
  67. }
  68. /* get ta preset tzmem size */
  69. ret = KREE_GetSecurechunkReleaseSize(session, size);
  70. if (ret != TZ_RESULT_SUCCESS) {
  71. pr_warn("[%s] _tzmem_get_poolsize: KREE_GetSecurechunkReleaseSize Error = 0x%x\n",
  72. MODULE_NAME, ret);
  73. KREE_CloseSession(session);
  74. return ret;
  75. }
  76. ret = KREE_CloseSession(session);
  77. if (ret != TZ_RESULT_SUCCESS) {
  78. pr_warn("[%s] _tzmem_get_poolsize: KREE_CloseSession Error = 0x%x\n",
  79. MODULE_NAME, ret);
  80. return ret;
  81. }
  82. return ret;
  83. }
  84. static long tzmem_gen_ioctl(dev_t dev, unsigned int cmd, unsigned long arg)
  85. {
  86. int ret = 0;
  87. #ifdef MTEE_TZMEM_DBG
  88. pr_debug("====> tzmem_gen_ioctl\n");
  89. #endif
  90. switch (cmd) {
  91. default:
  92. ret = -EINVAL;
  93. }
  94. return ret;
  95. }
  96. static void do_tzmem_blk_request(struct request_queue *q)
  97. {
  98. struct request *req;
  99. uint32_t i;
  100. #ifdef MTEE_TZMEM_DBG
  101. pr_debug("====> do_tzmem_blk_request\n");
  102. #endif
  103. req = blk_fetch_request(q);
  104. while (req) {
  105. unsigned long start = blk_rq_pos(req) << 9;
  106. unsigned long len = blk_rq_cur_bytes(req);
  107. int err = 0;
  108. struct gendisk *disk = req->rq_disk;
  109. tzmem_diskinfo_t *diskInfo =
  110. (tzmem_diskinfo_t *) disk->private_data;
  111. KREE_SESSION_HANDLE session;
  112. session = diskInfo->session;
  113. #ifdef MTEE_TZMEM_DBG
  114. pr_debug("====> 0x%x 0x%x\n", session, diskInfo->size);
  115. #endif
  116. if ((start + len > diskInfo->size) || (start > diskInfo->size)
  117. || (len > diskInfo->size)) {
  118. err = -EIO;
  119. goto done;
  120. }
  121. if (rq_data_dir(req) == READ) {
  122. #ifdef MTEE_TZMEM_DBG
  123. pr_debug("====> do_tzmem_blk_request: read = 0x%x, 0x%x\n",
  124. (uint32_t) start,
  125. (uint32_t) len);
  126. #endif
  127. for (i = 0; i < len / KREE_RELEASECM_MAX_SIZE; i++) {
  128. KREE_ReadSecurechunkmem(
  129. (KREE_SESSION_HANDLE) session,
  130. start + i * KREE_RELEASECM_MAX_SIZE,
  131. KREE_RELEASECM_MAX_SIZE,
  132. req->buffer + i * KREE_RELEASECM_MAX_SIZE);
  133. }
  134. if (len % KREE_RELEASECM_MAX_SIZE) {
  135. KREE_ReadSecurechunkmem(
  136. (KREE_SESSION_HANDLE) session,
  137. start + i * KREE_RELEASECM_MAX_SIZE,
  138. len % KREE_RELEASECM_MAX_SIZE,
  139. req->buffer + i * KREE_RELEASECM_MAX_SIZE);
  140. }
  141. } else {
  142. #ifdef MTEE_TZMEM_DBG
  143. pr_debug("====> do_tzmem_blk_request: write = 0x%x, 0x%x\n",
  144. (uint32_t) start, (uint32_t) len);
  145. #endif
  146. for (i = 0; i < len / KREE_RELEASECM_MAX_SIZE; i++) {
  147. KREE_WriteSecurechunkmem(
  148. (KREE_SESSION_HANDLE) session,
  149. start + i * KREE_RELEASECM_MAX_SIZE,
  150. KREE_RELEASECM_MAX_SIZE,
  151. req->buffer + i * KREE_RELEASECM_MAX_SIZE);
  152. }
  153. if (len % KREE_RELEASECM_MAX_SIZE) {
  154. KREE_WriteSecurechunkmem(
  155. (KREE_SESSION_HANDLE) session,
  156. start + i * KREE_RELEASECM_MAX_SIZE,
  157. len % KREE_RELEASECM_MAX_SIZE,
  158. req->buffer + i * KREE_RELEASECM_MAX_SIZE);
  159. }
  160. }
  161. done:
  162. if (!__blk_end_request_cur(req, err))
  163. req = blk_fetch_request(q);
  164. }
  165. }
  166. static int tzmem_blk_ioctl(struct block_device *bdev, fmode_t mode,
  167. unsigned cmd, unsigned long arg)
  168. {
  169. return tzmem_gen_ioctl(bdev->bd_dev, cmd, arg);
  170. }
  171. /* block device module info */
  172. static const struct block_device_operations tzmem_blk_fops = {
  173. .owner = THIS_MODULE,
  174. .ioctl = tzmem_blk_ioctl,
  175. };
  176. /* block device probe function */
  177. /* Create disk on demand. So we won't create lots of disk for un-used
  178. * devices. */
  179. static struct kobject *tzmem_blk_probe(dev_t dev, int *part, void *data)
  180. {
  181. uint32_t len;
  182. struct gendisk *disk;
  183. struct kobject *kobj;
  184. struct request_queue *queue;
  185. tzmem_diskinfo_t *diskInfo;
  186. int ret;
  187. KREE_SESSION_HANDLE session;
  188. #ifdef MTEE_TZMEM_DBG
  189. pr_debug("====> tzmem_blk_probe\n");
  190. #endif
  191. mutex_lock(&tzmem_probe_mutex);
  192. diskInfo = (tzmem_diskinfo_t *) &_tzmem_diskInfo[tzmem_poolIndex];
  193. if (diskInfo->disk == NULL) {
  194. disk = alloc_disk(1);
  195. if (!disk)
  196. goto out_info;
  197. queue = blk_init_queue(do_tzmem_blk_request, &tzmem_blk_lock);
  198. if (!queue)
  199. goto out_queue;
  200. blk_queue_max_hw_sectors(queue, 1024);
  201. blk_queue_bounce_limit(queue, BLK_BOUNCE_ANY);
  202. if (_tzmem_get_poolsize(&len))
  203. goto out_init;
  204. disk->major = IO_NODE_MAJOR_TZMEM;
  205. disk->first_minor = MINOR(dev);
  206. disk->fops = &tzmem_blk_fops;
  207. disk->private_data = &_tzmem_diskInfo;
  208. snprintf(disk->disk_name, sizeof(disk->disk_name), "tzmem%d",
  209. MINOR(dev));
  210. disk->queue = queue;
  211. set_capacity(disk, len / 512);
  212. add_disk(disk);
  213. ret = KREE_CreateSession(TZ_TA_MEM_UUID, &session);
  214. if (ret != TZ_RESULT_SUCCESS) {
  215. pr_warn("[%s] _tzmem_get_poolsize: KREE_CreateSession Error = 0x%x\n",
  216. MODULE_NAME, ret);
  217. goto out_init;
  218. }
  219. diskInfo->session = session;
  220. diskInfo->pool_size = len;
  221. diskInfo->disk = disk;
  222. diskInfo->size = len;
  223. }
  224. *part = 0;
  225. kobj = diskInfo ? get_disk(diskInfo->disk) : ERR_PTR(-ENOMEM);
  226. mutex_unlock(&tzmem_probe_mutex);
  227. return kobj;
  228. out_init:
  229. blk_cleanup_queue(queue);
  230. out_queue:
  231. put_disk(disk);
  232. out_info:
  233. mutex_unlock(&tzmem_probe_mutex);
  234. return ERR_PTR(-ENOMEM);
  235. }
  236. /* tzmem block device module init
  237. */
  238. static int __init tzmem_blkdev_init(void)
  239. {
  240. #ifdef MTEE_TZMEM_DBG
  241. pr_debug("====> tzmem_blkdev_init\n");
  242. #endif
  243. if (register_blkdev(IO_NODE_MAJOR_TZMEM, DEV_TZMEM)) {
  244. pr_warn("[%s] tzmem_blkdev_init: register_blkdev error\n",
  245. MODULE_NAME);
  246. return -EFAULT;
  247. }
  248. blk_register_region(MKDEV(IO_NODE_MAJOR_TZMEM, IO_NODE_MINOR_TZMEM),
  249. IO_NODE_NUMBER_TZMEM, THIS_MODULE,
  250. tzmem_blk_probe, NULL, NULL);
  251. return 0;
  252. }
  253. module_init(tzmem_blkdev_init);
  254. #endif