xref: /optee_os/core/include/mm/fobj.h (revision d5ad7ccf818dc8516f2abe9e3262955c91a03627)
1ee546289SJens Wiklander /* SPDX-License-Identifier: BSD-2-Clause */
2ee546289SJens Wiklander /*
32230fc67SJens Wiklander  * Copyright (c) 2019-2021, Linaro Limited
4ee546289SJens Wiklander  */
5ee546289SJens Wiklander 
6ee546289SJens Wiklander #ifndef __MM_FOBJ_H
7ee546289SJens Wiklander #define __MM_FOBJ_H
8ee546289SJens Wiklander 
9ee546289SJens Wiklander #include <kernel/panic.h>
10b83c0d5fSJens Wiklander #include <kernel/refcount.h>
11b83c0d5fSJens Wiklander #include <mm/tee_pager.h>
12b83c0d5fSJens Wiklander #include <sys/queue.h>
13ee546289SJens Wiklander #include <tee_api_types.h>
14ee546289SJens Wiklander #include <types_ext.h>
15ee546289SJens Wiklander 
16ee546289SJens Wiklander /*
17ee546289SJens Wiklander  * struct fobj - file object storage abstraction
18ee546289SJens Wiklander  * @ops:	Operations pointer
19ee546289SJens Wiklander  * @num_pages:	Number of pages covered
20ee546289SJens Wiklander  * @refc:	Reference counter
21ee546289SJens Wiklander  */
22ee546289SJens Wiklander struct fobj {
23ee546289SJens Wiklander 	const struct fobj_ops *ops;
24ee546289SJens Wiklander 	unsigned int num_pages;
25ee546289SJens Wiklander 	struct refcount refc;
26b83c0d5fSJens Wiklander #ifdef CFG_WITH_PAGER
27*d5ad7ccfSJens Wiklander 	struct vm_paged_region_head regions;
28b83c0d5fSJens Wiklander #endif
29ee546289SJens Wiklander };
30ee546289SJens Wiklander 
31ee546289SJens Wiklander /*
32ee546289SJens Wiklander  * struct fobj_ops - operations struct for struct fobj
33ee546289SJens Wiklander  * @free:	  Frees the @fobj
34ee546289SJens Wiklander  * @load_page:	  Loads page with index @page_idx at address @va
35ee546289SJens Wiklander  * @save_page:	  Saves page with index @page_idx from address @va
362230fc67SJens Wiklander  * @get_iv_vaddr: Returns virtual address of tag and IV for the page at
372230fc67SJens Wiklander  *		  @page_idx if tag and IV are paged for this fobj
38fbcaa411SJens Wiklander  * @get_pa:	  Returns physical address of page at @page_idx if not paged
39ee546289SJens Wiklander  */
40ee546289SJens Wiklander struct fobj_ops {
41ee546289SJens Wiklander 	void (*free)(struct fobj *fobj);
42ee546289SJens Wiklander #ifdef CFG_WITH_PAGER
43ee546289SJens Wiklander 	TEE_Result (*load_page)(struct fobj *fobj, unsigned int page_idx,
44ee546289SJens Wiklander 				void *va);
45ee546289SJens Wiklander 	TEE_Result (*save_page)(struct fobj *fobj, unsigned int page_idx,
46ee546289SJens Wiklander 				const void *va);
472230fc67SJens Wiklander 	vaddr_t (*get_iv_vaddr)(struct fobj *fobj, unsigned int page_idx);
48ee546289SJens Wiklander #endif
49fbcaa411SJens Wiklander 	paddr_t (*get_pa)(struct fobj *fobj, unsigned int page_idx);
50ee546289SJens Wiklander };
51ee546289SJens Wiklander 
52ee546289SJens Wiklander #ifdef CFG_WITH_PAGER
53ee546289SJens Wiklander /*
54ee546289SJens Wiklander  * fobj_locked_paged_alloc() - Allocate storage which is locked in memory
55ee546289SJens Wiklander  * @num_pages:	Number of pages covered
56ee546289SJens Wiklander  *
57ee546289SJens Wiklander  * This object only supports loading pages zero initialized. Saving a page
58ee546289SJens Wiklander  * will result in an error.
59ee546289SJens Wiklander  *
60ee546289SJens Wiklander  * Returns a valid pointer on success or NULL on failure.
61ee546289SJens Wiklander  */
62ee546289SJens Wiklander struct fobj *fobj_locked_paged_alloc(unsigned int num_pages);
63ee546289SJens Wiklander 
64ee546289SJens Wiklander /*
65ee546289SJens Wiklander  * fobj_rw_paged_alloc() - Allocate read/write storage
66ee546289SJens Wiklander  * @num_pages:	Number of pages covered
67ee546289SJens Wiklander  *
68ee546289SJens Wiklander  * This object supports both load and saving of pages. Pages are zero
69ee546289SJens Wiklander  * initialized the first time they are loaded.
70ee546289SJens Wiklander  *
71ee546289SJens Wiklander  * Returns a valid pointer on success or NULL on failure.
72ee546289SJens Wiklander  */
73ee546289SJens Wiklander struct fobj *fobj_rw_paged_alloc(unsigned int num_pages);
74ee546289SJens Wiklander 
75ee546289SJens Wiklander /*
76ee546289SJens Wiklander  * fobj_ro_paged_alloc() - Allocate initialized read-only storage
77ee546289SJens Wiklander  * @num_pages:	Number of pages covered
78ee546289SJens Wiklander  * @hashes:	Hashes to verify the pages
79ee546289SJens Wiklander  * @store:	Clear text data for all pages
80ee546289SJens Wiklander  *
81ee546289SJens Wiklander  * This object only support loading pages with an already provided content
82ee546289SJens Wiklander  * in @store. When a page is loaded it will be verified against an hash in
83ee546289SJens Wiklander  * @hash. Saving a page will result in an error.
84ee546289SJens Wiklander  *
85ee546289SJens Wiklander  * Returns a valid pointer on success or NULL on failure.
86ee546289SJens Wiklander  */
87ee546289SJens Wiklander struct fobj *fobj_ro_paged_alloc(unsigned int num_pages, void *hashes,
88ee546289SJens Wiklander 				 void *store);
89ee546289SJens Wiklander 
90ee546289SJens Wiklander /*
91c6744caaSJens Wiklander  * fobj_ro_reloc_paged_alloc() - Allocate initialized read-only storage with
92c6744caaSJens Wiklander  *				 relocation
93c6744caaSJens Wiklander  * @num_pages:	Number of pages covered
94c6744caaSJens Wiklander  * @hashes:	Hashes to verify the pages
95c6744caaSJens Wiklander  * @reloc_offs:	Offset from the base address in the relocations in @reloc
96c6744caaSJens Wiklander  * @reloc:	Relocation data
97c6744caaSJens Wiklander  * @reloc_len:	Length of relocation data
98c6744caaSJens Wiklander  * @store:	Clear text data for all pages
99c6744caaSJens Wiklander  *
100c6744caaSJens Wiklander  * This object is like fobj_ro_paged_alloc() above, but in addition the
101c6744caaSJens Wiklander  * relocation information is applied to a populated page. This makes sure
102c6744caaSJens Wiklander  * the offset to which all pages are relocated doesn't leak out to storage.
103c6744caaSJens Wiklander  *
104c6744caaSJens Wiklander  * Returns a valid pointer on success or NULL on failure.
105c6744caaSJens Wiklander  */
106c6744caaSJens Wiklander struct fobj *fobj_ro_reloc_paged_alloc(unsigned int num_pages, void *hashes,
107c6744caaSJens Wiklander 				       unsigned int reloc_offs,
108c6744caaSJens Wiklander 				       const void *reloc,
109c6744caaSJens Wiklander 				       unsigned int reloc_len, void *store);
110c6744caaSJens Wiklander 
111c6744caaSJens Wiklander /*
112ee546289SJens Wiklander  * fobj_load_page() - Load a page into memory
113ee546289SJens Wiklander  * @fobj:	Fobj pointer
114ee546289SJens Wiklander  * @page_index:	Index of page in @fobj
115ee546289SJens Wiklander  * @va:		Address where content should be stored and verified
116ee546289SJens Wiklander  *
117ee546289SJens Wiklander  * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure.
118ee546289SJens Wiklander  */
fobj_load_page(struct fobj * fobj,unsigned int page_idx,void * va)119ee546289SJens Wiklander static inline TEE_Result fobj_load_page(struct fobj *fobj,
120ee546289SJens Wiklander 					unsigned int page_idx, void *va)
121ee546289SJens Wiklander {
122ee546289SJens Wiklander 	if (fobj)
123ee546289SJens Wiklander 		return fobj->ops->load_page(fobj, page_idx, va);
124ee546289SJens Wiklander 
125ee546289SJens Wiklander 	return TEE_ERROR_GENERIC;
126ee546289SJens Wiklander }
127ee546289SJens Wiklander 
128ee546289SJens Wiklander /*
129ee546289SJens Wiklander  * fobj_save_page() - Save a page into storage
130ee546289SJens Wiklander  * @fobj:	Fobj pointer
131ee546289SJens Wiklander  * @page_index:	Index of page in @fobj
132ee546289SJens Wiklander  * @va:		Address of the page to store.
133ee546289SJens Wiklander  *
134ee546289SJens Wiklander  * Returns TEE_SUCCESS on success or TEE_ERROR_* on failure.
135ee546289SJens Wiklander  */
fobj_save_page(struct fobj * fobj,unsigned int page_idx,const void * va)136ee546289SJens Wiklander static inline TEE_Result fobj_save_page(struct fobj *fobj,
137ee546289SJens Wiklander 					unsigned int page_idx, const void *va)
138ee546289SJens Wiklander {
139ee546289SJens Wiklander 	if (fobj)
140ee546289SJens Wiklander 		return fobj->ops->save_page(fobj, page_idx, va);
141ee546289SJens Wiklander 
142ee546289SJens Wiklander 	return TEE_ERROR_GENERIC;
143ee546289SJens Wiklander }
1442230fc67SJens Wiklander 
fobj_get_iv_vaddr(struct fobj * fobj,unsigned int page_idx)1452230fc67SJens Wiklander static inline vaddr_t fobj_get_iv_vaddr(struct fobj *fobj,
1462230fc67SJens Wiklander 					unsigned int page_idx)
1472230fc67SJens Wiklander {
1482230fc67SJens Wiklander 	if (fobj && fobj->ops->get_iv_vaddr)
1492230fc67SJens Wiklander 		return fobj->ops->get_iv_vaddr(fobj, page_idx);
1502230fc67SJens Wiklander 
1512230fc67SJens Wiklander 	return 0;
1522230fc67SJens Wiklander }
153ee546289SJens Wiklander #endif
154ee546289SJens Wiklander 
155ee546289SJens Wiklander /*
156fbcaa411SJens Wiklander  * fobj_ta_mem_alloc() - Allocates TA memory
157fbcaa411SJens Wiklander  * @num_pages:	Number of pages
158fbcaa411SJens Wiklander  *
159fbcaa411SJens Wiklander  * If paging of user TAs read/write paged fobj is allocated otherwise a
160fbcaa411SJens Wiklander  * fobj which uses unpaged secure memory directly.
161fbcaa411SJens Wiklander  *
162fbcaa411SJens Wiklander  * Returns a valid pointer on success or NULL on failure.
163fbcaa411SJens Wiklander  */
164fbcaa411SJens Wiklander #ifdef CFG_PAGED_USER_TA
165fbcaa411SJens Wiklander #define fobj_ta_mem_alloc(num_pages)	fobj_rw_paged_alloc(num_pages)
166fbcaa411SJens Wiklander #else
167fbcaa411SJens Wiklander /*
168fbcaa411SJens Wiklander  * fobj_sec_mem_alloc() - Allocates storage directly in secure memory
169fbcaa411SJens Wiklander  * @num_pages:	Number of pages
170fbcaa411SJens Wiklander  *
171fbcaa411SJens Wiklander  * Returns a valid pointer on success or NULL on failure.
172fbcaa411SJens Wiklander  */
173fbcaa411SJens Wiklander struct fobj *fobj_sec_mem_alloc(unsigned int num_pages);
174fbcaa411SJens Wiklander 
175fbcaa411SJens Wiklander #define fobj_ta_mem_alloc(num_pages)	fobj_sec_mem_alloc(num_pages)
176fbcaa411SJens Wiklander #endif
177fbcaa411SJens Wiklander 
178fbcaa411SJens Wiklander /*
179ee546289SJens Wiklander  * fobj_get() - Increase fobj reference count
180ee546289SJens Wiklander  * @fobj:	Fobj pointer
181ee546289SJens Wiklander  *
182ee546289SJens Wiklander  * Returns @fobj, if @fobj isn't NULL its reference counter is first
183ee546289SJens Wiklander  * increased.
184ee546289SJens Wiklander  */
fobj_get(struct fobj * fobj)185ee546289SJens Wiklander static inline struct fobj *fobj_get(struct fobj *fobj)
186ee546289SJens Wiklander {
187ee546289SJens Wiklander 	if (fobj && !refcount_inc(&fobj->refc))
188ee546289SJens Wiklander 		panic();
189ee546289SJens Wiklander 
190ee546289SJens Wiklander 	return fobj;
191ee546289SJens Wiklander }
192ee546289SJens Wiklander 
193ee546289SJens Wiklander /*
194ee546289SJens Wiklander  * fobj_put() - Decrease reference counter of fobj
195ee546289SJens Wiklander  * @fobj:	Fobj pointer
196ee546289SJens Wiklander  *
197ee546289SJens Wiklander  * If reference counter reaches 0, matching the numbers of fobj_alloc_*() +
198ee546289SJens Wiklander  * fobj_get(), the fobj is freed.
199ee546289SJens Wiklander  */
fobj_put(struct fobj * fobj)200ee546289SJens Wiklander static inline void fobj_put(struct fobj *fobj)
201ee546289SJens Wiklander {
202ee546289SJens Wiklander 	if (fobj && refcount_dec(&fobj->refc))
203ee546289SJens Wiklander 		fobj->ops->free(fobj);
204ee546289SJens Wiklander }
205ee546289SJens Wiklander 
206ee546289SJens Wiklander #endif /*__MM_FOBJ_H*/
207