1 // SPDX-License-Identifier: BSD-3-Clause
2 /*
3  * Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.
4  */
5 
6 #include "ffa_direct_msg_routing_extension.h"
7 #include "ffa_api.h"
8 #include <stdbool.h>
9 
10 #define SP_ID_INVALID FFA_ID_GET_ID_MASK
11 #define FFA_ROUTING_EXT_RC_BIT		BIT32(31)
12 #define FFA_ROUTING_EXT_ERROR_BIT	BIT32(30)
13 #define FFA_ROUTING_EXT_BITS_MASK	(FFA_ROUTING_EXT_RC_BIT | FFA_ROUTING_EXT_ERROR_BIT)
14 
15 enum sp_rc_state { idle = 0, root, leaf, rc_root, internal, forwarding };
16 
17 enum sp_rc_state state = idle;
18 static uint16_t own_id = SP_ID_INVALID;
19 static uint16_t caller_id = SP_ID_INVALID;
20 static uint16_t callee_id = SP_ID_INVALID;
21 
is_rc_message(const struct ffa_direct_msg * msg)22 static bool is_rc_message(const struct ffa_direct_msg *msg)
23 {
24 	return msg->args.args32[0] & FFA_ROUTING_EXT_RC_BIT;
25 }
26 
is_error_message(const struct ffa_direct_msg * msg)27 static bool is_error_message(const struct ffa_direct_msg *msg)
28 {
29 	return msg->args.args32[0] & FFA_ROUTING_EXT_ERROR_BIT;
30 }
31 
get_error_code_from_message(const struct ffa_direct_msg * msg)32 static ffa_result get_error_code_from_message(const struct ffa_direct_msg *msg)
33 {
34 	return (ffa_result)msg->args.args32[1];
35 }
36 
send_rc_error_message(struct ffa_direct_msg * req,ffa_result error_code)37 static ffa_result send_rc_error_message(struct ffa_direct_msg *req,
38 					ffa_result error_code)
39 {
40 	return ffa_msg_send_direct_resp_32(req->destination_id, req->source_id,
41 					(FFA_ROUTING_EXT_ERROR_BIT |
42 					 FFA_ROUTING_EXT_RC_BIT),
43 					error_code, 0, 0, 0, req);
44 }
45 
send_rc_error_message_to_rc_root(struct ffa_direct_msg * resp,ffa_result error_code)46 static ffa_result send_rc_error_message_to_rc_root(struct ffa_direct_msg *resp,
47 						   ffa_result error_code)
48 {
49 	return ffa_msg_send_direct_req_32(own_id, callee_id,
50 				       (FFA_ROUTING_EXT_RC_BIT |
51 					FFA_ROUTING_EXT_ERROR_BIT),
52 				       error_code, 0, 0, 0, resp);
53 }
54 
deny_unexpected_rc_responses(struct ffa_direct_msg * req)55 static ffa_result deny_unexpected_rc_responses(struct ffa_direct_msg *req)
56 {
57 	ffa_result ffa_res = FFA_OK;
58 
59 	while (is_rc_message(req)) {
60 		ffa_res = send_rc_error_message(req, FFA_DENIED);
61 		if (ffa_res != FFA_OK)
62 			return ffa_res;
63 	}
64 
65 	return FFA_OK;
66 }
67 
deny_unexpected_requests(struct ffa_direct_msg * req)68 static ffa_result deny_unexpected_requests(struct ffa_direct_msg *req)
69 {
70 	ffa_result ffa_res = FFA_OK;
71 
72 	while (!is_rc_message(req) || req->source_id != caller_id) {
73 		ffa_res = send_rc_error_message(req, FFA_BUSY);
74 		if (ffa_res != FFA_OK) {
75 			/* Sending error message as a response to an invalid
76 			 * request has failed. Sending and FFA_MSG_WAIT to have
77 			 * a chance for receiving a valid message.
78 			 */
79 			ffa_res = ffa_msg_wait(req);
80 			if (ffa_res != FFA_OK) {
81 				/* Even the FFA_MSG_WAIT failed so return. */
82 				return ffa_res;
83 			}
84 		}
85 	}
86 
87 	return FFA_OK;
88 }
89 
request_received_hook(struct ffa_direct_msg * req)90 static ffa_result request_received_hook(struct ffa_direct_msg *req)
91 {
92 	ffa_result ffa_res = FFA_OK;
93 
94 	ffa_res = deny_unexpected_rc_responses(req);
95 	if (ffa_res != FFA_OK)
96 		return ffa_res;
97 
98 	state = leaf;
99 	own_id = req->destination_id;
100 	caller_id = req->source_id;
101 	callee_id = SP_ID_INVALID;
102 
103 	if (FFA_IS_32_BIT_FUNC(req->function_id))
104 		req->args.args32[0] &= ~FFA_ROUTING_EXT_BITS_MASK;
105 
106 	return FFA_OK;
107 }
108 
ffa_direct_msg_routing_ext_wait_post_hook(struct ffa_direct_msg * req)109 ffa_result ffa_direct_msg_routing_ext_wait_post_hook(struct ffa_direct_msg *req)
110 {
111 	return request_received_hook(req);
112 }
113 
ffa_direct_msg_routing_ext_req_pre_hook(struct ffa_direct_msg * req)114 ffa_result ffa_direct_msg_routing_ext_req_pre_hook(struct ffa_direct_msg *req)
115 {
116 	if (FFA_IS_32_BIT_FUNC(req->function_id)) {
117 		if (req->args.args32[0] & FFA_ROUTING_EXT_BITS_MASK)
118 			return FFA_INVALID_PARAMETERS;
119 	}
120 
121 	state = internal;
122 	callee_id = req->destination_id;
123 
124 	return FFA_OK;
125 }
126 
ffa_direct_msg_routing_ext_req_post_hook(struct ffa_direct_msg * resp)127 ffa_result ffa_direct_msg_routing_ext_req_post_hook(struct ffa_direct_msg *resp)
128 {
129 	ffa_result ffa_res = FFA_OK;
130 	struct ffa_direct_msg rc_resp = { 0 };
131 
132 	while (is_rc_message(resp)) {
133 		if (is_error_message(resp)) {
134 			/* The callee returned an error in an RC message. */
135 			ffa_res = get_error_code_from_message(resp);
136 			break;
137 		}
138 
139 		/* Forwarding RC request towards the root (normal world) */
140 		state = forwarding;
141 
142 		ffa_res = ffa_msg_send_direct_resp_32(own_id, caller_id,
143 						   resp->args.args32[0], resp->args.args32[1],
144 						   resp->args.args32[2], resp->args.args32[3],
145 						   resp->args.args32[4], &rc_resp);
146 		if (ffa_res != FFA_OK)
147 			goto forward_ffa_error_to_rc_root;
148 
149 		/*
150 		 * Denying messages which are not RC responses or came from a
151 		 * different endpoint than the original caller.
152 		 */
153 		ffa_res = deny_unexpected_requests(&rc_resp);
154 		if (ffa_res != FFA_OK)
155 			goto forward_ffa_error_to_rc_root;
156 
157 		/* Forwarding RC response towards the RC root. */
158 		state = internal;
159 		ffa_res = ffa_msg_send_direct_req_32(
160 			own_id, callee_id, rc_resp.args.args32[0], rc_resp.args.args32[1],
161 			rc_resp.args.args32[2], rc_resp.args.args32[3], rc_resp.args.args32[4],
162 			resp);
163 
164 		goto break_on_ffa_error;
165 
166 		/*
167 		 * At this point an FF-A error message was received while it was
168 		 * trying to forward the RC message. Forwarding erro to RC root.
169 		 */
170 forward_ffa_error_to_rc_root:
171 		ffa_res = send_rc_error_message_to_rc_root(resp, ffa_res);
172 
173 break_on_ffa_error:
174 		if (ffa_res != FFA_OK) {
175 			/* Exit loop, set leaf state and return with error. */
176 			break;
177 		}
178 	}
179 
180 	/* Non-RC message was received or a non-recoverable error happened. */
181 	state = leaf;
182 	callee_id = SP_ID_INVALID;
183 
184 	return ffa_res;
185 }
186 
ffa_direct_msg_routing_ext_req_error_hook(void)187 void ffa_direct_msg_routing_ext_req_error_hook(void)
188 {
189 	state = leaf;
190 	callee_id = SP_ID_INVALID;
191 }
192 
ffa_direct_msg_routing_ext_resp_pre_hook(struct ffa_direct_msg * resp)193 ffa_result ffa_direct_msg_routing_ext_resp_pre_hook(struct ffa_direct_msg *resp)
194 {
195 	if (FFA_IS_32_BIT_FUNC(resp->function_id)) {
196 		if (resp->args.args32[0] & FFA_ROUTING_EXT_BITS_MASK)
197 			return FFA_INVALID_PARAMETERS;
198 	}
199 
200 	state = idle;
201 	caller_id = SP_ID_INVALID;
202 	callee_id = SP_ID_INVALID;
203 
204 	return FFA_OK;
205 }
206 
ffa_direct_msg_routing_ext_resp_post_hook(struct ffa_direct_msg * req)207 ffa_result ffa_direct_msg_routing_ext_resp_post_hook(struct ffa_direct_msg *req)
208 {
209 	return request_received_hook(req);
210 }
211 
ffa_direct_msg_routing_ext_resp_error_hook(void)212 void ffa_direct_msg_routing_ext_resp_error_hook(void)
213 {
214 }
215 
ffa_direct_msg_routing_ext_rc_req_pre_hook(struct ffa_direct_msg * req)216 ffa_result ffa_direct_msg_routing_ext_rc_req_pre_hook(struct ffa_direct_msg *req)
217 {
218 	if (FFA_IS_32_BIT_FUNC(req->function_id)) {
219 		if (req->args.args32[0] & FFA_ROUTING_EXT_BITS_MASK)
220 			return FFA_INVALID_PARAMETERS;
221 	}
222 
223 	req->args.args32[0] |= FFA_ROUTING_EXT_RC_BIT;
224 	state = rc_root;
225 
226 	return FFA_OK;
227 }
228 
229 ffa_result
ffa_direct_msg_routing_ext_rc_req_post_hook(struct ffa_direct_msg * resp)230 ffa_direct_msg_routing_ext_rc_req_post_hook(struct ffa_direct_msg *resp)
231 {
232 	ffa_result ffa_res = FFA_OK;
233 
234 	ffa_res = deny_unexpected_requests(resp);
235 	state = leaf;
236 
237 	if (is_error_message(resp))
238 		ffa_res = get_error_code_from_message(resp);
239 
240 	return ffa_res;
241 }
242 
ffa_direct_msg_routing_ext_rc_req_error_hook(void)243 void ffa_direct_msg_routing_ext_rc_req_error_hook(void)
244 {
245 	state = leaf;
246 }
247