xref: /optee_os/core/include/mm/mobj.h (revision 8afe7a7c52204da38fc082c55f908fb819079f30)
1185b4595SMarouene Boubakri /* SPDX-License-Identifier: BSD-2-Clause */
2185b4595SMarouene Boubakri /*
3185b4595SMarouene Boubakri  * Copyright (c) 2016-2017, Linaro Limited
4185b4595SMarouene Boubakri  */
5185b4595SMarouene Boubakri 
6185b4595SMarouene Boubakri #ifndef __MM_MOBJ_H
7185b4595SMarouene Boubakri #define __MM_MOBJ_H
8185b4595SMarouene Boubakri 
9185b4595SMarouene Boubakri #include <compiler.h>
10185b4595SMarouene Boubakri #include <mm/core_memprot.h>
11185b4595SMarouene Boubakri #include <mm/file.h>
12185b4595SMarouene Boubakri #include <mm/fobj.h>
13185b4595SMarouene Boubakri #include <string_ext.h>
14185b4595SMarouene Boubakri #include <sys/queue.h>
15185b4595SMarouene Boubakri #include <tee_api_types.h>
16185b4595SMarouene Boubakri #include <types_ext.h>
17185b4595SMarouene Boubakri 
18c1bdf4fcSJens Wiklander #include <optee_msg.h>
19c1bdf4fcSJens Wiklander 
20185b4595SMarouene Boubakri struct mobj {
21185b4595SMarouene Boubakri 	const struct mobj_ops *ops;
22185b4595SMarouene Boubakri 	size_t size;
23185b4595SMarouene Boubakri 	size_t phys_granule;
24185b4595SMarouene Boubakri 	struct refcount refc;
25185b4595SMarouene Boubakri };
26185b4595SMarouene Boubakri 
27185b4595SMarouene Boubakri struct mobj_ops {
289c4aaf67SJens Wiklander 	void *(*get_va)(struct mobj *mobj, size_t offs, size_t len);
29185b4595SMarouene Boubakri 	TEE_Result (*get_pa)(struct mobj *mobj, size_t offs, size_t granule,
30185b4595SMarouene Boubakri 			     paddr_t *pa);
31185b4595SMarouene Boubakri 	size_t (*get_phys_offs)(struct mobj *mobj, size_t granule);
32*8afe7a7cSJens Wiklander 	TEE_Result (*get_mem_type)(struct mobj *mobj, uint32_t *mt);
33185b4595SMarouene Boubakri 	bool (*matches)(struct mobj *mobj, enum buf_is_attr attr);
34185b4595SMarouene Boubakri 	void (*free)(struct mobj *mobj);
35185b4595SMarouene Boubakri 	uint64_t (*get_cookie)(struct mobj *mobj);
36185b4595SMarouene Boubakri 	struct fobj *(*get_fobj)(struct mobj *mobj);
37185b4595SMarouene Boubakri 	TEE_Result (*inc_map)(struct mobj *mobj);
38185b4595SMarouene Boubakri 	TEE_Result (*dec_map)(struct mobj *mobj);
39185b4595SMarouene Boubakri };
40185b4595SMarouene Boubakri 
41185b4595SMarouene Boubakri extern struct mobj mobj_virt;
42185b4595SMarouene Boubakri extern struct mobj *mobj_sec_ddr;
43ff01e245SAnton Rybakov extern struct mobj *mobj_tee_ram_rx;
44ff01e245SAnton Rybakov extern struct mobj *mobj_tee_ram_rw;
45185b4595SMarouene Boubakri 
469c4aaf67SJens Wiklander /*
479c4aaf67SJens Wiklander  * mobj_get_va() - get virtual address of a mapped mobj
489c4aaf67SJens Wiklander  * @mobj:	memory object
499c4aaf67SJens Wiklander  * @offset:	find the va of this offset into @mobj
509c4aaf67SJens Wiklander  * @len:	how many bytes after @offset that must be valid, can be 1 if
519c4aaf67SJens Wiklander  *		the caller knows by other means that the expected buffer is
529c4aaf67SJens Wiklander  *		available.
539c4aaf67SJens Wiklander  *
549c4aaf67SJens Wiklander  * return a virtual address on success or NULL on error
559c4aaf67SJens Wiklander  */
569c4aaf67SJens Wiklander static inline void *mobj_get_va(struct mobj *mobj, size_t offset, size_t len)
57185b4595SMarouene Boubakri {
58185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->get_va)
599c4aaf67SJens Wiklander 		return mobj->ops->get_va(mobj, offset, len);
60185b4595SMarouene Boubakri 	return NULL;
61185b4595SMarouene Boubakri }
62185b4595SMarouene Boubakri 
63185b4595SMarouene Boubakri static inline TEE_Result mobj_get_pa(struct mobj *mobj, size_t offs,
64185b4595SMarouene Boubakri 				     size_t granule, paddr_t *pa)
65185b4595SMarouene Boubakri {
66185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->get_pa)
67185b4595SMarouene Boubakri 		return mobj->ops->get_pa(mobj, offs, granule, pa);
68185b4595SMarouene Boubakri 	return TEE_ERROR_GENERIC;
69185b4595SMarouene Boubakri }
70185b4595SMarouene Boubakri 
71185b4595SMarouene Boubakri static inline size_t mobj_get_phys_offs(struct mobj *mobj, size_t granule)
72185b4595SMarouene Boubakri {
73185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->get_phys_offs)
74185b4595SMarouene Boubakri 		return mobj->ops->get_phys_offs(mobj, granule);
75185b4595SMarouene Boubakri 	return 0;
76185b4595SMarouene Boubakri }
77185b4595SMarouene Boubakri 
78*8afe7a7cSJens Wiklander static inline TEE_Result mobj_get_mem_type(struct mobj *mobj, uint32_t *mt)
79185b4595SMarouene Boubakri {
80*8afe7a7cSJens Wiklander 	if (mobj && mobj->ops && mobj->ops->get_mem_type)
81*8afe7a7cSJens Wiklander 		return mobj->ops->get_mem_type(mobj, mt);
82185b4595SMarouene Boubakri 	return TEE_ERROR_GENERIC;
83185b4595SMarouene Boubakri }
84185b4595SMarouene Boubakri 
85185b4595SMarouene Boubakri static inline bool mobj_matches(struct mobj *mobj, enum buf_is_attr attr)
86185b4595SMarouene Boubakri {
87185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->matches)
88185b4595SMarouene Boubakri 		return mobj->ops->matches(mobj, attr);
89185b4595SMarouene Boubakri 	return false;
90185b4595SMarouene Boubakri }
91185b4595SMarouene Boubakri 
92185b4595SMarouene Boubakri /**
93185b4595SMarouene Boubakri  * mobj_inc_map() - increase map count
94185b4595SMarouene Boubakri  * @mobj:	pointer to a MOBJ
95185b4595SMarouene Boubakri  *
96185b4595SMarouene Boubakri  * Maps the MOBJ if it isn't mapped already and increases the map count
97185b4595SMarouene Boubakri  * Each call to mobj_inc_map() is supposed to be matches by a call to
98185b4595SMarouene Boubakri  * mobj_dec_map().
99185b4595SMarouene Boubakri  *
100185b4595SMarouene Boubakri  * Returns TEE_SUCCESS on success or an error code on failure
101185b4595SMarouene Boubakri  */
102185b4595SMarouene Boubakri static inline TEE_Result mobj_inc_map(struct mobj *mobj)
103185b4595SMarouene Boubakri {
104185b4595SMarouene Boubakri 	if (mobj && mobj->ops) {
105185b4595SMarouene Boubakri 		if (mobj->ops->inc_map)
106185b4595SMarouene Boubakri 			return mobj->ops->inc_map(mobj);
107185b4595SMarouene Boubakri 		return TEE_SUCCESS;
108185b4595SMarouene Boubakri 	}
109185b4595SMarouene Boubakri 	return TEE_ERROR_GENERIC;
110185b4595SMarouene Boubakri }
111185b4595SMarouene Boubakri 
112185b4595SMarouene Boubakri /**
113185b4595SMarouene Boubakri  * mobj_dec_map() - decrease map count
114185b4595SMarouene Boubakri  * @mobj:	pointer to a MOBJ
115185b4595SMarouene Boubakri  *
116185b4595SMarouene Boubakri  * Decreases the map count and also unmaps the MOBJ if the map count
117185b4595SMarouene Boubakri  * reaches 0.  Each call to mobj_inc_map() is supposed to be matched by a
118185b4595SMarouene Boubakri  * call to mobj_dec_map().
119185b4595SMarouene Boubakri  *
120185b4595SMarouene Boubakri  * Returns TEE_SUCCESS on success or an error code on failure
121185b4595SMarouene Boubakri  */
122185b4595SMarouene Boubakri static inline TEE_Result mobj_dec_map(struct mobj *mobj)
123185b4595SMarouene Boubakri {
124185b4595SMarouene Boubakri 	if (mobj && mobj->ops) {
125185b4595SMarouene Boubakri 		if (mobj->ops->dec_map)
126185b4595SMarouene Boubakri 			return mobj->ops->dec_map(mobj);
127185b4595SMarouene Boubakri 		return TEE_SUCCESS;
128185b4595SMarouene Boubakri 	}
129185b4595SMarouene Boubakri 	return TEE_ERROR_GENERIC;
130185b4595SMarouene Boubakri }
131185b4595SMarouene Boubakri 
132185b4595SMarouene Boubakri /**
133185b4595SMarouene Boubakri  * mobj_get() - get a MOBJ
134185b4595SMarouene Boubakri  * @mobj:	Pointer to a MOBJ or NULL
135185b4595SMarouene Boubakri  *
136185b4595SMarouene Boubakri  * Increases reference counter of the @mobj
137185b4595SMarouene Boubakri  *
138185b4595SMarouene Boubakri  * Returns @mobj with reference counter increased or NULL if @mobj was NULL
139185b4595SMarouene Boubakri  */
140185b4595SMarouene Boubakri static inline struct mobj *mobj_get(struct mobj *mobj)
141185b4595SMarouene Boubakri {
142185b4595SMarouene Boubakri 	if (mobj && !refcount_inc(&mobj->refc))
143185b4595SMarouene Boubakri 		panic();
144185b4595SMarouene Boubakri 
145185b4595SMarouene Boubakri 	return mobj;
146185b4595SMarouene Boubakri }
147185b4595SMarouene Boubakri 
148185b4595SMarouene Boubakri /**
149185b4595SMarouene Boubakri  * mobj_put() - put a MOBJ
150185b4595SMarouene Boubakri  * @mobj:	Pointer to a MOBJ or NULL
151185b4595SMarouene Boubakri  *
152185b4595SMarouene Boubakri  * Decreases reference counter of the @mobj and frees it if the counter
153185b4595SMarouene Boubakri  * reaches 0.
154185b4595SMarouene Boubakri  */
155185b4595SMarouene Boubakri static inline void mobj_put(struct mobj *mobj)
156185b4595SMarouene Boubakri {
157185b4595SMarouene Boubakri 	if (mobj && refcount_dec(&mobj->refc))
158185b4595SMarouene Boubakri 		mobj->ops->free(mobj);
159185b4595SMarouene Boubakri }
160185b4595SMarouene Boubakri 
161185b4595SMarouene Boubakri /**
162185b4595SMarouene Boubakri  * mobj_put_wipe() - wipe and put a MOBJ
163185b4595SMarouene Boubakri  * @mobj:	Pointer to a MOBJ or NULL
164185b4595SMarouene Boubakri  *
165185b4595SMarouene Boubakri  * Clears the memory represented by the mobj and then puts it.
166185b4595SMarouene Boubakri  */
167185b4595SMarouene Boubakri static inline void mobj_put_wipe(struct mobj *mobj)
168185b4595SMarouene Boubakri {
1699c4aaf67SJens Wiklander 	if (mobj) {
1709c4aaf67SJens Wiklander 		void *buf = mobj_get_va(mobj, 0, mobj->size);
171185b4595SMarouene Boubakri 
172185b4595SMarouene Boubakri 		if (buf)
173185b4595SMarouene Boubakri 			memzero_explicit(buf, mobj->size);
174185b4595SMarouene Boubakri 		mobj_put(mobj);
175185b4595SMarouene Boubakri 	}
1769c4aaf67SJens Wiklander }
177185b4595SMarouene Boubakri 
178185b4595SMarouene Boubakri static inline uint64_t mobj_get_cookie(struct mobj *mobj)
179185b4595SMarouene Boubakri {
180185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->get_cookie)
181185b4595SMarouene Boubakri 		return mobj->ops->get_cookie(mobj);
182185b4595SMarouene Boubakri 
183e26b8354SJens Wiklander #if defined(CFG_CORE_FFA)
184c1bdf4fcSJens Wiklander 	return OPTEE_MSG_FMEM_INVALID_GLOBAL_ID;
185c1bdf4fcSJens Wiklander #else
186185b4595SMarouene Boubakri 	return 0;
187c1bdf4fcSJens Wiklander #endif
188185b4595SMarouene Boubakri }
189185b4595SMarouene Boubakri 
190185b4595SMarouene Boubakri static inline struct fobj *mobj_get_fobj(struct mobj *mobj)
191185b4595SMarouene Boubakri {
192185b4595SMarouene Boubakri 	if (mobj && mobj->ops && mobj->ops->get_fobj)
193185b4595SMarouene Boubakri 		return mobj->ops->get_fobj(mobj);
194185b4595SMarouene Boubakri 
195185b4595SMarouene Boubakri 	return NULL;
196185b4595SMarouene Boubakri }
197185b4595SMarouene Boubakri 
198185b4595SMarouene Boubakri static inline bool mobj_is_nonsec(struct mobj *mobj)
199185b4595SMarouene Boubakri {
200185b4595SMarouene Boubakri 	return mobj_matches(mobj, CORE_MEM_NON_SEC);
201185b4595SMarouene Boubakri }
202185b4595SMarouene Boubakri 
203185b4595SMarouene Boubakri static inline bool mobj_is_secure(struct mobj *mobj)
204185b4595SMarouene Boubakri {
205185b4595SMarouene Boubakri 	return mobj_matches(mobj, CORE_MEM_SEC);
206185b4595SMarouene Boubakri }
207185b4595SMarouene Boubakri 
208185b4595SMarouene Boubakri static inline bool mobj_is_sdp_mem(struct mobj *mobj)
209185b4595SMarouene Boubakri {
210185b4595SMarouene Boubakri 	return mobj_matches(mobj, CORE_MEM_SDP_MEM);
211185b4595SMarouene Boubakri }
212185b4595SMarouene Boubakri 
213185b4595SMarouene Boubakri static inline size_t mobj_get_phys_granule(struct mobj *mobj)
214185b4595SMarouene Boubakri {
215185b4595SMarouene Boubakri 	if (mobj->phys_granule)
216185b4595SMarouene Boubakri 		return mobj->phys_granule;
217185b4595SMarouene Boubakri 	return mobj->size;
218185b4595SMarouene Boubakri }
219185b4595SMarouene Boubakri 
2209c4aaf67SJens Wiklander static inline bool mobj_check_offset_and_len(struct mobj *mobj, size_t offset,
2219c4aaf67SJens Wiklander 					     size_t len)
2229c4aaf67SJens Wiklander {
2239c4aaf67SJens Wiklander 	size_t end_offs = 0;
2249c4aaf67SJens Wiklander 
2259c4aaf67SJens Wiklander 	return len && !ADD_OVERFLOW(offset, len - 1, &end_offs) &&
2269c4aaf67SJens Wiklander 	       end_offs < mobj->size;
2279c4aaf67SJens Wiklander }
2289c4aaf67SJens Wiklander 
229185b4595SMarouene Boubakri struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size,
230185b4595SMarouene Boubakri 			   tee_mm_pool_t *pool);
231185b4595SMarouene Boubakri 
232185b4595SMarouene Boubakri struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr,
233185b4595SMarouene Boubakri 			     enum buf_is_attr battr);
234185b4595SMarouene Boubakri 
235185b4595SMarouene Boubakri #if defined(CFG_CORE_FFA)
236185b4595SMarouene Boubakri struct mobj *mobj_ffa_get_by_cookie(uint64_t cookie,
237185b4595SMarouene Boubakri 				    unsigned int internal_offs);
238185b4595SMarouene Boubakri 
239185b4595SMarouene Boubakri TEE_Result mobj_ffa_unregister_by_cookie(uint64_t cookie);
240185b4595SMarouene Boubakri 
241185b4595SMarouene Boubakri /* Functions for SPMC */
242185b4595SMarouene Boubakri #ifdef CFG_CORE_SEL1_SPMC
243185b4595SMarouene Boubakri struct mobj_ffa *mobj_ffa_sel1_spmc_new(unsigned int num_pages);
244185b4595SMarouene Boubakri void mobj_ffa_sel1_spmc_delete(struct mobj_ffa *mobj);
245185b4595SMarouene Boubakri TEE_Result mobj_ffa_sel1_spmc_reclaim(uint64_t cookie);
246e26b8354SJens Wiklander #else
247e26b8354SJens Wiklander struct mobj_ffa *mobj_ffa_spmc_new(uint64_t cookie, unsigned int num_pages);
248e26b8354SJens Wiklander void mobj_ffa_spmc_delete(struct mobj_ffa *mobj);
249fb19e98eSJens Wiklander #endif
250fb19e98eSJens Wiklander 
251185b4595SMarouene Boubakri uint64_t mobj_ffa_get_cookie(struct mobj_ffa *mobj);
252185b4595SMarouene Boubakri TEE_Result mobj_ffa_add_pages_at(struct mobj_ffa *mobj, unsigned int *idx,
253185b4595SMarouene Boubakri 				 paddr_t pa, unsigned int num_pages);
254185b4595SMarouene Boubakri uint64_t mobj_ffa_push_to_inactive(struct mobj_ffa *mobj);
255185b4595SMarouene Boubakri 
256185b4595SMarouene Boubakri #elif defined(CFG_CORE_DYN_SHM)
257185b4595SMarouene Boubakri /* reg_shm represents TEE shared memory */
258185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_alloc(paddr_t *pages, size_t num_pages,
259185b4595SMarouene Boubakri 				paddr_t page_offset, uint64_t cookie);
260185b4595SMarouene Boubakri 
261185b4595SMarouene Boubakri /**
262185b4595SMarouene Boubakri  * mobj_reg_shm_get_by_cookie() - get a MOBJ based on cookie
263185b4595SMarouene Boubakri  * @cookie:	Cookie used by normal world when suppling the shared memory
264185b4595SMarouene Boubakri  *
265185b4595SMarouene Boubakri  * Searches for a registered shared memory MOBJ and if one with a matching
266185b4595SMarouene Boubakri  * @cookie is found its reference counter is increased before returning
267185b4595SMarouene Boubakri  * the MOBJ.
268185b4595SMarouene Boubakri  *
269185b4595SMarouene Boubakri  * Returns a valid pointer on success or NULL on failure.
270185b4595SMarouene Boubakri  */
271185b4595SMarouene Boubakri struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie);
272185b4595SMarouene Boubakri 
273185b4595SMarouene Boubakri TEE_Result mobj_reg_shm_release_by_cookie(uint64_t cookie);
274185b4595SMarouene Boubakri 
275185b4595SMarouene Boubakri /**
276185b4595SMarouene Boubakri  * mobj_reg_shm_unguard() - unguards a reg_shm
277185b4595SMarouene Boubakri  * @mobj:	pointer to a registered shared memory mobj
278185b4595SMarouene Boubakri  *
279185b4595SMarouene Boubakri  * A registered shared memory mobj is normally guarded against being
280185b4595SMarouene Boubakri  * released with mobj_reg_shm_try_release_by_cookie(). After this function
281185b4595SMarouene Boubakri  * has returned the mobj can be released by a call to
282185b4595SMarouene Boubakri  * mobj_reg_shm_try_release_by_cookie() if the reference counter allows it.
283185b4595SMarouene Boubakri  */
284185b4595SMarouene Boubakri void mobj_reg_shm_unguard(struct mobj *mobj);
285185b4595SMarouene Boubakri 
286185b4595SMarouene Boubakri /*
287185b4595SMarouene Boubakri  * mapped_shm represents registered shared buffer
288185b4595SMarouene Boubakri  * which is mapped into OPTEE va space
289185b4595SMarouene Boubakri  */
290185b4595SMarouene Boubakri struct mobj *mobj_mapped_shm_alloc(paddr_t *pages, size_t num_pages,
291185b4595SMarouene Boubakri 				   paddr_t page_offset, uint64_t cookie);
292185b4595SMarouene Boubakri #endif /*CFG_CORE_DYN_SHM*/
293185b4595SMarouene Boubakri 
294185b4595SMarouene Boubakri #if !defined(CFG_CORE_DYN_SHM)
295185b4595SMarouene Boubakri static inline struct mobj *mobj_mapped_shm_alloc(paddr_t *pages __unused,
296185b4595SMarouene Boubakri 						 size_t num_pages __unused,
297185b4595SMarouene Boubakri 						 paddr_t page_offset __unused,
298185b4595SMarouene Boubakri 						 uint64_t cookie __unused)
299185b4595SMarouene Boubakri {
300185b4595SMarouene Boubakri 	return NULL;
301185b4595SMarouene Boubakri }
30264b74defSJens Wiklander 
30364b74defSJens Wiklander static inline struct mobj *mobj_reg_shm_get_by_cookie(uint64_t cookie __unused)
30464b74defSJens Wiklander {
30564b74defSJens Wiklander 	return NULL;
30664b74defSJens Wiklander }
307185b4595SMarouene Boubakri #endif
308185b4595SMarouene Boubakri 
309185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie);
310185b4595SMarouene Boubakri 
311185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA
312185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj);
313185b4595SMarouene Boubakri #else
314185b4595SMarouene Boubakri static inline bool mobj_is_paged(struct mobj *mobj __unused)
315185b4595SMarouene Boubakri {
316185b4595SMarouene Boubakri 	return false;
317185b4595SMarouene Boubakri }
318185b4595SMarouene Boubakri #endif
319185b4595SMarouene Boubakri 
320185b4595SMarouene Boubakri struct mobj *mobj_seccpy_shm_alloc(size_t size);
321185b4595SMarouene Boubakri 
322185b4595SMarouene Boubakri struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file);
323185b4595SMarouene Boubakri 
324185b4595SMarouene Boubakri #endif /*__MM_MOBJ_H*/
325