-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathshm_pool.c
More file actions
97 lines (75 loc) · 1.98 KB
/
shm_pool.c
File metadata and controls
97 lines (75 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2021-2023, Arm Limited
*/
#include <linux/arm_ffa.h>
#include <linux/device.h>
#include <linux/dma-buf.h>
#include <linux/genalloc.h>
#include <linux/slab.h>
#include <linux/tee_drv.h>
#include "tstee_private.h"
/*
* This file implements a dynamic shared memory pool. It's used by the TEE
* subsystem to allocate kernel memory to be shared with the SWd as part of the
* TEE_IOC_SHM_ALLOC call.
*/
static int pool_op_alloc(struct tee_shm_pool *pool __always_unused, struct tee_shm *shm,
size_t size, size_t align __always_unused)
{
unsigned int order, nr_pages, i;
struct page *page, **pages;
int rc;
if (size == 0)
return -EINVAL;
order = get_order(size);
nr_pages = 1 << order;
page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!page)
return -ENOMEM;
shm->kaddr = page_address(page);
shm->paddr = page_to_phys(page);
shm->size = PAGE_SIZE << order;
pages = kcalloc(nr_pages, sizeof(*pages), GFP_KERNEL);
if (!pages) {
rc = -ENOMEM;
goto err;
}
for (i = 0; i < nr_pages; i++)
pages[i] = page + i;
rc = tstee_shm_register(shm->ctx, shm, pages, nr_pages, (unsigned long)shm->kaddr);
kfree(pages);
if (rc)
goto err;
return 0;
err:
__free_pages(page, order);
return rc;
}
static void pool_op_free(struct tee_shm_pool *pool __always_unused, struct tee_shm *shm)
{
int rc;
rc = tstee_shm_unregister(shm->ctx, shm);
if (rc)
pr_err("shm id 0x%llx unregister rc %d\n", shm->sec_world_id, rc);
free_pages((unsigned long)shm->kaddr, get_order(shm->size));
shm->kaddr = NULL;
}
static void pool_op_destroy_pool(struct tee_shm_pool *pool)
{
kfree(pool);
}
static const struct tee_shm_pool_ops pool_ops = {
.alloc = pool_op_alloc,
.free = pool_op_free,
.destroy_pool = pool_op_destroy_pool,
};
struct tee_shm_pool *tstee_create_shm_pool(void)
{
struct tee_shm_pool *pool;
pool = kzalloc(sizeof(*pool), GFP_KERNEL);
if (!pool)
return ERR_PTR(-ENOMEM);
pool->ops = &pool_ops;
return pool;
}