1*e9b1f300SMarc Bonnici /* 2*e9b1f300SMarc Bonnici * Copyright (c) 2022, Arm Limited. All rights reserved. 3*e9b1f300SMarc Bonnici * 4*e9b1f300SMarc Bonnici * SPDX-License-Identifier: BSD-3-Clause 5*e9b1f300SMarc Bonnici */ 6*e9b1f300SMarc Bonnici 7*e9b1f300SMarc Bonnici #include <common/debug.h> 8*e9b1f300SMarc Bonnici #include "ffa_helpers.h" 9*e9b1f300SMarc Bonnici #include <services/ffa_svc.h> 10*e9b1f300SMarc Bonnici #include "tsp_private.h" 11*e9b1f300SMarc Bonnici 12*e9b1f300SMarc Bonnici /** 13*e9b1f300SMarc Bonnici * Initialises the header of the given `ffa_mtd`, not including the 14*e9b1f300SMarc Bonnici * composite memory region offset. 15*e9b1f300SMarc Bonnici */ 16*e9b1f300SMarc Bonnici static void ffa_memory_region_init_header( 17*e9b1f300SMarc Bonnici struct ffa_mtd *memory_region, ffa_endpoint_id16_t sender, 18*e9b1f300SMarc Bonnici ffa_mem_attr16_t attributes, ffa_mtd_flag32_t flags, 19*e9b1f300SMarc Bonnici uint64_t handle, uint64_t tag, ffa_endpoint_id16_t *receivers, 20*e9b1f300SMarc Bonnici uint32_t receiver_count, ffa_mem_perm8_t permissions) 21*e9b1f300SMarc Bonnici { 22*e9b1f300SMarc Bonnici struct ffa_emad_v1_0 *emad; 23*e9b1f300SMarc Bonnici 24*e9b1f300SMarc Bonnici memory_region->emad_offset = sizeof(struct ffa_mtd); 25*e9b1f300SMarc Bonnici memory_region->emad_size = sizeof(struct ffa_emad_v1_0); 26*e9b1f300SMarc Bonnici emad = (struct ffa_emad_v1_0 *) 27*e9b1f300SMarc Bonnici ((uint8_t *) memory_region + 28*e9b1f300SMarc Bonnici memory_region->emad_offset); 29*e9b1f300SMarc Bonnici memory_region->sender_id = sender; 30*e9b1f300SMarc Bonnici memory_region->memory_region_attributes = attributes; 31*e9b1f300SMarc Bonnici memory_region->reserved_36_39 = 0; 32*e9b1f300SMarc Bonnici memory_region->flags = flags; 33*e9b1f300SMarc Bonnici memory_region->handle = handle; 34*e9b1f300SMarc Bonnici memory_region->tag = tag; 35*e9b1f300SMarc Bonnici memory_region->reserved_40_47 = 0; 36*e9b1f300SMarc Bonnici memory_region->emad_count = receiver_count; 37*e9b1f300SMarc Bonnici for (uint32_t i = 0U; i < receiver_count; i++) { 38*e9b1f300SMarc Bonnici emad[i].mapd.endpoint_id = receivers[i]; 39*e9b1f300SMarc Bonnici emad[i].mapd.memory_access_permissions = permissions; 40*e9b1f300SMarc Bonnici emad[i].mapd.flags = 0; 41*e9b1f300SMarc Bonnici emad[i].comp_mrd_offset = 0; 42*e9b1f300SMarc Bonnici emad[i].reserved_8_15 = 0; 43*e9b1f300SMarc Bonnici } 44*e9b1f300SMarc Bonnici } 45*e9b1f300SMarc Bonnici /** 46*e9b1f300SMarc Bonnici * Initialises the given `ffa_mtd` to be used for an 47*e9b1f300SMarc Bonnici * `FFA_MEM_RETRIEVE_REQ` by the receiver of a memory transaction. 48*e9b1f300SMarc Bonnici * TODO: Support differing attributes per receiver. 49*e9b1f300SMarc Bonnici * 50*e9b1f300SMarc Bonnici * Returns the size of the descriptor written. 51*e9b1f300SMarc Bonnici */ 52*e9b1f300SMarc Bonnici uint32_t ffa_memory_retrieve_request_init( 53*e9b1f300SMarc Bonnici struct ffa_mtd *memory_region, uint64_t handle, 54*e9b1f300SMarc Bonnici ffa_endpoint_id16_t sender, ffa_endpoint_id16_t *receivers, uint32_t receiver_count, 55*e9b1f300SMarc Bonnici uint64_t tag, ffa_mtd_flag32_t flags, 56*e9b1f300SMarc Bonnici ffa_mem_perm8_t permissions, 57*e9b1f300SMarc Bonnici ffa_mem_attr16_t attributes) 58*e9b1f300SMarc Bonnici { 59*e9b1f300SMarc Bonnici ffa_memory_region_init_header(memory_region, sender, attributes, flags, 60*e9b1f300SMarc Bonnici handle, tag, receivers, 61*e9b1f300SMarc Bonnici receiver_count, permissions); 62*e9b1f300SMarc Bonnici 63*e9b1f300SMarc Bonnici return sizeof(struct ffa_mtd) + 64*e9b1f300SMarc Bonnici memory_region->emad_count * sizeof(struct ffa_emad_v1_0); 65*e9b1f300SMarc Bonnici } 66*e9b1f300SMarc Bonnici 67*e9b1f300SMarc Bonnici /* Relinquish access to memory region. */ 68*e9b1f300SMarc Bonnici bool ffa_mem_relinquish(void) 69*e9b1f300SMarc Bonnici { 70*e9b1f300SMarc Bonnici smc_args_t ret; 71*e9b1f300SMarc Bonnici 72*e9b1f300SMarc Bonnici ret = smc_helper(FFA_MEM_RELINQUISH, 0, 0, 0, 0, 0, 0, 0); 73*e9b1f300SMarc Bonnici if (ffa_func_id(ret) != FFA_SUCCESS_SMC32) { 74*e9b1f300SMarc Bonnici ERROR("%s failed to relinquish memory! error: (%x) %x\n", 75*e9b1f300SMarc Bonnici __func__, ffa_func_id(ret), ffa_error_code(ret)); 76*e9b1f300SMarc Bonnici return false; 77*e9b1f300SMarc Bonnici } 78*e9b1f300SMarc Bonnici return true; 79*e9b1f300SMarc Bonnici } 80*e9b1f300SMarc Bonnici 81*e9b1f300SMarc Bonnici /* Retrieve memory shared by another partition. */ 82*e9b1f300SMarc Bonnici smc_args_t ffa_mem_retrieve_req(uint32_t descriptor_length, 83*e9b1f300SMarc Bonnici uint32_t fragment_length) 84*e9b1f300SMarc Bonnici { 85*e9b1f300SMarc Bonnici return smc_helper(FFA_MEM_RETRIEVE_REQ_SMC32, 86*e9b1f300SMarc Bonnici descriptor_length, 87*e9b1f300SMarc Bonnici fragment_length, 88*e9b1f300SMarc Bonnici 0, 0, 0, 0, 0); 89*e9b1f300SMarc Bonnici } 90*e9b1f300SMarc Bonnici 91*e9b1f300SMarc Bonnici /* Retrieve the next memory descriptor fragment. */ 92*e9b1f300SMarc Bonnici smc_args_t ffa_mem_frag_rx(uint64_t handle, uint32_t recv_length) 93*e9b1f300SMarc Bonnici { 94*e9b1f300SMarc Bonnici return smc_helper(FFA_MEM_FRAG_RX, 95*e9b1f300SMarc Bonnici FFA_MEM_HANDLE_LOW(handle), 96*e9b1f300SMarc Bonnici FFA_MEM_HANDLE_HIGH(handle), 97*e9b1f300SMarc Bonnici recv_length, 98*e9b1f300SMarc Bonnici 0, 0, 0, 0); 99*e9b1f300SMarc Bonnici } 100*e9b1f300SMarc Bonnici 101*e9b1f300SMarc Bonnici /* Relinquish the memory region. */ 102*e9b1f300SMarc Bonnici bool memory_relinquish(struct ffa_mem_relinquish_descriptor *m, uint64_t handle, 103*e9b1f300SMarc Bonnici ffa_endpoint_id16_t id) 104*e9b1f300SMarc Bonnici { 105*e9b1f300SMarc Bonnici ffa_mem_relinquish_init(m, handle, 0, id); 106*e9b1f300SMarc Bonnici return ffa_mem_relinquish(); 107*e9b1f300SMarc Bonnici } 108*e9b1f300SMarc Bonnici 109*e9b1f300SMarc Bonnici /* Query SPMC that the rx buffer of the partition can be released. */ 110*e9b1f300SMarc Bonnici bool ffa_rx_release(void) 111*e9b1f300SMarc Bonnici { 112*e9b1f300SMarc Bonnici smc_args_t ret; 113*e9b1f300SMarc Bonnici 114*e9b1f300SMarc Bonnici ret = smc_helper(FFA_RX_RELEASE, 0, 0, 0, 0, 0, 0, 0); 115*e9b1f300SMarc Bonnici return ret._regs[SMC_ARG0] != FFA_SUCCESS_SMC32; 116*e9b1f300SMarc Bonnici } 117*e9b1f300SMarc Bonnici 118*e9b1f300SMarc Bonnici /* Map the provided buffers with the SPMC. */ 119*e9b1f300SMarc Bonnici bool ffa_rxtx_map(uintptr_t send, uintptr_t recv, uint32_t pages) 120*e9b1f300SMarc Bonnici { 121*e9b1f300SMarc Bonnici smc_args_t ret; 122*e9b1f300SMarc Bonnici 123*e9b1f300SMarc Bonnici ret = smc_helper(FFA_RXTX_MAP_SMC64, send, recv, pages, 0, 0, 0, 0); 124*e9b1f300SMarc Bonnici return ret._regs[0] != FFA_SUCCESS_SMC32; 125*e9b1f300SMarc Bonnici } 126