| /* |
| * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. |
| * |
| * SPDX-License-Identifier: BSD-3-Clause |
| */ |
| |
| #include <assert.h> |
| #include <string.h> |
| |
| #include <arch.h> |
| #include <arch_helpers.h> |
| #include <common/debug.h> |
| #include <context.h> |
| #include <lib/el3_runtime/context_mgmt.h> |
| #include <lib/utils.h> |
| #include <lib/xlat_tables/xlat_tables_v2.h> |
| #include <plat/common/common_def.h> |
| #include <plat/common/platform.h> |
| #include <services/ffa_svc.h> |
| #include "spm_common.h" |
| #include "spmc.h" |
| |
| #include <platform_def.h> |
| |
| /* |
| * We are assuming that the index of the execution |
| * context used is the linear index of the current physical cpu. |
| */ |
| unsigned int get_ec_index(struct secure_partition_desc *sp) |
| { |
| return plat_my_core_pos(); |
| } |
| |
| /* S-EL1 partition specific initialisation. */ |
| void spmc_el1_sp_setup(struct secure_partition_desc *sp, |
| entry_point_info_t *ep_info) |
| { |
| /* Sanity check input arguments. */ |
| assert(sp != NULL); |
| assert(ep_info != NULL); |
| |
| /* Initialise the SPSR for S-EL1 SPs. */ |
| ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, |
| DISABLE_ALL_EXCEPTIONS); |
| |
| /* |
| * Check whether setup is being performed for the primary or a secondary |
| * execution context. In the latter case, indicate to the SP that this |
| * is a warm boot. |
| * TODO: This check would need to be reworked if the same entry point is |
| * used for both primary and secondary initialisation. |
| */ |
| if (sp->secondary_ep != 0U) { |
| /* |
| * Sanity check that the secondary entry point is still what was |
| * originally set. |
| */ |
| assert(sp->secondary_ep == ep_info->pc); |
| ep_info->args.arg0 = FFA_WB_TYPE_S2RAM; |
| } |
| } |
| |
| /* Common initialisation for all SPs. */ |
| void spmc_sp_common_setup(struct secure_partition_desc *sp, |
| entry_point_info_t *ep_info) |
| { |
| uint16_t sp_id; |
| |
| /* Assign FF-A Partition ID if not already assigned. */ |
| if (sp->sp_id == INV_SP_ID) { |
| sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX; |
| /* |
| * Ensure we don't clash with previously assigned partition |
| * IDs. |
| */ |
| while (!is_ffa_secure_id_valid(sp_id)) { |
| sp_id++; |
| |
| if (sp_id == FFA_SWD_ID_LIMIT) { |
| ERROR("Unable to determine valid SP ID.\n"); |
| panic(); |
| } |
| } |
| sp->sp_id = sp_id; |
| } |
| |
| /* |
| * We currently only support S-EL1 partitions so ensure this is the |
| * case. |
| */ |
| assert(sp->runtime_el == S_EL1); |
| |
| /* |
| * Clear the general purpose registers. These should be populated as |
| * required. |
| */ |
| zeromem(&ep_info->args, sizeof(ep_info->args)); |
| } |
| |
| /* |
| * Initialise the SP context now we have populated the common and EL specific |
| * entrypoint information. |
| */ |
| void spmc_sp_common_ep_commit(struct secure_partition_desc *sp, |
| entry_point_info_t *ep_info) |
| { |
| cpu_context_t *cpu_ctx; |
| |
| cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx); |
| print_entry_point_info(ep_info); |
| cm_setup_context(cpu_ctx, ep_info); |
| } |