blob: 99a50566400be7b7df723f252b94c29d781203ed [file] [log] [blame]
Balint Dobszay3bd6ae92020-11-23 17:57:50 +01001/*
julhal01c3f4e9a2020-12-15 13:39:01 +00002 * Copyright (c) 2020-2021, Arm Limited and Contributors. All rights reserved.
Balint Dobszay3bd6ae92020-11-23 17:57:50 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include "ffarpc_call_args.h"
8#include "ffarpc_call_ep.h"
9#include "ffarpc_call_ops.h"
10#include <ffa_api.h>
11#include <sp_memory_management.h>
12#include <protocols/rpc/common/packed-c/status.h>
13#include <trace.h>
14#include <stddef.h>
15
16/* TODO: remove this when own ID will be available in libsp */
17extern uint16_t own_id;
18
julhal01c3f4e9a2020-12-15 13:39:01 +000019static void set_resp_args(uint32_t *resp_args, uint32_t ifaceid_opcode, uint32_t data_len,
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010020 rpc_status_t rpc_status, uint32_t opstatus)
21{
julhal01c3f4e9a2020-12-15 13:39:01 +000022 resp_args[FFA_CALL_ARGS_IFACE_ID_OPCODE] = ifaceid_opcode;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010023 resp_args[FFA_CALL_ARGS_RESP_DATA_LEN] = data_len;
24 resp_args[FFA_CALL_ARGS_RESP_RPC_STATUS] = rpc_status;
25 resp_args[FFA_CALL_ARGS_RESP_OP_STATUS] = opstatus;
26}
27
julhal01c3f4e9a2020-12-15 13:39:01 +000028static void set_mgmt_resp_args(uint32_t *resp_args, uint32_t ifaceid_opcode,
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010029 rpc_status_t rpc_status)
30{
31 /*
32 * Sets arguments for responses that originate from the ffa_call_ep
33 * rather than from a higher layer service. These responses are not
34 * associated with a shared buffer for any additional message payload.
35 */
julhal01c3f4e9a2020-12-15 13:39:01 +000036 set_resp_args(resp_args, ifaceid_opcode, 0, rpc_status, 0);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010037}
38
Balint Dobszay73043682021-06-30 10:46:47 +020039static int find_free_shm(struct ffa_call_ep *call_ep)
40{
41 int i;
42
43 if (!call_ep)
44 return -1;
45
46 for (i = 0; i < NUM_MAX_SESS; i++)
47 if (!call_ep->shmem_buf[i]) {
48 DMSG("shm slot %u allocated for %p", i, call_ep);
49 return i;
50 }
51
52 EMSG("shm slot allocation failed");
53 return -1;
54}
55
56static int find_shm(struct ffa_call_ep *call_ep, uint16_t source_id)
57{
58 int i;
59
60 if (!call_ep)
61 return -1;
62
63 for (i = 0; i < NUM_MAX_SESS; i++)
64 if (call_ep->src_id[i] == source_id)
65 return i;
66
67 EMSG("shm not found for source 0x%x", source_id);
68 return -1;
69}
70
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010071static void init_shmem_buf(struct ffa_call_ep *call_ep, uint16_t source_id,
72 const uint32_t *req_args, uint32_t *resp_args)
73{
74 sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
75 struct sp_memory_descriptor desc = { };
76 struct sp_memory_access_descriptor acc_desc = { };
77 struct sp_memory_region region = { };
78 uint32_t in_region_count = 1;
79 uint32_t out_region_count = 1;
80 uint64_t handle = 0;
81 rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
Balint Dobszay73043682021-06-30 10:46:47 +020082 int idx = find_free_shm(call_ep);
83
84 if (idx < 0) {
85 EMSG("shm init error");
86 goto out;
87 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +010088
89 desc.sender_id = source_id;
90 desc.memory_type = sp_memory_type_not_specified;
91 desc.flags.transaction_type = sp_memory_transaction_type_share;
92 acc_desc.receiver_id = own_id;
93 acc_desc.data_access = sp_data_access_read_write;
94 handle = req_args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_MSW];
95 handle = (handle << 32) | req_args[FFA_CALL_ARGS_SHARE_MEM_HANDLE_LSW];
96
97 sp_res = sp_memory_retrieve(&desc, &acc_desc, &region, in_region_count,
98 &out_region_count, handle);
99
100 if (sp_res == SP_RESULT_OK) {
Balint Dobszay73043682021-06-30 10:46:47 +0200101 call_ep->shmem_buf[idx] = region.address;
102 call_ep->shmem_buf_handle[idx] = handle;
103 call_ep->shmem_buf_size[idx] = (size_t)req_args[FFA_CALL_ARGS_SHARE_MEM_SIZE];
104 call_ep->src_id[idx] = source_id;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100105 rpc_status = TS_RPC_CALL_ACCEPTED;
106 } else {
107 EMSG("memory retrieve error: %d", sp_res);
108 }
109
Balint Dobszay73043682021-06-30 10:46:47 +0200110out:
julhal01c3f4e9a2020-12-15 13:39:01 +0000111 set_mgmt_resp_args(resp_args, req_args[FFA_CALL_ARGS_IFACE_ID_OPCODE], rpc_status);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100112}
113
Balint Dobszay73043682021-06-30 10:46:47 +0200114static void deinit_shmem_buf(struct ffa_call_ep *call_ep, uint16_t source_id,
115 const uint32_t *req_args, uint32_t *resp_args)
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100116{
117 sp_result sp_res = SP_RESULT_INTERNAL_ERROR;
118 rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
Balint Dobszay73043682021-06-30 10:46:47 +0200119 uint64_t handle;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100120 uint16_t endpoints[1] = { own_id };
121 uint32_t endpoint_cnt = 1;
122 struct sp_memory_transaction_flags flags = {
123 .zero_memory = false,
124 .operation_time_slicing = false,
125 };
Balint Dobszay73043682021-06-30 10:46:47 +0200126 int idx = find_shm(call_ep, source_id);
127
128 if (idx < 0) {
129 EMSG("shm deinit error");
130 goto out;
131 }
132
133 handle = call_ep->shmem_buf_handle[idx];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100134
135 sp_res = sp_memory_relinquish(handle, endpoints, endpoint_cnt, &flags);
136 if (sp_res == SP_RESULT_OK) {
Balint Dobszay73043682021-06-30 10:46:47 +0200137 call_ep->shmem_buf[idx] = NULL;
138 call_ep->shmem_buf_handle[idx] = 0;
139 call_ep->shmem_buf_size[idx] = 0;
140 call_ep->src_id[idx] = 0xffff;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100141 rpc_status = TS_RPC_CALL_ACCEPTED;
142 } else {
143 EMSG("memory relinquish error: %d", sp_res);
144 }
145
Balint Dobszay73043682021-06-30 10:46:47 +0200146out:
julhal01c3f4e9a2020-12-15 13:39:01 +0000147 set_mgmt_resp_args(resp_args, req_args[FFA_CALL_ARGS_IFACE_ID_OPCODE], rpc_status);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100148}
149
150static void handle_service_msg(struct ffa_call_ep *call_ep, uint16_t source_id,
151 const uint32_t *req_args, uint32_t *resp_args)
152{
Balint Dobszay73043682021-06-30 10:46:47 +0200153 rpc_status_t rpc_status = TS_RPC_ERROR_INTERNAL;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100154 struct call_req call_req;
155
julhal01c3f4e9a2020-12-15 13:39:01 +0000156 uint32_t ifaceid_opcode = req_args[FFA_CALL_ARGS_IFACE_ID_OPCODE];
Balint Dobszay73043682021-06-30 10:46:47 +0200157 int idx = find_shm(call_ep, source_id);
158
159 if (idx < 0) {
160 EMSG("handle service msg error");
161 goto out;
162 }
julhal01c3f4e9a2020-12-15 13:39:01 +0000163
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100164 call_req.caller_id = source_id;
julhal01c3f4e9a2020-12-15 13:39:01 +0000165 call_req.interface_id = FFA_CALL_ARGS_EXTRACT_IFACE(ifaceid_opcode);
166 call_req.opcode = FFA_CALL_ARGS_EXTRACT_OPCODE(ifaceid_opcode);
167 call_req.encoding = req_args[FFA_CALL_ARGS_ENCODING];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100168
Balint Dobszay73043682021-06-30 10:46:47 +0200169 call_req.req_buf.data = call_ep->shmem_buf[idx];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100170 call_req.req_buf.data_len = req_args[FFA_CALL_ARGS_REQ_DATA_LEN];
Balint Dobszay73043682021-06-30 10:46:47 +0200171 call_req.req_buf.size = call_ep->shmem_buf_size[idx];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100172
Balint Dobszay73043682021-06-30 10:46:47 +0200173 call_req.resp_buf.data = call_ep->shmem_buf[idx];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100174 call_req.resp_buf.data_len = 0;
Balint Dobszay73043682021-06-30 10:46:47 +0200175 call_req.resp_buf.size = call_ep->shmem_buf_size[idx];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100176
julhal01c3f4e9a2020-12-15 13:39:01 +0000177 rpc_status = rpc_interface_receive(call_ep->iface, &call_req);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100178
Balint Dobszay73043682021-06-30 10:46:47 +0200179out:
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100180 set_resp_args(resp_args,
julhal01c3f4e9a2020-12-15 13:39:01 +0000181 ifaceid_opcode,
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100182 call_req.resp_buf.data_len,
183 rpc_status,
184 call_req.opstatus);
185}
186
187static void handle_mgmt_msg(struct ffa_call_ep *call_ep, uint16_t source_id,
188 const uint32_t *req_args, uint32_t *resp_args)
189{
julhal01c3f4e9a2020-12-15 13:39:01 +0000190 uint32_t ifaceid_opcode = req_args[FFA_CALL_ARGS_IFACE_ID_OPCODE];
191 uint32_t opcode = FFA_CALL_ARGS_EXTRACT_OPCODE(ifaceid_opcode);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100192
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100193 switch (opcode) {
194 case FFA_CALL_OPCODE_SHARE_BUF:
195 init_shmem_buf(call_ep, source_id, req_args, resp_args);
196 break;
197 case FFA_CALL_OPCODE_UNSHARE_BUF:
Balint Dobszay73043682021-06-30 10:46:47 +0200198 deinit_shmem_buf(call_ep, source_id, req_args, resp_args);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100199 break;
200 default:
julhal01c3f4e9a2020-12-15 13:39:01 +0000201 set_mgmt_resp_args(resp_args, ifaceid_opcode, TS_RPC_ERROR_INVALID_OPCODE);
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100202 break;
203 }
204}
205
julhal01c3f4e9a2020-12-15 13:39:01 +0000206void ffa_call_ep_init(struct ffa_call_ep *ffa_call_ep, struct rpc_interface *iface)
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100207{
Balint Dobszay73043682021-06-30 10:46:47 +0200208 int i;
209
julhal01c3f4e9a2020-12-15 13:39:01 +0000210 ffa_call_ep->iface = iface;
Balint Dobszay73043682021-06-30 10:46:47 +0200211
212 for (i = 0; i < NUM_MAX_SESS; i++) {
213 ffa_call_ep->shmem_buf_handle[i] = 0;
214 ffa_call_ep->shmem_buf_size[i] = 0;
215 ffa_call_ep->shmem_buf[i] = NULL;
216 ffa_call_ep->src_id[i] = 0xffff;
217 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100218}
219
220void ffa_call_ep_receive(struct ffa_call_ep *call_ep,
221 const struct ffa_direct_msg *req_msg,
222 struct ffa_direct_msg *resp_msg)
223{
224 const uint32_t *req_args = req_msg->args;
225 uint32_t *resp_args = resp_msg->args;
Balint Dobszay73043682021-06-30 10:46:47 +0200226 int idx;
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100227
228 uint16_t source_id = req_msg->source_id;
julhal01c3f4e9a2020-12-15 13:39:01 +0000229 uint32_t ifaceid_opcode = req_args[FFA_CALL_ARGS_IFACE_ID_OPCODE];
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100230
julhal01c3f4e9a2020-12-15 13:39:01 +0000231 if (FFA_CALL_ARGS_EXTRACT_IFACE(ifaceid_opcode) == FFA_CALL_MGMT_IFACE_ID) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100232 /* It's an RPC layer management request */
233 handle_mgmt_msg(call_ep, source_id, req_args, resp_args);
234 } else {
235 /*
236 * Assume anything else is a service request. Service requests
237 * rely on a buffer being shared from the requesting client.
238 * If it hasn't been set-up, fail the request.
239 */
Balint Dobszay73043682021-06-30 10:46:47 +0200240 idx = find_shm(call_ep, source_id);
241
242 if (idx >= 0 && call_ep->shmem_buf[idx]) {
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100243 handle_service_msg(call_ep, source_id, req_args, resp_args);
Balint Dobszay73043682021-06-30 10:46:47 +0200244 } else {
245 EMSG("shared buffer not found or NULL");
julhal01c3f4e9a2020-12-15 13:39:01 +0000246 set_mgmt_resp_args(resp_args, ifaceid_opcode, TS_RPC_ERROR_NOT_READY);
Balint Dobszay73043682021-06-30 10:46:47 +0200247 }
Balint Dobszay3bd6ae92020-11-23 17:57:50 +0100248 }
249}