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