blob: 07bc33a48cb47d88390eca56f2007fe58f1eb044 [file] [log] [blame]
J-Alves7581c382020-05-07 18:34:20 +01001/*
Max Shvetsov103e0562021-02-04 16:58:31 +00002 * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
J-Alves7581c382020-05-07 18:34:20 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef FFA_HELPERS_H
8#define FFA_HELPERS_H
9
J-Alves8f08a052020-05-26 17:14:40 +010010#include <ffa_svc.h>
J-Alves7581c382020-05-07 18:34:20 +010011#include <tftf_lib.h>
12#include <utils_def.h>
13
14/* This error code must be different to the ones used by FFA */
15#define FFA_TFTF_ERROR -42
16
Daniel Boulbye79d2072021-03-03 11:34:53 +000017typedef unsigned short ffa_id_t;
J-Alves5aecd982020-06-11 10:25:33 +010018typedef unsigned short ffa_vm_count_t;
19typedef unsigned short ffa_vcpu_count_t;
J-Alvesf3a393c2020-10-23 16:00:39 +010020typedef uint64_t ffa_memory_handle_t;
21/** Flags to indicate properties of receivers during memory region retrieval. */
22typedef uint8_t ffa_memory_receiver_flags_t;
J-Alves5aecd982020-06-11 10:25:33 +010023
J-Alvesd708c032020-11-19 12:14:21 +000024struct ffa_uuid {
25 const uint32_t uuid[4];
26};
27
J-Alves7581c382020-05-07 18:34:20 +010028#ifndef __ASSEMBLY__
29
30#include <stdint.h>
31
Max Shvetsov0b7d25f2021-03-05 13:46:42 +000032/** Partition property: partition supports receipt of direct requests. */
33#define FFA_PARTITION_DIRECT_REQ_RECV 0x1
34
35/** Partition property: partition can send direct requests. */
36#define FFA_PARTITION_DIRECT_REQ_SEND 0x2
37
38/** Partition property: partition can send and receive indirect messages. */
39#define FFA_PARTITION_INDIRECT_MSG 0x4
40
Max Shvetsovc32f4782020-06-23 09:41:15 +010041struct ffa_partition_info {
42 /** The ID of the VM the information is about */
Daniel Boulbye79d2072021-03-03 11:34:53 +000043 ffa_id_t id;
Max Shvetsovc32f4782020-06-23 09:41:15 +010044 /** The number of execution contexts implemented by the partition */
45 uint16_t exec_context;
46 /** The Partition's properties, e.g. supported messaging methods */
47 uint32_t properties;
48};
49
J-Alves6cb21d92021-01-07 15:18:12 +000050static inline uint32_t ffa_func_id(smc_ret_values val) {
51 return (uint32_t) val.ret0;
52}
53
54static inline int32_t ffa_error_code(smc_ret_values val) {
55 return (int32_t) val.ret2;
56}
57
Daniel Boulby198deda2021-03-03 11:35:25 +000058static inline ffa_id_t ffa_endpoint_id(smc_ret_values val) {
59 return (ffa_id_t) val.ret2 & 0xffff;
60}
61
J-Alvesf3a393c2020-10-23 16:00:39 +010062enum ffa_data_access {
63 FFA_DATA_ACCESS_NOT_SPECIFIED,
64 FFA_DATA_ACCESS_RO,
65 FFA_DATA_ACCESS_RW,
66 FFA_DATA_ACCESS_RESERVED,
67};
68
69enum ffa_instruction_access {
70 FFA_INSTRUCTION_ACCESS_NOT_SPECIFIED,
71 FFA_INSTRUCTION_ACCESS_NX,
72 FFA_INSTRUCTION_ACCESS_X,
73 FFA_INSTRUCTION_ACCESS_RESERVED,
74};
75
76enum ffa_memory_type {
77 FFA_MEMORY_NOT_SPECIFIED_MEM,
78 FFA_MEMORY_DEVICE_MEM,
79 FFA_MEMORY_NORMAL_MEM,
80};
81
82enum ffa_memory_cacheability {
83 FFA_MEMORY_CACHE_RESERVED = 0x0,
84 FFA_MEMORY_CACHE_NON_CACHEABLE = 0x1,
85 FFA_MEMORY_CACHE_RESERVED_1 = 0x2,
86 FFA_MEMORY_CACHE_WRITE_BACK = 0x3,
87 FFA_MEMORY_DEV_NGNRNE = 0x0,
88 FFA_MEMORY_DEV_NGNRE = 0x1,
89 FFA_MEMORY_DEV_NGRE = 0x2,
90 FFA_MEMORY_DEV_GRE = 0x3,
91};
92
93enum ffa_memory_shareability {
94 FFA_MEMORY_SHARE_NON_SHAREABLE,
95 FFA_MEMORY_SHARE_RESERVED,
96 FFA_MEMORY_OUTER_SHAREABLE,
97 FFA_MEMORY_INNER_SHAREABLE,
98};
99
100typedef uint8_t ffa_memory_access_permissions_t;
101
102/**
103 * This corresponds to table "Memory region attributes descriptor" of the FF-A
104 * 1.0 specification.
105 */
106typedef uint8_t ffa_memory_attributes_t;
107
108#define FFA_DATA_ACCESS_OFFSET (0x0U)
109#define FFA_DATA_ACCESS_MASK ((0x3U) << FFA_DATA_ACCESS_OFFSET)
110
111#define FFA_INSTRUCTION_ACCESS_OFFSET (0x2U)
112#define FFA_INSTRUCTION_ACCESS_MASK ((0x3U) << FFA_INSTRUCTION_ACCESS_OFFSET)
113
114#define FFA_MEMORY_TYPE_OFFSET (0x4U)
115#define FFA_MEMORY_TYPE_MASK ((0x3U) << FFA_MEMORY_TYPE_OFFSET)
116
117#define FFA_MEMORY_CACHEABILITY_OFFSET (0x2U)
118#define FFA_MEMORY_CACHEABILITY_MASK ((0x3U) << FFA_MEMORY_CACHEABILITY_OFFSET)
119
120#define FFA_MEMORY_SHAREABILITY_OFFSET (0x0U)
121#define FFA_MEMORY_SHAREABILITY_MASK ((0x3U) << FFA_MEMORY_SHAREABILITY_OFFSET)
122
123#define ATTR_FUNCTION_SET(name, container_type, offset, mask) \
124 static inline void ffa_set_##name##_attr(container_type *attr, \
125 const enum ffa_##name perm) \
126 { \
127 *attr = (*attr & ~(mask)) | ((perm << offset) & mask); \
128 }
129
130#define ATTR_FUNCTION_GET(name, container_type, offset, mask) \
131 static inline enum ffa_##name ffa_get_##name##_attr( \
132 container_type attr) \
133 { \
134 return (enum ffa_##name)((attr & mask) >> offset); \
135 }
136
137ATTR_FUNCTION_SET(data_access, ffa_memory_access_permissions_t,
138 FFA_DATA_ACCESS_OFFSET, FFA_DATA_ACCESS_MASK)
139ATTR_FUNCTION_GET(data_access, ffa_memory_access_permissions_t,
140 FFA_DATA_ACCESS_OFFSET, FFA_DATA_ACCESS_MASK)
141
142ATTR_FUNCTION_SET(instruction_access, ffa_memory_access_permissions_t,
143 FFA_INSTRUCTION_ACCESS_OFFSET, FFA_INSTRUCTION_ACCESS_MASK)
144ATTR_FUNCTION_GET(instruction_access, ffa_memory_access_permissions_t,
145 FFA_INSTRUCTION_ACCESS_OFFSET, FFA_INSTRUCTION_ACCESS_MASK)
146
147ATTR_FUNCTION_SET(memory_type, ffa_memory_attributes_t, FFA_MEMORY_TYPE_OFFSET,
148 FFA_MEMORY_TYPE_MASK)
149ATTR_FUNCTION_GET(memory_type, ffa_memory_attributes_t, FFA_MEMORY_TYPE_OFFSET,
150 FFA_MEMORY_TYPE_MASK)
151
152ATTR_FUNCTION_SET(memory_cacheability, ffa_memory_attributes_t,
153 FFA_MEMORY_CACHEABILITY_OFFSET, FFA_MEMORY_CACHEABILITY_MASK)
154ATTR_FUNCTION_GET(memory_cacheability, ffa_memory_attributes_t,
155 FFA_MEMORY_CACHEABILITY_OFFSET, FFA_MEMORY_CACHEABILITY_MASK)
156
157ATTR_FUNCTION_SET(memory_shareability, ffa_memory_attributes_t,
158 FFA_MEMORY_SHAREABILITY_OFFSET, FFA_MEMORY_SHAREABILITY_MASK)
159ATTR_FUNCTION_GET(memory_shareability, ffa_memory_attributes_t,
160 FFA_MEMORY_SHAREABILITY_OFFSET, FFA_MEMORY_SHAREABILITY_MASK)
161
162#define FFA_MEMORY_HANDLE_ALLOCATOR_MASK \
163 ((ffa_memory_handle_t)(UINT64_C(1) << 63))
164#define FFA_MEMORY_HANDLE_ALLOCATOR_HYPERVISOR \
165 ((ffa_memory_handle_t)(UINT64_C(1) << 63))
166#define FFA_MEMORY_HANDLE_INVALID (~UINT64_C(0))
167
168/**
169 * A set of contiguous pages which is part of a memory region. This corresponds
170 * to table "Constituent memory region descriptor" of the FFA 1.0 specification.
171 */
172struct ffa_memory_region_constituent {
173 /**
174 * The base IPA of the constituent memory region, aligned to 4 kiB page
175 * size granularity.
176 */
177 void *address;
178 /** The number of 4 kiB pages in the constituent memory region. */
179 uint32_t page_count;
180 /** Reserved field, must be 0. */
181 uint32_t reserved;
182};
183
184/**
185 * A set of pages comprising a memory region. This corresponds to table
186 * "Composite memory region descriptor" of the FFA 1.0 specification.
187 */
188struct ffa_composite_memory_region {
189 /**
190 * The total number of 4 kiB pages included in this memory region. This
191 * must be equal to the sum of page counts specified in each
192 * `ffa_memory_region_constituent`.
193 */
194 uint32_t page_count;
195 /**
196 * The number of constituents (`ffa_memory_region_constituent`)
197 * included in this memory region range.
198 */
199 uint32_t constituent_count;
200 /** Reserved field, must be 0. */
201 uint64_t reserved_0;
202 /** An array of `constituent_count` memory region constituents. */
203 struct ffa_memory_region_constituent constituents[];
204};
205
206/**
207 * This corresponds to table "Memory access permissions descriptor" of the FFA
208 * 1.0 specification.
209 */
210struct ffa_memory_region_attributes {
211 /** The ID of the VM to which the memory is being given or shared. */
Daniel Boulbye79d2072021-03-03 11:34:53 +0000212 ffa_id_t receiver;
J-Alvesf3a393c2020-10-23 16:00:39 +0100213 /**
214 * The permissions with which the memory region should be mapped in the
215 * receiver's page table.
216 */
217 ffa_memory_access_permissions_t permissions;
218 /**
219 * Flags used during FFA_MEM_RETRIEVE_REQ and FFA_MEM_RETRIEVE_RESP
220 * for memory regions with multiple borrowers.
221 */
222 ffa_memory_receiver_flags_t flags;
223};
224
225/** Flags to control the behaviour of a memory sharing transaction. */
226typedef uint32_t ffa_memory_region_flags_t;
227
228/**
229 * Clear memory region contents after unmapping it from the sender and before
230 * mapping it for any receiver.
231 */
232#define FFA_MEMORY_REGION_FLAG_CLEAR 0x1U
233
234/**
235 * Whether the hypervisor may time slice the memory sharing or retrieval
236 * operation.
237 */
238#define FFA_MEMORY_REGION_FLAG_TIME_SLICE 0x2U
239
240/**
241 * Whether the hypervisor should clear the memory region after the receiver
242 * relinquishes it or is aborted.
243 */
244#define FFA_MEMORY_REGION_FLAG_CLEAR_RELINQUISH 0x4U
245
246#define FFA_MEMORY_REGION_TRANSACTION_TYPE_MASK ((0x3U) << 3)
247#define FFA_MEMORY_REGION_TRANSACTION_TYPE_UNSPECIFIED ((0x0U) << 3)
248#define FFA_MEMORY_REGION_TRANSACTION_TYPE_SHARE ((0x1U) << 3)
249#define FFA_MEMORY_REGION_TRANSACTION_TYPE_LEND ((0x2U) << 3)
250#define FFA_MEMORY_REGION_TRANSACTION_TYPE_DONATE ((0x3U) << 3)
251
J-Alves0435cae2020-11-06 10:49:56 +0000252/** The maximum number of recipients a memory region may be sent to. */
253#define MAX_MEM_SHARE_RECIPIENTS 1U
254
J-Alvesf3a393c2020-10-23 16:00:39 +0100255/**
256 * This corresponds to table "Endpoint memory access descriptor" of the FFA 1.0
257 * specification.
258 */
259struct ffa_memory_access {
260 struct ffa_memory_region_attributes receiver_permissions;
261 /**
262 * Offset in bytes from the start of the outer `ffa_memory_region` to
263 * an `ffa_composite_memory_region` struct.
264 */
265 uint32_t composite_memory_region_offset;
266 uint64_t reserved_0;
267};
268
269/**
270 * Information about a set of pages which are being shared. This corresponds to
271 * table "Lend, donate or share memory transaction descriptor" of the FFA
272 * 1.0 specification. Note that it is also used for retrieve requests and
273 * responses.
274 */
275struct ffa_memory_region {
276 /**
277 * The ID of the VM which originally sent the memory region, i.e. the
278 * owner.
279 */
Daniel Boulbye79d2072021-03-03 11:34:53 +0000280 ffa_id_t sender;
J-Alvesf3a393c2020-10-23 16:00:39 +0100281 ffa_memory_attributes_t attributes;
282 /** Reserved field, must be 0. */
283 uint8_t reserved_0;
284 /** Flags to control behaviour of the transaction. */
285 ffa_memory_region_flags_t flags;
286 ffa_memory_handle_t handle;
287 /**
288 * An implementation defined value associated with the receiver and the
289 * memory region.
290 */
291 uint64_t tag;
292 /** Reserved field, must be 0. */
293 uint32_t reserved_1;
294 /**
295 * The number of `ffa_memory_access` entries included in this
296 * transaction.
297 */
298 uint32_t receiver_count;
299 /**
300 * An array of `attribute_count` endpoint memory access descriptors.
301 * Each one specifies a memory region offset, an endpoint and the
302 * attributes with which this memory region should be mapped in that
303 * endpoint's page table.
304 */
305 struct ffa_memory_access receivers[];
306};
307
308/**
309 * Descriptor used for FFA_MEM_RELINQUISH requests. This corresponds to table
310 * "Descriptor to relinquish a memory region" of the FFA 1.0 specification.
311 */
312struct ffa_mem_relinquish {
313 ffa_memory_handle_t handle;
314 ffa_memory_region_flags_t flags;
315 uint32_t endpoint_count;
Daniel Boulbye79d2072021-03-03 11:34:53 +0000316 ffa_id_t endpoints[];
J-Alvesf3a393c2020-10-23 16:00:39 +0100317};
318
319static inline ffa_memory_handle_t ffa_assemble_handle(uint32_t h1, uint32_t h2)
320{
321 return (uint64_t)h1 | (uint64_t)h2 << 32;
322}
323
324static inline ffa_memory_handle_t ffa_mem_success_handle(smc_ret_values r)
325{
326 return ffa_assemble_handle(r.ret2, r.ret3);
327}
328
329/**
330 * Gets the `ffa_composite_memory_region` for the given receiver from an
331 * `ffa_memory_region`, or NULL if it is not valid.
332 */
333static inline struct ffa_composite_memory_region *
334ffa_memory_region_get_composite(struct ffa_memory_region *memory_region,
335 uint32_t receiver_index)
336{
337 uint32_t offset = memory_region->receivers[receiver_index]
338 .composite_memory_region_offset;
339
340 if (offset == 0) {
341 return NULL;
342 }
343
344 return (struct ffa_composite_memory_region *)((uint8_t *)memory_region +
345 offset);
346}
347
348static inline uint32_t ffa_mem_relinquish_init(
349 struct ffa_mem_relinquish *relinquish_request,
350 ffa_memory_handle_t handle, ffa_memory_region_flags_t flags,
Daniel Boulbye79d2072021-03-03 11:34:53 +0000351 ffa_id_t sender)
J-Alvesf3a393c2020-10-23 16:00:39 +0100352{
353 relinquish_request->handle = handle;
354 relinquish_request->flags = flags;
355 relinquish_request->endpoint_count = 1;
356 relinquish_request->endpoints[0] = sender;
Daniel Boulbye79d2072021-03-03 11:34:53 +0000357 return sizeof(struct ffa_mem_relinquish) + sizeof(ffa_id_t);
J-Alvesf3a393c2020-10-23 16:00:39 +0100358}
359
360uint32_t ffa_memory_retrieve_request_init(
361 struct ffa_memory_region *memory_region, ffa_memory_handle_t handle,
Daniel Boulbye79d2072021-03-03 11:34:53 +0000362 ffa_id_t sender, ffa_id_t receiver, uint32_t tag,
J-Alvesf3a393c2020-10-23 16:00:39 +0100363 ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
364 enum ffa_instruction_access instruction_access,
365 enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
366 enum ffa_memory_shareability shareability);
367
368uint32_t ffa_memory_region_init(
369 struct ffa_memory_region *memory_region, size_t memory_region_max_size,
Daniel Boulbye79d2072021-03-03 11:34:53 +0000370 ffa_id_t sender, ffa_id_t receiver,
J-Alvesf3a393c2020-10-23 16:00:39 +0100371 const struct ffa_memory_region_constituent constituents[],
372 uint32_t constituent_count, uint32_t tag,
373 ffa_memory_region_flags_t flags, enum ffa_data_access data_access,
374 enum ffa_instruction_access instruction_access,
375 enum ffa_memory_type type, enum ffa_memory_cacheability cacheability,
376 enum ffa_memory_shareability shareability, uint32_t *total_length,
377 uint32_t *fragment_length);
378
Daniel Boulbye79d2072021-03-03 11:34:53 +0000379static inline ffa_id_t ffa_dir_msg_dest(smc_ret_values val) {
380 return (ffa_id_t)val.ret1 & U(0xFFFF);
J-Alves6cb21d92021-01-07 15:18:12 +0000381}
382
Daniel Boulbye79d2072021-03-03 11:34:53 +0000383static inline ffa_id_t ffa_dir_msg_source(smc_ret_values val) {
384 return (ffa_id_t)(val.ret1 >> 16U);
J-Alves6cb21d92021-01-07 15:18:12 +0000385}
386
Daniel Boulbye79d2072021-03-03 11:34:53 +0000387smc_ret_values ffa_msg_send_direct_req64(ffa_id_t source_id,
388 ffa_id_t dest_id, uint64_t arg0,
J-Alvesecd30742021-02-19 18:31:06 +0000389 uint64_t arg1, uint64_t arg2,
390 uint64_t arg3, uint64_t arg4);
J-Alvesd1aae292020-10-08 17:16:58 +0100391
Daniel Boulbye79d2072021-03-03 11:34:53 +0000392smc_ret_values ffa_msg_send_direct_req32(ffa_id_t source_id,
393 ffa_id_t dest_id, uint32_t arg0,
J-Alvesecd30742021-02-19 18:31:06 +0000394 uint32_t arg1, uint32_t arg2,
395 uint32_t arg3, uint32_t arg4);
396
Daniel Boulbye79d2072021-03-03 11:34:53 +0000397smc_ret_values ffa_msg_send_direct_resp64(ffa_id_t source_id,
398 ffa_id_t dest_id, uint64_t arg0,
J-Alvesecd30742021-02-19 18:31:06 +0000399 uint64_t arg1, uint64_t arg2,
400 uint64_t arg3, uint64_t arg4);
401
Daniel Boulbye79d2072021-03-03 11:34:53 +0000402smc_ret_values ffa_msg_send_direct_resp32(ffa_id_t source_id,
403 ffa_id_t dest_id, uint32_t arg0,
J-Alvesecd30742021-02-19 18:31:06 +0000404 uint32_t arg1, uint32_t arg2,
405 uint32_t arg3, uint32_t arg4);
J-Alves035b7d02021-02-11 10:40:35 +0000406
J-Alves7581c382020-05-07 18:34:20 +0100407smc_ret_values ffa_run(uint32_t dest_id, uint32_t vcpu_id);
J-Alves8f08a052020-05-26 17:14:40 +0100408smc_ret_values ffa_version(uint32_t input_version);
J-Alves5aecd982020-06-11 10:25:33 +0100409smc_ret_values ffa_id_get(void);
Daniel Boulby198deda2021-03-03 11:35:25 +0000410smc_ret_values ffa_spm_id_get(void);
J-Alves5aecd982020-06-11 10:25:33 +0100411smc_ret_values ffa_msg_wait(void);
J-Alves5aecd982020-06-11 10:25:33 +0100412smc_ret_values ffa_error(int32_t error_code);
Max Shvetsovc17c1d32020-06-11 15:03:01 +0100413smc_ret_values ffa_features(uint32_t feature);
Max Shvetsov0b7d25f2021-03-05 13:46:42 +0000414smc_ret_values ffa_partition_info_get(const struct ffa_uuid uuid);
Max Shvetsovc32f4782020-06-23 09:41:15 +0100415smc_ret_values ffa_rx_release(void);
Ruari Phippsbd0a7e42020-07-17 16:42:21 +0100416smc_ret_values ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages);
Daniel Boulbye0602902021-07-07 11:14:39 +0100417smc_ret_values ffa_rxtx_unmap(void);
J-Alves3ea46d12020-09-09 11:13:05 +0100418smc_ret_values ffa_mem_donate(uint32_t descriptor_length,
419 uint32_t fragment_length);
420smc_ret_values ffa_mem_lend(uint32_t descriptor_length,
421 uint32_t fragment_length);
422smc_ret_values ffa_mem_share(uint32_t descriptor_length,
423 uint32_t fragment_length);
424smc_ret_values ffa_mem_retrieve_req(uint32_t descriptor_length,
425 uint32_t fragment_length);
426smc_ret_values ffa_mem_relinquish(void);
427smc_ret_values ffa_mem_reclaim(uint64_t handle, uint32_t flags);
J-Alvesbcb1f972021-03-11 14:03:54 +0000428smc_ret_values ffa_notification_bitmap_create(ffa_id_t vm_id,
429 ffa_vcpu_count_t vcpu_count);
430smc_ret_values ffa_notification_bitmap_destroy(ffa_id_t vm_id);
J-Alves3ea46d12020-09-09 11:13:05 +0100431
J-Alves7581c382020-05-07 18:34:20 +0100432#endif /* __ASSEMBLY__ */
433
434#endif /* FFA_HELPERS_H */