xref: /optee_os/core/mm/fobj.c (revision b83c0d5fb4acad7d4b990bad9488fada0f2bf9a7)
1ee546289SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause
2ee546289SJens Wiklander /*
3ee546289SJens Wiklander  * Copyright (c) 2019, Linaro Limited
4ee546289SJens Wiklander  */
5ee546289SJens Wiklander 
6ee546289SJens Wiklander #include <crypto/crypto.h>
7ee546289SJens Wiklander #include <crypto/internal_aes-gcm.h>
8ee546289SJens Wiklander #include <kernel/panic.h>
9ee546289SJens Wiklander #include <mm/core_memprot.h>
10ee546289SJens Wiklander #include <mm/core_mmu.h>
11ee546289SJens Wiklander #include <mm/fobj.h>
12ee546289SJens Wiklander #include <mm/tee_mm.h>
13ee546289SJens Wiklander #include <stdlib.h>
14ee546289SJens Wiklander #include <string.h>
15ee546289SJens Wiklander #include <tee_api_types.h>
16ee546289SJens Wiklander #include <types_ext.h>
17ee546289SJens Wiklander #include <util.h>
18ee546289SJens Wiklander 
19ee546289SJens Wiklander #ifdef CFG_WITH_PAGER
20ee546289SJens Wiklander 
21ee546289SJens Wiklander #define RWP_AE_KEY_BITS		256
22ee546289SJens Wiklander 
23ee546289SJens Wiklander struct rwp_aes_gcm_iv {
24ee546289SJens Wiklander 	uint32_t iv[3];
25ee546289SJens Wiklander };
26ee546289SJens Wiklander 
27ee546289SJens Wiklander #define RWP_AES_GCM_TAG_LEN	16
28ee546289SJens Wiklander 
29ee546289SJens Wiklander struct rwp_state {
30ee546289SJens Wiklander 	uint64_t iv;
31ee546289SJens Wiklander 	uint8_t tag[RWP_AES_GCM_TAG_LEN];
32ee546289SJens Wiklander };
33ee546289SJens Wiklander 
34ee546289SJens Wiklander struct fobj_rwp {
35ee546289SJens Wiklander 	uint8_t *store;
36ee546289SJens Wiklander 	struct rwp_state *state;
37ee546289SJens Wiklander 	struct fobj fobj;
38ee546289SJens Wiklander };
39ee546289SJens Wiklander 
40ee546289SJens Wiklander static struct fobj_ops ops_rw_paged;
41ee546289SJens Wiklander 
42ee546289SJens Wiklander static struct internal_aes_gcm_key rwp_ae_key;
43ee546289SJens Wiklander 
44ee546289SJens Wiklander void fobj_generate_authenc_key(void)
45ee546289SJens Wiklander {
46ee546289SJens Wiklander 	uint8_t key[RWP_AE_KEY_BITS / 8] = { 0 };
47ee546289SJens Wiklander 
48ee546289SJens Wiklander 	if (crypto_rng_read(key, sizeof(key)) != TEE_SUCCESS)
49ee546289SJens Wiklander 		panic("failed to generate random");
50ee546289SJens Wiklander 	if (internal_aes_gcm_expand_enc_key(key, sizeof(key), &rwp_ae_key))
51ee546289SJens Wiklander 		panic("failed to expand key");
52ee546289SJens Wiklander }
53ee546289SJens Wiklander 
54ee546289SJens Wiklander static void fobj_init(struct fobj *fobj, const struct fobj_ops *ops,
55ee546289SJens Wiklander 		      unsigned int num_pages)
56ee546289SJens Wiklander {
57ee546289SJens Wiklander 	fobj->ops = ops;
58ee546289SJens Wiklander 	fobj->num_pages = num_pages;
59ee546289SJens Wiklander 	refcount_set(&fobj->refc, 1);
60*b83c0d5fSJens Wiklander 	TAILQ_INIT(&fobj->areas);
61ee546289SJens Wiklander }
62ee546289SJens Wiklander 
63ee546289SJens Wiklander static void fobj_uninit(struct fobj *fobj)
64ee546289SJens Wiklander {
65ee546289SJens Wiklander 	assert(!refcount_val(&fobj->refc));
66*b83c0d5fSJens Wiklander 	assert(TAILQ_EMPTY(&fobj->areas));
67*b83c0d5fSJens Wiklander 	tee_pager_invalidate_fobj(fobj);
68ee546289SJens Wiklander }
69ee546289SJens Wiklander 
70ee546289SJens Wiklander struct fobj *fobj_rw_paged_alloc(unsigned int num_pages)
71ee546289SJens Wiklander {
72ee546289SJens Wiklander 	tee_mm_entry_t *mm = NULL;
73ee546289SJens Wiklander 	struct fobj_rwp *rwp = NULL;
74ee546289SJens Wiklander 	size_t size = 0;
75ee546289SJens Wiklander 
76ee546289SJens Wiklander 	assert(num_pages);
77ee546289SJens Wiklander 
78ee546289SJens Wiklander 	rwp = calloc(1, sizeof(*rwp));
79ee546289SJens Wiklander 	if (!rwp)
80ee546289SJens Wiklander 		return NULL;
81ee546289SJens Wiklander 
82ee546289SJens Wiklander 	rwp->state = calloc(num_pages, sizeof(*rwp->state));
83ee546289SJens Wiklander 	if (!rwp->state)
84ee546289SJens Wiklander 		goto err;
85ee546289SJens Wiklander 
86ee546289SJens Wiklander 	if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size))
87ee546289SJens Wiklander 		goto err;
88ee546289SJens Wiklander 	mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
89ee546289SJens Wiklander 	if (!mm)
90ee546289SJens Wiklander 		goto err;
91ee546289SJens Wiklander 	rwp->store = phys_to_virt(tee_mm_get_smem(mm), MEM_AREA_TA_RAM);
92ee546289SJens Wiklander 	assert(rwp->store); /* to assist debugging if it would ever happen */
93ee546289SJens Wiklander 	if (!rwp->store)
94ee546289SJens Wiklander 		goto err;
95ee546289SJens Wiklander 
96ee546289SJens Wiklander 	fobj_init(&rwp->fobj, &ops_rw_paged, num_pages);
97ee546289SJens Wiklander 
98ee546289SJens Wiklander 	return &rwp->fobj;
99ee546289SJens Wiklander 
100ee546289SJens Wiklander err:
101ee546289SJens Wiklander 	tee_mm_free(mm);
102ee546289SJens Wiklander 	free(rwp->state);
103ee546289SJens Wiklander 	free(rwp);
104ee546289SJens Wiklander 
105ee546289SJens Wiklander 	return NULL;
106ee546289SJens Wiklander }
107ee546289SJens Wiklander 
108ee546289SJens Wiklander static struct fobj_rwp *to_rwp(struct fobj *fobj)
109ee546289SJens Wiklander {
110ee546289SJens Wiklander 	assert(fobj->ops == &ops_rw_paged);
111ee546289SJens Wiklander 
112ee546289SJens Wiklander 	return container_of(fobj, struct fobj_rwp, fobj);
113ee546289SJens Wiklander }
114ee546289SJens Wiklander 
115ee546289SJens Wiklander static void rwp_free(struct fobj *fobj)
116ee546289SJens Wiklander {
117ee546289SJens Wiklander 	struct fobj_rwp *rwp = to_rwp(fobj);
118ee546289SJens Wiklander 
119ee546289SJens Wiklander 	fobj_uninit(fobj);
120ee546289SJens Wiklander 	tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rwp->store)));
121ee546289SJens Wiklander 	free(rwp->state);
122ee546289SJens Wiklander 	free(rwp);
123ee546289SJens Wiklander }
124ee546289SJens Wiklander 
125ee546289SJens Wiklander static TEE_Result rwp_load_page(struct fobj *fobj, unsigned int page_idx,
126ee546289SJens Wiklander 				void *va)
127ee546289SJens Wiklander {
128ee546289SJens Wiklander 	struct fobj_rwp *rwp = to_rwp(fobj);
129ee546289SJens Wiklander 	struct rwp_state *state = rwp->state + page_idx;
130ee546289SJens Wiklander 	uint8_t *src = rwp->store + page_idx * SMALL_PAGE_SIZE;
131ee546289SJens Wiklander 	struct rwp_aes_gcm_iv iv = {
132ee546289SJens Wiklander 		.iv = { (vaddr_t)state, state->iv >> 32, state->iv }
133ee546289SJens Wiklander 	};
134ee546289SJens Wiklander 
135ee546289SJens Wiklander 	assert(refcount_val(&fobj->refc));
136ee546289SJens Wiklander 	assert(page_idx < fobj->num_pages);
137ee546289SJens Wiklander 
138ee546289SJens Wiklander 	if (!state->iv) {
139ee546289SJens Wiklander 		/*
140ee546289SJens Wiklander 		 * iv still zero which means that this is previously unused
141ee546289SJens Wiklander 		 * page.
142ee546289SJens Wiklander 		 */
143ee546289SJens Wiklander 		memset(va, 0, SMALL_PAGE_SIZE);
144ee546289SJens Wiklander 		return TEE_SUCCESS;
145ee546289SJens Wiklander 	}
146ee546289SJens Wiklander 
147ee546289SJens Wiklander 	return internal_aes_gcm_dec(&rwp_ae_key, &iv, sizeof(iv),
148ee546289SJens Wiklander 				    NULL, 0, src, SMALL_PAGE_SIZE, va,
149ee546289SJens Wiklander 				    state->tag, sizeof(state->tag));
150ee546289SJens Wiklander }
151ee546289SJens Wiklander KEEP_PAGER(rwp_load_page);
152ee546289SJens Wiklander 
153ee546289SJens Wiklander static TEE_Result rwp_save_page(struct fobj *fobj, unsigned int page_idx,
154ee546289SJens Wiklander 				const void *va)
155ee546289SJens Wiklander {
156ee546289SJens Wiklander 	struct fobj_rwp *rwp = to_rwp(fobj);
157ee546289SJens Wiklander 	struct rwp_state *state = rwp->state + page_idx;
158ee546289SJens Wiklander 	size_t tag_len = sizeof(state->tag);
159ee546289SJens Wiklander 	uint8_t *dst = rwp->store + page_idx * SMALL_PAGE_SIZE;
160ee546289SJens Wiklander 	struct rwp_aes_gcm_iv iv;
161ee546289SJens Wiklander 
162ee546289SJens Wiklander 	memset(&iv, 0, sizeof(iv));
163*b83c0d5fSJens Wiklander 
164*b83c0d5fSJens Wiklander 	if (!refcount_val(&fobj->refc)) {
165*b83c0d5fSJens Wiklander 		/*
166*b83c0d5fSJens Wiklander 		 * This fobj is being teared down, it just hasn't had the time
167*b83c0d5fSJens Wiklander 		 * to call tee_pager_invalidate_fobj() yet.
168*b83c0d5fSJens Wiklander 		 */
169*b83c0d5fSJens Wiklander 		assert(TAILQ_EMPTY(&fobj->areas));
170*b83c0d5fSJens Wiklander 		return TEE_SUCCESS;
171*b83c0d5fSJens Wiklander 	}
172*b83c0d5fSJens Wiklander 
173ee546289SJens Wiklander 	assert(page_idx < fobj->num_pages);
174ee546289SJens Wiklander 	assert(state->iv + 1 > state->iv);
175ee546289SJens Wiklander 
176ee546289SJens Wiklander 	state->iv++;
177ee546289SJens Wiklander 	/*
178ee546289SJens Wiklander 	 * IV is constructed as recommended in section "8.2.1 Deterministic
179ee546289SJens Wiklander 	 * Construction" of "Recommendation for Block Cipher Modes of
180ee546289SJens Wiklander 	 * Operation: Galois/Counter Mode (GCM) and GMAC",
181ee546289SJens Wiklander 	 * http://csrc.nist.gov/publications/nistpubs/800-38D/SP-800-38D.pdf
182ee546289SJens Wiklander 	 */
183ee546289SJens Wiklander 
184ee546289SJens Wiklander 	iv.iv[0] = (vaddr_t)state;
185ee546289SJens Wiklander 	iv.iv[1] = state->iv >> 32;
186ee546289SJens Wiklander 	iv.iv[2] = state->iv;
187ee546289SJens Wiklander 
188ee546289SJens Wiklander 	return internal_aes_gcm_enc(&rwp_ae_key, &iv, sizeof(iv),
189ee546289SJens Wiklander 				    NULL, 0, va, SMALL_PAGE_SIZE, dst,
190ee546289SJens Wiklander 				    state->tag, &tag_len);
191ee546289SJens Wiklander }
192ee546289SJens Wiklander KEEP_PAGER(rwp_save_page);
193ee546289SJens Wiklander 
194ee546289SJens Wiklander static struct fobj_ops ops_rw_paged __rodata_unpaged = {
195ee546289SJens Wiklander 	.free = rwp_free,
196ee546289SJens Wiklander 	.load_page = rwp_load_page,
197ee546289SJens Wiklander 	.save_page = rwp_save_page,
198ee546289SJens Wiklander };
199ee546289SJens Wiklander 
200ee546289SJens Wiklander struct fobj_rop {
201ee546289SJens Wiklander 	uint8_t *hashes;
202ee546289SJens Wiklander 	uint8_t *store;
203ee546289SJens Wiklander 	struct fobj fobj;
204ee546289SJens Wiklander };
205ee546289SJens Wiklander 
206ee546289SJens Wiklander static struct fobj_ops ops_ro_paged;
207ee546289SJens Wiklander 
208ee546289SJens Wiklander struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes,
209ee546289SJens Wiklander 				 void *store)
210ee546289SJens Wiklander {
211ee546289SJens Wiklander 	struct fobj_rop *rop = NULL;
212ee546289SJens Wiklander 
213ee546289SJens Wiklander 	assert(num_pages && hashes && store);
214ee546289SJens Wiklander 
215ee546289SJens Wiklander 	rop = calloc(1, sizeof(*rop));
216ee546289SJens Wiklander 	if (!rop)
217ee546289SJens Wiklander 		return NULL;
218ee546289SJens Wiklander 
219ee546289SJens Wiklander 	rop->hashes = hashes;
220ee546289SJens Wiklander 	rop->store = store;
221ee546289SJens Wiklander 	fobj_init(&rop->fobj, &ops_ro_paged, num_pages);
222ee546289SJens Wiklander 
223ee546289SJens Wiklander 	return &rop->fobj;
224ee546289SJens Wiklander }
225ee546289SJens Wiklander 
226ee546289SJens Wiklander static struct fobj_rop *to_rop(struct fobj *fobj)
227ee546289SJens Wiklander {
228ee546289SJens Wiklander 	assert(fobj->ops == &ops_ro_paged);
229ee546289SJens Wiklander 
230ee546289SJens Wiklander 	return container_of(fobj, struct fobj_rop, fobj);
231ee546289SJens Wiklander }
232ee546289SJens Wiklander 
233ee546289SJens Wiklander static void rop_free(struct fobj *fobj)
234ee546289SJens Wiklander {
235ee546289SJens Wiklander 	struct fobj_rop *rop = to_rop(fobj);
236ee546289SJens Wiklander 
237ee546289SJens Wiklander 	fobj_uninit(fobj);
238ee546289SJens Wiklander 	tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, virt_to_phys(rop->store)));
239ee546289SJens Wiklander 	free(rop->hashes);
240ee546289SJens Wiklander 	free(rop);
241ee546289SJens Wiklander }
242ee546289SJens Wiklander 
243ee546289SJens Wiklander static TEE_Result rop_load_page(struct fobj *fobj, unsigned int page_idx,
244ee546289SJens Wiklander 				void *va)
245ee546289SJens Wiklander {
246ee546289SJens Wiklander 	struct fobj_rop *rop = to_rop(fobj);
247ee546289SJens Wiklander 	const uint8_t *hash = rop->hashes + page_idx * TEE_SHA256_HASH_SIZE;
248ee546289SJens Wiklander 	const uint8_t *src = rop->store + page_idx * SMALL_PAGE_SIZE;
249ee546289SJens Wiklander 
250ee546289SJens Wiklander 	assert(refcount_val(&fobj->refc));
251ee546289SJens Wiklander 	assert(page_idx < fobj->num_pages);
252ee546289SJens Wiklander 	memcpy(va, src, SMALL_PAGE_SIZE);
253ee546289SJens Wiklander 
254ee546289SJens Wiklander 	return hash_sha256_check(hash, va, SMALL_PAGE_SIZE);
255ee546289SJens Wiklander }
256ee546289SJens Wiklander KEEP_PAGER(rop_load_page);
257ee546289SJens Wiklander 
258ee546289SJens Wiklander static TEE_Result rop_save_page(struct fobj *fobj __unused,
259ee546289SJens Wiklander 				unsigned int page_idx __unused,
260ee546289SJens Wiklander 				const void *va __unused)
261ee546289SJens Wiklander {
262ee546289SJens Wiklander 	return TEE_ERROR_GENERIC;
263ee546289SJens Wiklander }
264ee546289SJens Wiklander KEEP_PAGER(rop_save_page);
265ee546289SJens Wiklander 
266ee546289SJens Wiklander static struct fobj_ops ops_ro_paged __rodata_unpaged = {
267ee546289SJens Wiklander 	.free = rop_free,
268ee546289SJens Wiklander 	.load_page = rop_load_page,
269ee546289SJens Wiklander 	.save_page = rop_save_page,
270ee546289SJens Wiklander };
271ee546289SJens Wiklander 
272ee546289SJens Wiklander static struct fobj_ops ops_locked_paged;
273ee546289SJens Wiklander 
274ee546289SJens Wiklander struct fobj *fobj_locked_paged_alloc(unsigned int num_pages)
275ee546289SJens Wiklander {
276ee546289SJens Wiklander 	struct fobj *f = NULL;
277ee546289SJens Wiklander 
278ee546289SJens Wiklander 	assert(num_pages);
279ee546289SJens Wiklander 
280ee546289SJens Wiklander 	f = calloc(1, sizeof(*f));
281ee546289SJens Wiklander 	if (!f)
282ee546289SJens Wiklander 		return NULL;
283ee546289SJens Wiklander 
284ee546289SJens Wiklander 	fobj_init(f, &ops_locked_paged, num_pages);
285ee546289SJens Wiklander 
286ee546289SJens Wiklander 	return f;
287ee546289SJens Wiklander }
288ee546289SJens Wiklander 
289ee546289SJens Wiklander static void lop_free(struct fobj *fobj)
290ee546289SJens Wiklander {
291ee546289SJens Wiklander 	assert(fobj->ops == &ops_locked_paged);
292ee546289SJens Wiklander 	fobj_uninit(fobj);
293ee546289SJens Wiklander 	free(fobj);
294ee546289SJens Wiklander }
295ee546289SJens Wiklander 
296ee546289SJens Wiklander static TEE_Result lop_load_page(struct fobj *fobj __maybe_unused,
297ee546289SJens Wiklander 				unsigned int page_idx __maybe_unused,
298ee546289SJens Wiklander 				void *va)
299ee546289SJens Wiklander {
300ee546289SJens Wiklander 	assert(fobj->ops == &ops_locked_paged);
301ee546289SJens Wiklander 	assert(refcount_val(&fobj->refc));
302ee546289SJens Wiklander 	assert(page_idx < fobj->num_pages);
303ee546289SJens Wiklander 
304ee546289SJens Wiklander 	memset(va, 0, SMALL_PAGE_SIZE);
305ee546289SJens Wiklander 
306ee546289SJens Wiklander 	return TEE_SUCCESS;
307ee546289SJens Wiklander }
308ee546289SJens Wiklander KEEP_PAGER(lop_load_page);
309ee546289SJens Wiklander 
310ee546289SJens Wiklander static TEE_Result lop_save_page(struct fobj *fobj __unused,
311ee546289SJens Wiklander 				unsigned int page_idx __unused,
312ee546289SJens Wiklander 				const void *va __unused)
313ee546289SJens Wiklander {
314ee546289SJens Wiklander 	return TEE_ERROR_GENERIC;
315ee546289SJens Wiklander }
316ee546289SJens Wiklander KEEP_PAGER(lop_save_page);
317ee546289SJens Wiklander 
318ee546289SJens Wiklander static struct fobj_ops ops_locked_paged __rodata_unpaged = {
319ee546289SJens Wiklander 	.free = lop_free,
320ee546289SJens Wiklander 	.load_page = lop_load_page,
321ee546289SJens Wiklander 	.save_page = lop_save_page,
322ee546289SJens Wiklander };
323ee546289SJens Wiklander #endif /*CFG_WITH_PAGER*/
324fbcaa411SJens Wiklander 
325fbcaa411SJens Wiklander #ifndef CFG_PAGED_USER_TA
326fbcaa411SJens Wiklander 
327fbcaa411SJens Wiklander struct fobj_sec_mem {
328fbcaa411SJens Wiklander 	tee_mm_entry_t *mm;
329fbcaa411SJens Wiklander 	struct fobj fobj;
330fbcaa411SJens Wiklander };
331fbcaa411SJens Wiklander 
332fbcaa411SJens Wiklander static struct fobj_ops ops_sec_mem;
333fbcaa411SJens Wiklander 
334fbcaa411SJens Wiklander struct fobj *fobj_sec_mem_alloc(unsigned int num_pages)
335fbcaa411SJens Wiklander {
336fbcaa411SJens Wiklander 	struct fobj_sec_mem *f = calloc(1, sizeof(*f));
337fbcaa411SJens Wiklander 	size_t size = 0;
338fbcaa411SJens Wiklander 	void *va = NULL;
339fbcaa411SJens Wiklander 
340fbcaa411SJens Wiklander 	if (!f)
341fbcaa411SJens Wiklander 		return NULL;
342fbcaa411SJens Wiklander 
343fbcaa411SJens Wiklander 	if (MUL_OVERFLOW(num_pages, SMALL_PAGE_SIZE, &size))
344fbcaa411SJens Wiklander 		goto err;
345fbcaa411SJens Wiklander 
346fbcaa411SJens Wiklander 	f->mm = tee_mm_alloc(&tee_mm_sec_ddr, size);
347fbcaa411SJens Wiklander 	if (!f->mm)
348fbcaa411SJens Wiklander 		goto err;
349fbcaa411SJens Wiklander 
350fbcaa411SJens Wiklander 	va = phys_to_virt(tee_mm_get_smem(f->mm), MEM_AREA_TA_RAM);
351fbcaa411SJens Wiklander 	if (!va)
352fbcaa411SJens Wiklander 		goto err;
353fbcaa411SJens Wiklander 
354fbcaa411SJens Wiklander 	memset(va, 0, size);
355fbcaa411SJens Wiklander 	f->fobj.ops = &ops_sec_mem;
356fbcaa411SJens Wiklander 	f->fobj.num_pages = num_pages;
357fbcaa411SJens Wiklander 	refcount_set(&f->fobj.refc, 1);
358fbcaa411SJens Wiklander 
359fbcaa411SJens Wiklander 	return &f->fobj;
360fbcaa411SJens Wiklander err:
361fbcaa411SJens Wiklander 	tee_mm_free(f->mm);
362fbcaa411SJens Wiklander 	free(f);
363fbcaa411SJens Wiklander 
364fbcaa411SJens Wiklander 	return NULL;
365fbcaa411SJens Wiklander }
366fbcaa411SJens Wiklander 
367fbcaa411SJens Wiklander static struct fobj_sec_mem *to_sec_mem(struct fobj *fobj)
368fbcaa411SJens Wiklander {
369fbcaa411SJens Wiklander 	assert(fobj->ops == &ops_sec_mem);
370fbcaa411SJens Wiklander 
371fbcaa411SJens Wiklander 	return container_of(fobj, struct fobj_sec_mem, fobj);
372fbcaa411SJens Wiklander }
373fbcaa411SJens Wiklander 
374fbcaa411SJens Wiklander static void sec_mem_free(struct fobj *fobj)
375fbcaa411SJens Wiklander {
376fbcaa411SJens Wiklander 	struct fobj_sec_mem *f = to_sec_mem(fobj);
377fbcaa411SJens Wiklander 
378fbcaa411SJens Wiklander 	assert(!refcount_val(&fobj->refc));
379fbcaa411SJens Wiklander 	tee_mm_free(f->mm);
380fbcaa411SJens Wiklander 	free(f);
381fbcaa411SJens Wiklander }
382fbcaa411SJens Wiklander 
383fbcaa411SJens Wiklander static paddr_t sec_mem_get_pa(struct fobj *fobj, unsigned int page_idx)
384fbcaa411SJens Wiklander {
385fbcaa411SJens Wiklander 	struct fobj_sec_mem *f = to_sec_mem(fobj);
386fbcaa411SJens Wiklander 
387fbcaa411SJens Wiklander 	assert(refcount_val(&fobj->refc));
388fbcaa411SJens Wiklander 	assert(page_idx < fobj->num_pages);
389fbcaa411SJens Wiklander 
390fbcaa411SJens Wiklander 	return tee_mm_get_smem(f->mm) + page_idx * SMALL_PAGE_SIZE;
391fbcaa411SJens Wiklander }
392fbcaa411SJens Wiklander 
393fbcaa411SJens Wiklander static struct fobj_ops ops_sec_mem __rodata_unpaged = {
394fbcaa411SJens Wiklander 	.free = sec_mem_free,
395fbcaa411SJens Wiklander 	.get_pa = sec_mem_get_pa,
396fbcaa411SJens Wiklander };
397fbcaa411SJens Wiklander 
398fbcaa411SJens Wiklander #endif /*PAGED_USER_TA*/
399