Skip to content

Commit e2aca5d

Browse files
committed
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 <jens.wiklander@linaro.org> Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
1 parent 50c4c4e commit e2aca5d

File tree

4 files changed

+199
-122
lines changed

4 files changed

+199
-122
lines changed

drivers/tee/tee_private.h

Lines changed: 2 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -21,68 +21,15 @@
2121
#include <linux/mutex.h>
2222
#include <linux/types.h>
2323

24-
struct tee_device;
25-
26-
/**
27-
* struct tee_shm - shared memory object
28-
* @teedev: device used to allocate the object
29-
* @ctx: context using the object, if NULL the context is gone
30-
* @link link element
31-
* @paddr: physical address of the shared memory
32-
* @kaddr: virtual address of the shared memory
33-
* @size: size of shared memory
34-
* @dmabuf: dmabuf used to for exporting to user space
35-
* @flags: defined by TEE_SHM_* in tee_drv.h
36-
* @id: unique id of a shared memory object on this device
37-
*/
38-
struct tee_shm {
39-
struct tee_device *teedev;
40-
struct tee_context *ctx;
41-
struct list_head link;
42-
phys_addr_t paddr;
43-
void *kaddr;
44-
size_t size;
45-
struct dma_buf *dmabuf;
46-
u32 flags;
47-
int id;
48-
};
49-
50-
struct tee_shm_pool_mgr;
51-
52-
/**
53-
* struct tee_shm_pool_mgr_ops - shared memory pool manager operations
54-
* @alloc: called when allocating shared memory
55-
* @free: called when freeing shared memory
56-
*/
57-
struct tee_shm_pool_mgr_ops {
58-
int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
59-
size_t size);
60-
void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
61-
};
62-
63-
/**
64-
* struct tee_shm_pool_mgr - shared memory manager
65-
* @ops: operations
66-
* @private_data: private data for the shared memory manager
67-
*/
68-
struct tee_shm_pool_mgr {
69-
const struct tee_shm_pool_mgr_ops *ops;
70-
void *private_data;
71-
};
72-
7324
/**
7425
* struct tee_shm_pool - shared memory pool
7526
* @private_mgr: pool manager for shared memory only between kernel
7627
* and secure world
7728
* @dma_buf_mgr: pool manager for shared memory exported to user space
78-
* @destroy: called when destroying the pool
79-
* @private_data: private data for the pool
8029
*/
8130
struct tee_shm_pool {
82-
struct tee_shm_pool_mgr private_mgr;
83-
struct tee_shm_pool_mgr dma_buf_mgr;
84-
void (*destroy)(struct tee_shm_pool *pool);
85-
void *private_data;
31+
struct tee_shm_pool_mgr *private_mgr;
32+
struct tee_shm_pool_mgr *dma_buf_mgr;
8633
};
8734

8835
#define TEE_DEVICE_FLAG_REGISTERED 0x1

drivers/tee/tee_shm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ static void tee_shm_release(struct tee_shm *shm)
3232
mutex_unlock(&teedev->mutex);
3333

3434
if (shm->flags & TEE_SHM_DMA_BUF)
35-
poolm = &teedev->pool->dma_buf_mgr;
35+
poolm = teedev->pool->dma_buf_mgr;
3636
else
37-
poolm = &teedev->pool->private_mgr;
37+
poolm = teedev->pool->private_mgr;
3838

3939
poolm->ops->free(poolm, shm);
4040
kfree(shm);
@@ -139,9 +139,9 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
139139
shm->teedev = teedev;
140140
shm->ctx = ctx;
141141
if (flags & TEE_SHM_DMA_BUF)
142-
poolm = &teedev->pool->dma_buf_mgr;
142+
poolm = teedev->pool->dma_buf_mgr;
143143
else
144-
poolm = &teedev->pool->private_mgr;
144+
poolm = teedev->pool->private_mgr;
145145

146146
rc = poolm->ops->alloc(poolm, shm, size);
147147
if (rc) {

drivers/tee/tee_shm_pool.c

Lines changed: 102 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -44,49 +44,18 @@ static void pool_op_gen_free(struct tee_shm_pool_mgr *poolm,
4444
shm->kaddr = NULL;
4545
}
4646

47+
static void pool_op_gen_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
48+
{
49+
gen_pool_destroy(poolm->private_data);
50+
kfree(poolm);
51+
}
52+
4753
static const struct tee_shm_pool_mgr_ops pool_ops_generic = {
4854
.alloc = pool_op_gen_alloc,
4955
.free = pool_op_gen_free,
56+
.destroy_poolmgr = pool_op_gen_destroy_poolmgr,
5057
};
5158

52-
static void pool_res_mem_destroy(struct tee_shm_pool *pool)
53-
{
54-
gen_pool_destroy(pool->private_mgr.private_data);
55-
gen_pool_destroy(pool->dma_buf_mgr.private_data);
56-
}
57-
58-
static int pool_res_mem_mgr_init(struct tee_shm_pool_mgr *mgr,
59-
struct tee_shm_pool_mem_info *info,
60-
int min_alloc_order)
61-
{
62-
size_t page_mask = PAGE_SIZE - 1;
63-
struct gen_pool *genpool = NULL;
64-
int rc;
65-
66-
/*
67-
* Start and end must be page aligned
68-
*/
69-
if ((info->vaddr & page_mask) || (info->paddr & page_mask) ||
70-
(info->size & page_mask))
71-
return -EINVAL;
72-
73-
genpool = gen_pool_create(min_alloc_order, -1);
74-
if (!genpool)
75-
return -ENOMEM;
76-
77-
gen_pool_set_algo(genpool, gen_pool_best_fit, NULL);
78-
rc = gen_pool_add_virt(genpool, info->vaddr, info->paddr, info->size,
79-
-1);
80-
if (rc) {
81-
gen_pool_destroy(genpool);
82-
return rc;
83-
}
84-
85-
mgr->private_data = genpool;
86-
mgr->ops = &pool_ops_generic;
87-
return 0;
88-
}
89-
9059
/**
9160
* tee_shm_pool_alloc_res_mem() - Create a shared memory pool from reserved
9261
* memory range
@@ -104,42 +73,109 @@ struct tee_shm_pool *
10473
tee_shm_pool_alloc_res_mem(struct tee_shm_pool_mem_info *priv_info,
10574
struct tee_shm_pool_mem_info *dmabuf_info)
10675
{
107-
struct tee_shm_pool *pool = NULL;
108-
int ret;
109-
110-
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
111-
if (!pool) {
112-
ret = -ENOMEM;
113-
goto err;
114-
}
76+
struct tee_shm_pool_mgr *priv_mgr;
77+
struct tee_shm_pool_mgr *dmabuf_mgr;
78+
void *rc;
11579

11680
/*
11781
* Create the pool for driver private shared memory
11882
*/
119-
ret = pool_res_mem_mgr_init(&pool->private_mgr, priv_info,
120-
3 /* 8 byte aligned */);
121-
if (ret)
122-
goto err;
83+
rc = tee_shm_pool_mgr_alloc_res_mem(priv_info->vaddr, priv_info->paddr,
84+
priv_info->size,
85+
3 /* 8 byte aligned */);
86+
if (IS_ERR(rc))
87+
return rc;
88+
priv_mgr = rc;
12389

12490
/*
12591
* Create the pool for dma_buf shared memory
12692
*/
127-
ret = pool_res_mem_mgr_init(&pool->dma_buf_mgr, dmabuf_info,
128-
PAGE_SHIFT);
129-
if (ret)
93+
rc = tee_shm_pool_mgr_alloc_res_mem(dmabuf_info->vaddr,
94+
dmabuf_info->paddr,
95+
dmabuf_info->size, PAGE_SHIFT);
96+
if (IS_ERR(rc))
97+
goto err_free_priv_mgr;
98+
dmabuf_mgr = rc;
99+
100+
rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
101+
if (IS_ERR(rc))
102+
goto err_free_dmabuf_mgr;
103+
104+
return rc;
105+
106+
err_free_dmabuf_mgr:
107+
tee_shm_pool_mgr_destroy(dmabuf_mgr);
108+
err_free_priv_mgr:
109+
tee_shm_pool_mgr_destroy(priv_mgr);
110+
111+
return rc;
112+
}
113+
EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
114+
115+
struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
116+
phys_addr_t paddr,
117+
size_t size,
118+
int min_alloc_order)
119+
{
120+
const size_t page_mask = PAGE_SIZE - 1;
121+
struct tee_shm_pool_mgr *mgr;
122+
int rc;
123+
124+
/* Start and end must be page aligned */
125+
if (vaddr & page_mask || paddr & page_mask || size & page_mask)
126+
return ERR_PTR(-EINVAL);
127+
128+
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
129+
if (!mgr)
130+
return ERR_PTR(-ENOMEM);
131+
132+
mgr->private_data = gen_pool_create(min_alloc_order, -1);
133+
if (!mgr->private_data) {
134+
rc = -ENOMEM;
130135
goto err;
136+
}
131137

132-
pool->destroy = pool_res_mem_destroy;
133-
return pool;
138+
gen_pool_set_algo(mgr->private_data, gen_pool_best_fit, NULL);
139+
rc = gen_pool_add_virt(mgr->private_data, vaddr, paddr, size, -1);
140+
if (rc) {
141+
gen_pool_destroy(mgr->private_data);
142+
goto err;
143+
}
144+
145+
mgr->ops = &pool_ops_generic;
146+
147+
return mgr;
134148
err:
135-
if (ret == -ENOMEM)
136-
pr_err("%s: can't allocate memory for res_mem shared memory pool\n", __func__);
137-
if (pool && pool->private_mgr.private_data)
138-
gen_pool_destroy(pool->private_mgr.private_data);
139-
kfree(pool);
140-
return ERR_PTR(ret);
149+
kfree(mgr);
150+
151+
return ERR_PTR(rc);
141152
}
142-
EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
153+
EXPORT_SYMBOL_GPL(tee_shm_pool_mgr_alloc_res_mem);
154+
155+
static bool check_mgr_ops(struct tee_shm_pool_mgr *mgr)
156+
{
157+
return mgr && mgr->ops && mgr->ops->alloc && mgr->ops->free &&
158+
mgr->ops->destroy_poolmgr;
159+
}
160+
161+
struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
162+
struct tee_shm_pool_mgr *dmabuf_mgr)
163+
{
164+
struct tee_shm_pool *pool;
165+
166+
if (!check_mgr_ops(priv_mgr) || !check_mgr_ops(dmabuf_mgr))
167+
return ERR_PTR(-EINVAL);
168+
169+
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
170+
if (!pool)
171+
return ERR_PTR(-ENOMEM);
172+
173+
pool->private_mgr = priv_mgr;
174+
pool->dma_buf_mgr = dmabuf_mgr;
175+
176+
return pool;
177+
}
178+
EXPORT_SYMBOL_GPL(tee_shm_pool_alloc);
143179

144180
/**
145181
* tee_shm_pool_free() - Free a shared memory pool
@@ -150,7 +186,10 @@ EXPORT_SYMBOL_GPL(tee_shm_pool_alloc_res_mem);
150186
*/
151187
void tee_shm_pool_free(struct tee_shm_pool *pool)
152188
{
153-
pool->destroy(pool);
189+
if (pool->private_mgr)
190+
tee_shm_pool_mgr_destroy(pool->private_mgr);
191+
if (pool->dma_buf_mgr)
192+
tee_shm_pool_mgr_destroy(pool->dma_buf_mgr);
154193
kfree(pool);
155194
}
156195
EXPORT_SYMBOL_GPL(tee_shm_pool_free);

include/linux/tee_drv.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,97 @@ int tee_device_register(struct tee_device *teedev);
149149
*/
150150
void tee_device_unregister(struct tee_device *teedev);
151151

152+
/**
153+
* struct tee_shm - shared memory object
154+
* @teedev: device used to allocate the object
155+
* @ctx: context using the object, if NULL the context is gone
156+
* @link link element
157+
* @paddr: physical address of the shared memory
158+
* @kaddr: virtual address of the shared memory
159+
* @size: size of shared memory
160+
* @offset: offset of buffer in user space
161+
* @pages: locked pages from userspace
162+
* @num_pages: number of locked pages
163+
* @dmabuf: dmabuf used to for exporting to user space
164+
* @flags: defined by TEE_SHM_* in tee_drv.h
165+
* @id: unique id of a shared memory object on this device
166+
*
167+
* This pool is only supposed to be accessed directly from the TEE
168+
* subsystem and from drivers that implements their own shm pool manager.
169+
*/
170+
struct tee_shm {
171+
struct tee_device *teedev;
172+
struct tee_context *ctx;
173+
struct list_head link;
174+
phys_addr_t paddr;
175+
void *kaddr;
176+
size_t size;
177+
unsigned int offset;
178+
struct page **pages;
179+
size_t num_pages;
180+
struct dma_buf *dmabuf;
181+
u32 flags;
182+
int id;
183+
};
184+
185+
/**
186+
* struct tee_shm_pool_mgr - shared memory manager
187+
* @ops: operations
188+
* @private_data: private data for the shared memory manager
189+
*/
190+
struct tee_shm_pool_mgr {
191+
const struct tee_shm_pool_mgr_ops *ops;
192+
void *private_data;
193+
};
194+
195+
/**
196+
* struct tee_shm_pool_mgr_ops - shared memory pool manager operations
197+
* @alloc: called when allocating shared memory
198+
* @free: called when freeing shared memory
199+
* @destroy_poolmgr: called when destroying the pool manager
200+
*/
201+
struct tee_shm_pool_mgr_ops {
202+
int (*alloc)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm,
203+
size_t size);
204+
void (*free)(struct tee_shm_pool_mgr *poolmgr, struct tee_shm *shm);
205+
void (*destroy_poolmgr)(struct tee_shm_pool_mgr *poolmgr);
206+
};
207+
208+
/**
209+
* tee_shm_pool_alloc() - Create a shared memory pool from shm managers
210+
* @priv_mgr: manager for driver private shared memory allocations
211+
* @dmabuf_mgr: manager for dma-buf shared memory allocations
212+
*
213+
* Allocation with the flag TEE_SHM_DMA_BUF set will use the range supplied
214+
* in @dmabuf, others will use the range provided by @priv.
215+
*
216+
* @returns pointer to a 'struct tee_shm_pool' or an ERR_PTR on failure.
217+
*/
218+
struct tee_shm_pool *tee_shm_pool_alloc(struct tee_shm_pool_mgr *priv_mgr,
219+
struct tee_shm_pool_mgr *dmabuf_mgr);
220+
221+
/*
222+
* tee_shm_pool_mgr_alloc_res_mem() - Create a shm manager for reserved
223+
* memory
224+
* @vaddr: Virtual address of start of pool
225+
* @paddr: Physical address of start of pool
226+
* @size: Size in bytes of the pool
227+
*
228+
* @returns pointer to a 'struct tee_shm_pool_mgr' or an ERR_PTR on failure.
229+
*/
230+
struct tee_shm_pool_mgr *tee_shm_pool_mgr_alloc_res_mem(unsigned long vaddr,
231+
phys_addr_t paddr,
232+
size_t size,
233+
int min_alloc_order);
234+
235+
/**
236+
* tee_shm_pool_mgr_destroy() - Free a shared memory manager
237+
*/
238+
static inline void tee_shm_pool_mgr_destroy(struct tee_shm_pool_mgr *poolm)
239+
{
240+
poolm->ops->destroy_poolmgr(poolm);
241+
}
242+
152243
/**
153244
* struct tee_shm_pool_mem_info - holds information needed to create a shared
154245
* memory pool

0 commit comments

Comments
 (0)