xref: /rk3399_ARM-atf/services/std_svc/spmd/spmd_logical_sp.c (revision 890b5088203e990d683a9c837e976be62c6501aa)
1*890b5088SRaghu Krishnamurthy /*
2*890b5088SRaghu Krishnamurthy  * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved.
3*890b5088SRaghu Krishnamurthy  *
4*890b5088SRaghu Krishnamurthy  * SPDX-License-Identifier: BSD-3-Clause
5*890b5088SRaghu Krishnamurthy  */
6*890b5088SRaghu Krishnamurthy 
7*890b5088SRaghu Krishnamurthy #include <assert.h>
8*890b5088SRaghu Krishnamurthy #include <errno.h>
9*890b5088SRaghu Krishnamurthy #include <string.h>
10*890b5088SRaghu Krishnamurthy 
11*890b5088SRaghu Krishnamurthy #include <common/debug.h>
12*890b5088SRaghu Krishnamurthy #include <services/el3_spmd_logical_sp.h>
13*890b5088SRaghu Krishnamurthy #include <services/ffa_svc.h>
14*890b5088SRaghu Krishnamurthy 
15*890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
16*890b5088SRaghu Krishnamurthy static bool is_spmd_lp_inited;
17*890b5088SRaghu Krishnamurthy static bool is_spmc_inited;
18*890b5088SRaghu Krishnamurthy 
19*890b5088SRaghu Krishnamurthy /*
20*890b5088SRaghu Krishnamurthy  * Helper function to obtain the array storing the EL3
21*890b5088SRaghu Krishnamurthy  * SPMD Logical Partition descriptors.
22*890b5088SRaghu Krishnamurthy  */
23*890b5088SRaghu Krishnamurthy static struct spmd_lp_desc *get_spmd_el3_lp_array(void)
24*890b5088SRaghu Krishnamurthy {
25*890b5088SRaghu Krishnamurthy 	return (struct spmd_lp_desc *) SPMD_LP_DESCS_START;
26*890b5088SRaghu Krishnamurthy }
27*890b5088SRaghu Krishnamurthy 
28*890b5088SRaghu Krishnamurthy /*******************************************************************************
29*890b5088SRaghu Krishnamurthy  * Validate any logical partition descriptors before we initialize.
30*890b5088SRaghu Krishnamurthy  * Initialization of said partitions will be taken care of during SPMD boot.
31*890b5088SRaghu Krishnamurthy  ******************************************************************************/
32*890b5088SRaghu Krishnamurthy static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array)
33*890b5088SRaghu Krishnamurthy {
34*890b5088SRaghu Krishnamurthy 	/* Check the array bounds are valid. */
35*890b5088SRaghu Krishnamurthy 	assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START);
36*890b5088SRaghu Krishnamurthy 
37*890b5088SRaghu Krishnamurthy 	/* If no SPMD logical partitions are implemented then simply bail out. */
38*890b5088SRaghu Krishnamurthy 	if (SPMD_LP_DESCS_COUNT == 0U) {
39*890b5088SRaghu Krishnamurthy 		return -1;
40*890b5088SRaghu Krishnamurthy 	}
41*890b5088SRaghu Krishnamurthy 
42*890b5088SRaghu Krishnamurthy 	for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) {
43*890b5088SRaghu Krishnamurthy 		struct spmd_lp_desc *lp_desc = &lp_array[index];
44*890b5088SRaghu Krishnamurthy 
45*890b5088SRaghu Krishnamurthy 		/* Validate our logical partition descriptors. */
46*890b5088SRaghu Krishnamurthy 		if (lp_desc == NULL) {
47*890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical SP Descriptor\n");
48*890b5088SRaghu Krishnamurthy 			return -EINVAL;
49*890b5088SRaghu Krishnamurthy 		}
50*890b5088SRaghu Krishnamurthy 
51*890b5088SRaghu Krishnamurthy 		/*
52*890b5088SRaghu Krishnamurthy 		 * Ensure the ID follows the convention to indicate it resides
53*890b5088SRaghu Krishnamurthy 		 * in the secure world.
54*890b5088SRaghu Krishnamurthy 		 */
55*890b5088SRaghu Krishnamurthy 		if (!ffa_is_secure_world_id(lp_desc->sp_id)) {
56*890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical SP ID (0x%x)\n",
57*890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
58*890b5088SRaghu Krishnamurthy 			return -EINVAL;
59*890b5088SRaghu Krishnamurthy 		}
60*890b5088SRaghu Krishnamurthy 
61*890b5088SRaghu Krishnamurthy 		/* Ensure SPMD logical partition is in valid range. */
62*890b5088SRaghu Krishnamurthy 		if (!is_spmd_lp_id(lp_desc->sp_id)) {
63*890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD Logical Partition ID (0x%x)\n",
64*890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
65*890b5088SRaghu Krishnamurthy 			return -EINVAL;
66*890b5088SRaghu Krishnamurthy 		}
67*890b5088SRaghu Krishnamurthy 
68*890b5088SRaghu Krishnamurthy 		/* Ensure the UUID is not the NULL UUID. */
69*890b5088SRaghu Krishnamurthy 		if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 &&
70*890b5088SRaghu Krishnamurthy 		    lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) {
71*890b5088SRaghu Krishnamurthy 			ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n",
72*890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
73*890b5088SRaghu Krishnamurthy 			return -EINVAL;
74*890b5088SRaghu Krishnamurthy 		}
75*890b5088SRaghu Krishnamurthy 
76*890b5088SRaghu Krishnamurthy 		/* Ensure init function callback is registered. */
77*890b5088SRaghu Krishnamurthy 		if (lp_desc->init == NULL) {
78*890b5088SRaghu Krishnamurthy 			ERROR("Missing init function for Logical SP(0x%x)\n",
79*890b5088SRaghu Krishnamurthy 			      lp_desc->sp_id);
80*890b5088SRaghu Krishnamurthy 			return -EINVAL;
81*890b5088SRaghu Krishnamurthy 		}
82*890b5088SRaghu Krishnamurthy 
83*890b5088SRaghu Krishnamurthy 		/* Ensure that SPMD LP only supports sending direct requests. */
84*890b5088SRaghu Krishnamurthy 		if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) {
85*890b5088SRaghu Krishnamurthy 			ERROR("Invalid SPMD logical partition properties (0x%x)\n",
86*890b5088SRaghu Krishnamurthy 			      lp_desc->properties);
87*890b5088SRaghu Krishnamurthy 			return -EINVAL;
88*890b5088SRaghu Krishnamurthy 		}
89*890b5088SRaghu Krishnamurthy 
90*890b5088SRaghu Krishnamurthy 		/* Ensure that all partition IDs are unique. */
91*890b5088SRaghu Krishnamurthy 		for (uint32_t inner_idx = index + 1;
92*890b5088SRaghu Krishnamurthy 		     inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) {
93*890b5088SRaghu Krishnamurthy 			if (lp_desc->sp_id == lp_array[inner_idx].sp_id) {
94*890b5088SRaghu Krishnamurthy 				ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n",
95*890b5088SRaghu Krishnamurthy 				      lp_desc->sp_id);
96*890b5088SRaghu Krishnamurthy 				return -EINVAL;
97*890b5088SRaghu Krishnamurthy 			}
98*890b5088SRaghu Krishnamurthy 		}
99*890b5088SRaghu Krishnamurthy 	}
100*890b5088SRaghu Krishnamurthy 	return 0;
101*890b5088SRaghu Krishnamurthy }
102*890b5088SRaghu Krishnamurthy #endif
103*890b5088SRaghu Krishnamurthy 
104*890b5088SRaghu Krishnamurthy /*
105*890b5088SRaghu Krishnamurthy  * Initialize SPMD logical partitions. This function assumes that it is called
106*890b5088SRaghu Krishnamurthy  * only after the SPMC has successfully initialized.
107*890b5088SRaghu Krishnamurthy  */
108*890b5088SRaghu Krishnamurthy int32_t spmd_logical_sp_init(void)
109*890b5088SRaghu Krishnamurthy {
110*890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
111*890b5088SRaghu Krishnamurthy 	int32_t rc = 0;
112*890b5088SRaghu Krishnamurthy 	struct spmd_lp_desc *spmd_lp_descs;
113*890b5088SRaghu Krishnamurthy 
114*890b5088SRaghu Krishnamurthy 	if (is_spmd_lp_inited == true) {
115*890b5088SRaghu Krishnamurthy 		return 0;
116*890b5088SRaghu Krishnamurthy 	}
117*890b5088SRaghu Krishnamurthy 
118*890b5088SRaghu Krishnamurthy 	if (is_spmc_inited == false) {
119*890b5088SRaghu Krishnamurthy 		return -1;
120*890b5088SRaghu Krishnamurthy 	}
121*890b5088SRaghu Krishnamurthy 
122*890b5088SRaghu Krishnamurthy 	spmd_lp_descs = get_spmd_el3_lp_array();
123*890b5088SRaghu Krishnamurthy 
124*890b5088SRaghu Krishnamurthy 	/* Perform initial validation of the SPMD Logical Partitions. */
125*890b5088SRaghu Krishnamurthy 	rc = el3_spmd_sp_desc_validate(spmd_lp_descs);
126*890b5088SRaghu Krishnamurthy 	if (rc != 0) {
127*890b5088SRaghu Krishnamurthy 		ERROR("Logical SPMD Partition validation failed!\n");
128*890b5088SRaghu Krishnamurthy 		return rc;
129*890b5088SRaghu Krishnamurthy 	}
130*890b5088SRaghu Krishnamurthy 
131*890b5088SRaghu Krishnamurthy 	VERBOSE("SPMD Logical Secure Partition init start.\n");
132*890b5088SRaghu Krishnamurthy 	for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) {
133*890b5088SRaghu Krishnamurthy 		rc = spmd_lp_descs[i].init();
134*890b5088SRaghu Krishnamurthy 		if (rc != 0) {
135*890b5088SRaghu Krishnamurthy 			ERROR("SPMD Logical SP (0x%x) failed to initialize\n",
136*890b5088SRaghu Krishnamurthy 			      spmd_lp_descs[i].sp_id);
137*890b5088SRaghu Krishnamurthy 			return rc;
138*890b5088SRaghu Krishnamurthy 		}
139*890b5088SRaghu Krishnamurthy 		VERBOSE("SPMD Logical SP (0x%x) Initialized\n",
140*890b5088SRaghu Krishnamurthy 			spmd_lp_descs[i].sp_id);
141*890b5088SRaghu Krishnamurthy 	}
142*890b5088SRaghu Krishnamurthy 
143*890b5088SRaghu Krishnamurthy 	INFO("SPMD Logical Secure Partition init completed.\n");
144*890b5088SRaghu Krishnamurthy 	if (rc == 0) {
145*890b5088SRaghu Krishnamurthy 		is_spmd_lp_inited = true;
146*890b5088SRaghu Krishnamurthy 	}
147*890b5088SRaghu Krishnamurthy 	return rc;
148*890b5088SRaghu Krishnamurthy #else
149*890b5088SRaghu Krishnamurthy 	return 0;
150*890b5088SRaghu Krishnamurthy #endif
151*890b5088SRaghu Krishnamurthy }
152*890b5088SRaghu Krishnamurthy 
153*890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_initialized(void)
154*890b5088SRaghu Krishnamurthy {
155*890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
156*890b5088SRaghu Krishnamurthy 	is_spmc_inited = true;
157*890b5088SRaghu Krishnamurthy #endif
158*890b5088SRaghu Krishnamurthy }
159*890b5088SRaghu Krishnamurthy 
160*890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_failure(void)
161*890b5088SRaghu Krishnamurthy {
162*890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP
163*890b5088SRaghu Krishnamurthy 	is_spmc_inited = false;
164*890b5088SRaghu Krishnamurthy #endif
165*890b5088SRaghu Krishnamurthy }
166