diff options
Diffstat (limited to 'tftf/tests')
-rw-r--r-- | tftf/tests/runtime_services/secure_service/ffa_helpers.c | 159 |
1 files changed, 159 insertions, 0 deletions
diff --git a/tftf/tests/runtime_services/secure_service/ffa_helpers.c b/tftf/tests/runtime_services/secure_service/ffa_helpers.c index 5690f4217..a17b01a91 100644 --- a/tftf/tests/runtime_services/secure_service/ffa_helpers.c +++ b/tftf/tests/runtime_services/secure_service/ffa_helpers.c @@ -155,6 +155,165 @@ bool check_spmc_execution_level(void) return (is_optee_spmc_criteria == 2U); } +/** + * Initialises the header of the given `ffa_memory_region`, not including the + * composite memory region offset. + */ +static void ffa_memory_region_init_header( + struct ffa_memory_region *memory_region, ffa_vm_id_t sender, + ffa_memory_attributes_t attributes, ffa_memory_region_flags_t flags, + ffa_memory_handle_t handle, uint32_t tag, ffa_vm_id_t receiver, + ffa_memory_access_permissions_t permissions) +{ + memory_region->sender = sender; + memory_region->attributes = attributes; + memory_region->reserved_0 = 0; + memory_region->flags = flags; + memory_region->handle = handle; + memory_region->tag = tag; + memory_region->reserved_1 = 0; + memory_region->receiver_count = 1; + memory_region->receivers[0].receiver_permissions.receiver = receiver; + memory_region->receivers[0].receiver_permissions.permissions = + permissions; + memory_region->receivers[0].receiver_permissions.flags = 0; + memory_region->receivers[0].reserved_0 = 0; +} + +/** + * Initialises the given `ffa_memory_region` and copies as many as possible of + * the given constituents to it. + * + * Returns the number of constituents remaining which wouldn't fit, and (via + * return parameters) the size in bytes of the first fragment of data copied to + * `memory_region` (attributes, constituents and memory region header size), and + * the total size of the memory sharing message including all constituents. + */ +uint32_t ffa_memory_region_init( + struct ffa_memory_region *memory_region, size_t memory_region_max_size, + ffa_vm_id_t sender, ffa_vm_id_t receiver, + const struct ffa_memory_region_constituent constituents[], + uint32_t constituent_count, uint32_t tag, + ffa_memory_region_flags_t flags, enum ffa_data_access data_access, + enum ffa_instruction_access instruction_access, + enum ffa_memory_type type, enum ffa_memory_cacheability cacheability, + enum ffa_memory_shareability shareability, uint32_t *total_length, + uint32_t *fragment_length) +{ + ffa_memory_access_permissions_t permissions = 0; + ffa_memory_attributes_t attributes = 0; + struct ffa_composite_memory_region *composite_memory_region; + uint32_t fragment_max_constituents; + uint32_t count_to_copy; + uint32_t i; + uint32_t constituents_offset; + + /* Set memory region's permissions. */ + ffa_set_data_access_attr(&permissions, data_access); + ffa_set_instruction_access_attr(&permissions, instruction_access); + + /* Set memory region's page attributes. */ + ffa_set_memory_type_attr(&attributes, type); + ffa_set_memory_cacheability_attr(&attributes, cacheability); + ffa_set_memory_shareability_attr(&attributes, shareability); + + ffa_memory_region_init_header(memory_region, sender, attributes, flags, + 0, tag, receiver, permissions); + /* + * Note that `sizeof(struct_ffa_memory_region)` and `sizeof(struct + * ffa_memory_access)` must both be multiples of 16 (as verified by the + * asserts in `ffa_memory.c`, so it is guaranteed that the offset we + * calculate here is aligned to a 64-bit boundary and so 64-bit values + * can be copied without alignment faults. + */ + memory_region->receivers[0].composite_memory_region_offset = + sizeof(struct ffa_memory_region) + + memory_region->receiver_count * + sizeof(struct ffa_memory_access); + + composite_memory_region = + ffa_memory_region_get_composite(memory_region, 0); + composite_memory_region->page_count = 0; + composite_memory_region->constituent_count = constituent_count; + composite_memory_region->reserved_0 = 0; + + constituents_offset = + memory_region->receivers[0].composite_memory_region_offset + + sizeof(struct ffa_composite_memory_region); + fragment_max_constituents = + (memory_region_max_size - constituents_offset) / + sizeof(struct ffa_memory_region_constituent); + + count_to_copy = constituent_count; + if (count_to_copy > fragment_max_constituents) { + count_to_copy = fragment_max_constituents; + } + + for (i = 0; i < constituent_count; ++i) { + if (i < count_to_copy) { + composite_memory_region->constituents[i] = + constituents[i]; + } + composite_memory_region->page_count += + constituents[i].page_count; + } + + if (total_length != NULL) { + *total_length = + constituents_offset + + composite_memory_region->constituent_count * + sizeof(struct ffa_memory_region_constituent); + } + if (fragment_length != NULL) { + *fragment_length = + constituents_offset + + count_to_copy * + sizeof(struct ffa_memory_region_constituent); + } + + return composite_memory_region->constituent_count - count_to_copy; +} + +/** + * Initialises the given `ffa_memory_region` to be used for an + * `FFA_MEM_RETRIEVE_REQ` by the receiver of a memory transaction. + * + * Returns the size of the message written. + */ +uint32_t ffa_memory_retrieve_request_init( + struct ffa_memory_region *memory_region, ffa_memory_handle_t handle, + ffa_vm_id_t sender, ffa_vm_id_t receiver, uint32_t tag, + ffa_memory_region_flags_t flags, enum ffa_data_access data_access, + enum ffa_instruction_access instruction_access, + enum ffa_memory_type type, enum ffa_memory_cacheability cacheability, + enum ffa_memory_shareability shareability) +{ + ffa_memory_access_permissions_t permissions = 0; + ffa_memory_attributes_t attributes = 0; + + /* Set memory region's permissions. */ + ffa_set_data_access_attr(&permissions, data_access); + ffa_set_instruction_access_attr(&permissions, instruction_access); + + /* Set memory region's page attributes. */ + ffa_set_memory_type_attr(&attributes, type); + ffa_set_memory_cacheability_attr(&attributes, cacheability); + ffa_set_memory_shareability_attr(&attributes, shareability); + + ffa_memory_region_init_header(memory_region, sender, attributes, flags, + handle, tag, receiver, permissions); + /* + * Offset 0 in this case means that the hypervisor should allocate the + * address ranges. This is the only configuration supported by Hafnium, + * as it enforces 1:1 mappings in the stage 2 page tables. + */ + memory_region->receivers[0].composite_memory_region_offset = 0; + memory_region->receivers[0].reserved_0 = 0; + + return sizeof(struct ffa_memory_region) + + memory_region->receiver_count * sizeof(struct ffa_memory_access); +} + /* * FFA Version ABI helper. * Version fields: |