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