1 /* 2 * Copyright (c) 2020, 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 #include "spmd_private.h" 10 11 struct spmd_pm_secondary_ep_t { 12 uintptr_t entry_point; 13 uintptr_t context; 14 bool locked; 15 }; 16 17 static struct spmd_pm_secondary_ep_t spmd_pm_secondary_ep[PLATFORM_CORE_COUNT]; 18 19 /******************************************************************************* 20 * spmd_pm_secondary_core_set_ep 21 ******************************************************************************/ 22 int32_t spmd_pm_secondary_core_set_ep(uint64_t mpidr, uintptr_t entry_point, 23 uint64_t context) 24 { 25 int id = plat_core_pos_by_mpidr(mpidr); 26 27 if ((id < 0) || (id >= PLATFORM_CORE_COUNT)) { 28 ERROR("%s inconsistent MPIDR (%llx)\n", __func__, mpidr); 29 return -EINVAL; 30 } 31 32 if (spmd_pm_secondary_ep[id].locked) { 33 ERROR("%s entry locked (%llx)\n", __func__, mpidr); 34 return -EINVAL; 35 } 36 37 /* 38 * Check entry_point address is a PA within 39 * load_address <= entry_point < load_address + binary_size 40 */ 41 if (!spmd_check_address_in_binary_image(entry_point)) { 42 ERROR("%s entry point is not within image boundaries (%llx)\n", 43 __func__, mpidr); 44 return -EINVAL; 45 } 46 47 /* Fill new entry to corresponding secondary core id and lock it */ 48 spmd_pm_secondary_ep[id].entry_point = entry_point; 49 spmd_pm_secondary_ep[id].context = context; 50 spmd_pm_secondary_ep[id].locked = true; 51 52 VERBOSE("%s %d %llx %lx %llx\n", 53 __func__, id, mpidr, entry_point, context); 54 55 return 0; 56 } 57 58 /******************************************************************************* 59 * This CPU has been turned on. Enter SPMC to initialise S-EL1 or S-EL2. As part 60 * of the SPMC initialization path, they will initialize any SPs that they 61 * manage. Entry into SPMC is done after initialising minimal architectural 62 * state that guarantees safe execution. 63 ******************************************************************************/ 64 static void spmd_cpu_on_finish_handler(u_register_t unused) 65 { 66 unsigned int linear_id = plat_my_core_pos(); 67 spmd_spm_core_context_t *ctx = spmd_get_context(); 68 int rc; 69 70 assert(ctx->state != SPMC_STATE_ON); 71 72 rc = spmd_spm_core_sync_entry(ctx); 73 if (rc != 0) { 74 ERROR("SPMC initialisation failed (%d) on CPU%u\n", rc, 75 linear_id); 76 ctx->state = SPMC_STATE_OFF; 77 return; 78 } 79 80 ctx->state = SPMC_STATE_ON; 81 } 82 83 /******************************************************************************* 84 * Structure populated by the SPM Dispatcher to perform any bookkeeping before 85 * PSCI executes a power mgmt. operation. 86 ******************************************************************************/ 87 const spd_pm_ops_t spmd_pm = { 88 .svc_on_finish = spmd_cpu_on_finish_handler, 89 }; 90