blob: 984bf021b5407eab14d4ff613a2ce5506f8a2fd8 [file] [log] [blame]
Andrew Walbranb5ab43c2020-04-30 11:32:54 +01001/*
2 * Copyright 2019 The Hafnium Authors.
3 *
Andrew Walbrane959ec12020-06-17 15:01:09 +01004 * Use of this source code is governed by a BSD-style
5 * license that can be found in the LICENSE file or at
6 * https://opensource.org/licenses/BSD-3-Clause.
Andrew Walbranb5ab43c2020-04-30 11:32:54 +01007 */
8
9#include "hf/ffa.h"
10
11#include <stddef.h>
12
13#include "hf/types.h"
14
15#if defined(__linux__) && defined(__KERNEL__)
16#include <linux/kernel.h>
17#include <linux/string.h>
18
19#else
20#include "hf/std.h"
21#endif
22
Raghu Krishnamurthy03f21d22021-11-02 18:39:23 -070023static void ffa_copy_memory_region_constituents(
24 struct ffa_memory_region_constituent *dest,
25 const struct ffa_memory_region_constituent *src)
26{
27 dest->address = src->address;
28 dest->page_count = src->page_count;
29 dest->reserved = 0;
30}
31
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010032/**
Andrew Walbranca808b12020-05-15 17:22:28 +010033 * Initialises the header of the given `ffa_memory_region`, not including the
34 * composite memory region offset.
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010035 */
Andrew Walbranca808b12020-05-15 17:22:28 +010036static void ffa_memory_region_init_header(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010037 struct ffa_memory_region *memory_region, ffa_vm_id_t sender,
38 ffa_memory_attributes_t attributes, ffa_memory_region_flags_t flags,
39 ffa_memory_handle_t handle, uint32_t tag, ffa_vm_id_t receiver,
Andrew Walbranca808b12020-05-15 17:22:28 +010040 ffa_memory_access_permissions_t permissions)
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010041{
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010042 memory_region->sender = sender;
43 memory_region->attributes = attributes;
44 memory_region->reserved_0 = 0;
45 memory_region->flags = flags;
46 memory_region->handle = handle;
47 memory_region->tag = tag;
48 memory_region->reserved_1 = 0;
49 memory_region->receiver_count = 1;
50 memory_region->receivers[0].receiver_permissions.receiver = receiver;
51 memory_region->receivers[0].receiver_permissions.permissions =
52 permissions;
53 memory_region->receivers[0].receiver_permissions.flags = 0;
Andrew Walbranca808b12020-05-15 17:22:28 +010054 memory_region->receivers[0].reserved_0 = 0;
55}
56
57/**
58 * Initialises the given `ffa_memory_region` and copies as many as possible of
59 * the given constituents to it.
60 *
61 * Returns the number of constituents remaining which wouldn't fit, and (via
62 * return parameters) the size in bytes of the first fragment of data copied to
63 * `memory_region` (attributes, constituents and memory region header size), and
64 * the total size of the memory sharing message including all constituents.
65 */
66uint32_t ffa_memory_region_init(
67 struct ffa_memory_region *memory_region, size_t memory_region_max_size,
68 ffa_vm_id_t sender, ffa_vm_id_t receiver,
69 const struct ffa_memory_region_constituent constituents[],
70 uint32_t constituent_count, uint32_t tag,
71 ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
72 enum ffa_instruction_access instruction_access,
73 enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
74 enum ffa_memory_shareability shareability, uint32_t *total_length,
75 uint32_t *fragment_length)
76{
77 ffa_memory_access_permissions_t permissions = 0;
78 ffa_memory_attributes_t attributes = 0;
79 struct ffa_composite_memory_region *composite_memory_region;
80 uint32_t fragment_max_constituents;
81 uint32_t count_to_copy;
82 uint32_t i;
83 uint32_t constituents_offset;
84
85 /* Set memory region's permissions. */
86 ffa_set_data_access_attr(&permissions, data_access);
87 ffa_set_instruction_access_attr(&permissions, instruction_access);
88
89 /* Set memory region's page attributes. */
90 ffa_set_memory_type_attr(&attributes, type);
91 ffa_set_memory_cacheability_attr(&attributes, cacheability);
92 ffa_set_memory_shareability_attr(&attributes, shareability);
93
94 ffa_memory_region_init_header(memory_region, sender, attributes, flags,
95 0, tag, receiver, permissions);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +010096 /*
97 * Note that `sizeof(struct_ffa_memory_region)` and `sizeof(struct
98 * ffa_memory_access)` must both be multiples of 16 (as verified by the
99 * asserts in `ffa_memory.c`, so it is guaranteed that the offset we
100 * calculate here is aligned to a 64-bit boundary and so 64-bit values
101 * can be copied without alignment faults.
102 */
103 memory_region->receivers[0].composite_memory_region_offset =
104 sizeof(struct ffa_memory_region) +
105 memory_region->receiver_count *
106 sizeof(struct ffa_memory_access);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100107
108 composite_memory_region =
109 ffa_memory_region_get_composite(memory_region, 0);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100110 composite_memory_region->page_count = 0;
111 composite_memory_region->constituent_count = constituent_count;
112 composite_memory_region->reserved_0 = 0;
113
Andrew Walbranca808b12020-05-15 17:22:28 +0100114 constituents_offset =
115 memory_region->receivers[0].composite_memory_region_offset +
116 sizeof(struct ffa_composite_memory_region);
117 fragment_max_constituents =
118 (memory_region_max_size - constituents_offset) /
119 sizeof(struct ffa_memory_region_constituent);
120
121 count_to_copy = constituent_count;
122 if (count_to_copy > fragment_max_constituents) {
123 count_to_copy = fragment_max_constituents;
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100124 }
125
Andrew Walbranca808b12020-05-15 17:22:28 +0100126 for (i = 0; i < constituent_count; ++i) {
127 if (i < count_to_copy) {
Raghu Krishnamurthy03f21d22021-11-02 18:39:23 -0700128 ffa_copy_memory_region_constituents(
129 &composite_memory_region->constituents[i],
130 &constituents[i]);
Andrew Walbranca808b12020-05-15 17:22:28 +0100131 }
132 composite_memory_region->page_count +=
133 constituents[i].page_count;
134 }
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100135
Andrew Walbranca808b12020-05-15 17:22:28 +0100136 if (total_length != NULL) {
137 *total_length =
138 constituents_offset +
139 composite_memory_region->constituent_count *
140 sizeof(struct ffa_memory_region_constituent);
141 }
142 if (fragment_length != NULL) {
143 *fragment_length =
144 constituents_offset +
145 count_to_copy *
146 sizeof(struct ffa_memory_region_constituent);
147 }
148
149 return composite_memory_region->constituent_count - count_to_copy;
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100150}
151
152/**
Andrew Walbranca808b12020-05-15 17:22:28 +0100153 * Initialises the given `ffa_memory_region` to be used for an
154 * `FFA_MEM_RETRIEVE_REQ` by the receiver of a memory transaction.
155 *
156 * Returns the size of the message written.
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100157 */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100158uint32_t ffa_memory_retrieve_request_init(
159 struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
160 ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag,
161 ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
162 enum ffa_instruction_access instruction_access,
163 enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
164 enum ffa_memory_shareability shareability)
165{
166 ffa_memory_access_permissions_t permissions = 0;
167 ffa_memory_attributes_t attributes = 0;
168
169 /* Set memory region's permissions. */
170 ffa_set_data_access_attr(&permissions, data_access);
171 ffa_set_instruction_access_attr(&permissions, instruction_access);
172
173 /* Set memory region's page attributes. */
174 ffa_set_memory_type_attr(&attributes, type);
175 ffa_set_memory_cacheability_attr(&attributes, cacheability);
176 ffa_set_memory_shareability_attr(&attributes, shareability);
177
Andrew Walbranca808b12020-05-15 17:22:28 +0100178 ffa_memory_region_init_header(memory_region, sender, attributes, flags,
179 handle, tag, receiver, permissions);
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100180 /*
181 * Offset 0 in this case means that the hypervisor should allocate the
182 * address ranges. This is the only configuration supported by Hafnium,
183 * as it enforces 1:1 mappings in the stage 2 page tables.
184 */
185 memory_region->receivers[0].composite_memory_region_offset = 0;
186 memory_region->receivers[0].reserved_0 = 0;
187
188 return sizeof(struct ffa_memory_region) +
189 memory_region->receiver_count * sizeof(struct ffa_memory_access);
190}
191
Andrew Walbranca808b12020-05-15 17:22:28 +0100192/**
193 * Initialises the given `ffa_memory_region` to be used for an
194 * `FFA_MEM_RETRIEVE_REQ` from the hypervisor to the TEE.
195 *
196 * Returns the size of the message written.
197 */
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100198uint32_t ffa_memory_lender_retrieve_request_init(
199 struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
200 ffa_vm_id_t sender)
201{
202 memory_region->sender = sender;
203 memory_region->attributes = 0;
204 memory_region->reserved_0 = 0;
205 memory_region->flags = 0;
206 memory_region->reserved_1 = 0;
207 memory_region->handle = handle;
208 memory_region->tag = 0;
209 memory_region->receiver_count = 0;
210
211 return sizeof(struct ffa_memory_region);
212}
213
Andrew Walbranca808b12020-05-15 17:22:28 +0100214/**
215 * Initialises the given `ffa_memory_region` to be used for an
216 * `FFA_MEM_RETRIEVE_RESP`, including the given constituents for the first
217 * fragment.
218 *
219 * Returns true on success, or false if the given constituents won't all fit in
220 * the first fragment.
221 */
222bool ffa_retrieved_memory_region_init(
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100223 struct ffa_memory_region *response, size_t response_max_size,
224 ffa_vm_id_t sender, ffa_memory_attributes_t attributes,
225 ffa_memory_region_flags_t flags, ffa_memory_handle_t handle,
226 ffa_vm_id_t receiver, ffa_memory_access_permissions_t permissions,
Andrew Walbranca808b12020-05-15 17:22:28 +0100227 uint32_t page_count, uint32_t total_constituent_count,
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100228 const struct ffa_memory_region_constituent constituents[],
Andrew Walbranca808b12020-05-15 17:22:28 +0100229 uint32_t fragment_constituent_count, uint32_t *total_length,
230 uint32_t *fragment_length)
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100231{
Andrew Walbranca808b12020-05-15 17:22:28 +0100232 struct ffa_composite_memory_region *composite_memory_region;
233 uint32_t i;
234 uint32_t constituents_offset;
235
236 ffa_memory_region_init_header(response, sender, attributes, flags,
237 handle, 0, receiver, permissions);
238 /*
239 * Note that `sizeof(struct_ffa_memory_region)` and `sizeof(struct
240 * ffa_memory_access)` must both be multiples of 16 (as verified by the
241 * asserts in `ffa_memory.c`, so it is guaranteed that the offset we
242 * calculate here is aligned to a 64-bit boundary and so 64-bit values
243 * can be copied without alignment faults.
244 */
245 response->receivers[0].composite_memory_region_offset =
246 sizeof(struct ffa_memory_region) +
247 response->receiver_count * sizeof(struct ffa_memory_access);
248
249 composite_memory_region = ffa_memory_region_get_composite(response, 0);
250 composite_memory_region->page_count = page_count;
251 composite_memory_region->constituent_count = total_constituent_count;
252 composite_memory_region->reserved_0 = 0;
253
254 constituents_offset =
255 response->receivers[0].composite_memory_region_offset +
256 sizeof(struct ffa_composite_memory_region);
257 if (constituents_offset +
258 fragment_constituent_count *
259 sizeof(struct ffa_memory_region_constituent) >
260 response_max_size) {
261 return false;
262 }
263
264 for (i = 0; i < fragment_constituent_count; ++i) {
265 composite_memory_region->constituents[i] = constituents[i];
266 }
267
268 if (total_length != NULL) {
269 *total_length =
270 constituents_offset +
271 composite_memory_region->constituent_count *
272 sizeof(struct ffa_memory_region_constituent);
273 }
274 if (fragment_length != NULL) {
275 *fragment_length =
276 constituents_offset +
277 fragment_constituent_count *
278 sizeof(struct ffa_memory_region_constituent);
279 }
280
281 return true;
282}
283
284uint32_t ffa_memory_fragment_init(
285 struct ffa_memory_region_constituent *fragment,
286 size_t fragment_max_size,
287 const struct ffa_memory_region_constituent constituents[],
288 uint32_t constituent_count, uint32_t *fragment_length)
289{
290 uint32_t fragment_max_constituents =
291 fragment_max_size /
292 sizeof(struct ffa_memory_region_constituent);
293 uint32_t count_to_copy = constituent_count;
294 uint32_t i;
295
296 if (count_to_copy > fragment_max_constituents) {
297 count_to_copy = fragment_max_constituents;
298 }
299
300 for (i = 0; i < count_to_copy; ++i) {
Raghu Krishnamurthy03f21d22021-11-02 18:39:23 -0700301 ffa_copy_memory_region_constituents(&fragment[i],
302 &constituents[i]);
Andrew Walbranca808b12020-05-15 17:22:28 +0100303 }
304
305 if (fragment_length != NULL) {
306 *fragment_length = count_to_copy *
307 sizeof(struct ffa_memory_region_constituent);
308 }
309
310 return constituent_count - count_to_copy;
Andrew Walbranb5ab43c2020-04-30 11:32:54 +0100311}