1 /*
2 * Copyright (c) 2020 LK Trusty Authors. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #pragma once
25
26 #include <kernel/vm_obj.h>
27 #include <lib/binary_search_tree.h>
28 #include <lk/reflist.h>
29 #include <sys/types.h>
30
31 struct vmm_obj;
32 struct obj_ref;
33 struct vmm_aspace;
34
35 /**
36 * typedef ext_mem_client_id_t - External client identifier.
37 *
38 * Type use to store a 64 bit external client identifier.
39 */
40 typedef uint64_t ext_mem_client_id_t;
41
42 /**
43 * typedef ext_mem_obj_id_t - External memory identifier.
44 *
45 * Type use to store a 64 bit external memory identifier. The value is chosen
46 * by the specific external memory implementation, but must be unique for the
47 * namespace it is used in (@objs argument of ext_mem_insert).
48 */
49 typedef uint64_t ext_mem_obj_id_t;
50
51 /**
52 * struct ext_mem_page_run - Contiguous region of physical memory.
53 * @paddr: Physical address where region starts.
54 * @size: Number of bytes in region. Should be a multiple of PAGE_SIZE for the
55 * region to be mappable.
56 */
57 struct ext_mem_page_run {
58 paddr_t paddr;
59 size_t size;
60 };
61
62 /**
63 * struct ext_mem_obj - Memory object for external sources.
64 * @id: Unique id used for lookup.
65 * @tag: Metadata used by some systems. Set to 0 if unused.
66 * @match_tag: Metadata used by some systems. Set to 0 if unused.
67 * Must match @tag before the object can be mapped. An object
68 * attached to an ipc message can be created before sending it
69 * to the app but only be mapable after the tag has been
70 * matched.
71 * @vmm_obj: VMM object.
72 * @node: Search tree node.
73 * @arch_mmu_flags: Memory type and required permission flags.
74 * @page_run_count: Number of entries in @page_runs.
75 * @page_runs: Array of physically contiguous regions.
76 */
77 struct ext_mem_obj {
78 ext_mem_obj_id_t id;
79 uint64_t tag;
80 uint64_t match_tag;
81 struct vmm_obj vmm_obj;
82 struct bst_node node;
83 uint arch_mmu_flags;
84 size_t page_run_count;
85 struct ext_mem_page_run page_runs[];
86 };
87
88 /**
89 * ext_mem_obj_page_runs_size - Get size of page_runs.
90 * @page_run_count: Number if page runs.
91 *
92 * Calculate size of page_runs array. This can be added by the caller to the
93 * size of struct ext_mem_obj, or the size of a struct that embeds struct
94 * ext_mem_obj at the end, to get the number of bytes to allocate.
95 *
96 * Return: Size of ext_mem_obj page_runs array in bytes.
97 */
ext_mem_obj_page_runs_size(size_t page_run_count)98 static inline size_t ext_mem_obj_page_runs_size(size_t page_run_count) {
99 return sizeof(struct ext_mem_page_run) * page_run_count;
100 }
101
102 /**
103 * ext_mem_obj_initialize - Initialize struct ext_mem_obj.
104 * @obj: Object to initialize.
105 * @ref: Initial reference.
106 * @id: Unique id used by ext_mem_insert and ext_mem_lookup.
107 * @tag: Extra metadata used by some systems. Set to 0 if unused.
108 * @ops: Pointer to &struct vmm_obj_ops. @ops->check_flags can point
109 * directly to ext_mem_obj_check_flags. @ops->get_page can
110 * point directly to ext_mem_obj_get_page. @ops->destroy must
111 * point to a function supplied by the caller.
112 * @arch_mmu_flags: Memory type and required permission flags.
113 * @page_run_count: Number of entries in @page_runs.
114 */
115 void ext_mem_obj_initialize(struct ext_mem_obj* obj,
116 struct obj_ref* ref,
117 ext_mem_obj_id_t id,
118 uint64_t tag,
119 struct vmm_obj_ops* ops,
120 uint arch_mmu_flags,
121 size_t page_run_count);
122
123 /**
124 * ext_mem_insert - Insert ext_mem_obj.
125 * @objs: Root of search tree to insert @obj into.
126 * @obj: ext_mem_obj to insert.
127 *
128 * Insert @obj into @objs.
129 * Caller is responsible for locking.
130 *
131 * Return: %true if @obj was inserted. %false if a node with the same id as
132 * @obj->id is already in @objs.
133 */
134 bool ext_mem_insert(struct bst_root* objs, struct ext_mem_obj* obj);
135
136 /**
137 * ext_mem_delete - Remove ext_mem_obj.
138 * @objs: Root of search tree that contains @obj.
139 * @obj: ext_mem_obj to delete.
140 *
141 * Delete @obj from @objs.
142 * Caller is responsible for locking.
143 */
ext_mem_delete(struct bst_root * objs,struct ext_mem_obj * obj)144 static inline void ext_mem_delete(struct bst_root* objs,
145 struct ext_mem_obj* obj) {
146 bst_delete(objs, &obj->node);
147 }
148
149 /**
150 * ext_mem_lookup - Lookup ext_mem_obj by id.
151 * @objs: Root of search tree that might contain and object with id @id.
152 * @id: Id of object to return.
153 *
154 * Caller is responsible for locking.
155 *
156 * Return: ext_mem_obj in @objs matching @id, or %NULL if no matching
157 * ext_mem_obj is found.
158 */
159 struct ext_mem_obj* ext_mem_lookup(struct bst_root* objs, ext_mem_obj_id_t id);
160
161 /**
162 * ext_mem_obj_set_match_tag - Set match tag on ext_mem_obj.
163 * @obj: &ext_mem_obj->vmm_obj.
164 * @match_tag: Set match_tag on @obj. The object can only be mapped if this
165 * matches the tag used when creating @obj. Pass 0 to return to
166 * initial state.
167 */
168 void ext_mem_obj_set_match_tag(struct vmm_obj* obj, uint64_t match_tag);
169
170 /**
171 * ext_mem_obj_check_flags - vmm_obj_ops->check_flags for ext_mem_obj.
172 * @obj: &ext_mem_obj->vmm_obj.
173 * @arch_mmu_flags: arch_mmu_flags to check and modify.
174 *
175 * Compare @arch_mmu_flags against &ext_mem_obj->arch_mmu_flags. Return
176 * ERR_ACCESS_DENIED if permissions &ext_mem_obj->arch_mmu_flags are more
177 * restrictive than @arch_mmu_flags. Copy memory type flags from
178 * &ext_mem_obj->arch_mmu_flags to @arch_mmu_flags.
179 *
180 * Return: 0 on success, error code on failure.
181 */
182 int ext_mem_obj_check_flags(struct vmm_obj* obj, uint* arch_mmu_flags);
183
184 /**
185 * ext_mem_obj_get_page - vmm_obj_ops->get_page for ext_mem_obj.
186 * @obj: &ext_mem_obj->vmm_obj.
187 * @offset: Byte offset into @obj.
188 * @paddr: Pointer to return physical address in.
189 * @paddr_size: Pointer to return size of physically contiguous region at
190 * @offset.
191 *
192 * Get single page or physically contiguous region at @offset bytes from
193 * start of @obj.
194 *
195 * Return: 0 on success, error code on failure.
196 */
197 int ext_mem_obj_get_page(struct vmm_obj* obj,
198 size_t offset,
199 paddr_t* paddr,
200 size_t* paddr_size);
201
202 /**
203 * ext_mem_map_obj_id - Lookup and map external memory object.
204 * @aspace: Pass-through to vmm_alloc_obj.
205 * @name: Pass-through to vmm_alloc_obj.
206 * @client_id: Id of external entity where the memory originated.
207 * @mem_obj_id: Id of shared memory object to lookup and map.
208 * @tag: Tag of the memory. If a non-FF-A object, use 0.
209 * @offset: Pass-through to vmm_alloc_obj.
210 * @size: Pass-through to vmm_alloc_obj.
211 * @ptr: Pass-through to vmm_alloc_obj.
212 * @align_log2: Pass-through to vmm_alloc_obj.
213 * @vmm_flags: Pass-through to vmm_alloc_obj.
214 * @arch_mmu_flags: Pass-through to vmm_alloc_obj.
215 *
216 * Return: 0 on success, negative error code if object could not be mapped.
217 */
218 status_t ext_mem_map_obj_id(struct vmm_aspace* aspace,
219 const char* name,
220 ext_mem_client_id_t client_id,
221 ext_mem_obj_id_t mem_obj_id,
222 uint64_t tag,
223 size_t offset,
224 size_t size,
225 void** ptr,
226 uint8_t align_log2,
227 uint vmm_flags,
228 uint arch_mmu_flags);
229
230 /**
231 * ext_mem_get_vmm_obj - Lookup shared memory object.
232 * @client_id: Id of external entity where the memory originated.
233 * @mem_obj_id: Id of shared memory object to lookup and return.
234 * @tag: Tag of the memory. If a non-FF-A object, use 0.
235 * @size: Size hint for object. Caller expects an object at least this
236 * big.
237 * @objp: Pointer to return object in.
238 * @obj_ref: Reference to *@objp.
239 *
240 * Not provided by ext_mem.
241 *
242 * Return: 0 on success. ERR_NOT_FOUND if @id does not exist.
243 */
244 status_t ext_mem_get_vmm_obj(ext_mem_client_id_t client_id,
245 ext_mem_obj_id_t mem_obj_id,
246 uint64_t tag,
247 size_t size,
248 struct vmm_obj** objp,
249 struct obj_ref* obj_ref);
250