xref: /rk3399_ARM-atf/services/std_svc/spmd/spmd_logical_sp.c (revision 66bdfd6e4e6d8e086a30397be6055dbb04846895)
1890b5088SRaghu Krishnamurthy /*
2890b5088SRaghu Krishnamurthy  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3890b5088SRaghu Krishnamurthy  *
4890b5088SRaghu Krishnamurthy  * SPDX-License-Identifier: BSD-3-Clause
5890b5088SRaghu Krishnamurthy  */
6890b5088SRaghu Krishnamurthy 
7890b5088SRaghu Krishnamurthy #include <assert.h>
8890b5088SRaghu Krishnamurthy #include <errno.h>
9890b5088SRaghu Krishnamurthy #include <string.h>
10*66bdfd6eSRaghu Krishnamurthy #include "spmd_private.h"
11890b5088SRaghu Krishnamurthy 
12890b5088SRaghu Krishnamurthy #include <common/debug.h>
13*66bdfd6eSRaghu Krishnamurthy #include <lib/el3_runtime/context_mgmt.h>
14890b5088SRaghu Krishnamurthy #include <services/el3_spmd_logical_sp.h>
15*66bdfd6eSRaghu Krishnamurthy #include <services/spmc_svc.h>
16*66bdfd6eSRaghu Krishnamurthy 
17890b5088SRaghu Krishnamurthy 
18890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
19890b5088SRaghu Krishnamurthy static bool is_spmd_lp_inited;
20890b5088SRaghu Krishnamurthy static bool is_spmc_inited;
21890b5088SRaghu Krishnamurthy 
22890b5088SRaghu Krishnamurthy /*
23890b5088SRaghu Krishnamurthy  * Helper function to obtain the array storing the EL3
24890b5088SRaghu Krishnamurthy  * SPMD Logical Partition descriptors.
25890b5088SRaghu Krishnamurthy  */
26890b5088SRaghu Krishnamurthy static struct spmd_lp_desc *get_spmd_el3_lp_array(void)
27890b5088SRaghu Krishnamurthy {
28890b5088SRaghu Krishnamurthy 	return (struct spmd_lp_desc *) SPMD_LP_DESCS_START;
29890b5088SRaghu Krishnamurthy }
30890b5088SRaghu Krishnamurthy 
31890b5088SRaghu Krishnamurthy /*******************************************************************************
32890b5088SRaghu Krishnamurthy  * Validate any logical partition descriptors before we initialize.
33890b5088SRaghu Krishnamurthy  * Initialization of said partitions will be taken care of during SPMD boot.
34890b5088SRaghu Krishnamurthy  ******************************************************************************/
35890b5088SRaghu Krishnamurthy static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array)
36890b5088SRaghu Krishnamurthy {
37890b5088SRaghu Krishnamurthy 	/* Check the array bounds are valid. */
38890b5088SRaghu Krishnamurthy 	assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START);
39890b5088SRaghu Krishnamurthy 
40*66bdfd6eSRaghu Krishnamurthy 	/*
41*66bdfd6eSRaghu Krishnamurthy 	 * No support for SPMD logical partitions when SPMC is at EL3.
42*66bdfd6eSRaghu Krishnamurthy 	 */
43*66bdfd6eSRaghu Krishnamurthy 	assert(!is_spmc_at_el3());
44*66bdfd6eSRaghu Krishnamurthy 
45890b5088SRaghu Krishnamurthy 	/* If no SPMD logical partitions are implemented then simply bail out. */
46890b5088SRaghu Krishnamurthy 	if (SPMD_LP_DESCS_COUNT == 0U) {
47890b5088SRaghu Krishnamurthy 		return -1;
48890b5088SRaghu Krishnamurthy 	}
49890b5088SRaghu Krishnamurthy 
50890b5088SRaghu Krishnamurthy 	for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) {
51890b5088SRaghu Krishnamurthy 		struct spmd_lp_desc *lp_desc = &lp_array[index];
52890b5088SRaghu Krishnamurthy 
53890b5088SRaghu Krishnamurthy 		/* Validate our logical partition descriptors. */
54890b5088SRaghu Krishnamurthy 		if (lp_desc == NULL) {
55890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical SP Descriptor\n");
56890b5088SRaghu Krishnamurthy 			return -EINVAL;
57890b5088SRaghu Krishnamurthy 		}
58890b5088SRaghu Krishnamurthy 
59890b5088SRaghu Krishnamurthy 		/*
60890b5088SRaghu Krishnamurthy 		 * Ensure the ID follows the convention to indicate it resides
61890b5088SRaghu Krishnamurthy 		 * in the secure world.
62890b5088SRaghu Krishnamurthy 		 */
63890b5088SRaghu Krishnamurthy 		if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
64890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical SP ID (0x%x)\n",
65890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
66890b5088SRaghu Krishnamurthy 			return -EINVAL;
67890b5088SRaghu Krishnamurthy 		}
68890b5088SRaghu Krishnamurthy 
69890b5088SRaghu Krishnamurthy 		/* Ensure SPMD logical partition is in valid range. */
70890b5088SRaghu Krishnamurthy 		if (!is_spmd_lp_id(lp_desc->sp_id)) {
71890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical Partition ID (0x%x)\n",
72890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
73890b5088SRaghu Krishnamurthy 			return -EINVAL;
74890b5088SRaghu Krishnamurthy 		}
75890b5088SRaghu Krishnamurthy 
76890b5088SRaghu Krishnamurthy 		/* Ensure the UUID is not the NULL UUID. */
77890b5088SRaghu Krishnamurthy 		if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 &&
78890b5088SRaghu Krishnamurthy 		    lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) {
79890b5088SRaghu Krishnamurthy 			ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n",
80890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
81890b5088SRaghu Krishnamurthy 			return -EINVAL;
82890b5088SRaghu Krishnamurthy 		}
83890b5088SRaghu Krishnamurthy 
84890b5088SRaghu Krishnamurthy 		/* Ensure init function callback is registered. */
85890b5088SRaghu Krishnamurthy 		if (lp_desc->init == NULL) {
86890b5088SRaghu Krishnamurthy 			ERROR("Missing init function for Logical SP(0x%x)\n",
87890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
88890b5088SRaghu Krishnamurthy 			return -EINVAL;
89890b5088SRaghu Krishnamurthy 		}
90890b5088SRaghu Krishnamurthy 
91890b5088SRaghu Krishnamurthy 		/* Ensure that SPMD LP only supports sending direct requests. */
92890b5088SRaghu Krishnamurthy 		if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) {
93890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD logical partition properties (0x%x)\n",
94890b5088SRaghu Krishnamurthy 			      lp_desc->properties);
95890b5088SRaghu Krishnamurthy 			return -EINVAL;
96890b5088SRaghu Krishnamurthy 		}
97890b5088SRaghu Krishnamurthy 
98890b5088SRaghu Krishnamurthy 		/* Ensure that all partition IDs are unique. */
99890b5088SRaghu Krishnamurthy 		for (uint32_t inner_idx = index + 1;
100890b5088SRaghu Krishnamurthy 		     inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) {
101890b5088SRaghu Krishnamurthy 			if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
102890b5088SRaghu Krishnamurthy 				ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n",
103890b5088SRaghu Krishnamurthy 				      lp_desc->sp_id);
104890b5088SRaghu Krishnamurthy 				return -EINVAL;
105890b5088SRaghu Krishnamurthy 			}
106890b5088SRaghu Krishnamurthy 		}
107890b5088SRaghu Krishnamurthy 	}
108890b5088SRaghu Krishnamurthy 	return 0;
109890b5088SRaghu Krishnamurthy }
110*66bdfd6eSRaghu Krishnamurthy 
111*66bdfd6eSRaghu Krishnamurthy static void spmd_encode_ffa_error(struct ffa_value *retval, int32_t error_code)
112*66bdfd6eSRaghu Krishnamurthy {
113*66bdfd6eSRaghu Krishnamurthy 	retval->func = FFA_ERROR;
114*66bdfd6eSRaghu Krishnamurthy 	retval->arg1 = FFA_TARGET_INFO_MBZ;
115*66bdfd6eSRaghu Krishnamurthy 	retval->arg2 = (uint32_t)error_code;
116*66bdfd6eSRaghu Krishnamurthy 	retval->arg3 = FFA_TARGET_INFO_MBZ;
117*66bdfd6eSRaghu Krishnamurthy 	retval->arg4 = FFA_TARGET_INFO_MBZ;
118*66bdfd6eSRaghu Krishnamurthy 	retval->arg5 = FFA_TARGET_INFO_MBZ;
119*66bdfd6eSRaghu Krishnamurthy 	retval->arg6 = FFA_TARGET_INFO_MBZ;
120*66bdfd6eSRaghu Krishnamurthy 	retval->arg7 = FFA_TARGET_INFO_MBZ;
121*66bdfd6eSRaghu Krishnamurthy }
122*66bdfd6eSRaghu Krishnamurthy 
123*66bdfd6eSRaghu Krishnamurthy static void spmd_build_direct_message_req(spmd_spm_core_context_t *ctx,
124*66bdfd6eSRaghu Krishnamurthy 					  uint64_t x1, uint64_t x2,
125*66bdfd6eSRaghu Krishnamurthy 					  uint64_t x3, uint64_t x4)
126*66bdfd6eSRaghu Krishnamurthy {
127*66bdfd6eSRaghu Krishnamurthy 	gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
128*66bdfd6eSRaghu Krishnamurthy 
129*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32);
130*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X1, x1);
131*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X2, x2);
132*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X3, x3);
133*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X4, x4);
134*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X5, 0U);
135*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X6, 0U);
136*66bdfd6eSRaghu Krishnamurthy 	write_ctx_reg(gpregs, CTX_GPREG_X7, 0U);
137*66bdfd6eSRaghu Krishnamurthy }
138*66bdfd6eSRaghu Krishnamurthy 
139*66bdfd6eSRaghu Krishnamurthy static void spmd_encode_ctx_to_ffa_value(spmd_spm_core_context_t *ctx,
140*66bdfd6eSRaghu Krishnamurthy 					 struct ffa_value *retval)
141*66bdfd6eSRaghu Krishnamurthy {
142*66bdfd6eSRaghu Krishnamurthy 	gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
143*66bdfd6eSRaghu Krishnamurthy 
144*66bdfd6eSRaghu Krishnamurthy 	retval->func = read_ctx_reg(gpregs, CTX_GPREG_X0);
145*66bdfd6eSRaghu Krishnamurthy 	retval->arg1 = read_ctx_reg(gpregs, CTX_GPREG_X1);
146*66bdfd6eSRaghu Krishnamurthy 	retval->arg2 = read_ctx_reg(gpregs, CTX_GPREG_X2);
147*66bdfd6eSRaghu Krishnamurthy 	retval->arg3 = read_ctx_reg(gpregs, CTX_GPREG_X3);
148*66bdfd6eSRaghu Krishnamurthy 	retval->arg4 = read_ctx_reg(gpregs, CTX_GPREG_X4);
149*66bdfd6eSRaghu Krishnamurthy 	retval->arg5 = read_ctx_reg(gpregs, CTX_GPREG_X5);
150*66bdfd6eSRaghu Krishnamurthy 	retval->arg6 = read_ctx_reg(gpregs, CTX_GPREG_X6);
151*66bdfd6eSRaghu Krishnamurthy 	retval->arg7 = read_ctx_reg(gpregs, CTX_GPREG_X7);
152*66bdfd6eSRaghu Krishnamurthy }
153*66bdfd6eSRaghu Krishnamurthy 
154*66bdfd6eSRaghu Krishnamurthy static void spmd_logical_sp_set_dir_req_ongoing(spmd_spm_core_context_t *ctx)
155*66bdfd6eSRaghu Krishnamurthy {
156*66bdfd6eSRaghu Krishnamurthy 	ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_DIR_REQ_ONGOING;
157*66bdfd6eSRaghu Krishnamurthy }
158*66bdfd6eSRaghu Krishnamurthy 
159*66bdfd6eSRaghu Krishnamurthy static void spmd_logical_sp_reset_dir_req_ongoing(spmd_spm_core_context_t *ctx)
160*66bdfd6eSRaghu Krishnamurthy {
161*66bdfd6eSRaghu Krishnamurthy 	ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_DIR_REQ_ONGOING;
162*66bdfd6eSRaghu Krishnamurthy }
163*66bdfd6eSRaghu Krishnamurthy 
164890b5088SRaghu Krishnamurthy #endif
165890b5088SRaghu Krishnamurthy 
166890b5088SRaghu Krishnamurthy /*
167890b5088SRaghu Krishnamurthy  * Initialize SPMD logical partitions. This function assumes that it is called
168890b5088SRaghu Krishnamurthy  * only after the SPMC has successfully initialized.
169890b5088SRaghu Krishnamurthy  */
170890b5088SRaghu Krishnamurthy int32_t spmd_logical_sp_init(void)
171890b5088SRaghu Krishnamurthy {
172890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
173890b5088SRaghu Krishnamurthy 	int32_t rc = 0;
174890b5088SRaghu Krishnamurthy 	struct spmd_lp_desc *spmd_lp_descs;
175890b5088SRaghu Krishnamurthy 
176890b5088SRaghu Krishnamurthy 	if (is_spmd_lp_inited == true) {
177890b5088SRaghu Krishnamurthy 		return 0;
178890b5088SRaghu Krishnamurthy 	}
179890b5088SRaghu Krishnamurthy 
180890b5088SRaghu Krishnamurthy 	if (is_spmc_inited == false) {
181890b5088SRaghu Krishnamurthy 		return -1;
182890b5088SRaghu Krishnamurthy 	}
183890b5088SRaghu Krishnamurthy 
184890b5088SRaghu Krishnamurthy 	spmd_lp_descs = get_spmd_el3_lp_array();
185890b5088SRaghu Krishnamurthy 
186890b5088SRaghu Krishnamurthy 	/* Perform initial validation of the SPMD Logical Partitions. */
187890b5088SRaghu Krishnamurthy 	rc = el3_spmd_sp_desc_validate(spmd_lp_descs);
188890b5088SRaghu Krishnamurthy 	if (rc != 0) {
189890b5088SRaghu Krishnamurthy 		ERROR("Logical SPMD Partition validation failed!\n");
190890b5088SRaghu Krishnamurthy 		return rc;
191890b5088SRaghu Krishnamurthy 	}
192890b5088SRaghu Krishnamurthy 
193890b5088SRaghu Krishnamurthy 	VERBOSE("SPMD Logical Secure Partition init start.\n");
194890b5088SRaghu Krishnamurthy 	for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) {
195890b5088SRaghu Krishnamurthy 		rc = spmd_lp_descs[i].init();
196890b5088SRaghu Krishnamurthy 		if (rc != 0) {
197890b5088SRaghu Krishnamurthy 			ERROR("SPMD Logical SP (0x%x) failed to initialize\n",
198890b5088SRaghu Krishnamurthy 			      spmd_lp_descs[i].sp_id);
199890b5088SRaghu Krishnamurthy 			return rc;
200890b5088SRaghu Krishnamurthy 		}
201890b5088SRaghu Krishnamurthy 		VERBOSE("SPMD Logical SP (0x%x) Initialized\n",
202890b5088SRaghu Krishnamurthy 			spmd_lp_descs[i].sp_id);
203890b5088SRaghu Krishnamurthy 	}
204890b5088SRaghu Krishnamurthy 
205890b5088SRaghu Krishnamurthy 	INFO("SPMD Logical Secure Partition init completed.\n");
206890b5088SRaghu Krishnamurthy 	if (rc == 0) {
207890b5088SRaghu Krishnamurthy 		is_spmd_lp_inited = true;
208890b5088SRaghu Krishnamurthy 	}
209890b5088SRaghu Krishnamurthy 	return rc;
210890b5088SRaghu Krishnamurthy #else
211890b5088SRaghu Krishnamurthy 	return 0;
212890b5088SRaghu Krishnamurthy #endif
213890b5088SRaghu Krishnamurthy }
214890b5088SRaghu Krishnamurthy 
215890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_initialized(void)
216890b5088SRaghu Krishnamurthy {
217890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
218890b5088SRaghu Krishnamurthy 	is_spmc_inited = true;
219890b5088SRaghu Krishnamurthy #endif
220890b5088SRaghu Krishnamurthy }
221890b5088SRaghu Krishnamurthy 
222890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_failure(void)
223890b5088SRaghu Krishnamurthy {
224890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
225890b5088SRaghu Krishnamurthy 	is_spmc_inited = false;
226890b5088SRaghu Krishnamurthy #endif
227890b5088SRaghu Krishnamurthy }
228*66bdfd6eSRaghu Krishnamurthy 
229*66bdfd6eSRaghu Krishnamurthy /*******************************************************************************
230*66bdfd6eSRaghu Krishnamurthy  * This function sends an FF-A Direct Request from a partition in EL3 to a
231*66bdfd6eSRaghu Krishnamurthy  * partition that may reside under an SPMC (only lower ELs supported). The main
232*66bdfd6eSRaghu Krishnamurthy  * use of this API is for SPMD logical partitions.
233*66bdfd6eSRaghu Krishnamurthy  * The API is expected to be used when there are platform specific SMCs that
234*66bdfd6eSRaghu Krishnamurthy  * need to be routed to a secure partition that is FF-A compliant or when
235*66bdfd6eSRaghu Krishnamurthy  * there are group 0 interrupts that need to be handled first in EL3 and then
236*66bdfd6eSRaghu Krishnamurthy  * forwarded to an FF-A compliant secure partition. Therefore, it is expected
237*66bdfd6eSRaghu Krishnamurthy  * that the handle to the context provided belongs to the non-secure context.
238*66bdfd6eSRaghu Krishnamurthy  * This also means that interrupts/SMCs that trap to EL3 during secure execution
239*66bdfd6eSRaghu Krishnamurthy  * cannot use this API.
240*66bdfd6eSRaghu Krishnamurthy  * x1, x2, x3 and x4 are encoded as specified in the FF-A specification.
241*66bdfd6eSRaghu Krishnamurthy  * retval is used to pass the direct response values to the caller.
242*66bdfd6eSRaghu Krishnamurthy  * The function returns true if retval has valid values, and false otherwise.
243*66bdfd6eSRaghu Krishnamurthy  ******************************************************************************/
244*66bdfd6eSRaghu Krishnamurthy bool spmd_el3_ffa_msg_direct_req(uint64_t x1,
245*66bdfd6eSRaghu Krishnamurthy 				 uint64_t x2,
246*66bdfd6eSRaghu Krishnamurthy 				 uint64_t x3,
247*66bdfd6eSRaghu Krishnamurthy 				 uint64_t x4,
248*66bdfd6eSRaghu Krishnamurthy 				 void *handle,
249*66bdfd6eSRaghu Krishnamurthy 				 struct ffa_value *retval)
250*66bdfd6eSRaghu Krishnamurthy {
251*66bdfd6eSRaghu Krishnamurthy #if ENABLE_SPMD_LP
252*66bdfd6eSRaghu Krishnamurthy 
253*66bdfd6eSRaghu Krishnamurthy 	uint64_t rc = UINT64_MAX;
254*66bdfd6eSRaghu Krishnamurthy 	spmd_spm_core_context_t *ctx = spmd_get_context();
255*66bdfd6eSRaghu Krishnamurthy 
256*66bdfd6eSRaghu Krishnamurthy 	if (retval == NULL) {
257*66bdfd6eSRaghu Krishnamurthy 		return false;
258*66bdfd6eSRaghu Krishnamurthy 	}
259*66bdfd6eSRaghu Krishnamurthy 
260*66bdfd6eSRaghu Krishnamurthy 	memset(retval, 0, sizeof(*retval));
261*66bdfd6eSRaghu Krishnamurthy 
262*66bdfd6eSRaghu Krishnamurthy 	if (!is_spmd_lp_inited || !is_spmc_inited) {
263*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Cannot send SPMD logical partition direct message,"
264*66bdfd6eSRaghu Krishnamurthy 			" Partitions not initialized or SPMC not initialized.\n");
265*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
266*66bdfd6eSRaghu Krishnamurthy 		return true;
267*66bdfd6eSRaghu Krishnamurthy 	}
268*66bdfd6eSRaghu Krishnamurthy 
269*66bdfd6eSRaghu Krishnamurthy 	/*
270*66bdfd6eSRaghu Krishnamurthy 	 * x2 must be zero, since there is no support for framework message via
271*66bdfd6eSRaghu Krishnamurthy 	 * an SPMD logical partition. This is sort of a useless check and it is
272*66bdfd6eSRaghu Krishnamurthy 	 * possible to not take parameter. However, as the framework extends it
273*66bdfd6eSRaghu Krishnamurthy 	 * may be useful to have x2 and extend this function later with
274*66bdfd6eSRaghu Krishnamurthy 	 * functionality based on x2.
275*66bdfd6eSRaghu Krishnamurthy 	 */
276*66bdfd6eSRaghu Krishnamurthy 	if (x2 != 0) {
277*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("x2 must be zero. Cannot send framework message.\n");
278*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
279*66bdfd6eSRaghu Krishnamurthy 		return true;
280*66bdfd6eSRaghu Krishnamurthy 	}
281*66bdfd6eSRaghu Krishnamurthy 
282*66bdfd6eSRaghu Krishnamurthy 	/*
283*66bdfd6eSRaghu Krishnamurthy 	 * Current context must be non-secure. API is expected to be used
284*66bdfd6eSRaghu Krishnamurthy 	 * when entry into EL3 and the SPMD logical partition is via an
285*66bdfd6eSRaghu Krishnamurthy 	 * interrupt that occurs when execution is in normal world and
286*66bdfd6eSRaghu Krishnamurthy 	 * SMCs from normal world. FF-A compliant SPMCs are expected to
287*66bdfd6eSRaghu Krishnamurthy 	 * trap interrupts during secure execution in lower ELs since they
288*66bdfd6eSRaghu Krishnamurthy 	 * are usually not re-entrant and SMCs from secure world can be
289*66bdfd6eSRaghu Krishnamurthy 	 * handled synchronously. There is no known use case for an SPMD
290*66bdfd6eSRaghu Krishnamurthy 	 * logical partition to send a direct message to another partition
291*66bdfd6eSRaghu Krishnamurthy 	 * in response to a secure interrupt or SMCs from secure world.
292*66bdfd6eSRaghu Krishnamurthy 	 */
293*66bdfd6eSRaghu Krishnamurthy 	if (handle != cm_get_context(NON_SECURE)) {
294*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Handle must be for the non-secure context.\n");
295*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
296*66bdfd6eSRaghu Krishnamurthy 		return true;
297*66bdfd6eSRaghu Krishnamurthy 	}
298*66bdfd6eSRaghu Krishnamurthy 
299*66bdfd6eSRaghu Krishnamurthy 	if (!is_spmd_lp_id(ffa_endpoint_source(x1))) {
300*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Source ID must be valid SPMD logical partition"
301*66bdfd6eSRaghu Krishnamurthy 			" ID.\n");
302*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval,
303*66bdfd6eSRaghu Krishnamurthy 					      FFA_ERROR_INVALID_PARAMETER);
304*66bdfd6eSRaghu Krishnamurthy 		return true;
305*66bdfd6eSRaghu Krishnamurthy 	}
306*66bdfd6eSRaghu Krishnamurthy 
307*66bdfd6eSRaghu Krishnamurthy 	if (is_spmd_lp_id(ffa_endpoint_destination(x1))) {
308*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Destination ID must not be SPMD logical partition"
309*66bdfd6eSRaghu Krishnamurthy 			" ID.\n");
310*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval,
311*66bdfd6eSRaghu Krishnamurthy 					      FFA_ERROR_INVALID_PARAMETER);
312*66bdfd6eSRaghu Krishnamurthy 		return true;
313*66bdfd6eSRaghu Krishnamurthy 	}
314*66bdfd6eSRaghu Krishnamurthy 
315*66bdfd6eSRaghu Krishnamurthy 	if (!ffa_is_secure_world_id(ffa_endpoint_destination(x1))) {
316*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Destination ID must be secure world ID.\n");
317*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval,
318*66bdfd6eSRaghu Krishnamurthy 					      FFA_ERROR_INVALID_PARAMETER);
319*66bdfd6eSRaghu Krishnamurthy 		return true;
320*66bdfd6eSRaghu Krishnamurthy 	}
321*66bdfd6eSRaghu Krishnamurthy 
322*66bdfd6eSRaghu Krishnamurthy 	if (ffa_endpoint_destination(x1) == SPMD_DIRECT_MSG_ENDPOINT_ID) {
323*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Destination ID must not be SPMD ID.\n");
324*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval,
325*66bdfd6eSRaghu Krishnamurthy 					      FFA_ERROR_INVALID_PARAMETER);
326*66bdfd6eSRaghu Krishnamurthy 		return true;
327*66bdfd6eSRaghu Krishnamurthy 	}
328*66bdfd6eSRaghu Krishnamurthy 
329*66bdfd6eSRaghu Krishnamurthy 	if (ffa_endpoint_destination(x1) == spmd_spmc_id_get()) {
330*66bdfd6eSRaghu Krishnamurthy 		VERBOSE("Destination ID must not be SPMC ID.\n");
331*66bdfd6eSRaghu Krishnamurthy 			spmd_encode_ffa_error(retval,
332*66bdfd6eSRaghu Krishnamurthy 					      FFA_ERROR_INVALID_PARAMETER);
333*66bdfd6eSRaghu Krishnamurthy 		return true;
334*66bdfd6eSRaghu Krishnamurthy 	}
335*66bdfd6eSRaghu Krishnamurthy 
336*66bdfd6eSRaghu Krishnamurthy 	/* Save the non-secure context before entering SPMC */
337*66bdfd6eSRaghu Krishnamurthy 	cm_el1_sysregs_context_save(NON_SECURE);
338*66bdfd6eSRaghu Krishnamurthy #if SPMD_SPM_AT_SEL2
339*66bdfd6eSRaghu Krishnamurthy 	cm_el2_sysregs_context_save(NON_SECURE);
340*66bdfd6eSRaghu Krishnamurthy #endif
341*66bdfd6eSRaghu Krishnamurthy 
342*66bdfd6eSRaghu Krishnamurthy 	/*
343*66bdfd6eSRaghu Krishnamurthy 	 * Perform synchronous entry into the SPMC. Synchronous entry is
344*66bdfd6eSRaghu Krishnamurthy 	 * required because the spec requires that a direct message request
345*66bdfd6eSRaghu Krishnamurthy 	 * from an SPMD LP look like a function call from it's perspective.
346*66bdfd6eSRaghu Krishnamurthy 	 */
347*66bdfd6eSRaghu Krishnamurthy 	spmd_build_direct_message_req(ctx, x1, x2, x3, x4);
348*66bdfd6eSRaghu Krishnamurthy 	spmd_logical_sp_set_dir_req_ongoing(ctx);
349*66bdfd6eSRaghu Krishnamurthy 
350*66bdfd6eSRaghu Krishnamurthy 	rc = spmd_spm_core_sync_entry(ctx);
351*66bdfd6eSRaghu Krishnamurthy 
352*66bdfd6eSRaghu Krishnamurthy 	spmd_logical_sp_reset_dir_req_ongoing(ctx);
353*66bdfd6eSRaghu Krishnamurthy 
354*66bdfd6eSRaghu Krishnamurthy 	if (rc != 0ULL) {
355*66bdfd6eSRaghu Krishnamurthy 		ERROR("%s failed (%lx) on CPU%u\n", __func__, rc,
356*66bdfd6eSRaghu Krishnamurthy 		      plat_my_core_pos());
357*66bdfd6eSRaghu Krishnamurthy 		panic();
358*66bdfd6eSRaghu Krishnamurthy 	} else {
359*66bdfd6eSRaghu Krishnamurthy 		spmd_encode_ctx_to_ffa_value(ctx, retval);
360*66bdfd6eSRaghu Krishnamurthy 
361*66bdfd6eSRaghu Krishnamurthy 		/*
362*66bdfd6eSRaghu Krishnamurthy 		 * Only expect error or direct response,
363*66bdfd6eSRaghu Krishnamurthy 		 * spmd_spm_core_sync_exit should not be called on other paths.
364*66bdfd6eSRaghu Krishnamurthy 		 * Checks are asserts since the LSP can fail gracefully if the
365*66bdfd6eSRaghu Krishnamurthy 		 * source or destination ids are not the same. Panic'ing would
366*66bdfd6eSRaghu Krishnamurthy 		 * not provide any benefit.
367*66bdfd6eSRaghu Krishnamurthy 		 */
368*66bdfd6eSRaghu Krishnamurthy 		assert(is_ffa_error(retval) || is_ffa_direct_msg_resp(retval));
369*66bdfd6eSRaghu Krishnamurthy 		assert(is_ffa_error(retval) ||
370*66bdfd6eSRaghu Krishnamurthy 			(ffa_endpoint_destination(retval->arg1) ==
371*66bdfd6eSRaghu Krishnamurthy 				ffa_endpoint_source(x1)));
372*66bdfd6eSRaghu Krishnamurthy 		assert(is_ffa_error(retval) ||
373*66bdfd6eSRaghu Krishnamurthy 			(ffa_endpoint_source(retval->arg1) ==
374*66bdfd6eSRaghu Krishnamurthy 				ffa_endpoint_destination(x1)));
375*66bdfd6eSRaghu Krishnamurthy 	}
376*66bdfd6eSRaghu Krishnamurthy 
377*66bdfd6eSRaghu Krishnamurthy 	cm_el1_sysregs_context_restore(NON_SECURE);
378*66bdfd6eSRaghu Krishnamurthy #if SPMD_SPM_AT_SEL2
379*66bdfd6eSRaghu Krishnamurthy 	cm_el2_sysregs_context_restore(NON_SECURE);
380*66bdfd6eSRaghu Krishnamurthy #endif
381*66bdfd6eSRaghu Krishnamurthy 	cm_set_next_eret_context(NON_SECURE);
382*66bdfd6eSRaghu Krishnamurthy 
383*66bdfd6eSRaghu Krishnamurthy 	return true;
384*66bdfd6eSRaghu Krishnamurthy #else
385*66bdfd6eSRaghu Krishnamurthy 	return false;
386*66bdfd6eSRaghu Krishnamurthy #endif
387*66bdfd6eSRaghu Krishnamurthy }
388*66bdfd6eSRaghu Krishnamurthy 
389*66bdfd6eSRaghu Krishnamurthy bool is_spmd_logical_sp_dir_req_in_progress(
390*66bdfd6eSRaghu Krishnamurthy 		spmd_spm_core_context_t *ctx)
391*66bdfd6eSRaghu Krishnamurthy {
392*66bdfd6eSRaghu Krishnamurthy #if ENABLE_SPMD_LP
393*66bdfd6eSRaghu Krishnamurthy 	return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_DIR_REQ_ONGOING)
394*66bdfd6eSRaghu Krishnamurthy 		== SPMD_LP_FFA_DIR_REQ_ONGOING);
395*66bdfd6eSRaghu Krishnamurthy #else
396*66bdfd6eSRaghu Krishnamurthy 	return false;
397*66bdfd6eSRaghu Krishnamurthy #endif
398*66bdfd6eSRaghu Krishnamurthy }
399