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 <string.h> 9 10 #include <arch.h> 11 #include <arch_helpers.h> 12 #include <common/debug.h> 13 #include <context.h> 14 #include <lib/el3_runtime/context_mgmt.h> 15 #include <lib/utils.h> 16 #include <lib/xlat_tables/xlat_tables_v2.h> 17 #include <plat/common/common_def.h> 18 #include <plat/common/platform.h> 19 #include <services/ffa_svc.h> 20 #include "spm_common.h" 21 #include "spmc.h" 22 23 #include <platform_def.h> 24 25 /* 26 * We are assuming that the index of the execution 27 * context used is the linear index of the current physical cpu. 28 */ 29 unsigned int get_ec_index(struct secure_partition_desc *sp) 30 { 31 return plat_my_core_pos(); 32 } 33 34 /* S-EL1 partition specific initialisation. */ 35 void spmc_el1_sp_setup(struct secure_partition_desc *sp, 36 entry_point_info_t *ep_info) 37 { 38 /* Sanity check input arguments. */ 39 assert(sp != NULL); 40 assert(ep_info != NULL); 41 42 /* Initialise the SPSR for S-EL1 SPs. */ 43 ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, 44 DISABLE_ALL_EXCEPTIONS); 45 46 /* 47 * TF-A Implementation defined behaviour to provide the linear 48 * core ID in the x4 register. 49 */ 50 ep_info->args.arg4 = (uintptr_t) plat_my_core_pos(); 51 52 /* 53 * Check whether setup is being performed for the primary or a secondary 54 * execution context. In the latter case, indicate to the SP that this 55 * is a warm boot. 56 * TODO: This check would need to be reworked if the same entry point is 57 * used for both primary and secondary initialisation. 58 */ 59 if (sp->secondary_ep != 0U) { 60 /* 61 * Sanity check that the secondary entry point is still what was 62 * originally set. 63 */ 64 assert(sp->secondary_ep == ep_info->pc); 65 ep_info->args.arg0 = FFA_WB_TYPE_S2RAM; 66 } 67 } 68 69 /* Common initialisation for all SPs. */ 70 void spmc_sp_common_setup(struct secure_partition_desc *sp, 71 entry_point_info_t *ep_info) 72 { 73 uint16_t sp_id; 74 75 /* Assign FF-A Partition ID if not already assigned. */ 76 if (sp->sp_id == INV_SP_ID) { 77 sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX; 78 /* 79 * Ensure we don't clash with previously assigned partition 80 * IDs. 81 */ 82 while (!is_ffa_secure_id_valid(sp_id)) { 83 sp_id++; 84 85 if (sp_id == FFA_SWD_ID_LIMIT) { 86 ERROR("Unable to determine valid SP ID.\n"); 87 panic(); 88 } 89 } 90 sp->sp_id = sp_id; 91 } 92 93 /* 94 * We currently only support S-EL1 partitions so ensure this is the 95 * case. 96 */ 97 assert(sp->runtime_el == S_EL1); 98 99 /* 100 * Clear the general purpose registers. These should be populated as 101 * required. 102 */ 103 zeromem(&ep_info->args, sizeof(ep_info->args)); 104 } 105 106 /* 107 * Initialise the SP context now we have populated the common and EL specific 108 * entrypoint information. 109 */ 110 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp, 111 entry_point_info_t *ep_info) 112 { 113 cpu_context_t *cpu_ctx; 114 115 cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx); 116 print_entry_point_info(ep_info); 117 cm_setup_context(cpu_ctx, ep_info); 118 } 119