summaryrefslogtreecommitdiff
path: root/core/tee/tee_fs_rpc_cache.c
blob: d1fc51c026fbf2102e99e7590268a1502cfc9d16 (plain)
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
// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2016, Linaro Limited
 */

#include <kernel/thread.h>
#include <mm/core_memprot.h>
#include <mm/core_mmu.h>
#include <mm/mobj.h>
#include <tee/tee_fs_rpc.h>

void tee_fs_rpc_cache_clear(struct thread_specific_data *tsd)
{
	if (tsd->rpc_fs_payload) {
		thread_rpc_free_payload(tsd->rpc_fs_payload_cookie,
					tsd->rpc_fs_payload_mobj);
		tsd->rpc_fs_payload = NULL;
		tsd->rpc_fs_payload_cookie = 0;
		tsd->rpc_fs_payload_size = 0;
		tsd->rpc_fs_payload_mobj = NULL;
	}
}

void *tee_fs_rpc_cache_alloc(size_t size, struct mobj **mobj, uint64_t *cookie)
{
	struct thread_specific_data *tsd = thread_get_tsd();
	size_t sz = size;
	uint64_t c = 0;
	paddr_t p;
	void *va;

	if (!size)
		return NULL;

	/*
	 * Always allocate in page chunks as normal world allocates payload
	 * memory as complete pages.
	 */
	sz = ROUNDUP(size, SMALL_PAGE_SIZE);

	if (sz > tsd->rpc_fs_payload_size) {
		tee_fs_rpc_cache_clear(tsd);

		*mobj = thread_rpc_alloc_payload(sz,  &c);
		if (!*mobj)
			return NULL;

		if (mobj_get_pa(*mobj, 0, 0, &p))
			goto err;

		if (!ALIGNMENT_IS_OK(p, uint64_t))
			goto err;

		va = mobj_get_va(*mobj, 0);
		if (!va)
			goto err;

		tsd->rpc_fs_payload = va;
		tsd->rpc_fs_payload_mobj = *mobj;
		tsd->rpc_fs_payload_cookie = c;
		tsd->rpc_fs_payload_size = sz;
	} else
		*mobj = tsd->rpc_fs_payload_mobj;

	*cookie = tsd->rpc_fs_payload_cookie;
	return tsd->rpc_fs_payload;
err:
	thread_rpc_free_payload(c, *mobj);
	return NULL;
}