xref: /arm-trusted-firmware/services/std_svc/spmd/spmd_logical_sp.c (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #include <assert.h>
8*91f16700Schasinglulu #include <errno.h>
9*91f16700Schasinglulu #include <string.h>
10*91f16700Schasinglulu #include "spmd_private.h"
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <common/debug.h>
13*91f16700Schasinglulu #include <common/uuid.h>
14*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h>
15*91f16700Schasinglulu #include <services/el3_spmd_logical_sp.h>
16*91f16700Schasinglulu #include <services/spmc_svc.h>
17*91f16700Schasinglulu #include <smccc_helpers.h>
18*91f16700Schasinglulu 
19*91f16700Schasinglulu 
20*91f16700Schasinglulu /*
21*91f16700Schasinglulu  * Maximum ffa_partition_info entries that can be returned by an invocation
22*91f16700Schasinglulu  * of FFA_PARTITION_INFO_GET_REGS_64 is size in bytes, of available
23*91f16700Schasinglulu  * registers/args in struct ffa_value divided by size of struct
24*91f16700Schasinglulu  * ffa_partition_info. For this ABI, arg3-arg17 in ffa_value can be used, i.e.
25*91f16700Schasinglulu  * 15 uint64_t fields. For FF-A v1.1, this value should be 5.
26*91f16700Schasinglulu  */
27*91f16700Schasinglulu #define MAX_INFO_REGS_ENTRIES_PER_CALL \
28*91f16700Schasinglulu 	(uint8_t)((15 * sizeof(uint64_t)) / \
29*91f16700Schasinglulu 		  sizeof(struct ffa_partition_info_v1_1))
30*91f16700Schasinglulu CASSERT(MAX_INFO_REGS_ENTRIES_PER_CALL == 5, assert_too_many_info_reg_entries);
31*91f16700Schasinglulu 
32*91f16700Schasinglulu #if ENABLE_SPMD_LP
33*91f16700Schasinglulu static bool is_spmd_lp_inited;
34*91f16700Schasinglulu static bool is_spmc_inited;
35*91f16700Schasinglulu 
36*91f16700Schasinglulu /*
37*91f16700Schasinglulu  * Helper function to obtain the array storing the EL3
38*91f16700Schasinglulu  * SPMD Logical Partition descriptors.
39*91f16700Schasinglulu  */
40*91f16700Schasinglulu static struct spmd_lp_desc *get_spmd_el3_lp_array(void)
41*91f16700Schasinglulu {
42*91f16700Schasinglulu 	return (struct spmd_lp_desc *) SPMD_LP_DESCS_START;
43*91f16700Schasinglulu }
44*91f16700Schasinglulu 
45*91f16700Schasinglulu /*******************************************************************************
46*91f16700Schasinglulu  * Validate any logical partition descriptors before we initialize.
47*91f16700Schasinglulu  * Initialization of said partitions will be taken care of during SPMD boot.
48*91f16700Schasinglulu  ******************************************************************************/
49*91f16700Schasinglulu static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array)
50*91f16700Schasinglulu {
51*91f16700Schasinglulu 	/* Check the array bounds are valid. */
52*91f16700Schasinglulu 	assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START);
53*91f16700Schasinglulu 
54*91f16700Schasinglulu 	/*
55*91f16700Schasinglulu 	 * No support for SPMD logical partitions when SPMC is at EL3.
56*91f16700Schasinglulu 	 */
57*91f16700Schasinglulu 	assert(!is_spmc_at_el3());
58*91f16700Schasinglulu 
59*91f16700Schasinglulu 	/* If no SPMD logical partitions are implemented then simply bail out. */
60*91f16700Schasinglulu 	if (SPMD_LP_DESCS_COUNT == 0U) {
61*91f16700Schasinglulu 		return -1;
62*91f16700Schasinglulu 	}
63*91f16700Schasinglulu 
64*91f16700Schasinglulu 	for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) {
65*91f16700Schasinglulu 		struct spmd_lp_desc *lp_desc = &lp_array[index];
66*91f16700Schasinglulu 
67*91f16700Schasinglulu 		/* Validate our logical partition descriptors. */
68*91f16700Schasinglulu 		if (lp_desc == NULL) {
69*91f16700Schasinglulu 			ERROR("Invalid SPMD Logical SP Descriptor\n");
70*91f16700Schasinglulu 			return -EINVAL;
71*91f16700Schasinglulu 		}
72*91f16700Schasinglulu 
73*91f16700Schasinglulu 		/*
74*91f16700Schasinglulu 		 * Ensure the ID follows the convention to indicate it resides
75*91f16700Schasinglulu 		 * in the secure world.
76*91f16700Schasinglulu 		 */
77*91f16700Schasinglulu 		if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
78*91f16700Schasinglulu 			ERROR("Invalid SPMD Logical SP ID (0x%x)\n",
79*91f16700Schasinglulu 			      lp_desc->sp_id);
80*91f16700Schasinglulu 			return -EINVAL;
81*91f16700Schasinglulu 		}
82*91f16700Schasinglulu 
83*91f16700Schasinglulu 		/* Ensure SPMD logical partition is in valid range. */
84*91f16700Schasinglulu 		if (!is_spmd_lp_id(lp_desc->sp_id)) {
85*91f16700Schasinglulu 			ERROR("Invalid SPMD Logical Partition ID (0x%x)\n",
86*91f16700Schasinglulu 			      lp_desc->sp_id);
87*91f16700Schasinglulu 			return -EINVAL;
88*91f16700Schasinglulu 		}
89*91f16700Schasinglulu 
90*91f16700Schasinglulu 		/* Ensure the UUID is not the NULL UUID. */
91*91f16700Schasinglulu 		if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 &&
92*91f16700Schasinglulu 		    lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) {
93*91f16700Schasinglulu 			ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n",
94*91f16700Schasinglulu 			      lp_desc->sp_id);
95*91f16700Schasinglulu 			return -EINVAL;
96*91f16700Schasinglulu 		}
97*91f16700Schasinglulu 
98*91f16700Schasinglulu 		/* Ensure init function callback is registered. */
99*91f16700Schasinglulu 		if (lp_desc->init == NULL) {
100*91f16700Schasinglulu 			ERROR("Missing init function for Logical SP(0x%x)\n",
101*91f16700Schasinglulu 			      lp_desc->sp_id);
102*91f16700Schasinglulu 			return -EINVAL;
103*91f16700Schasinglulu 		}
104*91f16700Schasinglulu 
105*91f16700Schasinglulu 		/* Ensure that SPMD LP only supports sending direct requests. */
106*91f16700Schasinglulu 		if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) {
107*91f16700Schasinglulu 			ERROR("Invalid SPMD logical partition properties (0x%x)\n",
108*91f16700Schasinglulu 			      lp_desc->properties);
109*91f16700Schasinglulu 			return -EINVAL;
110*91f16700Schasinglulu 		}
111*91f16700Schasinglulu 
112*91f16700Schasinglulu 		/* Ensure that all partition IDs are unique. */
113*91f16700Schasinglulu 		for (uint32_t inner_idx = index + 1;
114*91f16700Schasinglulu 		     inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) {
115*91f16700Schasinglulu 			if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
116*91f16700Schasinglulu 				ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n",
117*91f16700Schasinglulu 				      lp_desc->sp_id);
118*91f16700Schasinglulu 				return -EINVAL;
119*91f16700Schasinglulu 			}
120*91f16700Schasinglulu 		}
121*91f16700Schasinglulu 	}
122*91f16700Schasinglulu 	return 0;
123*91f16700Schasinglulu }
124*91f16700Schasinglulu 
125*91f16700Schasinglulu static void spmd_encode_ffa_error(struct ffa_value *retval, int32_t error_code)
126*91f16700Schasinglulu {
127*91f16700Schasinglulu 	retval->func = FFA_ERROR;
128*91f16700Schasinglulu 	retval->arg1 = FFA_TARGET_INFO_MBZ;
129*91f16700Schasinglulu 	retval->arg2 = (uint32_t)error_code;
130*91f16700Schasinglulu 	retval->arg3 = FFA_TARGET_INFO_MBZ;
131*91f16700Schasinglulu 	retval->arg4 = FFA_TARGET_INFO_MBZ;
132*91f16700Schasinglulu 	retval->arg5 = FFA_TARGET_INFO_MBZ;
133*91f16700Schasinglulu 	retval->arg6 = FFA_TARGET_INFO_MBZ;
134*91f16700Schasinglulu 	retval->arg7 = FFA_TARGET_INFO_MBZ;
135*91f16700Schasinglulu }
136*91f16700Schasinglulu 
137*91f16700Schasinglulu static void spmd_build_direct_message_req(spmd_spm_core_context_t *ctx,
138*91f16700Schasinglulu 					  uint64_t x1, uint64_t x2,
139*91f16700Schasinglulu 					  uint64_t x3, uint64_t x4)
140*91f16700Schasinglulu {
141*91f16700Schasinglulu 	gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
142*91f16700Schasinglulu 
143*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32);
144*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X1, x1);
145*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X2, x2);
146*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X3, x3);
147*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X4, x4);
148*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X5, 0U);
149*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X6, 0U);
150*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X7, 0U);
151*91f16700Schasinglulu }
152*91f16700Schasinglulu 
153*91f16700Schasinglulu static void spmd_encode_ctx_to_ffa_value(spmd_spm_core_context_t *ctx,
154*91f16700Schasinglulu 					 struct ffa_value *retval)
155*91f16700Schasinglulu {
156*91f16700Schasinglulu 	gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
157*91f16700Schasinglulu 
158*91f16700Schasinglulu 	retval->func = read_ctx_reg(gpregs, CTX_GPREG_X0);
159*91f16700Schasinglulu 	retval->arg1 = read_ctx_reg(gpregs, CTX_GPREG_X1);
160*91f16700Schasinglulu 	retval->arg2 = read_ctx_reg(gpregs, CTX_GPREG_X2);
161*91f16700Schasinglulu 	retval->arg3 = read_ctx_reg(gpregs, CTX_GPREG_X3);
162*91f16700Schasinglulu 	retval->arg4 = read_ctx_reg(gpregs, CTX_GPREG_X4);
163*91f16700Schasinglulu 	retval->arg5 = read_ctx_reg(gpregs, CTX_GPREG_X5);
164*91f16700Schasinglulu 	retval->arg6 = read_ctx_reg(gpregs, CTX_GPREG_X6);
165*91f16700Schasinglulu 	retval->arg7 = read_ctx_reg(gpregs, CTX_GPREG_X7);
166*91f16700Schasinglulu 	retval->arg8 = read_ctx_reg(gpregs, CTX_GPREG_X8);
167*91f16700Schasinglulu 	retval->arg9 = read_ctx_reg(gpregs, CTX_GPREG_X9);
168*91f16700Schasinglulu 	retval->arg10 = read_ctx_reg(gpregs, CTX_GPREG_X10);
169*91f16700Schasinglulu 	retval->arg11 = read_ctx_reg(gpregs, CTX_GPREG_X11);
170*91f16700Schasinglulu 	retval->arg12 = read_ctx_reg(gpregs, CTX_GPREG_X12);
171*91f16700Schasinglulu 	retval->arg13 = read_ctx_reg(gpregs, CTX_GPREG_X13);
172*91f16700Schasinglulu 	retval->arg14 = read_ctx_reg(gpregs, CTX_GPREG_X14);
173*91f16700Schasinglulu 	retval->arg15 = read_ctx_reg(gpregs, CTX_GPREG_X15);
174*91f16700Schasinglulu 	retval->arg16 = read_ctx_reg(gpregs, CTX_GPREG_X16);
175*91f16700Schasinglulu 	retval->arg17 = read_ctx_reg(gpregs, CTX_GPREG_X17);
176*91f16700Schasinglulu }
177*91f16700Schasinglulu 
178*91f16700Schasinglulu static void spmd_logical_sp_set_dir_req_ongoing(spmd_spm_core_context_t *ctx)
179*91f16700Schasinglulu {
180*91f16700Schasinglulu 	ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_DIR_REQ_ONGOING;
181*91f16700Schasinglulu }
182*91f16700Schasinglulu 
183*91f16700Schasinglulu static void spmd_logical_sp_reset_dir_req_ongoing(spmd_spm_core_context_t *ctx)
184*91f16700Schasinglulu {
185*91f16700Schasinglulu 	ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_DIR_REQ_ONGOING;
186*91f16700Schasinglulu }
187*91f16700Schasinglulu 
188*91f16700Schasinglulu static void spmd_build_ffa_info_get_regs(spmd_spm_core_context_t *ctx,
189*91f16700Schasinglulu 					 const uint32_t uuid[4],
190*91f16700Schasinglulu 					 const uint16_t start_index,
191*91f16700Schasinglulu 					 const uint16_t tag)
192*91f16700Schasinglulu {
193*91f16700Schasinglulu 	gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx);
194*91f16700Schasinglulu 
195*91f16700Schasinglulu 	uint64_t arg1 = (uint64_t)uuid[1] << 32 | uuid[0];
196*91f16700Schasinglulu 	uint64_t arg2 = (uint64_t)uuid[3] << 32 | uuid[2];
197*91f16700Schasinglulu 	uint64_t arg3 = start_index | (uint64_t)tag << 16;
198*91f16700Schasinglulu 
199*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_PARTITION_INFO_GET_REGS_SMC64);
200*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X1, arg1);
201*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X2, arg2);
202*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X3, arg3);
203*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X4, 0U);
204*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X5, 0U);
205*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X6, 0U);
206*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X7, 0U);
207*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X8, 0U);
208*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X9, 0U);
209*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X10, 0U);
210*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X11, 0U);
211*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X12, 0U);
212*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X13, 0U);
213*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X14, 0U);
214*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X15, 0U);
215*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X16, 0U);
216*91f16700Schasinglulu 	write_ctx_reg(gpregs, CTX_GPREG_X17, 0U);
217*91f16700Schasinglulu }
218*91f16700Schasinglulu 
219*91f16700Schasinglulu static void spmd_logical_sp_set_info_regs_ongoing(spmd_spm_core_context_t *ctx)
220*91f16700Schasinglulu {
221*91f16700Schasinglulu 	ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_INFO_GET_REG_ONGOING;
222*91f16700Schasinglulu }
223*91f16700Schasinglulu 
224*91f16700Schasinglulu static void spmd_logical_sp_reset_info_regs_ongoing(
225*91f16700Schasinglulu 		spmd_spm_core_context_t *ctx)
226*91f16700Schasinglulu {
227*91f16700Schasinglulu 	ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_INFO_GET_REG_ONGOING;
228*91f16700Schasinglulu }
229*91f16700Schasinglulu 
230*91f16700Schasinglulu static void spmd_fill_lp_info_array(
231*91f16700Schasinglulu 	struct ffa_partition_info_v1_1 (*partitions)[EL3_SPMD_MAX_NUM_LP],
232*91f16700Schasinglulu 	uint32_t uuid[4], uint16_t *lp_count_out)
233*91f16700Schasinglulu {
234*91f16700Schasinglulu 	uint16_t lp_count = 0;
235*91f16700Schasinglulu 	struct spmd_lp_desc *lp_array;
236*91f16700Schasinglulu 	bool uuid_is_null = is_null_uuid(uuid);
237*91f16700Schasinglulu 
238*91f16700Schasinglulu 	if (SPMD_LP_DESCS_COUNT == 0U) {
239*91f16700Schasinglulu 		*lp_count_out = 0;
240*91f16700Schasinglulu 		return;
241*91f16700Schasinglulu 	}
242*91f16700Schasinglulu 
243*91f16700Schasinglulu 	lp_array = get_spmd_el3_lp_array();
244*91f16700Schasinglulu 	for (uint16_t index = 0; index < SPMD_LP_DESCS_COUNT; ++index) {
245*91f16700Schasinglulu 		struct spmd_lp_desc *lp = &lp_array[index];
246*91f16700Schasinglulu 
247*91f16700Schasinglulu 		if (uuid_is_null || uuid_match(uuid, lp->uuid)) {
248*91f16700Schasinglulu 			uint16_t array_index = lp_count;
249*91f16700Schasinglulu 
250*91f16700Schasinglulu 			++lp_count;
251*91f16700Schasinglulu 
252*91f16700Schasinglulu 			(*partitions)[array_index].ep_id = lp->sp_id;
253*91f16700Schasinglulu 			(*partitions)[array_index].execution_ctx_count = 1;
254*91f16700Schasinglulu 			(*partitions)[array_index].properties = lp->properties;
255*91f16700Schasinglulu 			(*partitions)[array_index].properties |=
256*91f16700Schasinglulu 				(FFA_PARTITION_INFO_GET_AARCH64_STATE <<
257*91f16700Schasinglulu 				 FFA_PARTITION_INFO_GET_EXEC_STATE_SHIFT);
258*91f16700Schasinglulu 			if (uuid_is_null) {
259*91f16700Schasinglulu 				memcpy(&((*partitions)[array_index].uuid),
260*91f16700Schasinglulu 					  &lp->uuid, sizeof(lp->uuid));
261*91f16700Schasinglulu 			}
262*91f16700Schasinglulu 		}
263*91f16700Schasinglulu 	}
264*91f16700Schasinglulu 
265*91f16700Schasinglulu 	*lp_count_out = lp_count;
266*91f16700Schasinglulu }
267*91f16700Schasinglulu 
268*91f16700Schasinglulu static inline void spmd_pack_lp_count_props(
269*91f16700Schasinglulu 	uint64_t *xn, uint16_t ep_id, uint16_t vcpu_count,
270*91f16700Schasinglulu 	uint32_t properties)
271*91f16700Schasinglulu {
272*91f16700Schasinglulu 	*xn = (uint64_t)ep_id;
273*91f16700Schasinglulu 	*xn |= (uint64_t)vcpu_count << 16;
274*91f16700Schasinglulu 	*xn |= (uint64_t)properties << 32;
275*91f16700Schasinglulu }
276*91f16700Schasinglulu 
277*91f16700Schasinglulu static inline void spmd_pack_lp_uuid(uint64_t *xn_1, uint64_t *xn_2,
278*91f16700Schasinglulu 				     uint32_t uuid[4])
279*91f16700Schasinglulu {
280*91f16700Schasinglulu 	*xn_1 = (uint64_t)uuid[0];
281*91f16700Schasinglulu 	*xn_1 |= (uint64_t)uuid[1] << 32;
282*91f16700Schasinglulu 	*xn_2 = (uint64_t)uuid[2];
283*91f16700Schasinglulu 	*xn_2 |= (uint64_t)uuid[3] << 32;
284*91f16700Schasinglulu }
285*91f16700Schasinglulu #endif
286*91f16700Schasinglulu 
287*91f16700Schasinglulu /*
288*91f16700Schasinglulu  * Initialize SPMD logical partitions. This function assumes that it is called
289*91f16700Schasinglulu  * only after the SPMC has successfully initialized.
290*91f16700Schasinglulu  */
291*91f16700Schasinglulu int32_t spmd_logical_sp_init(void)
292*91f16700Schasinglulu {
293*91f16700Schasinglulu #if ENABLE_SPMD_LP
294*91f16700Schasinglulu 	int32_t rc = 0;
295*91f16700Schasinglulu 	struct spmd_lp_desc *spmd_lp_descs;
296*91f16700Schasinglulu 
297*91f16700Schasinglulu 	assert(SPMD_LP_DESCS_COUNT <= EL3_SPMD_MAX_NUM_LP);
298*91f16700Schasinglulu 
299*91f16700Schasinglulu 	if (is_spmd_lp_inited == true) {
300*91f16700Schasinglulu 		return 0;
301*91f16700Schasinglulu 	}
302*91f16700Schasinglulu 
303*91f16700Schasinglulu 	if (is_spmc_inited == false) {
304*91f16700Schasinglulu 		return -1;
305*91f16700Schasinglulu 	}
306*91f16700Schasinglulu 
307*91f16700Schasinglulu 	spmd_lp_descs = get_spmd_el3_lp_array();
308*91f16700Schasinglulu 
309*91f16700Schasinglulu 	/* Perform initial validation of the SPMD Logical Partitions. */
310*91f16700Schasinglulu 	rc = el3_spmd_sp_desc_validate(spmd_lp_descs);
311*91f16700Schasinglulu 	if (rc != 0) {
312*91f16700Schasinglulu 		ERROR("Logical SPMD Partition validation failed!\n");
313*91f16700Schasinglulu 		return rc;
314*91f16700Schasinglulu 	}
315*91f16700Schasinglulu 
316*91f16700Schasinglulu 	VERBOSE("SPMD Logical Secure Partition init start.\n");
317*91f16700Schasinglulu 	for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) {
318*91f16700Schasinglulu 		rc = spmd_lp_descs[i].init();
319*91f16700Schasinglulu 		if (rc != 0) {
320*91f16700Schasinglulu 			ERROR("SPMD Logical SP (0x%x) failed to initialize\n",
321*91f16700Schasinglulu 			      spmd_lp_descs[i].sp_id);
322*91f16700Schasinglulu 			return rc;
323*91f16700Schasinglulu 		}
324*91f16700Schasinglulu 		VERBOSE("SPMD Logical SP (0x%x) Initialized\n",
325*91f16700Schasinglulu 			spmd_lp_descs[i].sp_id);
326*91f16700Schasinglulu 	}
327*91f16700Schasinglulu 
328*91f16700Schasinglulu 	INFO("SPMD Logical Secure Partition init completed.\n");
329*91f16700Schasinglulu 	if (rc == 0) {
330*91f16700Schasinglulu 		is_spmd_lp_inited = true;
331*91f16700Schasinglulu 	}
332*91f16700Schasinglulu 	return rc;
333*91f16700Schasinglulu #else
334*91f16700Schasinglulu 	return 0;
335*91f16700Schasinglulu #endif
336*91f16700Schasinglulu }
337*91f16700Schasinglulu 
338*91f16700Schasinglulu void spmd_logical_sp_set_spmc_initialized(void)
339*91f16700Schasinglulu {
340*91f16700Schasinglulu #if ENABLE_SPMD_LP
341*91f16700Schasinglulu 	is_spmc_inited = true;
342*91f16700Schasinglulu #endif
343*91f16700Schasinglulu }
344*91f16700Schasinglulu 
345*91f16700Schasinglulu void spmd_logical_sp_set_spmc_failure(void)
346*91f16700Schasinglulu {
347*91f16700Schasinglulu #if ENABLE_SPMD_LP
348*91f16700Schasinglulu 	is_spmc_inited = false;
349*91f16700Schasinglulu #endif
350*91f16700Schasinglulu }
351*91f16700Schasinglulu 
352*91f16700Schasinglulu /*
353*91f16700Schasinglulu  * This function takes an ffa_value structure populated with partition
354*91f16700Schasinglulu  * information from an FFA_PARTITION_INFO_GET_REGS ABI call, extracts
355*91f16700Schasinglulu  * the values and writes it into a ffa_partition_info_v1_1 structure for
356*91f16700Schasinglulu  * other code to consume.
357*91f16700Schasinglulu  */
358*91f16700Schasinglulu bool ffa_partition_info_regs_get_part_info(
359*91f16700Schasinglulu 	struct ffa_value *args, uint8_t idx,
360*91f16700Schasinglulu 	struct ffa_partition_info_v1_1 *partition_info)
361*91f16700Schasinglulu {
362*91f16700Schasinglulu 	uint64_t *arg_ptrs;
363*91f16700Schasinglulu 	uint64_t info, uuid_lo, uuid_high;
364*91f16700Schasinglulu 
365*91f16700Schasinglulu 	/*
366*91f16700Schasinglulu 	 * Each partition information is encoded in 3 registers, so there can be
367*91f16700Schasinglulu 	 * a maximum of 5 entries.
368*91f16700Schasinglulu 	 */
369*91f16700Schasinglulu 	if (idx >= 5 || partition_info == NULL) {
370*91f16700Schasinglulu 		return false;
371*91f16700Schasinglulu 	}
372*91f16700Schasinglulu 
373*91f16700Schasinglulu 	/*
374*91f16700Schasinglulu 	 * List of pointers to args in return value. arg0/func encodes ff-a
375*91f16700Schasinglulu 	 * function, arg1 is reserved, arg2 encodes indices. arg3 and greater
376*91f16700Schasinglulu 	 * values reflect partition properties.
377*91f16700Schasinglulu 	 */
378*91f16700Schasinglulu 	arg_ptrs = (uint64_t *)args + ((idx * 3) + 3);
379*91f16700Schasinglulu 	info = *arg_ptrs;
380*91f16700Schasinglulu 
381*91f16700Schasinglulu 	arg_ptrs++;
382*91f16700Schasinglulu 	uuid_lo = *arg_ptrs;
383*91f16700Schasinglulu 
384*91f16700Schasinglulu 	arg_ptrs++;
385*91f16700Schasinglulu 	uuid_high = *arg_ptrs;
386*91f16700Schasinglulu 
387*91f16700Schasinglulu 	partition_info->ep_id = (uint16_t)(info & 0xFFFFU);
388*91f16700Schasinglulu 	partition_info->execution_ctx_count = (uint16_t)((info >> 16) & 0xFFFFU);
389*91f16700Schasinglulu 	partition_info->properties = (uint32_t)(info >> 32);
390*91f16700Schasinglulu 	partition_info->uuid[0] = (uint32_t)(uuid_lo & 0xFFFFFFFFU);
391*91f16700Schasinglulu 	partition_info->uuid[1] = (uint32_t)((uuid_lo >> 32) & 0xFFFFFFFFU);
392*91f16700Schasinglulu 	partition_info->uuid[2] = (uint32_t)(uuid_high & 0xFFFFFFFFU);
393*91f16700Schasinglulu 	partition_info->uuid[3] = (uint32_t)((uuid_high >> 32) & 0xFFFFFFFFU);
394*91f16700Schasinglulu 
395*91f16700Schasinglulu 	return true;
396*91f16700Schasinglulu }
397*91f16700Schasinglulu 
398*91f16700Schasinglulu /*
399*91f16700Schasinglulu  * This function is called by the SPMD in response to
400*91f16700Schasinglulu  * an FFA_PARTITION_INFO_GET_REG ABI invocation by the SPMC. Secure partitions
401*91f16700Schasinglulu  * are allowed to discover the presence of EL3 SPMD logical partitions by
402*91f16700Schasinglulu  * invoking the aforementioned ABI and this function populates the required
403*91f16700Schasinglulu  * information about EL3 SPMD logical partitions.
404*91f16700Schasinglulu  */
405*91f16700Schasinglulu uint64_t spmd_el3_populate_logical_partition_info(void *handle, uint64_t x1,
406*91f16700Schasinglulu 						  uint64_t x2, uint64_t x3)
407*91f16700Schasinglulu {
408*91f16700Schasinglulu #if ENABLE_SPMD_LP
409*91f16700Schasinglulu 	uint32_t target_uuid[4] = { 0 };
410*91f16700Schasinglulu 	uint32_t w0;
411*91f16700Schasinglulu 	uint32_t w1;
412*91f16700Schasinglulu 	uint32_t w2;
413*91f16700Schasinglulu 	uint32_t w3;
414*91f16700Schasinglulu 	uint16_t start_index;
415*91f16700Schasinglulu 	uint16_t tag;
416*91f16700Schasinglulu 	static struct ffa_partition_info_v1_1 partitions[EL3_SPMD_MAX_NUM_LP];
417*91f16700Schasinglulu 	uint16_t lp_count = 0;
418*91f16700Schasinglulu 	uint16_t max_idx = 0;
419*91f16700Schasinglulu 	uint16_t curr_idx = 0;
420*91f16700Schasinglulu 	uint8_t num_entries_to_ret = 0;
421*91f16700Schasinglulu 	struct ffa_value ret = { 0 };
422*91f16700Schasinglulu 	uint64_t *arg_ptrs = (uint64_t *)&ret + 3;
423*91f16700Schasinglulu 
424*91f16700Schasinglulu 	w0 = (uint32_t)(x1 & 0xFFFFFFFFU);
425*91f16700Schasinglulu 	w1 = (uint32_t)(x1 >> 32);
426*91f16700Schasinglulu 	w2 = (uint32_t)(x2 & 0xFFFFFFFFU);
427*91f16700Schasinglulu 	w3 = (uint32_t)(x2 >> 32);
428*91f16700Schasinglulu 
429*91f16700Schasinglulu 	target_uuid[0] = w0;
430*91f16700Schasinglulu 	target_uuid[1] = w1;
431*91f16700Schasinglulu 	target_uuid[2] = w2;
432*91f16700Schasinglulu 	target_uuid[3] = w3;
433*91f16700Schasinglulu 
434*91f16700Schasinglulu 	start_index = (uint16_t)(x3 & 0xFFFFU);
435*91f16700Schasinglulu 	tag = (uint16_t)((x3 >> 16) & 0xFFFFU);
436*91f16700Schasinglulu 
437*91f16700Schasinglulu 	assert(handle == cm_get_context(SECURE));
438*91f16700Schasinglulu 
439*91f16700Schasinglulu 	if (tag != 0) {
440*91f16700Schasinglulu 		VERBOSE("Tag is not 0. Cannot return partition info.\n");
441*91f16700Schasinglulu 		return spmd_ffa_error_return(handle, FFA_ERROR_RETRY);
442*91f16700Schasinglulu 	}
443*91f16700Schasinglulu 
444*91f16700Schasinglulu 	memset(&partitions, 0, sizeof(partitions));
445*91f16700Schasinglulu 
446*91f16700Schasinglulu 	spmd_fill_lp_info_array(&partitions, target_uuid, &lp_count);
447*91f16700Schasinglulu 
448*91f16700Schasinglulu 	if (lp_count == 0) {
449*91f16700Schasinglulu 		VERBOSE("No SPDM EL3 logical partitions exist.\n");
450*91f16700Schasinglulu 		return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
451*91f16700Schasinglulu 	}
452*91f16700Schasinglulu 
453*91f16700Schasinglulu 	if (start_index >= lp_count) {
454*91f16700Schasinglulu 		VERBOSE("start_index = %d, lp_count = %d (start index must be"
455*91f16700Schasinglulu 			" less than partition count.\n",
456*91f16700Schasinglulu 			start_index, lp_count);
457*91f16700Schasinglulu 		return spmd_ffa_error_return(handle,
458*91f16700Schasinglulu 					     FFA_ERROR_INVALID_PARAMETER);
459*91f16700Schasinglulu 	}
460*91f16700Schasinglulu 
461*91f16700Schasinglulu 	max_idx = lp_count - 1;
462*91f16700Schasinglulu 	num_entries_to_ret = (max_idx - start_index) + 1;
463*91f16700Schasinglulu 	num_entries_to_ret =
464*91f16700Schasinglulu 		MIN(num_entries_to_ret, MAX_INFO_REGS_ENTRIES_PER_CALL);
465*91f16700Schasinglulu 	curr_idx = start_index + num_entries_to_ret - 1;
466*91f16700Schasinglulu 	assert(curr_idx <= max_idx);
467*91f16700Schasinglulu 
468*91f16700Schasinglulu 	ret.func = FFA_SUCCESS_SMC64;
469*91f16700Schasinglulu 	ret.arg2 = (uint64_t)((sizeof(struct ffa_partition_info_v1_1) & 0xFFFFU) << 48);
470*91f16700Schasinglulu 	ret.arg2 |= (uint64_t)(curr_idx << 16);
471*91f16700Schasinglulu 	ret.arg2 |= (uint64_t)max_idx;
472*91f16700Schasinglulu 
473*91f16700Schasinglulu 	for (uint16_t idx = start_index; idx <= curr_idx; ++idx) {
474*91f16700Schasinglulu 		spmd_pack_lp_count_props(arg_ptrs, partitions[idx].ep_id,
475*91f16700Schasinglulu 					 partitions[idx].execution_ctx_count,
476*91f16700Schasinglulu 					 partitions[idx].properties);
477*91f16700Schasinglulu 		arg_ptrs++;
478*91f16700Schasinglulu 		if (is_null_uuid(target_uuid)) {
479*91f16700Schasinglulu 			spmd_pack_lp_uuid(arg_ptrs, (arg_ptrs + 1),
480*91f16700Schasinglulu 					  partitions[idx].uuid);
481*91f16700Schasinglulu 		}
482*91f16700Schasinglulu 		arg_ptrs += 2;
483*91f16700Schasinglulu 	}
484*91f16700Schasinglulu 
485*91f16700Schasinglulu 	SMC_RET18(handle, ret.func, ret.arg1, ret.arg2, ret.arg3, ret.arg4,
486*91f16700Schasinglulu 		  ret.arg5, ret.arg6, ret.arg7, ret.arg8, ret.arg9, ret.arg10,
487*91f16700Schasinglulu 		  ret.arg11, ret.arg12, ret.arg13, ret.arg14, ret.arg15,
488*91f16700Schasinglulu 		  ret.arg16, ret.arg17);
489*91f16700Schasinglulu #else
490*91f16700Schasinglulu 	return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
491*91f16700Schasinglulu #endif
492*91f16700Schasinglulu }
493*91f16700Schasinglulu 
494*91f16700Schasinglulu /* This function can be used by an SPMD logical partition to invoke the
495*91f16700Schasinglulu  * FFA_PARTITION_INFO_GET_REGS ABI to the SPMC, to discover the secure
496*91f16700Schasinglulu  * partitions in the system. The function takes a UUID, start index and
497*91f16700Schasinglulu  * tag and the partition information are returned in an ffa_value structure
498*91f16700Schasinglulu  * and can be consumed by using appropriate helper functions.
499*91f16700Schasinglulu  */
500*91f16700Schasinglulu bool spmd_el3_invoke_partition_info_get(
501*91f16700Schasinglulu 				const uint32_t target_uuid[4],
502*91f16700Schasinglulu 				const uint16_t start_index,
503*91f16700Schasinglulu 				const uint16_t tag,
504*91f16700Schasinglulu 				struct ffa_value *retval)
505*91f16700Schasinglulu {
506*91f16700Schasinglulu #if ENABLE_SPMD_LP
507*91f16700Schasinglulu 	uint64_t rc = UINT64_MAX;
508*91f16700Schasinglulu 	spmd_spm_core_context_t *ctx = spmd_get_context();
509*91f16700Schasinglulu 
510*91f16700Schasinglulu 	if (retval == NULL) {
511*91f16700Schasinglulu 		return false;
512*91f16700Schasinglulu 	}
513*91f16700Schasinglulu 
514*91f16700Schasinglulu 	memset(retval, 0, sizeof(*retval));
515*91f16700Schasinglulu 
516*91f16700Schasinglulu 	if (!is_spmc_inited) {
517*91f16700Schasinglulu 		VERBOSE("Cannot discover partition before,"
518*91f16700Schasinglulu 			" SPMC is initialized.\n");
519*91f16700Schasinglulu 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
520*91f16700Schasinglulu 		return true;
521*91f16700Schasinglulu 	}
522*91f16700Schasinglulu 
523*91f16700Schasinglulu 	if (tag != 0) {
524*91f16700Schasinglulu 		VERBOSE("Tag must be zero. other tags unsupported\n");
525*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
526*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
527*91f16700Schasinglulu 		return true;
528*91f16700Schasinglulu 	}
529*91f16700Schasinglulu 
530*91f16700Schasinglulu 	/* Save the non-secure context before entering SPMC */
531*91f16700Schasinglulu 	cm_el1_sysregs_context_save(NON_SECURE);
532*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2
533*91f16700Schasinglulu 	cm_el2_sysregs_context_save(NON_SECURE);
534*91f16700Schasinglulu #endif
535*91f16700Schasinglulu 
536*91f16700Schasinglulu 	spmd_build_ffa_info_get_regs(ctx, target_uuid, start_index, tag);
537*91f16700Schasinglulu 	spmd_logical_sp_set_info_regs_ongoing(ctx);
538*91f16700Schasinglulu 
539*91f16700Schasinglulu 	rc = spmd_spm_core_sync_entry(ctx);
540*91f16700Schasinglulu 	if (rc != 0ULL) {
541*91f16700Schasinglulu 		ERROR("%s failed (%lx) on CPU%u\n", __func__, rc,
542*91f16700Schasinglulu 		      plat_my_core_pos());
543*91f16700Schasinglulu 		panic();
544*91f16700Schasinglulu 	}
545*91f16700Schasinglulu 
546*91f16700Schasinglulu 	spmd_logical_sp_reset_info_regs_ongoing(ctx);
547*91f16700Schasinglulu 	spmd_encode_ctx_to_ffa_value(ctx, retval);
548*91f16700Schasinglulu 
549*91f16700Schasinglulu 	assert(is_ffa_error(retval) || is_ffa_success(retval));
550*91f16700Schasinglulu 
551*91f16700Schasinglulu 	cm_el1_sysregs_context_restore(NON_SECURE);
552*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2
553*91f16700Schasinglulu 	cm_el2_sysregs_context_restore(NON_SECURE);
554*91f16700Schasinglulu #endif
555*91f16700Schasinglulu 	cm_set_next_eret_context(NON_SECURE);
556*91f16700Schasinglulu 	return true;
557*91f16700Schasinglulu #else
558*91f16700Schasinglulu 	return false;
559*91f16700Schasinglulu #endif
560*91f16700Schasinglulu }
561*91f16700Schasinglulu 
562*91f16700Schasinglulu /*******************************************************************************
563*91f16700Schasinglulu  * This function sends an FF-A Direct Request from a partition in EL3 to a
564*91f16700Schasinglulu  * partition that may reside under an SPMC (only lower ELs supported). The main
565*91f16700Schasinglulu  * use of this API is for SPMD logical partitions.
566*91f16700Schasinglulu  * The API is expected to be used when there are platform specific SMCs that
567*91f16700Schasinglulu  * need to be routed to a secure partition that is FF-A compliant or when
568*91f16700Schasinglulu  * there are group 0 interrupts that need to be handled first in EL3 and then
569*91f16700Schasinglulu  * forwarded to an FF-A compliant secure partition. Therefore, it is expected
570*91f16700Schasinglulu  * that the handle to the context provided belongs to the non-secure context.
571*91f16700Schasinglulu  * This also means that interrupts/SMCs that trap to EL3 during secure execution
572*91f16700Schasinglulu  * cannot use this API.
573*91f16700Schasinglulu  * x1, x2, x3 and x4 are encoded as specified in the FF-A specification.
574*91f16700Schasinglulu  * retval is used to pass the direct response values to the caller.
575*91f16700Schasinglulu  * The function returns true if retval has valid values, and false otherwise.
576*91f16700Schasinglulu  ******************************************************************************/
577*91f16700Schasinglulu bool spmd_el3_ffa_msg_direct_req(uint64_t x1,
578*91f16700Schasinglulu 				 uint64_t x2,
579*91f16700Schasinglulu 				 uint64_t x3,
580*91f16700Schasinglulu 				 uint64_t x4,
581*91f16700Schasinglulu 				 void *handle,
582*91f16700Schasinglulu 				 struct ffa_value *retval)
583*91f16700Schasinglulu {
584*91f16700Schasinglulu #if ENABLE_SPMD_LP
585*91f16700Schasinglulu 
586*91f16700Schasinglulu 	uint64_t rc = UINT64_MAX;
587*91f16700Schasinglulu 	spmd_spm_core_context_t *ctx = spmd_get_context();
588*91f16700Schasinglulu 
589*91f16700Schasinglulu 	if (retval == NULL) {
590*91f16700Schasinglulu 		return false;
591*91f16700Schasinglulu 	}
592*91f16700Schasinglulu 
593*91f16700Schasinglulu 	memset(retval, 0, sizeof(*retval));
594*91f16700Schasinglulu 
595*91f16700Schasinglulu 	if (!is_spmd_lp_inited || !is_spmc_inited) {
596*91f16700Schasinglulu 		VERBOSE("Cannot send SPMD logical partition direct message,"
597*91f16700Schasinglulu 			" Partitions not initialized or SPMC not initialized.\n");
598*91f16700Schasinglulu 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
599*91f16700Schasinglulu 		return true;
600*91f16700Schasinglulu 	}
601*91f16700Schasinglulu 
602*91f16700Schasinglulu 	/*
603*91f16700Schasinglulu 	 * x2 must be zero, since there is no support for framework message via
604*91f16700Schasinglulu 	 * an SPMD logical partition. This is sort of a useless check and it is
605*91f16700Schasinglulu 	 * possible to not take parameter. However, as the framework extends it
606*91f16700Schasinglulu 	 * may be useful to have x2 and extend this function later with
607*91f16700Schasinglulu 	 * functionality based on x2.
608*91f16700Schasinglulu 	 */
609*91f16700Schasinglulu 	if (x2 != 0) {
610*91f16700Schasinglulu 		VERBOSE("x2 must be zero. Cannot send framework message.\n");
611*91f16700Schasinglulu 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
612*91f16700Schasinglulu 		return true;
613*91f16700Schasinglulu 	}
614*91f16700Schasinglulu 
615*91f16700Schasinglulu 	/*
616*91f16700Schasinglulu 	 * Current context must be non-secure. API is expected to be used
617*91f16700Schasinglulu 	 * when entry into EL3 and the SPMD logical partition is via an
618*91f16700Schasinglulu 	 * interrupt that occurs when execution is in normal world and
619*91f16700Schasinglulu 	 * SMCs from normal world. FF-A compliant SPMCs are expected to
620*91f16700Schasinglulu 	 * trap interrupts during secure execution in lower ELs since they
621*91f16700Schasinglulu 	 * are usually not re-entrant and SMCs from secure world can be
622*91f16700Schasinglulu 	 * handled synchronously. There is no known use case for an SPMD
623*91f16700Schasinglulu 	 * logical partition to send a direct message to another partition
624*91f16700Schasinglulu 	 * in response to a secure interrupt or SMCs from secure world.
625*91f16700Schasinglulu 	 */
626*91f16700Schasinglulu 	if (handle != cm_get_context(NON_SECURE)) {
627*91f16700Schasinglulu 		VERBOSE("Handle must be for the non-secure context.\n");
628*91f16700Schasinglulu 			spmd_encode_ffa_error(retval, FFA_ERROR_DENIED);
629*91f16700Schasinglulu 		return true;
630*91f16700Schasinglulu 	}
631*91f16700Schasinglulu 
632*91f16700Schasinglulu 	if (!is_spmd_lp_id(ffa_endpoint_source(x1))) {
633*91f16700Schasinglulu 		VERBOSE("Source ID must be valid SPMD logical partition"
634*91f16700Schasinglulu 			" ID.\n");
635*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
636*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
637*91f16700Schasinglulu 		return true;
638*91f16700Schasinglulu 	}
639*91f16700Schasinglulu 
640*91f16700Schasinglulu 	if (is_spmd_lp_id(ffa_endpoint_destination(x1))) {
641*91f16700Schasinglulu 		VERBOSE("Destination ID must not be SPMD logical partition"
642*91f16700Schasinglulu 			" ID.\n");
643*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
644*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
645*91f16700Schasinglulu 		return true;
646*91f16700Schasinglulu 	}
647*91f16700Schasinglulu 
648*91f16700Schasinglulu 	if (!ffa_is_secure_world_id(ffa_endpoint_destination(x1))) {
649*91f16700Schasinglulu 		VERBOSE("Destination ID must be secure world ID.\n");
650*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
651*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
652*91f16700Schasinglulu 		return true;
653*91f16700Schasinglulu 	}
654*91f16700Schasinglulu 
655*91f16700Schasinglulu 	if (ffa_endpoint_destination(x1) == SPMD_DIRECT_MSG_ENDPOINT_ID) {
656*91f16700Schasinglulu 		VERBOSE("Destination ID must not be SPMD ID.\n");
657*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
658*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
659*91f16700Schasinglulu 		return true;
660*91f16700Schasinglulu 	}
661*91f16700Schasinglulu 
662*91f16700Schasinglulu 	if (ffa_endpoint_destination(x1) == spmd_spmc_id_get()) {
663*91f16700Schasinglulu 		VERBOSE("Destination ID must not be SPMC ID.\n");
664*91f16700Schasinglulu 			spmd_encode_ffa_error(retval,
665*91f16700Schasinglulu 					      FFA_ERROR_INVALID_PARAMETER);
666*91f16700Schasinglulu 		return true;
667*91f16700Schasinglulu 	}
668*91f16700Schasinglulu 
669*91f16700Schasinglulu 	/* Save the non-secure context before entering SPMC */
670*91f16700Schasinglulu 	cm_el1_sysregs_context_save(NON_SECURE);
671*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2
672*91f16700Schasinglulu 	cm_el2_sysregs_context_save(NON_SECURE);
673*91f16700Schasinglulu #endif
674*91f16700Schasinglulu 
675*91f16700Schasinglulu 	/*
676*91f16700Schasinglulu 	 * Perform synchronous entry into the SPMC. Synchronous entry is
677*91f16700Schasinglulu 	 * required because the spec requires that a direct message request
678*91f16700Schasinglulu 	 * from an SPMD LP look like a function call from it's perspective.
679*91f16700Schasinglulu 	 */
680*91f16700Schasinglulu 	spmd_build_direct_message_req(ctx, x1, x2, x3, x4);
681*91f16700Schasinglulu 	spmd_logical_sp_set_dir_req_ongoing(ctx);
682*91f16700Schasinglulu 
683*91f16700Schasinglulu 	rc = spmd_spm_core_sync_entry(ctx);
684*91f16700Schasinglulu 
685*91f16700Schasinglulu 	spmd_logical_sp_reset_dir_req_ongoing(ctx);
686*91f16700Schasinglulu 
687*91f16700Schasinglulu 	if (rc != 0ULL) {
688*91f16700Schasinglulu 		ERROR("%s failed (%lx) on CPU%u\n", __func__, rc,
689*91f16700Schasinglulu 		      plat_my_core_pos());
690*91f16700Schasinglulu 		panic();
691*91f16700Schasinglulu 	} else {
692*91f16700Schasinglulu 		spmd_encode_ctx_to_ffa_value(ctx, retval);
693*91f16700Schasinglulu 
694*91f16700Schasinglulu 		/*
695*91f16700Schasinglulu 		 * Only expect error or direct response,
696*91f16700Schasinglulu 		 * spmd_spm_core_sync_exit should not be called on other paths.
697*91f16700Schasinglulu 		 * Checks are asserts since the LSP can fail gracefully if the
698*91f16700Schasinglulu 		 * source or destination ids are not the same. Panic'ing would
699*91f16700Schasinglulu 		 * not provide any benefit.
700*91f16700Schasinglulu 		 */
701*91f16700Schasinglulu 		assert(is_ffa_error(retval) || is_ffa_direct_msg_resp(retval));
702*91f16700Schasinglulu 		assert(is_ffa_error(retval) ||
703*91f16700Schasinglulu 			(ffa_endpoint_destination(retval->arg1) ==
704*91f16700Schasinglulu 				ffa_endpoint_source(x1)));
705*91f16700Schasinglulu 		assert(is_ffa_error(retval) ||
706*91f16700Schasinglulu 			(ffa_endpoint_source(retval->arg1) ==
707*91f16700Schasinglulu 				ffa_endpoint_destination(x1)));
708*91f16700Schasinglulu 	}
709*91f16700Schasinglulu 
710*91f16700Schasinglulu 	cm_el1_sysregs_context_restore(NON_SECURE);
711*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2
712*91f16700Schasinglulu 	cm_el2_sysregs_context_restore(NON_SECURE);
713*91f16700Schasinglulu #endif
714*91f16700Schasinglulu 	cm_set_next_eret_context(NON_SECURE);
715*91f16700Schasinglulu 
716*91f16700Schasinglulu 	return true;
717*91f16700Schasinglulu #else
718*91f16700Schasinglulu 	return false;
719*91f16700Schasinglulu #endif
720*91f16700Schasinglulu }
721*91f16700Schasinglulu 
722*91f16700Schasinglulu bool is_spmd_logical_sp_info_regs_req_in_progress(
723*91f16700Schasinglulu 		spmd_spm_core_context_t *ctx)
724*91f16700Schasinglulu {
725*91f16700Schasinglulu #if ENABLE_SPMD_LP
726*91f16700Schasinglulu 	return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_INFO_GET_REG_ONGOING)
727*91f16700Schasinglulu 			== SPMD_LP_FFA_INFO_GET_REG_ONGOING);
728*91f16700Schasinglulu #else
729*91f16700Schasinglulu 	return false;
730*91f16700Schasinglulu #endif
731*91f16700Schasinglulu }
732*91f16700Schasinglulu 
733*91f16700Schasinglulu bool is_spmd_logical_sp_dir_req_in_progress(
734*91f16700Schasinglulu 		spmd_spm_core_context_t *ctx)
735*91f16700Schasinglulu {
736*91f16700Schasinglulu #if ENABLE_SPMD_LP
737*91f16700Schasinglulu 	return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_DIR_REQ_ONGOING)
738*91f16700Schasinglulu 		== SPMD_LP_FFA_DIR_REQ_ONGOING);
739*91f16700Schasinglulu #else
740*91f16700Schasinglulu 	return false;
741*91f16700Schasinglulu #endif
742*91f16700Schasinglulu }
743