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 either forwards the request to the other world or returns 141 * with an ERET depending on the source of the call. 142 ******************************************************************************/ 143 static uint64_t spmc_smc_return(uint32_t smc_fid, 144 bool secure_origin, 145 uint64_t x1, 146 uint64_t x2, 147 uint64_t x3, 148 uint64_t x4, 149 void *handle, 150 void *cookie, 151 uint64_t flags, 152 uint16_t dst_id) 153 { 154 /* If the destination is in the normal world always go via the SPMD. */ 155 if (ffa_is_normal_world_id(dst_id)) { 156 return spmd_smc_handler(smc_fid, x1, x2, x3, x4, 157 cookie, handle, flags); 158 } 159 /* 160 * If the caller is secure and we want to return to the secure world, 161 * ERET directly. 162 */ 163 else if (secure_origin && ffa_is_secure_world_id(dst_id)) { 164 SMC_RET5(handle, smc_fid, x1, x2, x3, x4); 165 } 166 /* If we originated in the normal world then switch contexts. */ 167 else if (!secure_origin && ffa_is_secure_world_id(dst_id)) { 168 return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, 169 x3, x4, handle); 170 } else { 171 /* Unknown State. */ 172 panic(); 173 } 174 175 /* Shouldn't be Reached. */ 176 return 0; 177 } 178 179 /******************************************************************************* 180 * This function will parse the Secure Partition Manifest. From manifest, it 181 * will fetch details for preparing Secure partition image context and secure 182 * partition image boot arguments if any. 183 ******************************************************************************/ 184 static int sp_manifest_parse(void *sp_manifest, int offset, 185 struct secure_partition_desc *sp, 186 entry_point_info_t *ep_info) 187 { 188 int32_t ret, node; 189 uint32_t config_32; 190 191 /* 192 * Look for the mandatory fields that are expected to be present in 193 * the SP manifests. 194 */ 195 node = fdt_path_offset(sp_manifest, "/"); 196 if (node < 0) { 197 ERROR("Did not find root node.\n"); 198 return node; 199 } 200 201 ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32); 202 if (ret != 0) { 203 ERROR("Missing SP Exception Level information.\n"); 204 return ret; 205 } 206 207 sp->runtime_el = config_32; 208 209 ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32); 210 if (ret != 0) { 211 ERROR("Missing Secure Partition FF-A Version.\n"); 212 return ret; 213 } 214 215 sp->ffa_version = config_32; 216 217 ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32); 218 if (ret != 0) { 219 ERROR("Missing Secure Partition Execution State.\n"); 220 return ret; 221 } 222 223 sp->execution_state = config_32; 224 225 /* 226 * Look for the optional fields that are expected to be present in 227 * an SP manifest. 228 */ 229 ret = fdt_read_uint32(sp_manifest, node, "id", &config_32); 230 if (ret != 0) { 231 WARN("Missing Secure Partition ID.\n"); 232 } else { 233 if (!is_ffa_secure_id_valid(config_32)) { 234 ERROR("Invalid Secure Partition ID (0x%x).\n", 235 config_32); 236 return -EINVAL; 237 } 238 sp->sp_id = config_32; 239 } 240 241 return 0; 242 } 243 244 /******************************************************************************* 245 * This function gets the Secure Partition Manifest base and maps the manifest 246 * region. 247 * Currently only one Secure Partition manifest is considered which is used to 248 * prepare the context for the single Secure Partition. 249 ******************************************************************************/ 250 static int find_and_prepare_sp_context(void) 251 { 252 void *sp_manifest; 253 uintptr_t manifest_base; 254 uintptr_t manifest_base_align; 255 entry_point_info_t *next_image_ep_info; 256 int32_t ret; 257 struct secure_partition_desc *sp; 258 259 next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 260 if (next_image_ep_info == NULL) { 261 WARN("No Secure Partition image provided by BL2.\n"); 262 return -ENOENT; 263 } 264 265 sp_manifest = (void *)next_image_ep_info->args.arg0; 266 if (sp_manifest == NULL) { 267 WARN("Secure Partition manifest absent.\n"); 268 return -ENOENT; 269 } 270 271 manifest_base = (uintptr_t)sp_manifest; 272 manifest_base_align = page_align(manifest_base, DOWN); 273 274 /* 275 * Map the secure partition manifest region in the EL3 translation 276 * regime. 277 * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base 278 * alignment the region of 1 PAGE_SIZE from manifest align base may 279 * not completely accommodate the secure partition manifest region. 280 */ 281 ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align, 282 manifest_base_align, 283 PAGE_SIZE * 2, 284 MT_RO_DATA); 285 if (ret != 0) { 286 ERROR("Error while mapping SP manifest (%d).\n", ret); 287 return ret; 288 } 289 290 ret = fdt_node_offset_by_compatible(sp_manifest, -1, 291 "arm,ffa-manifest-1.0"); 292 if (ret < 0) { 293 ERROR("Error happened in SP manifest reading.\n"); 294 return -EINVAL; 295 } 296 297 /* 298 * Store the size of the manifest so that it can be used later to pass 299 * the manifest as boot information later. 300 */ 301 next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest); 302 INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1); 303 304 /* 305 * Select an SP descriptor for initialising the partition's execution 306 * context on the primary CPU. 307 */ 308 sp = spmc_get_current_sp_ctx(); 309 310 /* Initialize entry point information for the SP */ 311 SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1, 312 SECURE | EP_ST_ENABLE); 313 314 /* Parse the SP manifest. */ 315 ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info); 316 if (ret != 0) { 317 ERROR("Error in Secure Partition manifest parsing.\n"); 318 return ret; 319 } 320 321 /* Check that the runtime EL in the manifest was correct. */ 322 if (sp->runtime_el != S_EL1) { 323 ERROR("Unexpected runtime EL: %d\n", sp->runtime_el); 324 return -EINVAL; 325 } 326 327 /* Perform any common initialisation. */ 328 spmc_sp_common_setup(sp, next_image_ep_info); 329 330 /* Perform any initialisation specific to S-EL1 SPs. */ 331 spmc_el1_sp_setup(sp, next_image_ep_info); 332 333 /* Initialize the SP context with the required ep info. */ 334 spmc_sp_common_ep_commit(sp, next_image_ep_info); 335 336 return 0; 337 } 338 339 /******************************************************************************* 340 * This function takes an SP context pointer and performs a synchronous entry 341 * into it. 342 ******************************************************************************/ 343 uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec) 344 { 345 uint64_t rc; 346 347 assert(ec != NULL); 348 349 /* Assign the context of the SP to this CPU */ 350 cm_set_context(&(ec->cpu_ctx), SECURE); 351 352 /* Restore the context assigned above */ 353 cm_el1_sysregs_context_restore(SECURE); 354 cm_set_next_eret_context(SECURE); 355 356 /* Invalidate TLBs at EL1. */ 357 tlbivmalle1(); 358 dsbish(); 359 360 /* Enter Secure Partition */ 361 rc = spm_secure_partition_enter(&ec->c_rt_ctx); 362 363 /* Save secure state */ 364 cm_el1_sysregs_context_save(SECURE); 365 366 return rc; 367 } 368 369 /******************************************************************************* 370 * SPMC Helper Functions. 371 ******************************************************************************/ 372 static int32_t sp_init(void) 373 { 374 uint64_t rc; 375 struct secure_partition_desc *sp; 376 struct sp_exec_ctx *ec; 377 378 sp = spmc_get_current_sp_ctx(); 379 ec = spmc_get_sp_ec(sp); 380 ec->rt_model = RT_MODEL_INIT; 381 ec->rt_state = RT_STATE_RUNNING; 382 383 INFO("Secure Partition (0x%x) init start.\n", sp->sp_id); 384 385 rc = spmc_sp_synchronous_entry(ec); 386 if (rc != 0) { 387 /* Indicate SP init was not successful. */ 388 ERROR("SP (0x%x) failed to initialize (%lu).\n", 389 sp->sp_id, rc); 390 return 0; 391 } 392 393 ec->rt_state = RT_STATE_WAITING; 394 INFO("Secure Partition initialized.\n"); 395 396 return 1; 397 } 398 399 static void initalize_sp_descs(void) 400 { 401 struct secure_partition_desc *sp; 402 403 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 404 sp = &sp_desc[i]; 405 sp->sp_id = INV_SP_ID; 406 sp->secondary_ep = 0; 407 } 408 } 409 410 static void initalize_ns_ep_descs(void) 411 { 412 struct ns_endpoint_desc *ns_ep; 413 414 for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) { 415 ns_ep = &ns_ep_desc[i]; 416 /* 417 * Clashes with the Hypervisor ID but will not be a 418 * problem in practice. 419 */ 420 ns_ep->ns_ep_id = 0; 421 ns_ep->ffa_version = 0; 422 } 423 } 424 425 /******************************************************************************* 426 * Initialize SPMC attributes for the SPMD. 427 ******************************************************************************/ 428 void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs) 429 { 430 spmc_attrs->major_version = FFA_VERSION_MAJOR; 431 spmc_attrs->minor_version = FFA_VERSION_MINOR; 432 spmc_attrs->exec_state = MODE_RW_64; 433 spmc_attrs->spmc_id = FFA_SPMC_ID; 434 } 435 436 /******************************************************************************* 437 * Initialize contexts of all Secure Partitions. 438 ******************************************************************************/ 439 int32_t spmc_setup(void) 440 { 441 int32_t ret; 442 443 /* Initialize endpoint descriptors */ 444 initalize_sp_descs(); 445 initalize_ns_ep_descs(); 446 447 /* Perform physical SP setup. */ 448 449 /* Disable MMU at EL1 (initialized by BL2) */ 450 disable_mmu_icache_el1(); 451 452 /* Initialize context of the SP */ 453 INFO("Secure Partition context setup start.\n"); 454 455 ret = find_and_prepare_sp_context(); 456 if (ret != 0) { 457 ERROR("Error in SP finding and context preparation.\n"); 458 return ret; 459 } 460 461 /* Register init function for deferred init. */ 462 bl31_register_bl32_init(&sp_init); 463 464 INFO("Secure Partition setup done.\n"); 465 466 return 0; 467 } 468 469 /******************************************************************************* 470 * Secure Partition Manager SMC handler. 471 ******************************************************************************/ 472 uint64_t spmc_smc_handler(uint32_t smc_fid, 473 bool secure_origin, 474 uint64_t x1, 475 uint64_t x2, 476 uint64_t x3, 477 uint64_t x4, 478 void *cookie, 479 void *handle, 480 uint64_t flags) 481 { 482 switch (smc_fid) { 483 484 default: 485 WARN("Unsupported FF-A call 0x%08x.\n", smc_fid); 486 break; 487 } 488 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 489 } 490