diff options
author | Arnd Bergmann <arnd@arndb.de> | 2017-12-21 11:23:52 -0500 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2017-12-21 11:23:52 -0500 |
commit | bad19e0d0460564a067f901b6848c0cc0c403c52 (patch) | |
tree | a18b9f2796aee7ce366108e684c12b5fe9d95f89 /include | |
parent | f9988fbb93c8c4de9f8ec37f63ebb7bf705c7c45 (diff) | |
parent | ef8e08d24ca84846ce639b835ebd2f15a943f42b (diff) |
Merge tag 'tee-drv-dynamic-shm-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee into next/drivers
Pull "tee dynamic shm for v4.16" from Jens Wiklander:
This pull request enables dynamic shared memory support in the TEE
subsystem as a whole and in OP-TEE in particular.
Global Platform TEE specification [1] allows client applications
to register part of own memory as a shared buffer between
application and TEE. This allows fast zero-copy communication between
TEE and REE. But current implementation of TEE in Linux does not support
this feature.
Also, current implementation of OP-TEE transport uses fixed size
pre-shared buffer for all communications with OP-TEE OS. This is okay
in the most use cases. But this prevents use of OP-TEE in virtualized
environments, because:
a) We can't share the same buffer between different virtual machines
b) Physically contiguous memory as seen by VM can be non-contiguous
in reality (and as seen by OP-TEE OS) due to second stage of
MMU translation.
c) Size of this pre-shared buffer is limited.
So, first part of this pull request adds generic register/unregister
interface to tee subsystem. The second part adds necessary features into
OP-TEE driver, so it can use not only static pre-shared buffer, but
whole RAM to communicate with OP-TEE OS.
This change is backwards compatible allowing older secure world or
user space to work with newer kernels and vice versa.
[1] https://www.globalplatform.org/specificationsdevice.asp
* tag 'tee-drv-dynamic-shm-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee:
tee: shm: inline tee_shm_get_id()
tee: use reference counting for tee_context
tee: optee: enable dynamic SHM support
tee: optee: add optee-specific shared pool implementation
tee: optee: store OP-TEE capabilities in private data
tee: optee: add registered buffers handling into RPC calls
tee: optee: add registered shared parameters handling
tee: optee: add shared buffer registration functions
tee: optee: add page list manipulation functions
tee: optee: Update protocol definitions
tee: shm: add page accessor functions
tee: shm: add accessors for buffer size and page offset
tee: add register user memory
tee: flexible shared memory pool creation
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/tee_drv.h | 183 | ||||
-rw-r--r-- | include/uapi/linux/tee.h | 30 |
2 files changed, 210 insertions, 3 deletions
diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index f4a0ac05ebb4..41bd4bded28c 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h | |||
@@ -17,6 +17,7 @@ | |||
17 | 17 | ||
18 | #include <linux/types.h> | 18 | #include <linux/types.h> |
19 | #include <linux/idr.h> | 19 | #include <linux/idr.h> |
20 | #include <linux/kref.h> | ||
20 | #include <linux/list.h> | 21 | #include <linux/list.h> |
21 | #include <linux/tee.h> | 22 | #include <linux/tee.h> |
22 | 23 | ||
@@ -25,8 +26,12 @@ | |||
25 | * specific TEE driver. | 26 | * specific TEE driver. |
26 | */ | 27 | */ |
27 | 28 | ||
28 | #define TEE_SHM_MAPPED 0x1 /* Memory mapped by the kernel */ | 29 | #define TEE_SHM_MAPPED BIT(0) /* Memory mapped by the kernel */ |
29 | #define TEE_SHM_DMA_BUF 0x2 /* Memory with dma-buf handle */ | 30 | #define TEE_SHM_DMA_BUF BIT(1) /* Memory with dma-buf handle */ |
31 | #define TEE_SHM_EXT_DMA_BUF BIT(2) /* Memory with dma-buf handle */ | ||
32 | #define TEE_SHM_REGISTER BIT(3) /* Memory registered in secure world */ | ||
33 | #define TEE_SHM_USER_MAPPED BIT(4) /* Memory mapped in user space */ | ||
34 | #define TEE_SHM_POOL BIT(5) /* Memory allocated from pool */ | ||
30 | 35 | ||
31 | struct device; | 36 | struct device; |
32 | struct tee_device; | 37 | struct tee_device; |
@@ -38,11 +43,17 @@ struct tee_shm_pool; | |||
38 | * @teedev: pointer to this drivers struct tee_device | 43 | * @teedev: pointer to this drivers struct tee_device |
39 | * @list_shm: List of shared memory object owned by this context | 44 | * @list_shm: List of shared memory object owned by this context |
40 | * @data: driver specific context data, managed by the driver | 45 | * @data: driver specific context data, managed by the driver |
46 | * @refcount: reference counter for this structure | ||
47 | * @releasing: flag that indicates if context is being released right now. | ||
48 | * It is needed to break circular dependency on context during | ||
49 | * shared memory release. | ||
41 | */ | 50 | */ |
42 | struct tee_context { | 51 | struct tee_context { |
43 | struct tee_device *teedev; | 52 | struct tee_device *teedev; |
44 | struct list_head list_shm; | 53 | struct list_head list_shm; |
45 | void *data; | 54 | void *data; |
55 | struct kref refcount; | ||
56 | bool releasing; | ||
46 | }; | 57 | }; |
47 | 58 | ||
48 | struct tee_param_memref { | 59 | struct tee_param_memref { |
@@ -76,6 +87,8 @@ struct tee_param { | |||
76 | * @cancel_req: request cancel of an ongoing invoke or open | 87 | * @cancel_req: request cancel of an ongoing invoke or open |
77 | * @supp_revc: called for supplicant to get a command | 88 | * @supp_revc: called for supplicant to get a command |
78 | * @supp_send: called for supplicant to send a response | 89 | * @supp_send: called for supplicant to send a response |
90 | * @shm_register: register shared memory buffer in TEE | ||
91 | * @shm_unregister: unregister shared memory buffer in TEE | ||
79 | */ | 92 | */ |
80 | struct tee_driver_ops { | 93 | struct tee_driver_ops { |
81 | void (*get_version)(struct tee_device *teedev, | 94 | void (*get_version)(struct tee_device *teedev, |
@@ -94,6 +107,9 @@ struct tee_driver_ops { | |||
94 | struct tee_param *param); | 107 | struct tee_param *param); |
95 | int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params, | 108 | int (*supp_send)(struct tee_context *ctx, u32 ret, u32 num_params, |
96 | struct tee_param *param); | 109 | struct tee_param *param); |
110 | int (*shm_register)(struct tee_context *ctx, struct tee_shm *shm, | ||
111 | struct page **pages, size_t num_pages); | ||
112 | int (*shm_unregister)(struct tee_context *ctx, struct tee_shm *shm); | ||
97 | }; | 113 | }; |
98 | 114 | ||
99 | /** | 115 | /** |
@@ -150,6 +166,97 @@ int tee_device_register(struct tee_device *teedev); | |||
150 | void tee_device_unregister(struct tee_device *teedev); | 166 | void tee_device_unregister(struct tee_device *teedev); |
151 | 167 | ||
152 | /** | 168 | /** |
169 | * struct tee_shm - shared memory object | ||
170 | * @teedev: device used to allocate the object | ||
171 | * @ctx: context using the object, if NULL the context is gone | ||
172 | * @link link element | ||
173 | * @paddr: physical address of the shared memory | ||
174 | * @kaddr: virtual address of the shared memory | ||
175 | * @size: size of shared memory | ||
176 | * @offset: offset of buffer in user space | ||
177 | * @pages: locked pages from userspace | ||
178 | * @num_pages: number of locked pages | ||
179 | * @dmabuf: dmabuf used to for exporting to user space | ||
180 | * @flags: defined by TEE_SHM_* in tee_drv.h | ||
181 | * @id: unique id of a shared memory object on this device | ||
182 | * | ||
183 | * This pool is only supposed to be accessed directly from the TEE | ||
184 | * subsystem and from drivers that implements their own shm pool manager. | ||
185 | */ | ||
186 | struct tee_shm { | ||
187 | struct tee_device *teedev; | ||
188 | struct tee_context *ctx; | ||
189 | struct list_head link; | ||
190 | phys_addr_t paddr; | ||
191 | void *kaddr; | ||
192 | size_t size; | ||
193 | unsigned int offset; | ||
194 | struct page **pages; | ||
195 | size_t num_pages; | ||
196 | struct dma_buf *dmabuf; | ||
197 | u32 flags; | ||
198 | int id; | ||
199 | }; | ||
200 | |||
201 | /** | ||
202 | * struct tee_shm_pool_mgr - shared memory manager | ||
203 | * @ops: operations | ||
204 | * @private_data: private data for the shared memory manager | ||
205 | */ | ||
206 | struct tee_shm_pool_mgr { | ||
207 | const struct tee_shm_pool_mgr_ops *ops; | ||
208 | void *private_data; | ||
209 | }; | ||
210 | |||
211 | /** | ||
212 | * struct tee_shm_pool_mgr_ops - shared memory pool manager operations | ||
213 | * @alloc: called when allocating shared memory | ||
214 | * @free: called when freeing shared memory | ||
215 | * @destroy_poolmgr: called when destroying the pool manager | ||
216 | */ | ||
217 | struct tee_shm_pool_mgr_ops { | ||
218 | int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm, | ||
219 | size_t size); | ||
220 | void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm); | ||
221 | void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr); | ||
222 | }; | ||
223 | |||
224 | /** | ||
225 | * tee_shm_pool_alloc() - Create a shared memory pool from shm managers | ||
226 | * @priv_mgr: manager for driver private shared memory allocations | ||
227 | * @dmabuf_mgr: manager for dma-buf shared memory allocations | ||
228 | * | ||
229 | * Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied | ||
230 | * in @dmabuf, others will use the range provided by @priv. | ||
231 | * | ||
232 | * @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure. | ||
233 | */ | ||
234 | struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr, | ||
235 | struct tee_shm_pool_mgr *dmabuf_mgr); | ||
236 | |||
237 | /* | ||
238 | * tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved | ||
239 | * memory | ||
240 | * @vaddr: Virtual address of start of pool | ||
241 | * @paddr: Physical address of start of pool | ||
242 | * @size: Size in bytes of the pool | ||
243 | * | ||
244 | * @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure. | ||
245 | */ | ||
246 | struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr, | ||
247 | phys_addr_t paddr, | ||
248 | size_t size, | ||
249 | int min_alloc_order); | ||
250 | |||
251 | /** | ||
252 | * tee_shm_pool_mgr_destroy() - Free a shared memory manager | ||
253 | */ | ||
254 | static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm) | ||
255 | { | ||
256 | poolm->ops->destroy_poolmgr(poolm); | ||
257 | } | ||
258 | |||
259 | /** | ||
153 | * struct tee_shm_pool_mem_info - holds information needed to create a shared | 260 | * struct tee_shm_pool_mem_info - holds information needed to create a shared |
154 | * memory pool | 261 | * memory pool |
155 | * @vaddr: Virtual address of start of pool | 262 | * @vaddr: Virtual address of start of pool |
@@ -211,6 +318,40 @@ void *tee_get_drvdata(struct tee_device *teedev); | |||
211 | struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); | 318 | struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags); |
212 | 319 | ||
213 | /** | 320 | /** |
321 | * tee_shm_priv_alloc() - Allocate shared memory privately | ||
322 | * @dev: Device that allocates the shared memory | ||
323 | * @size: Requested size of shared memory | ||
324 | * | ||
325 | * Allocates shared memory buffer that is not associated with any client | ||
326 | * context. Such buffers are owned by TEE driver and used for internal calls. | ||
327 | * | ||
328 | * @returns a pointer to 'struct tee_shm' | ||
329 | */ | ||
330 | struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size); | ||
331 | |||
332 | /** | ||
333 | * tee_shm_register() - Register shared memory buffer | ||
334 | * @ctx: Context that registers the shared memory | ||
335 | * @addr: Address is userspace of the shared buffer | ||
336 | * @length: Length of the shared buffer | ||
337 | * @flags: Flags setting properties for the requested shared memory. | ||
338 | * | ||
339 | * @returns a pointer to 'struct tee_shm' | ||
340 | */ | ||
341 | struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, | ||
342 | size_t length, u32 flags); | ||
343 | |||
344 | /** | ||
345 | * tee_shm_is_registered() - Check if shared memory object in registered in TEE | ||
346 | * @shm: Shared memory handle | ||
347 | * @returns true if object is registered in TEE | ||
348 | */ | ||
349 | static inline bool tee_shm_is_registered(struct tee_shm *shm) | ||
350 | { | ||
351 | return shm && (shm->flags & TEE_SHM_REGISTER); | ||
352 | } | ||
353 | |||
354 | /** | ||
214 | * tee_shm_free() - Free shared memory | 355 | * tee_shm_free() - Free shared memory |
215 | * @shm: Handle to shared memory to free | 356 | * @shm: Handle to shared memory to free |
216 | */ | 357 | */ |
@@ -260,11 +401,47 @@ void *tee_shm_get_va(struct tee_shm *shm, size_t offs); | |||
260 | int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); | 401 | int tee_shm_get_pa(struct tee_shm *shm, size_t offs, phys_addr_t *pa); |
261 | 402 | ||
262 | /** | 403 | /** |
404 | * tee_shm_get_size() - Get size of shared memory buffer | ||
405 | * @shm: Shared memory handle | ||
406 | * @returns size of shared memory | ||
407 | */ | ||
408 | static inline size_t tee_shm_get_size(struct tee_shm *shm) | ||
409 | { | ||
410 | return shm->size; | ||
411 | } | ||
412 | |||
413 | /** | ||
414 | * tee_shm_get_pages() - Get list of pages that hold shared buffer | ||
415 | * @shm: Shared memory handle | ||
416 | * @num_pages: Number of pages will be stored there | ||
417 | * @returns pointer to pages array | ||
418 | */ | ||
419 | static inline struct page **tee_shm_get_pages(struct tee_shm *shm, | ||
420 | size_t *num_pages) | ||
421 | { | ||
422 | *num_pages = shm->num_pages; | ||
423 | return shm->pages; | ||
424 | } | ||
425 | |||
426 | /** | ||
427 | * tee_shm_get_page_offset() - Get shared buffer offset from page start | ||
428 | * @shm: Shared memory handle | ||
429 | * @returns page offset of shared buffer | ||
430 | */ | ||
431 | static inline size_t tee_shm_get_page_offset(struct tee_shm *shm) | ||
432 | { | ||
433 | return shm->offset; | ||
434 | } | ||
435 | |||
436 | /** | ||
263 | * tee_shm_get_id() - Get id of a shared memory object | 437 | * tee_shm_get_id() - Get id of a shared memory object |
264 | * @shm: Shared memory handle | 438 | * @shm: Shared memory handle |
265 | * @returns id | 439 | * @returns id |
266 | */ | 440 | */ |
267 | int tee_shm_get_id(struct tee_shm *shm); | 441 | static inline int tee_shm_get_id(struct tee_shm *shm) |
442 | { | ||
443 | return shm->id; | ||
444 | } | ||
268 | 445 | ||
269 | /** | 446 | /** |
270 | * tee_shm_get_from_id() - Find shared memory object and increase reference | 447 | * tee_shm_get_from_id() - Find shared memory object and increase reference |
diff --git a/include/uapi/linux/tee.h b/include/uapi/linux/tee.h index 267c12e7fd79..4b9eb064d7e7 100644 --- a/include/uapi/linux/tee.h +++ b/include/uapi/linux/tee.h | |||
@@ -50,6 +50,7 @@ | |||
50 | 50 | ||
51 | #define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ | 51 | #define TEE_GEN_CAP_GP (1 << 0)/* GlobalPlatform compliant TEE */ |
52 | #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ | 52 | #define TEE_GEN_CAP_PRIVILEGED (1 << 1)/* Privileged device (for supplicant) */ |
53 | #define TEE_GEN_CAP_REG_MEM (1 << 2)/* Supports registering shared memory */ | ||
53 | 54 | ||
54 | /* | 55 | /* |
55 | * TEE Implementation ID | 56 | * TEE Implementation ID |
@@ -339,6 +340,35 @@ struct tee_iocl_supp_send_arg { | |||
339 | #define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ | 340 | #define TEE_IOC_SUPPL_SEND _IOR(TEE_IOC_MAGIC, TEE_IOC_BASE + 7, \ |
340 | struct tee_ioctl_buf_data) | 341 | struct tee_ioctl_buf_data) |
341 | 342 | ||
343 | /** | ||
344 | * struct tee_ioctl_shm_register_data - Shared memory register argument | ||
345 | * @addr: [in] Start address of shared memory to register | ||
346 | * @length: [in/out] Length of shared memory to register | ||
347 | * @flags: [in/out] Flags to/from registration. | ||
348 | * @id: [out] Identifier of the shared memory | ||
349 | * | ||
350 | * The flags field should currently be zero as input. Updated by the call | ||
351 | * with actual flags as defined by TEE_IOCTL_SHM_* above. | ||
352 | * This structure is used as argument for TEE_IOC_SHM_REGISTER below. | ||
353 | */ | ||
354 | struct tee_ioctl_shm_register_data { | ||
355 | __u64 addr; | ||
356 | __u64 length; | ||
357 | __u32 flags; | ||
358 | __s32 id; | ||
359 | }; | ||
360 | |||
361 | /** | ||
362 | * TEE_IOC_SHM_REGISTER - Register shared memory argument | ||
363 | * | ||
364 | * Registers shared memory between the user space process and secure OS. | ||
365 | * | ||
366 | * Returns a file descriptor on success or < 0 on failure | ||
367 | * | ||
368 | * The shared memory is unregisterred when the descriptor is closed. | ||
369 | */ | ||
370 | #define TEE_IOC_SHM_REGISTER _IOWR(TEE_IOC_MAGIC, TEE_IOC_BASE + 9, \ | ||
371 | struct tee_ioctl_shm_register_data) | ||
342 | /* | 372 | /* |
343 | * Five syscalls are used when communicating with the TEE driver. | 373 | * Five syscalls are used when communicating with the TEE driver. |
344 | * open(): opens the device associated with the driver | 374 | * open(): opens the device associated with the driver |