xref: /optee_os/core/mm/mobj.c (revision 185b4595b97588a2eac575168daf128358397c14)
1*185b4595SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause
2*185b4595SMarouene Boubakri /*
3*185b4595SMarouene Boubakri  * Copyright (c) 2016-2017, Linaro Limited
4*185b4595SMarouene Boubakri  */
5*185b4595SMarouene Boubakri 
6*185b4595SMarouene Boubakri #include <assert.h>
7*185b4595SMarouene Boubakri #include <initcall.h>
8*185b4595SMarouene Boubakri #include <keep.h>
9*185b4595SMarouene Boubakri #include <kernel/linker.h>
10*185b4595SMarouene Boubakri #include <kernel/mutex.h>
11*185b4595SMarouene Boubakri #include <kernel/panic.h>
12*185b4595SMarouene Boubakri #include <kernel/refcount.h>
13*185b4595SMarouene Boubakri #include <kernel/spinlock.h>
14*185b4595SMarouene Boubakri #include <kernel/tee_misc.h>
15*185b4595SMarouene Boubakri #include <mm/core_mmu.h>
16*185b4595SMarouene Boubakri #include <mm/mobj.h>
17*185b4595SMarouene Boubakri #include <mm/tee_pager.h>
18*185b4595SMarouene Boubakri #include <mm/vm.h>
19*185b4595SMarouene Boubakri #include <optee_msg.h>
20*185b4595SMarouene Boubakri #include <sm/optee_smc.h>
21*185b4595SMarouene Boubakri #include <stdlib.h>
22*185b4595SMarouene Boubakri #include <tee_api_types.h>
23*185b4595SMarouene Boubakri #include <types_ext.h>
24*185b4595SMarouene Boubakri #include <util.h>
25*185b4595SMarouene Boubakri 
26*185b4595SMarouene Boubakri struct mobj *mobj_sec_ddr;
27*185b4595SMarouene Boubakri struct mobj *mobj_tee_ram;
28*185b4595SMarouene Boubakri 
29*185b4595SMarouene Boubakri /*
30*185b4595SMarouene Boubakri  * mobj_phys implementation
31*185b4595SMarouene Boubakri  */
32*185b4595SMarouene Boubakri 
33*185b4595SMarouene Boubakri struct mobj_phys {
34*185b4595SMarouene Boubakri 	struct mobj mobj;
35*185b4595SMarouene Boubakri 	enum buf_is_attr battr;
36*185b4595SMarouene Boubakri 	uint32_t cattr; /* Defined by TEE_MATTR_CACHE_* in tee_mmu_types.h */
37*185b4595SMarouene Boubakri 	vaddr_t va;
38*185b4595SMarouene Boubakri 	paddr_t pa;
39*185b4595SMarouene Boubakri };
40*185b4595SMarouene Boubakri 
41*185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj);
42*185b4595SMarouene Boubakri 
43*185b4595SMarouene Boubakri static void *mobj_phys_get_va(struct mobj *mobj, size_t offset)
44*185b4595SMarouene Boubakri {
45*185b4595SMarouene Boubakri 	struct mobj_phys *moph = to_mobj_phys(mobj);
46*185b4595SMarouene Boubakri 
47*185b4595SMarouene Boubakri 	if (!moph->va || offset >= mobj->size)
48*185b4595SMarouene Boubakri 		return NULL;
49*185b4595SMarouene Boubakri 
50*185b4595SMarouene Boubakri 	return (void *)(moph->va + offset);
51*185b4595SMarouene Boubakri }
52*185b4595SMarouene Boubakri 
53*185b4595SMarouene Boubakri static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs,
54*185b4595SMarouene Boubakri 				   size_t granule, paddr_t *pa)
55*185b4595SMarouene Boubakri {
56*185b4595SMarouene Boubakri 	struct mobj_phys *moph = to_mobj_phys(mobj);
57*185b4595SMarouene Boubakri 	paddr_t p;
58*185b4595SMarouene Boubakri 
59*185b4595SMarouene Boubakri 	if (!pa)
60*185b4595SMarouene Boubakri 		return TEE_ERROR_GENERIC;
61*185b4595SMarouene Boubakri 
62*185b4595SMarouene Boubakri 	p = moph->pa + offs;
63*185b4595SMarouene Boubakri 
64*185b4595SMarouene Boubakri 	if (granule) {
65*185b4595SMarouene Boubakri 		if (granule != SMALL_PAGE_SIZE &&
66*185b4595SMarouene Boubakri 		    granule != CORE_MMU_PGDIR_SIZE)
67*185b4595SMarouene Boubakri 			return TEE_ERROR_GENERIC;
68*185b4595SMarouene Boubakri 		p &= ~(granule - 1);
69*185b4595SMarouene Boubakri 	}
70*185b4595SMarouene Boubakri 
71*185b4595SMarouene Boubakri 	*pa = p;
72*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
73*185b4595SMarouene Boubakri }
74*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_phys_get_pa);
75*185b4595SMarouene Boubakri 
76*185b4595SMarouene Boubakri static TEE_Result mobj_phys_get_cattr(struct mobj *mobj, uint32_t *cattr)
77*185b4595SMarouene Boubakri {
78*185b4595SMarouene Boubakri 	struct mobj_phys *moph = to_mobj_phys(mobj);
79*185b4595SMarouene Boubakri 
80*185b4595SMarouene Boubakri 	if (!cattr)
81*185b4595SMarouene Boubakri 		return TEE_ERROR_GENERIC;
82*185b4595SMarouene Boubakri 
83*185b4595SMarouene Boubakri 	*cattr = moph->cattr;
84*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
85*185b4595SMarouene Boubakri }
86*185b4595SMarouene Boubakri 
87*185b4595SMarouene Boubakri static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr)
88*185b4595SMarouene Boubakri {
89*185b4595SMarouene Boubakri 	struct mobj_phys *moph = to_mobj_phys(mobj);
90*185b4595SMarouene Boubakri 	enum buf_is_attr a;
91*185b4595SMarouene Boubakri 
92*185b4595SMarouene Boubakri 	a = moph->battr;
93*185b4595SMarouene Boubakri 
94*185b4595SMarouene Boubakri 	switch (attr) {
95*185b4595SMarouene Boubakri 	case CORE_MEM_SEC:
96*185b4595SMarouene Boubakri 		return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM ||
97*185b4595SMarouene Boubakri 		       a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM;
98*185b4595SMarouene Boubakri 	case CORE_MEM_NON_SEC:
99*185b4595SMarouene Boubakri 		return a == CORE_MEM_NSEC_SHM;
100*185b4595SMarouene Boubakri 	case CORE_MEM_TEE_RAM:
101*185b4595SMarouene Boubakri 	case CORE_MEM_TA_RAM:
102*185b4595SMarouene Boubakri 	case CORE_MEM_NSEC_SHM:
103*185b4595SMarouene Boubakri 	case CORE_MEM_SDP_MEM:
104*185b4595SMarouene Boubakri 		return attr == a;
105*185b4595SMarouene Boubakri 	default:
106*185b4595SMarouene Boubakri 		return false;
107*185b4595SMarouene Boubakri 	}
108*185b4595SMarouene Boubakri }
109*185b4595SMarouene Boubakri 
110*185b4595SMarouene Boubakri static void mobj_phys_free(struct mobj *mobj)
111*185b4595SMarouene Boubakri {
112*185b4595SMarouene Boubakri 	struct mobj_phys *moph = to_mobj_phys(mobj);
113*185b4595SMarouene Boubakri 
114*185b4595SMarouene Boubakri 	free(moph);
115*185b4595SMarouene Boubakri }
116*185b4595SMarouene Boubakri 
117*185b4595SMarouene Boubakri static const struct mobj_ops mobj_phys_ops __rodata_unpaged = {
118*185b4595SMarouene Boubakri 	.get_va = mobj_phys_get_va,
119*185b4595SMarouene Boubakri 	.get_pa = mobj_phys_get_pa,
120*185b4595SMarouene Boubakri 	.get_phys_offs = NULL, /* only offset 0 */
121*185b4595SMarouene Boubakri 	.get_cattr = mobj_phys_get_cattr,
122*185b4595SMarouene Boubakri 	.matches = mobj_phys_matches,
123*185b4595SMarouene Boubakri 	.free = mobj_phys_free,
124*185b4595SMarouene Boubakri };
125*185b4595SMarouene Boubakri 
126*185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj)
127*185b4595SMarouene Boubakri {
128*185b4595SMarouene Boubakri 	assert(mobj->ops == &mobj_phys_ops);
129*185b4595SMarouene Boubakri 	return container_of(mobj, struct mobj_phys, mobj);
130*185b4595SMarouene Boubakri }
131*185b4595SMarouene Boubakri 
132*185b4595SMarouene Boubakri struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
133*185b4595SMarouene Boubakri 			     enum buf_is_attr battr)
134*185b4595SMarouene Boubakri {
135*185b4595SMarouene Boubakri 	struct mobj_phys *moph;
136*185b4595SMarouene Boubakri 	enum teecore_memtypes area_type;
137*185b4595SMarouene Boubakri 	void *va;
138*185b4595SMarouene Boubakri 
139*185b4595SMarouene Boubakri 	if ((pa & CORE_MMU_USER_PARAM_MASK) ||
140*185b4595SMarouene Boubakri 	    (size & CORE_MMU_USER_PARAM_MASK)) {
141*185b4595SMarouene Boubakri 		DMSG("Expect %#x alignment", CORE_MMU_USER_PARAM_SIZE);
142*185b4595SMarouene Boubakri 		return NULL;
143*185b4595SMarouene Boubakri 	}
144*185b4595SMarouene Boubakri 
145*185b4595SMarouene Boubakri 	switch (battr) {
146*185b4595SMarouene Boubakri 	case CORE_MEM_TEE_RAM:
147*185b4595SMarouene Boubakri 		area_type = MEM_AREA_TEE_RAM_RW_DATA;
148*185b4595SMarouene Boubakri 		break;
149*185b4595SMarouene Boubakri 	case CORE_MEM_TA_RAM:
150*185b4595SMarouene Boubakri 		area_type = MEM_AREA_TA_RAM;
151*185b4595SMarouene Boubakri 		break;
152*185b4595SMarouene Boubakri 	case CORE_MEM_NSEC_SHM:
153*185b4595SMarouene Boubakri 		area_type = MEM_AREA_NSEC_SHM;
154*185b4595SMarouene Boubakri 		break;
155*185b4595SMarouene Boubakri 	case CORE_MEM_SDP_MEM:
156*185b4595SMarouene Boubakri 		area_type = MEM_AREA_SDP_MEM;
157*185b4595SMarouene Boubakri 		break;
158*185b4595SMarouene Boubakri 	default:
159*185b4595SMarouene Boubakri 		DMSG("can't allocate with specified attribute");
160*185b4595SMarouene Boubakri 		return NULL;
161*185b4595SMarouene Boubakri 	}
162*185b4595SMarouene Boubakri 
163*185b4595SMarouene Boubakri 	/* Only SDP memory may not have a virtual address */
164*185b4595SMarouene Boubakri 	va = phys_to_virt(pa, area_type);
165*185b4595SMarouene Boubakri 	if (!va && battr != CORE_MEM_SDP_MEM)
166*185b4595SMarouene Boubakri 		return NULL;
167*185b4595SMarouene Boubakri 
168*185b4595SMarouene Boubakri 	moph = calloc(1, sizeof(*moph));
169*185b4595SMarouene Boubakri 	if (!moph)
170*185b4595SMarouene Boubakri 		return NULL;
171*185b4595SMarouene Boubakri 
172*185b4595SMarouene Boubakri 	moph->battr = battr;
173*185b4595SMarouene Boubakri 	moph->cattr = cattr;
174*185b4595SMarouene Boubakri 	moph->mobj.size = size;
175*185b4595SMarouene Boubakri 	moph->mobj.ops = &mobj_phys_ops;
176*185b4595SMarouene Boubakri 	refcount_set(&moph->mobj.refc, 1);
177*185b4595SMarouene Boubakri 	moph->pa = pa;
178*185b4595SMarouene Boubakri 	moph->va = (vaddr_t)va;
179*185b4595SMarouene Boubakri 
180*185b4595SMarouene Boubakri 	return &moph->mobj;
181*185b4595SMarouene Boubakri }
182*185b4595SMarouene Boubakri 
183*185b4595SMarouene Boubakri /*
184*185b4595SMarouene Boubakri  * mobj_virt implementation
185*185b4595SMarouene Boubakri  */
186*185b4595SMarouene Boubakri 
187*185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj);
188*185b4595SMarouene Boubakri 
189*185b4595SMarouene Boubakri static void *mobj_virt_get_va(struct mobj *mobj, size_t offset)
190*185b4595SMarouene Boubakri {
191*185b4595SMarouene Boubakri 	mobj_virt_assert_type(mobj);
192*185b4595SMarouene Boubakri 
193*185b4595SMarouene Boubakri 	return (void *)(vaddr_t)offset;
194*185b4595SMarouene Boubakri }
195*185b4595SMarouene Boubakri 
196*185b4595SMarouene Boubakri static const struct mobj_ops mobj_virt_ops __rodata_unpaged = {
197*185b4595SMarouene Boubakri 	.get_va = mobj_virt_get_va,
198*185b4595SMarouene Boubakri };
199*185b4595SMarouene Boubakri 
200*185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj __maybe_unused)
201*185b4595SMarouene Boubakri {
202*185b4595SMarouene Boubakri 	assert(mobj->ops == &mobj_virt_ops);
203*185b4595SMarouene Boubakri }
204*185b4595SMarouene Boubakri 
205*185b4595SMarouene Boubakri struct mobj mobj_virt = { .ops = &mobj_virt_ops, .size = SIZE_MAX };
206*185b4595SMarouene Boubakri 
207*185b4595SMarouene Boubakri /*
208*185b4595SMarouene Boubakri  * mobj_mm implementation
209*185b4595SMarouene Boubakri  */
210*185b4595SMarouene Boubakri 
211*185b4595SMarouene Boubakri struct mobj_mm {
212*185b4595SMarouene Boubakri 	tee_mm_entry_t *mm;
213*185b4595SMarouene Boubakri 	struct mobj *parent_mobj;
214*185b4595SMarouene Boubakri 	struct mobj mobj;
215*185b4595SMarouene Boubakri };
216*185b4595SMarouene Boubakri 
217*185b4595SMarouene Boubakri static struct mobj_mm *to_mobj_mm(struct mobj *mobj);
218*185b4595SMarouene Boubakri 
219*185b4595SMarouene Boubakri static size_t mobj_mm_offs(struct mobj *mobj, size_t offs)
220*185b4595SMarouene Boubakri {
221*185b4595SMarouene Boubakri 	tee_mm_entry_t *mm = to_mobj_mm(mobj)->mm;
222*185b4595SMarouene Boubakri 
223*185b4595SMarouene Boubakri 	return (mm->offset << mm->pool->shift) + offs;
224*185b4595SMarouene Boubakri }
225*185b4595SMarouene Boubakri 
226*185b4595SMarouene Boubakri static void *mobj_mm_get_va(struct mobj *mobj, size_t offs)
227*185b4595SMarouene Boubakri {
228*185b4595SMarouene Boubakri 	return mobj_get_va(to_mobj_mm(mobj)->parent_mobj,
229*185b4595SMarouene Boubakri 			   mobj_mm_offs(mobj, offs));
230*185b4595SMarouene Boubakri }
231*185b4595SMarouene Boubakri 
232*185b4595SMarouene Boubakri 
233*185b4595SMarouene Boubakri static TEE_Result mobj_mm_get_pa(struct mobj *mobj, size_t offs,
234*185b4595SMarouene Boubakri 				    size_t granule, paddr_t *pa)
235*185b4595SMarouene Boubakri {
236*185b4595SMarouene Boubakri 	return mobj_get_pa(to_mobj_mm(mobj)->parent_mobj,
237*185b4595SMarouene Boubakri 			   mobj_mm_offs(mobj, offs), granule, pa);
238*185b4595SMarouene Boubakri }
239*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_mm_get_pa);
240*185b4595SMarouene Boubakri 
241*185b4595SMarouene Boubakri static size_t mobj_mm_get_phys_offs(struct mobj *mobj, size_t granule)
242*185b4595SMarouene Boubakri {
243*185b4595SMarouene Boubakri 	return mobj_get_phys_offs(to_mobj_mm(mobj)->parent_mobj, granule);
244*185b4595SMarouene Boubakri }
245*185b4595SMarouene Boubakri 
246*185b4595SMarouene Boubakri static TEE_Result mobj_mm_get_cattr(struct mobj *mobj, uint32_t *cattr)
247*185b4595SMarouene Boubakri {
248*185b4595SMarouene Boubakri 	return mobj_get_cattr(to_mobj_mm(mobj)->parent_mobj, cattr);
249*185b4595SMarouene Boubakri }
250*185b4595SMarouene Boubakri 
251*185b4595SMarouene Boubakri static bool mobj_mm_matches(struct mobj *mobj, enum buf_is_attr attr)
252*185b4595SMarouene Boubakri {
253*185b4595SMarouene Boubakri 	return mobj_matches(to_mobj_mm(mobj)->parent_mobj, attr);
254*185b4595SMarouene Boubakri }
255*185b4595SMarouene Boubakri 
256*185b4595SMarouene Boubakri static void mobj_mm_free(struct mobj *mobj)
257*185b4595SMarouene Boubakri {
258*185b4595SMarouene Boubakri 	struct mobj_mm *m = to_mobj_mm(mobj);
259*185b4595SMarouene Boubakri 
260*185b4595SMarouene Boubakri 	tee_mm_free(m->mm);
261*185b4595SMarouene Boubakri 	free(m);
262*185b4595SMarouene Boubakri }
263*185b4595SMarouene Boubakri 
264*185b4595SMarouene Boubakri static const struct mobj_ops mobj_mm_ops __rodata_unpaged = {
265*185b4595SMarouene Boubakri 	.get_va = mobj_mm_get_va,
266*185b4595SMarouene Boubakri 	.get_pa = mobj_mm_get_pa,
267*185b4595SMarouene Boubakri 	.get_phys_offs = mobj_mm_get_phys_offs,
268*185b4595SMarouene Boubakri 	.get_cattr = mobj_mm_get_cattr,
269*185b4595SMarouene Boubakri 	.matches = mobj_mm_matches,
270*185b4595SMarouene Boubakri 	.free = mobj_mm_free,
271*185b4595SMarouene Boubakri };
272*185b4595SMarouene Boubakri 
273*185b4595SMarouene Boubakri static struct mobj_mm *to_mobj_mm(struct mobj *mobj)
274*185b4595SMarouene Boubakri {
275*185b4595SMarouene Boubakri 	assert(mobj->ops == &mobj_mm_ops);
276*185b4595SMarouene Boubakri 	return container_of(mobj, struct mobj_mm, mobj);
277*185b4595SMarouene Boubakri }
278*185b4595SMarouene Boubakri 
279*185b4595SMarouene Boubakri struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size,
280*185b4595SMarouene Boubakri 			      tee_mm_pool_t *pool)
281*185b4595SMarouene Boubakri {
282*185b4595SMarouene Boubakri 	struct mobj_mm *m = calloc(1, sizeof(*m));
283*185b4595SMarouene Boubakri 
284*185b4595SMarouene Boubakri 	if (!m)
285*185b4595SMarouene Boubakri 		return NULL;
286*185b4595SMarouene Boubakri 
287*185b4595SMarouene Boubakri 	m->mm = tee_mm_alloc(pool, size);
288*185b4595SMarouene Boubakri 	if (!m->mm) {
289*185b4595SMarouene Boubakri 		free(m);
290*185b4595SMarouene Boubakri 		return NULL;
291*185b4595SMarouene Boubakri 	}
292*185b4595SMarouene Boubakri 
293*185b4595SMarouene Boubakri 	m->parent_mobj = mobj_parent;
294*185b4595SMarouene Boubakri 	m->mobj.size = size;
295*185b4595SMarouene Boubakri 	m->mobj.ops = &mobj_mm_ops;
296*185b4595SMarouene Boubakri 	refcount_set(&m->mobj.refc, 1);
297*185b4595SMarouene Boubakri 
298*185b4595SMarouene Boubakri 	return &m->mobj;
299*185b4595SMarouene Boubakri }
300*185b4595SMarouene Boubakri 
301*185b4595SMarouene Boubakri 
302*185b4595SMarouene Boubakri /*
303*185b4595SMarouene Boubakri  * mobj_shm implementation. mobj_shm represents buffer in predefined shm region
304*185b4595SMarouene Boubakri  * - it is physically contiguous.
305*185b4595SMarouene Boubakri  * - it is identified in static physical layout as MEM_AREA_NSEC_SHM.
306*185b4595SMarouene Boubakri  * - it creates mobjs that match specific CORE_MEM_NSEC_SHM and non secure
307*185b4595SMarouene Boubakri  *   generic CORE_MEM_NON_SEC.
308*185b4595SMarouene Boubakri  */
309*185b4595SMarouene Boubakri 
310*185b4595SMarouene Boubakri struct mobj_shm {
311*185b4595SMarouene Boubakri 	struct mobj mobj;
312*185b4595SMarouene Boubakri 	paddr_t pa;
313*185b4595SMarouene Boubakri 	uint64_t cookie;
314*185b4595SMarouene Boubakri };
315*185b4595SMarouene Boubakri 
316*185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj);
317*185b4595SMarouene Boubakri 
318*185b4595SMarouene Boubakri static void *mobj_shm_get_va(struct mobj *mobj, size_t offset)
319*185b4595SMarouene Boubakri {
320*185b4595SMarouene Boubakri 	struct mobj_shm *m = to_mobj_shm(mobj);
321*185b4595SMarouene Boubakri 
322*185b4595SMarouene Boubakri 	if (offset >= mobj->size)
323*185b4595SMarouene Boubakri 		return NULL;
324*185b4595SMarouene Boubakri 
325*185b4595SMarouene Boubakri 	return phys_to_virt(m->pa + offset, MEM_AREA_NSEC_SHM);
326*185b4595SMarouene Boubakri }
327*185b4595SMarouene Boubakri 
328*185b4595SMarouene Boubakri static TEE_Result mobj_shm_get_pa(struct mobj *mobj, size_t offs,
329*185b4595SMarouene Boubakri 				   size_t granule, paddr_t *pa)
330*185b4595SMarouene Boubakri {
331*185b4595SMarouene Boubakri 	struct mobj_shm *m = to_mobj_shm(mobj);
332*185b4595SMarouene Boubakri 	paddr_t p;
333*185b4595SMarouene Boubakri 
334*185b4595SMarouene Boubakri 	if (!pa || offs >= mobj->size)
335*185b4595SMarouene Boubakri 		return TEE_ERROR_GENERIC;
336*185b4595SMarouene Boubakri 
337*185b4595SMarouene Boubakri 	p = m->pa + offs;
338*185b4595SMarouene Boubakri 
339*185b4595SMarouene Boubakri 	if (granule) {
340*185b4595SMarouene Boubakri 		if (granule != SMALL_PAGE_SIZE &&
341*185b4595SMarouene Boubakri 		    granule != CORE_MMU_PGDIR_SIZE)
342*185b4595SMarouene Boubakri 			return TEE_ERROR_GENERIC;
343*185b4595SMarouene Boubakri 		p &= ~(granule - 1);
344*185b4595SMarouene Boubakri 	}
345*185b4595SMarouene Boubakri 
346*185b4595SMarouene Boubakri 	*pa = p;
347*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
348*185b4595SMarouene Boubakri }
349*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_shm_get_pa);
350*185b4595SMarouene Boubakri 
351*185b4595SMarouene Boubakri static size_t mobj_shm_get_phys_offs(struct mobj *mobj, size_t granule)
352*185b4595SMarouene Boubakri {
353*185b4595SMarouene Boubakri 	assert(IS_POWER_OF_TWO(granule));
354*185b4595SMarouene Boubakri 	return to_mobj_shm(mobj)->pa & (granule - 1);
355*185b4595SMarouene Boubakri }
356*185b4595SMarouene Boubakri 
357*185b4595SMarouene Boubakri static bool mobj_shm_matches(struct mobj *mobj __unused, enum buf_is_attr attr)
358*185b4595SMarouene Boubakri {
359*185b4595SMarouene Boubakri 	return attr == CORE_MEM_NSEC_SHM || attr == CORE_MEM_NON_SEC;
360*185b4595SMarouene Boubakri }
361*185b4595SMarouene Boubakri 
362*185b4595SMarouene Boubakri static void mobj_shm_free(struct mobj *mobj)
363*185b4595SMarouene Boubakri {
364*185b4595SMarouene Boubakri 	struct mobj_shm *m = to_mobj_shm(mobj);
365*185b4595SMarouene Boubakri 
366*185b4595SMarouene Boubakri 	free(m);
367*185b4595SMarouene Boubakri }
368*185b4595SMarouene Boubakri 
369*185b4595SMarouene Boubakri static uint64_t mobj_shm_get_cookie(struct mobj *mobj)
370*185b4595SMarouene Boubakri {
371*185b4595SMarouene Boubakri 	return to_mobj_shm(mobj)->cookie;
372*185b4595SMarouene Boubakri }
373*185b4595SMarouene Boubakri 
374*185b4595SMarouene Boubakri static const struct mobj_ops mobj_shm_ops __rodata_unpaged = {
375*185b4595SMarouene Boubakri 	.get_va = mobj_shm_get_va,
376*185b4595SMarouene Boubakri 	.get_pa = mobj_shm_get_pa,
377*185b4595SMarouene Boubakri 	.get_phys_offs = mobj_shm_get_phys_offs,
378*185b4595SMarouene Boubakri 	.matches = mobj_shm_matches,
379*185b4595SMarouene Boubakri 	.free = mobj_shm_free,
380*185b4595SMarouene Boubakri 	.get_cookie = mobj_shm_get_cookie,
381*185b4595SMarouene Boubakri };
382*185b4595SMarouene Boubakri 
383*185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj)
384*185b4595SMarouene Boubakri {
385*185b4595SMarouene Boubakri 	assert(mobj->ops == &mobj_shm_ops);
386*185b4595SMarouene Boubakri 	return container_of(mobj, struct mobj_shm, mobj);
387*185b4595SMarouene Boubakri }
388*185b4595SMarouene Boubakri 
389*185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie)
390*185b4595SMarouene Boubakri {
391*185b4595SMarouene Boubakri 	struct mobj_shm *m;
392*185b4595SMarouene Boubakri 
393*185b4595SMarouene Boubakri 	if (!core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size))
394*185b4595SMarouene Boubakri 		return NULL;
395*185b4595SMarouene Boubakri 
396*185b4595SMarouene Boubakri 	m = calloc(1, sizeof(*m));
397*185b4595SMarouene Boubakri 	if (!m)
398*185b4595SMarouene Boubakri 		return NULL;
399*185b4595SMarouene Boubakri 
400*185b4595SMarouene Boubakri 	m->mobj.size = size;
401*185b4595SMarouene Boubakri 	m->mobj.ops = &mobj_shm_ops;
402*185b4595SMarouene Boubakri 	refcount_set(&m->mobj.refc, 1);
403*185b4595SMarouene Boubakri 	m->pa = pa;
404*185b4595SMarouene Boubakri 	m->cookie = cookie;
405*185b4595SMarouene Boubakri 
406*185b4595SMarouene Boubakri 	return &m->mobj;
407*185b4595SMarouene Boubakri }
408*185b4595SMarouene Boubakri 
409*185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA
410*185b4595SMarouene Boubakri /*
411*185b4595SMarouene Boubakri  * mobj_seccpy_shm implementation
412*185b4595SMarouene Boubakri  */
413*185b4595SMarouene Boubakri 
414*185b4595SMarouene Boubakri struct mobj_seccpy_shm {
415*185b4595SMarouene Boubakri 	struct user_ta_ctx *utc;
416*185b4595SMarouene Boubakri 	vaddr_t va;
417*185b4595SMarouene Boubakri 	struct mobj mobj;
418*185b4595SMarouene Boubakri 	struct fobj *fobj;
419*185b4595SMarouene Boubakri };
420*185b4595SMarouene Boubakri 
421*185b4595SMarouene Boubakri static bool __maybe_unused mobj_is_seccpy_shm(struct mobj *mobj);
422*185b4595SMarouene Boubakri 
423*185b4595SMarouene Boubakri static struct mobj_seccpy_shm *to_mobj_seccpy_shm(struct mobj *mobj)
424*185b4595SMarouene Boubakri {
425*185b4595SMarouene Boubakri 	assert(mobj_is_seccpy_shm(mobj));
426*185b4595SMarouene Boubakri 	return container_of(mobj, struct mobj_seccpy_shm, mobj);
427*185b4595SMarouene Boubakri }
428*185b4595SMarouene Boubakri 
429*185b4595SMarouene Boubakri static void *mobj_seccpy_shm_get_va(struct mobj *mobj, size_t offs)
430*185b4595SMarouene Boubakri {
431*185b4595SMarouene Boubakri 	struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj);
432*185b4595SMarouene Boubakri 
433*185b4595SMarouene Boubakri 	if (&m->utc->ta_ctx.ts_ctx != thread_get_tsd()->ctx)
434*185b4595SMarouene Boubakri 		return NULL;
435*185b4595SMarouene Boubakri 
436*185b4595SMarouene Boubakri 	if (offs >= mobj->size)
437*185b4595SMarouene Boubakri 		return NULL;
438*185b4595SMarouene Boubakri 	return (void *)(m->va + offs);
439*185b4595SMarouene Boubakri }
440*185b4595SMarouene Boubakri 
441*185b4595SMarouene Boubakri static bool mobj_seccpy_shm_matches(struct mobj *mobj __maybe_unused,
442*185b4595SMarouene Boubakri 				 enum buf_is_attr attr)
443*185b4595SMarouene Boubakri {
444*185b4595SMarouene Boubakri 	assert(mobj_is_seccpy_shm(mobj));
445*185b4595SMarouene Boubakri 
446*185b4595SMarouene Boubakri 	return attr == CORE_MEM_SEC || attr == CORE_MEM_TEE_RAM;
447*185b4595SMarouene Boubakri }
448*185b4595SMarouene Boubakri 
449*185b4595SMarouene Boubakri static void mobj_seccpy_shm_free(struct mobj *mobj)
450*185b4595SMarouene Boubakri {
451*185b4595SMarouene Boubakri 	struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj);
452*185b4595SMarouene Boubakri 
453*185b4595SMarouene Boubakri 	tee_pager_rem_um_region(&m->utc->uctx, m->va, mobj->size);
454*185b4595SMarouene Boubakri 	vm_rem_rwmem(&m->utc->uctx, mobj, m->va);
455*185b4595SMarouene Boubakri 	fobj_put(m->fobj);
456*185b4595SMarouene Boubakri 	free(m);
457*185b4595SMarouene Boubakri }
458*185b4595SMarouene Boubakri 
459*185b4595SMarouene Boubakri static struct fobj *mobj_seccpy_shm_get_fobj(struct mobj *mobj)
460*185b4595SMarouene Boubakri {
461*185b4595SMarouene Boubakri 	return fobj_get(to_mobj_seccpy_shm(mobj)->fobj);
462*185b4595SMarouene Boubakri }
463*185b4595SMarouene Boubakri 
464*185b4595SMarouene Boubakri static const struct mobj_ops mobj_seccpy_shm_ops __rodata_unpaged = {
465*185b4595SMarouene Boubakri 	.get_va = mobj_seccpy_shm_get_va,
466*185b4595SMarouene Boubakri 	.matches = mobj_seccpy_shm_matches,
467*185b4595SMarouene Boubakri 	.free = mobj_seccpy_shm_free,
468*185b4595SMarouene Boubakri 	.get_fobj = mobj_seccpy_shm_get_fobj,
469*185b4595SMarouene Boubakri };
470*185b4595SMarouene Boubakri 
471*185b4595SMarouene Boubakri static bool mobj_is_seccpy_shm(struct mobj *mobj)
472*185b4595SMarouene Boubakri {
473*185b4595SMarouene Boubakri 	return mobj && mobj->ops == &mobj_seccpy_shm_ops;
474*185b4595SMarouene Boubakri }
475*185b4595SMarouene Boubakri 
476*185b4595SMarouene Boubakri struct mobj *mobj_seccpy_shm_alloc(size_t size)
477*185b4595SMarouene Boubakri {
478*185b4595SMarouene Boubakri 	struct thread_specific_data *tsd = thread_get_tsd();
479*185b4595SMarouene Boubakri 	struct mobj_seccpy_shm *m;
480*185b4595SMarouene Boubakri 	struct user_ta_ctx *utc;
481*185b4595SMarouene Boubakri 	vaddr_t va = 0;
482*185b4595SMarouene Boubakri 
483*185b4595SMarouene Boubakri 	if (!is_user_ta_ctx(tsd->ctx))
484*185b4595SMarouene Boubakri 		return NULL;
485*185b4595SMarouene Boubakri 	utc = to_user_ta_ctx(tsd->ctx);
486*185b4595SMarouene Boubakri 
487*185b4595SMarouene Boubakri 	m = calloc(1, sizeof(*m));
488*185b4595SMarouene Boubakri 	if (!m)
489*185b4595SMarouene Boubakri 		return NULL;
490*185b4595SMarouene Boubakri 
491*185b4595SMarouene Boubakri 	m->mobj.size = size;
492*185b4595SMarouene Boubakri 	m->mobj.ops = &mobj_seccpy_shm_ops;
493*185b4595SMarouene Boubakri 	refcount_set(&m->mobj.refc, 1);
494*185b4595SMarouene Boubakri 
495*185b4595SMarouene Boubakri 	if (vm_add_rwmem(&utc->uctx, &m->mobj, &va) != TEE_SUCCESS)
496*185b4595SMarouene Boubakri 		goto bad;
497*185b4595SMarouene Boubakri 
498*185b4595SMarouene Boubakri 	m->fobj = fobj_rw_paged_alloc(ROUNDUP(size, SMALL_PAGE_SIZE) /
499*185b4595SMarouene Boubakri 				      SMALL_PAGE_SIZE);
500*185b4595SMarouene Boubakri 	if (tee_pager_add_um_area(&utc->uctx, va, m->fobj,
501*185b4595SMarouene Boubakri 				  TEE_MATTR_PRW | TEE_MATTR_URW))
502*185b4595SMarouene Boubakri 		goto bad;
503*185b4595SMarouene Boubakri 
504*185b4595SMarouene Boubakri 	m->va = va;
505*185b4595SMarouene Boubakri 	m->utc = to_user_ta_ctx(tsd->ctx);
506*185b4595SMarouene Boubakri 	return &m->mobj;
507*185b4595SMarouene Boubakri bad:
508*185b4595SMarouene Boubakri 	if (va)
509*185b4595SMarouene Boubakri 		vm_rem_rwmem(&utc->uctx, &m->mobj, va);
510*185b4595SMarouene Boubakri 	fobj_put(m->fobj);
511*185b4595SMarouene Boubakri 	free(m);
512*185b4595SMarouene Boubakri 	return NULL;
513*185b4595SMarouene Boubakri }
514*185b4595SMarouene Boubakri 
515*185b4595SMarouene Boubakri 
516*185b4595SMarouene Boubakri #endif /*CFG_PAGED_USER_TA*/
517*185b4595SMarouene Boubakri 
518*185b4595SMarouene Boubakri struct mobj_with_fobj {
519*185b4595SMarouene Boubakri 	struct fobj *fobj;
520*185b4595SMarouene Boubakri 	struct file *file;
521*185b4595SMarouene Boubakri 	struct mobj mobj;
522*185b4595SMarouene Boubakri };
523*185b4595SMarouene Boubakri 
524*185b4595SMarouene Boubakri static const struct mobj_ops mobj_with_fobj_ops;
525*185b4595SMarouene Boubakri 
526*185b4595SMarouene Boubakri struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file)
527*185b4595SMarouene Boubakri {
528*185b4595SMarouene Boubakri 	struct mobj_with_fobj *m = NULL;
529*185b4595SMarouene Boubakri 
530*185b4595SMarouene Boubakri 	if (!fobj)
531*185b4595SMarouene Boubakri 		return NULL;
532*185b4595SMarouene Boubakri 
533*185b4595SMarouene Boubakri 	m = calloc(1, sizeof(*m));
534*185b4595SMarouene Boubakri 	if (!m)
535*185b4595SMarouene Boubakri 		return NULL;
536*185b4595SMarouene Boubakri 
537*185b4595SMarouene Boubakri 	m->mobj.ops = &mobj_with_fobj_ops;
538*185b4595SMarouene Boubakri 	refcount_set(&m->mobj.refc, 1);
539*185b4595SMarouene Boubakri 	m->mobj.size = fobj->num_pages * SMALL_PAGE_SIZE;
540*185b4595SMarouene Boubakri 	m->mobj.phys_granule = SMALL_PAGE_SIZE;
541*185b4595SMarouene Boubakri 	m->fobj = fobj_get(fobj);
542*185b4595SMarouene Boubakri 	m->file = file_get(file);
543*185b4595SMarouene Boubakri 
544*185b4595SMarouene Boubakri 	return &m->mobj;
545*185b4595SMarouene Boubakri }
546*185b4595SMarouene Boubakri 
547*185b4595SMarouene Boubakri static struct mobj_with_fobj *to_mobj_with_fobj(struct mobj *mobj)
548*185b4595SMarouene Boubakri {
549*185b4595SMarouene Boubakri 	assert(mobj && mobj->ops == &mobj_with_fobj_ops);
550*185b4595SMarouene Boubakri 
551*185b4595SMarouene Boubakri 	return container_of(mobj, struct mobj_with_fobj, mobj);
552*185b4595SMarouene Boubakri }
553*185b4595SMarouene Boubakri 
554*185b4595SMarouene Boubakri static bool mobj_with_fobj_matches(struct mobj *mobj __maybe_unused,
555*185b4595SMarouene Boubakri 				 enum buf_is_attr attr)
556*185b4595SMarouene Boubakri {
557*185b4595SMarouene Boubakri 	assert(to_mobj_with_fobj(mobj));
558*185b4595SMarouene Boubakri 
559*185b4595SMarouene Boubakri 	/*
560*185b4595SMarouene Boubakri 	 * All fobjs are supposed to be mapped secure so classify it as
561*185b4595SMarouene Boubakri 	 * CORE_MEM_SEC. Stay out of CORE_MEM_TEE_RAM etc, if that information
562*185b4595SMarouene Boubakri 	 * needed it can probably be carried in another way than to put the
563*185b4595SMarouene Boubakri 	 * burden directly on fobj.
564*185b4595SMarouene Boubakri 	 */
565*185b4595SMarouene Boubakri 	return attr == CORE_MEM_SEC;
566*185b4595SMarouene Boubakri }
567*185b4595SMarouene Boubakri 
568*185b4595SMarouene Boubakri static void mobj_with_fobj_free(struct mobj *mobj)
569*185b4595SMarouene Boubakri {
570*185b4595SMarouene Boubakri 	struct mobj_with_fobj *m = to_mobj_with_fobj(mobj);
571*185b4595SMarouene Boubakri 
572*185b4595SMarouene Boubakri 	fobj_put(m->fobj);
573*185b4595SMarouene Boubakri 	file_put(m->file);
574*185b4595SMarouene Boubakri 	free(m);
575*185b4595SMarouene Boubakri }
576*185b4595SMarouene Boubakri 
577*185b4595SMarouene Boubakri static struct fobj *mobj_with_fobj_get_fobj(struct mobj *mobj)
578*185b4595SMarouene Boubakri {
579*185b4595SMarouene Boubakri 	return fobj_get(to_mobj_with_fobj(mobj)->fobj);
580*185b4595SMarouene Boubakri }
581*185b4595SMarouene Boubakri 
582*185b4595SMarouene Boubakri static TEE_Result mobj_with_fobj_get_cattr(struct mobj *mobj __unused,
583*185b4595SMarouene Boubakri 					   uint32_t *cattr)
584*185b4595SMarouene Boubakri {
585*185b4595SMarouene Boubakri 	if (!cattr)
586*185b4595SMarouene Boubakri 		return TEE_ERROR_GENERIC;
587*185b4595SMarouene Boubakri 
588*185b4595SMarouene Boubakri 	/* All fobjs are mapped as normal cached memory */
589*185b4595SMarouene Boubakri 	*cattr = TEE_MATTR_CACHE_CACHED;
590*185b4595SMarouene Boubakri 
591*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
592*185b4595SMarouene Boubakri }
593*185b4595SMarouene Boubakri 
594*185b4595SMarouene Boubakri static TEE_Result mobj_with_fobj_get_pa(struct mobj *mobj, size_t offs,
595*185b4595SMarouene Boubakri 					size_t granule, paddr_t *pa)
596*185b4595SMarouene Boubakri {
597*185b4595SMarouene Boubakri 	struct mobj_with_fobj *f = to_mobj_with_fobj(mobj);
598*185b4595SMarouene Boubakri 	paddr_t p = 0;
599*185b4595SMarouene Boubakri 
600*185b4595SMarouene Boubakri 	if (!f->fobj->ops->get_pa) {
601*185b4595SMarouene Boubakri 		assert(mobj_is_paged(mobj));
602*185b4595SMarouene Boubakri 		return TEE_ERROR_NOT_SUPPORTED;
603*185b4595SMarouene Boubakri 	}
604*185b4595SMarouene Boubakri 
605*185b4595SMarouene Boubakri 	p = f->fobj->ops->get_pa(f->fobj, offs / SMALL_PAGE_SIZE) +
606*185b4595SMarouene Boubakri 	    offs % SMALL_PAGE_SIZE;
607*185b4595SMarouene Boubakri 
608*185b4595SMarouene Boubakri 	if (granule) {
609*185b4595SMarouene Boubakri 		if (granule != SMALL_PAGE_SIZE &&
610*185b4595SMarouene Boubakri 		    granule != CORE_MMU_PGDIR_SIZE)
611*185b4595SMarouene Boubakri 			return TEE_ERROR_GENERIC;
612*185b4595SMarouene Boubakri 		p &= ~(granule - 1);
613*185b4595SMarouene Boubakri 	}
614*185b4595SMarouene Boubakri 
615*185b4595SMarouene Boubakri 	*pa = p;
616*185b4595SMarouene Boubakri 
617*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
618*185b4595SMarouene Boubakri }
619*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_with_fobj_get_pa);
620*185b4595SMarouene Boubakri 
621*185b4595SMarouene Boubakri static const struct mobj_ops mobj_with_fobj_ops __rodata_unpaged = {
622*185b4595SMarouene Boubakri 	.matches = mobj_with_fobj_matches,
623*185b4595SMarouene Boubakri 	.free = mobj_with_fobj_free,
624*185b4595SMarouene Boubakri 	.get_fobj = mobj_with_fobj_get_fobj,
625*185b4595SMarouene Boubakri 	.get_cattr = mobj_with_fobj_get_cattr,
626*185b4595SMarouene Boubakri 	.get_pa = mobj_with_fobj_get_pa,
627*185b4595SMarouene Boubakri };
628*185b4595SMarouene Boubakri 
629*185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA
630*185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj)
631*185b4595SMarouene Boubakri {
632*185b4595SMarouene Boubakri 	if (mobj->ops == &mobj_seccpy_shm_ops)
633*185b4595SMarouene Boubakri 		return true;
634*185b4595SMarouene Boubakri 
635*185b4595SMarouene Boubakri 	if (mobj->ops == &mobj_with_fobj_ops &&
636*185b4595SMarouene Boubakri 	    !to_mobj_with_fobj(mobj)->fobj->ops->get_pa)
637*185b4595SMarouene Boubakri 		return true;
638*185b4595SMarouene Boubakri 
639*185b4595SMarouene Boubakri 	return false;
640*185b4595SMarouene Boubakri }
641*185b4595SMarouene Boubakri #endif /*CFG_PAGED_USER_TA*/
642*185b4595SMarouene Boubakri 
643*185b4595SMarouene Boubakri static TEE_Result mobj_init(void)
644*185b4595SMarouene Boubakri {
645*185b4595SMarouene Boubakri 	mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo,
646*185b4595SMarouene Boubakri 				       tee_mm_sec_ddr.hi - tee_mm_sec_ddr.lo,
647*185b4595SMarouene Boubakri 				       OPTEE_SMC_SHM_CACHED, CORE_MEM_TA_RAM);
648*185b4595SMarouene Boubakri 	if (!mobj_sec_ddr)
649*185b4595SMarouene Boubakri 		panic("Failed to register secure ta ram");
650*185b4595SMarouene Boubakri 
651*185b4595SMarouene Boubakri 	mobj_tee_ram = mobj_phys_alloc(TEE_RAM_START,
652*185b4595SMarouene Boubakri 				       VCORE_UNPG_RW_PA + VCORE_UNPG_RW_SZ -
653*185b4595SMarouene Boubakri 						TEE_RAM_START,
654*185b4595SMarouene Boubakri 				       TEE_MATTR_CACHE_CACHED,
655*185b4595SMarouene Boubakri 				       CORE_MEM_TEE_RAM);
656*185b4595SMarouene Boubakri 	if (!mobj_tee_ram)
657*185b4595SMarouene Boubakri 		panic("Failed to register tee ram");
658*185b4595SMarouene Boubakri 
659*185b4595SMarouene Boubakri 	return TEE_SUCCESS;
660*185b4595SMarouene Boubakri }
661*185b4595SMarouene Boubakri 
662*185b4595SMarouene Boubakri driver_init_late(mobj_init);
663