1 /* 2 * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <errno.h> 9 10 #include <arch_helpers.h> 11 #include <bl31/bl31.h> 12 #include <bl31/ehf.h> 13 #include <common/debug.h> 14 #include <common/fdt_wrappers.h> 15 #include <common/runtime_svc.h> 16 #include <lib/el3_runtime/context_mgmt.h> 17 #include <lib/smccc.h> 18 #include <lib/utils.h> 19 #include <lib/xlat_tables/xlat_tables_v2.h> 20 #include <libfdt.h> 21 #include <plat/common/platform.h> 22 #include <services/ffa_svc.h> 23 #include <services/spmc_svc.h> 24 #include <services/spmd_svc.h> 25 #include "spmc.h" 26 27 #include <platform_def.h> 28 29 /* 30 * Allocate a secure partition descriptor to describe each SP in the system that 31 * does not reside at EL3. 32 */ 33 static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT]; 34 35 /* 36 * Allocate an NS endpoint descriptor to describe each VM and the Hypervisor in 37 * the system that interacts with a SP. It is used to track the Hypervisor 38 * buffer pair, version and ID for now. It could be extended to track VM 39 * properties when the SPMC supports indirect messaging. 40 */ 41 static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT]; 42 43 /* 44 * Helper function to obtain the descriptor of the last SP to whom control was 45 * handed to on this physical cpu. Currently, we assume there is only one SP. 46 * TODO: Expand to track multiple partitions when required. 47 */ 48 struct secure_partition_desc *spmc_get_current_sp_ctx(void) 49 { 50 return &(sp_desc[ACTIVE_SP_DESC_INDEX]); 51 } 52 53 /* 54 * Helper function to obtain the execution context of an SP on the 55 * current physical cpu. 56 */ 57 struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp) 58 { 59 return &(sp->ec[get_ec_index(sp)]); 60 } 61 62 /* Helper function to get pointer to SP context from its ID. */ 63 struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id) 64 { 65 /* Check for SWd Partitions. */ 66 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 67 if (sp_desc[i].sp_id == id) { 68 return &(sp_desc[i]); 69 } 70 } 71 return NULL; 72 } 73 74 /****************************************************************************** 75 * This function returns to the place where spmc_sp_synchronous_entry() was 76 * called originally. 77 ******************************************************************************/ 78 __dead2 void spmc_sp_synchronous_exit(struct sp_exec_ctx *ec, uint64_t rc) 79 { 80 /* 81 * The SPM must have initiated the original request through a 82 * synchronous entry into the secure partition. Jump back to the 83 * original C runtime context with the value of rc in x0; 84 */ 85 spm_secure_partition_exit(ec->c_rt_ctx, rc); 86 87 panic(); 88 } 89 90 /******************************************************************************* 91 * Return FFA_ERROR with specified error code. 92 ******************************************************************************/ 93 uint64_t spmc_ffa_error_return(void *handle, int error_code) 94 { 95 SMC_RET8(handle, FFA_ERROR, 96 FFA_TARGET_INFO_MBZ, error_code, 97 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, 98 FFA_PARAM_MBZ, FFA_PARAM_MBZ); 99 } 100 101 /****************************************************************************** 102 * Helper function to validate a secure partition ID to ensure it does not 103 * conflict with any other FF-A component and follows the convention to 104 * indicate it resides within the secure world. 105 ******************************************************************************/ 106 bool is_ffa_secure_id_valid(uint16_t partition_id) 107 { 108 /* Ensure the ID is not the invalid partition ID. */ 109 if (partition_id == INV_SP_ID) { 110 return false; 111 } 112 113 /* Ensure the ID is not the SPMD ID. */ 114 if (partition_id == SPMD_DIRECT_MSG_ENDPOINT_ID) { 115 return false; 116 } 117 118 /* 119 * Ensure the ID follows the convention to indicate it resides 120 * in the secure world. 121 */ 122 if (!ffa_is_secure_world_id(partition_id)) { 123 return false; 124 } 125 126 /* Ensure we don't conflict with the SPMC partition ID. */ 127 if (partition_id == FFA_SPMC_ID) { 128 return false; 129 } 130 131 /* Ensure we do not already have an SP context with this ID. */ 132 if (spmc_get_sp_ctx(partition_id)) { 133 return false; 134 } 135 136 return true; 137 } 138 139 /******************************************************************************* 140 * This function will parse the Secure Partition Manifest. From manifest, it 141 * will fetch details for preparing Secure partition image context and secure 142 * partition image boot arguments if any. 143 ******************************************************************************/ 144 static int sp_manifest_parse(void *sp_manifest, int offset, 145 struct secure_partition_desc *sp, 146 entry_point_info_t *ep_info) 147 { 148 int32_t ret, node; 149 uint32_t config_32; 150 151 /* 152 * Look for the mandatory fields that are expected to be present in 153 * the SP manifests. 154 */ 155 node = fdt_path_offset(sp_manifest, "/"); 156 if (node < 0) { 157 ERROR("Did not find root node.\n"); 158 return node; 159 } 160 161 ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32); 162 if (ret != 0) { 163 ERROR("Missing SP Exception Level information.\n"); 164 return ret; 165 } 166 167 sp->runtime_el = config_32; 168 169 ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32); 170 if (ret != 0) { 171 ERROR("Missing Secure Partition FF-A Version.\n"); 172 return ret; 173 } 174 175 sp->ffa_version = config_32; 176 177 ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32); 178 if (ret != 0) { 179 ERROR("Missing Secure Partition Execution State.\n"); 180 return ret; 181 } 182 183 sp->execution_state = config_32; 184 185 /* 186 * Look for the optional fields that are expected to be present in 187 * an SP manifest. 188 */ 189 ret = fdt_read_uint32(sp_manifest, node, "id", &config_32); 190 if (ret != 0) { 191 WARN("Missing Secure Partition ID.\n"); 192 } else { 193 if (!is_ffa_secure_id_valid(config_32)) { 194 ERROR("Invalid Secure Partition ID (0x%x).\n", 195 config_32); 196 return -EINVAL; 197 } 198 sp->sp_id = config_32; 199 } 200 201 return 0; 202 } 203 204 /******************************************************************************* 205 * This function gets the Secure Partition Manifest base and maps the manifest 206 * region. 207 * Currently only one Secure Partition manifest is considered which is used to 208 * prepare the context for the single Secure Partition. 209 ******************************************************************************/ 210 static int find_and_prepare_sp_context(void) 211 { 212 void *sp_manifest; 213 uintptr_t manifest_base; 214 uintptr_t manifest_base_align; 215 entry_point_info_t *next_image_ep_info; 216 int32_t ret; 217 struct secure_partition_desc *sp; 218 219 next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 220 if (next_image_ep_info == NULL) { 221 WARN("No Secure Partition image provided by BL2.\n"); 222 return -ENOENT; 223 } 224 225 sp_manifest = (void *)next_image_ep_info->args.arg0; 226 if (sp_manifest == NULL) { 227 WARN("Secure Partition manifest absent.\n"); 228 return -ENOENT; 229 } 230 231 manifest_base = (uintptr_t)sp_manifest; 232 manifest_base_align = page_align(manifest_base, DOWN); 233 234 /* 235 * Map the secure partition manifest region in the EL3 translation 236 * regime. 237 * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base 238 * alignment the region of 1 PAGE_SIZE from manifest align base may 239 * not completely accommodate the secure partition manifest region. 240 */ 241 ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align, 242 manifest_base_align, 243 PAGE_SIZE * 2, 244 MT_RO_DATA); 245 if (ret != 0) { 246 ERROR("Error while mapping SP manifest (%d).\n", ret); 247 return ret; 248 } 249 250 ret = fdt_node_offset_by_compatible(sp_manifest, -1, 251 "arm,ffa-manifest-1.0"); 252 if (ret < 0) { 253 ERROR("Error happened in SP manifest reading.\n"); 254 return -EINVAL; 255 } 256 257 /* 258 * Store the size of the manifest so that it can be used later to pass 259 * the manifest as boot information later. 260 */ 261 next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest); 262 INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1); 263 264 /* 265 * Select an SP descriptor for initialising the partition's execution 266 * context on the primary CPU. 267 */ 268 sp = spmc_get_current_sp_ctx(); 269 270 /* Initialize entry point information for the SP */ 271 SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1, 272 SECURE | EP_ST_ENABLE); 273 274 /* Parse the SP manifest. */ 275 ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info); 276 if (ret != 0) { 277 ERROR("Error in Secure Partition manifest parsing.\n"); 278 return ret; 279 } 280 281 /* Check that the runtime EL in the manifest was correct. */ 282 if (sp->runtime_el != S_EL1) { 283 ERROR("Unexpected runtime EL: %d\n", sp->runtime_el); 284 return -EINVAL; 285 } 286 287 /* Perform any common initialisation. */ 288 spmc_sp_common_setup(sp, next_image_ep_info); 289 290 /* Perform any initialisation specific to S-EL1 SPs. */ 291 spmc_el1_sp_setup(sp, next_image_ep_info); 292 293 /* Initialize the SP context with the required ep info. */ 294 spmc_sp_common_ep_commit(sp, next_image_ep_info); 295 296 return 0; 297 } 298 299 /******************************************************************************* 300 * This function takes an SP context pointer and performs a synchronous entry 301 * into it. 302 ******************************************************************************/ 303 uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec) 304 { 305 uint64_t rc; 306 307 assert(ec != NULL); 308 309 /* Assign the context of the SP to this CPU */ 310 cm_set_context(&(ec->cpu_ctx), SECURE); 311 312 /* Restore the context assigned above */ 313 cm_el1_sysregs_context_restore(SECURE); 314 cm_set_next_eret_context(SECURE); 315 316 /* Invalidate TLBs at EL1. */ 317 tlbivmalle1(); 318 dsbish(); 319 320 /* Enter Secure Partition */ 321 rc = spm_secure_partition_enter(&ec->c_rt_ctx); 322 323 /* Save secure state */ 324 cm_el1_sysregs_context_save(SECURE); 325 326 return rc; 327 } 328 329 /******************************************************************************* 330 * SPMC Helper Functions. 331 ******************************************************************************/ 332 static int32_t sp_init(void) 333 { 334 uint64_t rc; 335 struct secure_partition_desc *sp; 336 struct sp_exec_ctx *ec; 337 338 sp = spmc_get_current_sp_ctx(); 339 ec = spmc_get_sp_ec(sp); 340 ec->rt_model = RT_MODEL_INIT; 341 ec->rt_state = RT_STATE_RUNNING; 342 343 INFO("Secure Partition (0x%x) init start.\n", sp->sp_id); 344 345 rc = spmc_sp_synchronous_entry(ec); 346 if (rc != 0) { 347 /* Indicate SP init was not successful. */ 348 ERROR("SP (0x%x) failed to initialize (%lu).\n", 349 sp->sp_id, rc); 350 return 0; 351 } 352 353 ec->rt_state = RT_STATE_WAITING; 354 INFO("Secure Partition initialized.\n"); 355 356 return 1; 357 } 358 359 static void initalize_sp_descs(void) 360 { 361 struct secure_partition_desc *sp; 362 363 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 364 sp = &sp_desc[i]; 365 sp->sp_id = INV_SP_ID; 366 sp->secondary_ep = 0; 367 } 368 } 369 370 static void initalize_ns_ep_descs(void) 371 { 372 struct ns_endpoint_desc *ns_ep; 373 374 for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) { 375 ns_ep = &ns_ep_desc[i]; 376 /* 377 * Clashes with the Hypervisor ID but will not be a 378 * problem in practice. 379 */ 380 ns_ep->ns_ep_id = 0; 381 ns_ep->ffa_version = 0; 382 } 383 } 384 385 /******************************************************************************* 386 * Initialize contexts of all Secure Partitions. 387 ******************************************************************************/ 388 int32_t spmc_setup(void) 389 { 390 int32_t ret; 391 392 /* Initialize endpoint descriptors */ 393 initalize_sp_descs(); 394 initalize_ns_ep_descs(); 395 396 /* Perform physical SP setup. */ 397 398 /* Disable MMU at EL1 (initialized by BL2) */ 399 disable_mmu_icache_el1(); 400 401 /* Initialize context of the SP */ 402 INFO("Secure Partition context setup start.\n"); 403 404 ret = find_and_prepare_sp_context(); 405 if (ret != 0) { 406 ERROR("Error in SP finding and context preparation.\n"); 407 return ret; 408 } 409 410 /* Register init function for deferred init. */ 411 bl31_register_bl32_init(&sp_init); 412 413 INFO("Secure Partition setup done.\n"); 414 415 return 0; 416 } 417 418 /******************************************************************************* 419 * Secure Partition Manager SMC handler. 420 ******************************************************************************/ 421 uint64_t spmc_smc_handler(uint32_t smc_fid, 422 bool secure_origin, 423 uint64_t x1, 424 uint64_t x2, 425 uint64_t x3, 426 uint64_t x4, 427 void *cookie, 428 void *handle, 429 uint64_t flags) 430 { 431 switch (smc_fid) { 432 433 default: 434 WARN("Unsupported FF-A call 0x%08x.\n", smc_fid); 435 break; 436 } 437 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 438 } 439