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