xref: /optee_os/core/include/mm/mobj.h (revision f6e2b9e2d1a270542c6f6f5e36ed4e36abe18256)
1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*
3  * Copyright (c) 2016-2017, Linaro Limited
4  */
5 
6 #ifndef __MM_MOBJ_H
7 #define __MM_MOBJ_H
8 
9 #include <compiler.h>
10 #include <mm/core_memprot.h>
11 #include <mm/file.h>
12 #include <mm/fobj.h>
13 #include <string_ext.h>
14 #include <sys/queue.h>
15 #include <tee_api_types.h>
16 #include <types_ext.h>
17 
18 struct mobj {
19 	const struct mobj_ops *ops;
20 	size_t size;
21 	size_t phys_granule;
22 	struct refcount refc;
23 };
24 
25 struct mobj_ops {
26 	void *(*get_va)(struct mobj *mobj, size_t offs);
27 	TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule,
28 			     paddr_t *pa);
29 	size_t (*get_phys_offs)(struct mobj *mobj, size_t granule);
30 	TEE_Result (*get_cattr)(struct mobj *mobj, uint32_t *cattr);
31 	bool (*matches)(struct mobj *mobj, enum buf_is_attr attr);
32 	void (*free)(struct mobj *mobj);
33 	uint64_t (*get_cookie)(struct mobj *mobj);
34 	struct fobj *(*get_fobj)(struct mobj *mobj);
35 	TEE_Result (*inc_map)(struct mobj *mobj);
36 	TEE_Result (*dec_map)(struct mobj *mobj);
37 };
38 
39 extern struct mobj mobj_virt;
40 extern struct mobj *mobj_sec_ddr;
41 extern struct mobj *mobj_tee_ram;
42 
43 static inline void *mobj_get_va(struct mobj *mobj, size_t offset)
44 {
45 	if (mobj && mobj->ops && mobj->ops->get_va)
46 		return mobj->ops->get_va(mobj, offset);
47 	return NULL;
48 }
49 
50 static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs,
51 				     size_t granule, paddr_t *pa)
52 {
53 	if (mobj && mobj->ops && mobj->ops->get_pa)
54 		return mobj->ops->get_pa(mobj, offs, granule, pa);
55 	return TEE_ERROR_GENERIC;
56 }
57 
58 static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule)
59 {
60 	if (mobj && mobj->ops && mobj->ops->get_phys_offs)
61 		return mobj->ops->get_phys_offs(mobj, granule);
62 	return 0;
63 }
64 
65 static inline TEE_Result mobj_get_cattr(struct mobj *mobj, uint32_t *cattr)
66 {
67 	if (mobj && mobj->ops && mobj->ops->get_cattr)
68 		return mobj->ops->get_cattr(mobj, cattr);
69 	return TEE_ERROR_GENERIC;
70 }
71 
72 static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr)
73 {
74 	if (mobj && mobj->ops && mobj->ops->matches)
75 		return mobj->ops->matches(mobj, attr);
76 	return false;
77 }
78 
79 /**
80  * mobj_inc_map() - increase map count
81  * @mobj:	pointer to a MOBJ
82  *
83  * Maps the MOBJ if it isn't mapped already and increases the map count
84  * Each call to mobj_inc_map() is supposed to be matches by a call to
85  * mobj_dec_map().
86  *
87  * Returns TEE_SUCCESS on success or an error code on failure
88  */
89 static inline TEE_Result mobj_inc_map(struct mobj *mobj)
90 {
91 	if (mobj && mobj->ops) {
92 		if (mobj->ops->inc_map)
93 			return mobj->ops->inc_map(mobj);
94 		return TEE_SUCCESS;
95 	}
96 	return TEE_ERROR_GENERIC;
97 }
98 
99 /**
100  * mobj_dec_map() - decrease map count
101  * @mobj:	pointer to a MOBJ
102  *
103  * Decreases the map count and also unmaps the MOBJ if the map count
104  * reaches 0.  Each call to mobj_inc_map() is supposed to be matched by a
105  * call to mobj_dec_map().
106  *
107  * Returns TEE_SUCCESS on success or an error code on failure
108  */
109 static inline TEE_Result mobj_dec_map(struct mobj *mobj)
110 {
111 	if (mobj && mobj->ops) {
112 		if (mobj->ops->dec_map)
113 			return mobj->ops->dec_map(mobj);
114 		return TEE_SUCCESS;
115 	}
116 	return TEE_ERROR_GENERIC;
117 }
118 
119 /**
120  * mobj_get() - get a MOBJ
121  * @mobj:	Pointer to a MOBJ or NULL
122  *
123  * Increases reference counter of the @mobj
124  *
125  * Returns @mobj with reference counter increased or NULL if @mobj was NULL
126  */
127 static inline struct mobj *mobj_get(struct mobj *mobj)
128 {
129 	if (mobj && !refcount_inc(&mobj->refc))
130 		panic();
131 
132 	return mobj;
133 }
134 
135 /**
136  * mobj_put() - put a MOBJ
137  * @mobj:	Pointer to a MOBJ or NULL
138  *
139  * Decreases reference counter of the @mobj and frees it if the counter
140  * reaches 0.
141  */
142 static inline void mobj_put(struct mobj *mobj)
143 {
144 	if (mobj && refcount_dec(&mobj->refc))
145 		mobj->ops->free(mobj);
146 }
147 
148 /**
149  * mobj_put_wipe() - wipe and put a MOBJ
150  * @mobj:	Pointer to a MOBJ or NULL
151  *
152  * Clears the memory represented by the mobj and then puts it.
153  */
154 static inline void mobj_put_wipe(struct mobj *mobj)
155 {
156 	void *buf = mobj_get_va(mobj, 0);
157 
158 	if (buf)
159 		memzero_explicit(buf, mobj->size);
160 	mobj_put(mobj);
161 }
162 
163 static inline uint64_t mobj_get_cookie(struct mobj *mobj)
164 {
165 	if (mobj && mobj->ops && mobj->ops->get_cookie)
166 		return mobj->ops->get_cookie(mobj);
167 
168 	return 0;
169 }
170 
171 static inline struct fobj *mobj_get_fobj(struct mobj *mobj)
172 {
173 	if (mobj && mobj->ops && mobj->ops->get_fobj)
174 		return mobj->ops->get_fobj(mobj);
175 
176 	return NULL;
177 }
178 
179 static inline bool mobj_is_nonsec(struct mobj *mobj)
180 {
181 	return mobj_matches(mobj, CORE_MEM_NON_SEC);
182 }
183 
184 static inline bool mobj_is_secure(struct mobj *mobj)
185 {
186 	return mobj_matches(mobj, CORE_MEM_SEC);
187 }
188 
189 static inline bool mobj_is_sdp_mem(struct mobj *mobj)
190 {
191 	return mobj_matches(mobj, CORE_MEM_SDP_MEM);
192 }
193 
194 static inline size_t mobj_get_phys_granule(struct mobj *mobj)
195 {
196 	if (mobj->phys_granule)
197 		return mobj->phys_granule;
198 	return mobj->size;
199 }
200 
201 struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size,
202 			   tee_mm_pool_t *pool);
203 
204 struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
205 			     enum buf_is_attr battr);
206 
207 #if defined(CFG_CORE_FFA)
208 struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
209 				    unsigned int internal_offs);
210 
211 TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie);
212 
213 /* Functions for SPMC */
214 #ifdef CFG_CORE_SEL1_SPMC
215 struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages);
216 void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj);
217 TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie);
218 #endif
219 uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj);
220 TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx,
221 				 paddr_t pa, unsigned int num_pages);
222 uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj);
223 
224 #elif defined(CFG_CORE_DYN_SHM)
225 /* reg_shm represents TEE shared memory */
226 struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages,
227 				paddr_t page_offset, uint64_t cookie);
228 
229 /**
230  * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie
231  * @cookie:	Cookie used by normal world when suppling the shared memory
232  *
233  * Searches for a registered shared memory MOBJ and if one with a matching
234  * @cookie is found its reference counter is increased before returning
235  * the MOBJ.
236  *
237  * Returns a valid pointer on success or NULL on failure.
238  */
239 struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie);
240 
241 TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie);
242 
243 /**
244  * mobj_reg_shm_unguard() - unguards a reg_shm
245  * @mobj:	pointer to a registered shared memory mobj
246  *
247  * A registered shared memory mobj is normally guarded against being
248  * released with mobj_reg_shm_try_release_by_cookie(). After this function
249  * has returned the mobj can be released by a call to
250  * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it.
251  */
252 void mobj_reg_shm_unguard(struct mobj *mobj);
253 
254 /*
255  * mapped_shm represents registered shared buffer
256  * which is mapped into OPTEE va space
257  */
258 struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages,
259 				   paddr_t page_offset, uint64_t cookie);
260 #endif /*CFG_CORE_DYN_SHM*/
261 
262 #if !defined(CFG_CORE_DYN_SHM)
263 static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused,
264 						 size_t num_pages __unused,
265 						 paddr_t page_offset __unused,
266 						 uint64_t cookie __unused)
267 {
268 	return NULL;
269 }
270 #endif
271 
272 struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie);
273 
274 #ifdef CFG_PAGED_USER_TA
275 bool mobj_is_paged(struct mobj *mobj);
276 #else
277 static inline bool mobj_is_paged(struct mobj *mobj __unused)
278 {
279 	return false;
280 }
281 #endif
282 
283 struct mobj *mobj_seccpy_shm_alloc(size_t size);
284 
285 struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file);
286 
287 #endif /*__MM_MOBJ_H*/
288