1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Copyright (c) 2015, Linaro Limited
4 * Copyright (c) 2017, EPAM Systems
5 */
6#include <linux/device.h>
7#include <linux/dma-buf.h>
8#include <linux/genalloc.h>
9#include <linux/slab.h>
10#include <linux/tee_drv.h>
11#include "optee_private.h"
12#include "optee_smc.h"
13#include "shm_pool.h"
14
15static int pool_op_alloc(struct tee_shm_pool_mgr *poolm,
16			 struct tee_shm *shm, size_t size)
17{
18	unsigned int order = get_order(size);
19	struct page *page;
20	int rc = 0;
21
22	page = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
23	if (!page)
24		return -ENOMEM;
25
26	shm->kaddr = page_address(page);
27	shm->paddr = page_to_phys(page);
28	shm->size = PAGE_SIZE << order;
29
30	/*
31	 * Shared memory private to the OP-TEE driver doesn't need
32	 * to be registered with OP-TEE.
33	 */
34	if (!(shm->flags & TEE_SHM_PRIV)) {
35		unsigned int nr_pages = 1 << order, i;
36		struct page **pages;
37
38		pages = kcalloc(nr_pages, sizeof(pages), GFP_KERNEL);
39		if (!pages) {
40			rc = -ENOMEM;
41			goto err;
42		}
43
44		for (i = 0; i < nr_pages; i++)
45			pages[i] = page + i;
46
47		shm->flags |= TEE_SHM_REGISTER;
48		rc = optee_shm_register(shm->ctx, shm, pages, nr_pages,
49					(unsigned long)shm->kaddr);
50		kfree(pages);
51		if (rc)
52			goto err;
53	}
54
55	return 0;
56
57err:
58	__free_pages(page, order);
59	return rc;
60}
61
62static void pool_op_free(struct tee_shm_pool_mgr *poolm,
63			 struct tee_shm *shm)
64{
65	if (!(shm->flags & TEE_SHM_PRIV))
66		optee_shm_unregister(shm->ctx, shm);
67
68	free_pages((unsigned long)shm->kaddr, get_order(shm->size));
69	shm->kaddr = NULL;
70}
71
72static void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
73{
74	kfree(poolm);
75}
76
77static const struct tee_shm_pool_mgr_ops pool_ops = {
78	.alloc = pool_op_alloc,
79	.free = pool_op_free,
80	.destroy_poolmgr = pool_op_destroy_poolmgr,
81};
82
83/**
84 * optee_shm_pool_alloc_pages() - create page-based allocator pool
85 *
86 * This pool is used when OP-TEE supports dymanic SHM. In this case
87 * command buffers and such are allocated from kernel's own memory.
88 */
89struct tee_shm_pool_mgr *optee_shm_pool_alloc_pages(void)
90{
91	struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
92
93	if (!mgr)
94		return ERR_PTR(-ENOMEM);
95
96	mgr->ops = &pool_ops;
97
98	return mgr;
99}
100