From e2aca5d8928acb9cc9a87802b02102d4f9b9b596 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Wed, 29 Nov 2017 14:48:25 +0200 Subject: tee: flexible shared memory pool creation Makes creation of shm pools more flexible by adding new more primitive functions to allocate a shm pool. This makes it easier to add driver specific shm pool management. Signed-off-by: Jens Wiklander Signed-off-by: Volodymyr Babchuk --- include/linux/tee_drv.h | 91 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index cb889afe576b..e9be4a45ff3e 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -149,6 +149,97 @@ int tee_device_register(struct tee_device *teedev); */ void tee_device_unregister(struct tee_device *teedev); +/** + * struct tee_shm - shared memory object + * @teedev: device used to allocate the object + * @ctx: context using the object, if NULL the context is gone + * @link link element + * @paddr: physical address of the shared memory + * @kaddr: virtual address of the shared memory + * @size: size of shared memory + * @offset: offset of buffer in user space + * @pages: locked pages from userspace + * @num_pages: number of locked pages + * @dmabuf: dmabuf used to for exporting to user space + * @flags: defined by TEE_SHM_* in tee_drv.h + * @id: unique id of a shared memory object on this device + * + * This pool is only supposed to be accessed directly from the TEE + * subsystem and from drivers that implements their own shm pool manager. + */ +struct tee_shm { + struct tee_device *teedev; + struct tee_context *ctx; + struct list_head link; + phys_addr_t paddr; + void *kaddr; + size_t size; + unsigned int offset; + struct page **pages; + size_t num_pages; + struct dma_buf *dmabuf; + u32 flags; + int id; +}; + +/** + * struct tee_shm_pool_mgr - shared memory manager + * @ops: operations + * @private_data: private data for the shared memory manager + */ +struct tee_shm_pool_mgr { + const struct tee_shm_pool_mgr_ops *ops; + void *private_data; +}; + +/** + * struct tee_shm_pool_mgr_ops - shared memory pool manager operations + * @alloc: called when allocating shared memory + * @free: called when freeing shared memory + * @destroy_poolmgr: called when destroying the pool manager + */ +struct tee_shm_pool_mgr_ops { + int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm, + size_t size); + void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm); + void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr); +}; + +/** + * tee_shm_pool_alloc() - Create a shared memory pool from shm managers + * @priv_mgr: manager for driver private shared memory allocations + * @dmabuf_mgr: manager for dma-buf shared memory allocations + * + * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied + * in @dmabuf, others will use the range provided by @priv. + * + * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. + */ +struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr, + struct tee_shm_pool_mgr *dmabuf_mgr); + +/* + * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved + * memory + * @vaddr: Virtual address of start of pool + * @paddr: Physical address of start of pool + * @size: Size in bytes of the pool + * + * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure. + */ +struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr, + phys_addr_t paddr, + size_t size, + int min_alloc_order); + +/** + * tee_shm_pool_mgr_destroy() - Free a shared memory manager + */ +static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm) +{ + poolm->ops->destroy_poolmgr(poolm); +} + /** * struct tee_shm_pool_mem_info - holds information needed to create a shared * memory pool -- cgit From 033ddf12bcf5326b93bd604f50a7474a434a35f9 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Wed, 29 Nov 2017 14:48:26 +0200 Subject: tee: add register user memory Added new ioctl to allow users register own buffers as a shared memory. Signed-off-by: Volodymyr Babchuk [jw: moved tee_shm_is_registered() declaration] [jw: added space after __tee_shm_alloc() implementation] Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 47 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index e9be4a45ff3e..7c8495607b99 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -25,8 +25,12 @@ * specific TEE driver. */ -#define TEE_SHM_MAPPED 0x1 /* Memory mapped by the kernel */ -#define TEE_SHM_DMA_BUF 0x2 /* Memory with dma-buf handle */ +#define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */ +#define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */ +#define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */ +#define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */ +#define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */ +#define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */ struct device; struct tee_device; @@ -76,6 +80,8 @@ struct tee_param { * @cancel_req: request cancel of an ongoing invoke or open * @supp_revc: called for supplicant to get a command * @supp_send: called for supplicant to send a response + * @shm_register: register shared memory buffer in TEE + * @shm_unregister: unregister shared memory buffer in TEE */ struct tee_driver_ops { void (*get_version)(struct tee_device *teedev, @@ -94,6 +100,9 @@ struct tee_driver_ops { struct tee_param *param); int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params, struct tee_param *param); + int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, + struct page **pages, size_t num_pages); + int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm); }; /** @@ -301,6 +310,40 @@ void *tee_get_drvdata(struct tee_device *teedev); */ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); +/** + * tee_shm_priv_alloc() - Allocate shared memory privately + * @dev: Device that allocates the shared memory + * @size: Requested size of shared memory + * + * Allocates shared memory buffer that is not associated with any client + * context. Such buffers are owned by TEE driver and used for internal calls. + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size); + +/** + * tee_shm_register() - Register shared memory buffer + * @ctx: Context that registers the shared memory + * @addr: Address is userspace of the shared buffer + * @length: Length of the shared buffer + * @flags: Flags setting properties for the requested shared memory. + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, + size_t length, u32 flags); + +/** + * tee_shm_is_registered() - Check if shared memory object in registered in TEE + * @shm: Shared memory handle + * @returns true if object is registered in TEE + */ +static inline bool tee_shm_is_registered(struct tee_shm *shm) +{ + return shm && (shm->flags & TEE_SHM_REGISTER); +} + /** * tee_shm_free() - Free shared memory * @shm: Handle to shared memory to free -- cgit From b25946ad951c013c31d0a0e82d2017004bdc8fed Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Wed, 29 Nov 2017 14:48:27 +0200 Subject: tee: shm: add accessors for buffer size and page offset These two function will be needed for shared memory registration in OP-TEE Signed-off-by: Volodymyr Babchuk Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 7c8495607b99..6838f25e1421 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -393,6 +393,26 @@ void *tee_shm_get_va(struct tee_shm *shm, size_t offs); */ int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); +/** + * tee_shm_get_size() - Get size of shared memory buffer + * @shm: Shared memory handle + * @returns size of shared memory + */ +static inline size_t tee_shm_get_size(struct tee_shm *shm) +{ + return shm->size; +} + +/** + * tee_shm_get_page_offset() - Get shared buffer offset from page start + * @shm: Shared memory handle + * @returns page offset of shared buffer + */ +static inline size_t tee_shm_get_page_offset(struct tee_shm *shm) +{ + return shm->offset; +} + /** * tee_shm_get_id() - Get id of a shared memory object * @shm: Shared memory handle -- cgit From e0c69ae8bfb500facebe1fa331f9400c216eaab0 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Wed, 29 Nov 2017 14:48:28 +0200 Subject: tee: shm: add page accessor functions In order to register a shared buffer in TEE, we need accessor function that return list of pages for that buffer. Signed-off-by: Volodymyr Babchuk Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 6838f25e1421..0f86a480c204 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -403,6 +403,19 @@ static inline size_t tee_shm_get_size(struct tee_shm *shm) return shm->size; } +/** + * tee_shm_get_pages() - Get list of pages that hold shared buffer + * @shm: Shared memory handle + * @num_pages: Number of pages will be stored there + * @returns pointer to pages array + */ +static inline struct page **tee_shm_get_pages(struct tee_shm *shm, + size_t *num_pages) +{ + *num_pages = shm->num_pages; + return shm->pages; +} + /** * tee_shm_get_page_offset() - Get shared buffer offset from page start * @shm: Shared memory handle -- cgit From 217e0250cccb9e54d457991446cd3fab413085e1 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Wed, 29 Nov 2017 14:48:37 +0200 Subject: tee: use reference counting for tee_context We need to ensure that tee_context is present until last shared buffer will be freed. Signed-off-by: Volodymyr Babchuk Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 0f86a480c204..157e8d06bf49 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -17,6 +17,7 @@ #include #include +#include #include #include @@ -42,11 +43,17 @@ struct tee_shm_pool; * @teedev: pointer to this drivers struct tee_device * @list_shm: List of shared memory object owned by this context * @data: driver specific context data, managed by the driver + * @refcount: reference counter for this structure + * @releasing: flag that indicates if context is being released right now. + * It is needed to break circular dependency on context during + * shared memory release. */ struct tee_context { struct tee_device *teedev; struct list_head list_shm; void *data; + struct kref refcount; + bool releasing; }; struct tee_param_memref { -- cgit From ef8e08d24ca84846ce639b835ebd2f15a943f42b Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Wed, 29 Nov 2017 14:48:38 +0200 Subject: tee: shm: inline tee_shm_get_id() Now, when struct tee_shm is defined in public header, we can inline small getter functions like this one. Signed-off-by: Volodymyr Babchuk Signed-off-by: Jens Wiklander --- include/linux/tee_drv.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/linux/tee_drv.h') diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 157e8d06bf49..a1d7f467657c 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -438,7 +438,10 @@ static inline size_t tee_shm_get_page_offset(struct tee_shm *shm) * @shm: Shared memory handle * @returns id */ -int tee_shm_get_id(struct tee_shm *shm); +static inline int tee_shm_get_id(struct tee_shm *shm) +{ + return shm->id; +} /** * tee_shm_get_from_id() - Find shared memory object and increase reference -- cgit