1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*
3  * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
4  */
5 
6 #ifndef LIBSP_INCLUDE_SP_MEMORY_MANAGEMENT_H_
7 #define LIBSP_INCLUDE_SP_MEMORY_MANAGEMENT_H_
8 
9 /**
10  * @file  sp_memory_management.h
11  * @brief The file contains wrapper functions around the FF-A interfaces
12  *        described in section 8 of the specification.
13  */
14 
15 #include "ffa_memory_descriptors.h"
16 #include "sp_api_defines.h"
17 #include "sp_api_types.h"
18 #include <stdbool.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #ifdef __cplusplus
23 extern "C" {
24 #endif
25 
26 #if CFG_FFA_VERSION >= FFA_VERSION_1_1
27 /**
28  * @brief      Security state of the memory region
29  */
30 enum sp_memory_security_state {
31 	sp_memory_security_state_secure = 0x00,
32 	sp_memory_security_state_non_secure = 0x01,
33 };
34 #endif /* CFG_FFA_VERSION */
35 
36 /**
37  * @brief      Memory type of the region
38  */
39 enum sp_memory_type {
40 	sp_memory_type_not_specified = 0x00,	/**< Not specified */
41 	sp_memory_type_device_memory = 0x01,	/**< Device memory */
42 	sp_memory_type_normal_memory = 0x02,	/**< Normal memory */
43 	sp_memory_type_reserved = 0x03		/**< Reserved */
44 };
45 
46 /**
47  * @brief      Cacheability attribute of the memory region
48  */
49 enum sp_cacheability_attribute {
50 	sp_cacheability_reserved0 = 0x00,	/**< Reserved */
51 	sp_cacheability_non_cacheable = 0x01,	/**< Non-cacheable */
52 	sp_cacheability_reserved2 = 0x02,	/**< Reserved */
53 	sp_cacheability_write_back = 0x03	/**< Write-back */
54 };
55 
56 /**
57  * @brief      Device memory attributes (Gathering, Reordering, Early Write
58  *             Acknowledgment) of the memory region
59  */
60 enum sp_device_memory_attributes {
61 	sp_device_memory_nGnRnE = 0x00,	/**< nGnRnE */
62 	sp_device_memory_nGnRE = 0x01,	/**< nGnRE */
63 	sp_device_memory_nGRE = 0x02,	/**< nGRE */
64 	sp_device_memory_GRE = 0x03	/**< GRE */
65 };
66 
67 /**
68  * @brief      Shareability attribute of the memory region
69  */
70 enum sp_shareablity_attribute {
71 	sp_shareability_non_shareable = 0x00,	/**< Non-shareable */
72 	sp_shareability_reserved = 0x01,	/**< Reserved */
73 	sp_shareability_outer_shareable = 0x02,	/**< Outer shareable */
74 	sp_shareability_inner_shareable = 0x03	/**< Inner shareable */
75 };
76 
77 /**
78  * @brief      Instruction access permission of the memory region
79  */
80 enum sp_instruction_access_permission {
81 	sp_instruction_access_not_specified = 0x00,	/**< Not specified*/
82 	sp_instruction_access_not_executable = 0x01,	/**< Not executable */
83 	sp_instruction_access_executable = 0x02,	/**< Executable */
84 	sp_instruction_access_reserved = 0x03		/**< Reserved */
85 };
86 
87 /**
88  * @brief      Data access permission of the memory region
89  */
90 enum sp_data_access_permission {
91 	sp_data_access_not_specified = 0x00,	/**< Not specified */
92 	sp_data_access_read_only = 0x01,	/**< Read-only */
93 	sp_data_access_read_write = 0x02,	/**< Read-write */
94 	sp_data_access_reserved = 0x03		/**< Reserved */
95 };
96 
97 /**
98  * @brief      Memory management transaction type
99  */
100 enum sp_memory_transaction_type {
101 	/** Relayer specified */
102 	sp_memory_transaction_type_relayer_specified = 0x00,
103 	sp_memory_transaction_type_share = 0x01,	/**< Share */
104 	sp_memory_transaction_type_lend = 0x02,		/**< Lend */
105 	sp_memory_transaction_type_donate = 0x03,	/**< Donate */
106 };
107 
108 /**
109  * @brief       This union contains the memory attributes for normal and device
110  *              memory areas.
111  */
112 union sp_memory_attr {
113 	/** Normal memory attributes */
114 	struct sp_normal_memory_attributes {
115 		/** Cacheability attribute */
116 		enum sp_cacheability_attribute cacheability;
117 
118 		/** Shareability attribute */
119 		enum sp_shareablity_attribute shareability;
120 	} normal_memory;
121 
122 	/** Device memory attributes */
123 	enum sp_device_memory_attributes device_memory;
124 
125 #if CFG_FFA_VERSION >= FFA_VERSION_1_1
126 	/* Memory security state (secure/non-secure) */
127 	enum sp_memory_security_state security_state;
128 #endif /* CFG_FFA_VERSION */
129 };
130 
131 /**
132  * @brief      Flags are used to govern the behavior of a memory management
133  *             transaction.
134  */
135 struct sp_memory_transaction_flags {
136 	/**
137 	 * Zero memory on share, lend and donate call or zero memory before
138 	 * retrieval flag on a retrieve call or zero memory after relinquish on
139 	 * a relinquish call.
140 	 */
141 	bool zero_memory;
142 
143 	/**
144 	 * The flag specifies if the relayer can time slice this operation.
145 	 */
146 	bool operation_time_slicing;
147 
148 	/**
149 	 * The flag specified if the relayer must zero the memory region
150 	 * contents after unmapping it from the borrower's translation regime or
151 	 * if the borrower crashes.
152 	 * **This field can only be used at a retrieve call.**
153 	 */
154 	bool zero_memory_after_relinquish;
155 
156 	/**
157 	 * In an invocation of a retrieve call, this flag is used by the
158 	 * receiver to either specify the memory management transaction it is
159 	 * participating in or indicate that it will discover this information
160 	 * in the response structure.
161 	 * **This field can only be used at a retrieve call.**
162 	 */
163 	enum sp_memory_transaction_type transaction_type;
164 
165 	/**
166 	 * This flag is used by the receiver to specify the boundary.
167 	 * The valid range is 8K-120K in 8K steps. Zero means the relayer must
168 	 * choose the alignment boundary. The value of this field is multiplied
169 	 * by 8K.
170 	 *  **This field can only be used at a retrieve call.**
171 	 */
172 	uint32_t alignment_hint;
173 };
174 
175 /**
176  * @brief      This structure describes the details of a memory transaction. The
177  *             type is used in donate, lend, share and retrieve calls but the
178  *             mandatory and optional fields vary according to the description
179  *             of the individual fields.
180  */
181 struct sp_memory_descriptor {
182 	uint16_t sender_id;	/**< Sender FF-A ID, **must** be specified */
183 
184 	/**
185 	 * The type of the memory region (device, normal, not specified)
186 	 * * Donate: The owner **must not** specify it
187 	 * * Lend: The owner **must not** specify it
188 	 * * Share: The owner **must** specify it
189 	 * * Retrieve: The receiver **should** specify same or less permissive
190 	 *             as the owner. This field is filled with the value used by
191 	 *             the relayer on retrieve.
192 	 */
193 	enum sp_memory_type memory_type;
194 
195 	/**
196 	 * Memory region attributes
197 	 * The field of the union which is matching with the memory type should
198 	 * be used. In case of non-specified memory type the contents of the
199 	 * union is ignored.
200 	 */
201 	union sp_memory_attr mem_region_attr;
202 
203 	/**
204 	 * Flags are used to govern the behavior of a memory management
205 	 * transaction.
206 	 * The allowed flags for each transaction type is describe in the type's
207 	 * comment.
208 	 */
209 	struct sp_memory_transaction_flags flags;
210 
211 	/**
212 	 *  This 64-bit field must be used to specify an implementation defined
213 	 *  value associated with the transaction and known to participating
214 	 *  endpoints.
215 	 */
216 	uint64_t tag;
217 };
218 
219 /**
220  * @brief      Structure for specifying access restrictions for
221  *             receiver endpoints.
222  */
223 struct sp_memory_access_descriptor {
224 	uint16_t receiver_id;	/**< Receiver FF-A ID, **must** be specified */
225 
226 	/**
227 	 * Instruction access permission of the memory region
228 	 * * Donate: The owner **must not** specify it
229 	 * * Lend: The owner **must not** specify it
230 	 * * Share: The owner **must not** specify it
231 	 * * Retrieve: The receiver **must not** specify it on retrieving a
232 	 *             **shared or lent** memory region. The receiver **should**
233 	 *             specify it on retrieving a **donated** region. This field
234 	 *             is filled with the value used by the relayer on retrieve.
235 	 */
236 	enum sp_instruction_access_permission instruction_access;
237 
238 	/**
239 	 * Data access permission of the memory region
240 	 * * Donate: The owner **must not** specify it
241 	 * * Lend: The owner **must** specify it
242 	 * * Share: The owner **must** specify it
243 	 * * Retrieve: The receiver **must** specify it on retrieving a
244 	 *             **donated** memory region. The receiver **should**
245 	 *             specify same or less permissive as the owner on
246 	 *             retrieving **shared or lent** memory region.This field
247 	 *             is filled with the value used by the relayer on retrieve.
248 	 */
249 	enum sp_data_access_permission data_access;
250 };
251 
252 /**
253  * @brief      The structure describes a memory region by its base address
254  *             and its page count.
255  */
256 struct sp_memory_region {
257 	void *address;		/**< Base address of the memory region */
258 	uint32_t page_count;	/**< Number of 4K pages in memory region */
259 };
260 
261 /**
262  * @brief	Enum for describing data access permissions in
263  *		sp_memory_permission_get/set calls (FFA_MEM_PERM_GET/SET).
264  */
265 enum sp_mem_perm_data_access_permission {
266 	sp_mem_perm_data_perm_no_access = 0x00,
267 	sp_mem_perm_data_perm_read_write = 0x01,
268 	sp_mem_perm_data_perm_reserved = 0x02,
269 	sp_mem_perm_data_perm_read_only = 0x03
270 };
271 
272 /**
273  * @brief	Enum for describing instruction access permissions in
274  *		sp_memory_permission_get/set calls (FFA_MEM_PERM_GET/SET).
275  */
276 enum sp_mem_perm_instruction_access_permission {
277 	sp_mem_perm_instruction_perm_executable = 0x00,
278 	sp_mem_perm_instruction_perm_non_executable = 0x01
279 };
280 
281 /**
282  * @brief	Struct for describing memory access setting in
283  *		sp_memory_permission_get/set calls (FFA_MEM_PERM_GET/SET).
284  *
285  */
286 struct sp_mem_perm {
287 	enum sp_mem_perm_data_access_permission data_access;
288 	enum sp_mem_perm_instruction_access_permission instruction_access;
289 };
290 
291 /**
292  * @brief      Starts a transaction to transfer of ownership of a memory region
293  *             from a Sender endpoint to a Receiver endpoint.
294  *
295  * @param[in]  descriptor    The memory descriptor
296  * @param[in]  acc_desc      Access descriptor
297  * @param[in]  regions       Memory region array
298  * @param[in]  region_count  Memory region count
299  * @param[out] handle        The handle for identifying the memory transaction
300  *
301  * @return     The SP API result
302  */
303 sp_result sp_memory_donate(struct sp_memory_descriptor *descriptor,
304 			   struct sp_memory_access_descriptor *acc_desc,
305 			   struct sp_memory_region regions[],
306 			   uint32_t region_count, uint64_t *handle);
307 
308 sp_result sp_memory_donate_dynamic(struct sp_memory_descriptor *descriptor,
309 				   struct sp_memory_access_descriptor *acc_desc,
310 				   struct sp_memory_region regions[],
311 				   uint32_t region_count, uint64_t *handle,
312 				   struct ffa_mem_transaction_buffer *buffer);
313 
314 /**
315  * @brief      Queries if sp_memory_donate_dynamic is supported by the SPM.
316  *
317  * @param[out] supported  Flag indicating the support state
318  *
319  * @return     The SP API result
320  */
321 sp_result sp_memory_donate_dynamic_is_supported(bool *supported);
322 
323 /**
324  * @brief      Starts a transaction to transfer an Owner’s access to a memory
325  *             region and  grant access to it to one or more Borrowers.
326  *
327  * @param[in]  descriptor      The memory descriptor
328  * @param[in]  acc_desc        Access descriptor array
329  * @param[in]  acc_desc_count  Access descriptor count, must be greater than 0
330  * @param[in]  regions         Memory region array
331  * @param[in]  region_count    Memory region count
332  * @param[out] handle          The handle for identifying the memory transaction
333  *
334  * @return     The SP API result
335  */
336 sp_result sp_memory_lend(struct sp_memory_descriptor *descriptor,
337 			 struct sp_memory_access_descriptor acc_desc[],
338 			 uint32_t acc_desc_count,
339 			 struct sp_memory_region regions[],
340 			 uint32_t region_count, uint64_t *handle);
341 
342 sp_result sp_memory_lend_dynamic(struct sp_memory_descriptor *descriptor,
343 				 struct sp_memory_access_descriptor acc_desc[],
344 				 uint32_t acc_desc_count,
345 				 struct sp_memory_region regions[],
346 				 uint32_t region_count, uint64_t *handle,
347 				 struct ffa_mem_transaction_buffer *buffer);
348 
349 /**
350  * @brief      Queries if sp_memory_lend_dynamic is supported by the SPM.
351  *
352  * @param[out] supported  Flag indicating the support state
353  *
354  * @return     The SP API result
355  */
356 sp_result sp_memory_lend_dynamic_is_supported(bool *supported);
357 
358 /**
359  * @brief      Starts a transaction to grant access to a memory region to one or
360  *             more Borrowers.
361  *
362  * @param[in]  descriptor      The memory descriptor
363  * @param[in]  acc_desc        Access descriptor array
364  * @param[in]  acc_desc_count  Access descriptor count, must be greater than 0
365  * @param[in]  regions         Memory region array
366  * @param[in]  region_count    Memory region count
367  * @param[out] handle          The handle for identifying the memory transaction
368  *
369  * @return     The SP API result
370  */
371 sp_result sp_memory_share(struct sp_memory_descriptor *descriptor,
372 			  struct sp_memory_access_descriptor acc_desc[],
373 			  uint32_t acc_desc_count,
374 			  struct sp_memory_region regions[],
375 			  uint32_t region_count, uint64_t *handle);
376 
377 sp_result sp_memory_share_dynamic(struct sp_memory_descriptor *descriptor,
378 				  struct sp_memory_access_descriptor acc_desc[],
379 				  uint32_t acc_desc_count,
380 				  struct sp_memory_region regions[],
381 				  uint32_t region_count, uint64_t *handle,
382 				  struct ffa_mem_transaction_buffer *buffer);
383 
384 /**
385  * @brief      Queries if sp_memory_share_dynamic is supported by the SPM.
386  *
387  * @param[out] supported  Flag indicating the support state
388  *
389  * @return     The SP API result
390  */
391 sp_result sp_memory_share_dynamic_is_supported(bool *supported);
392 
393 /**
394  * @brief          Requests completion of a donate, lend or share memory
395  *                 management transaction.
396  *
397  * @param[in]      descriptor        The memory descriptor
398  * @param[in,out]  acc_desc          Access descriptor
399  * @param[in,out]  regions           Memory region array
400  * @param[in]      in_region_count   Count of the specified regions, can be 0
401  * @param[in,out]  out_region_count  Count of the reserved space of in the
402  *                                   regions buffer for retrieved regions. After
403  *                                   call it will contain the exact count of the
404  *                                   retrieved regions.
405  * @param[in]      handle            The handle for identifying the memory
406  *                                   transaction
407  *
408  * @return     The SP API result
409  */
410 sp_result sp_memory_retrieve(struct sp_memory_descriptor *descriptor,
411 			     struct sp_memory_access_descriptor *acc_desc,
412 			     struct sp_memory_region regions[],
413 			     uint32_t in_region_count,
414 			     uint32_t *out_region_count, uint64_t handle);
415 
416 sp_result
417 sp_memory_retrieve_dynamic(struct sp_memory_descriptor *descriptor,
418 			   struct sp_memory_access_descriptor *acc_desc,
419 			   struct sp_memory_region regions[],
420 			   uint32_t in_region_count, uint32_t *out_region_count,
421 			   uint64_t handle,
422 			   struct ffa_mem_transaction_buffer *buffer);
423 
424 /**
425  * @brief      Queries if sp_memory_retrieve_dynamic is supported by the SPM.
426  *
427  * @param[out] supported  Flag indicating the support state
428  *
429  * @return     The SP API result
430  */
431 sp_result sp_memory_retrieve_dynamic_is_supported(bool *supported);
432 
433 /**
434  * @brief      Starts a transaction to transfer access to a shared or lent
435  *             memory region from a Borrower back to its Owner.
436  *
437  * @param[in]  handle          The handle for identifying the memory transaction
438  * @param[in]  endpoints       The endpoints
439  * @param[in]  endpoint_count  The endpoint count
440  *
441  * @return     The SP API result
442  */
443 sp_result sp_memory_relinquish(uint64_t handle, const uint16_t endpoints[],
444 			       uint32_t endpoint_count,
445 			       struct sp_memory_transaction_flags *flags);
446 
447 /**
448  * @brief      Restores exclusive access to a memory region back to its Owner.
449  *
450  * @param[in]  handle  The handle for identifying the memory transaction
451  * @param[in]  flags   Flags for modifying the reclaim behavior
452  *
453  * @return     The SP API result
454  */
455 sp_result sp_memory_reclaim(uint64_t handle, uint32_t flags);
456 
457 /**
458  * @brief       Queries the memory attributes of a memory region. It can only
459  *              access the regions of the SP's own translation regine. Moreover
460  *              this function is only available in the boot phase, i.e. before
461  *              calling sp_msg_wait.
462  *
463  *
464  * @param[in]   base_address    Base VA of a translation granule whose
465  *                              permission attributes must be returned.
466  * @param[out]  mem_perm        Permission attributes of the memory region
467  * @return      The SP API result
468  */
469 sp_result sp_memory_permission_get(const void *base_address,
470 				   struct sp_mem_perm *mem_perm);
471 
472 /**
473  * @brief       Sets the memory attributes of a memory regions. It can only
474  *              access the regions of the SP's own translation regine. Moreover
475  *              this function is only available in the boot phase, i.e. before
476  *              calling sp_msg_wait.
477  *
478  * @param[in]   base_address    Base VA of a memory region whose permission
479  *                              attributes must be set.
480  * @param[in]   region_size     Memory regions size in bytes
481  * @param[in]   mem_perm        Permission attributes to be set for the memory
482  *                              region
483  * @return      The SP API result
484  */
485 sp_result sp_memory_permission_set(const void *base_address, size_t region_size,
486 				   const struct sp_mem_perm *mem_perm);
487 
488 #ifdef __cplusplus
489 }
490 #endif
491 
492 #endif /* LIBSP_INCLUDE_SP_MEMORY_MANAGEMENT_H_ */
493