blob: 923461e85065a6cbadac7602c4ee0b746bf69fea [file] [log] [blame]
Achin Gupta86f23532019-10-11 15:41:16 +01001/*
Olivier Deprezeae45962021-01-19 15:06:47 +01002 * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved.
Achin Gupta86f23532019-10-11 15:41:16 +01003 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <assert.h>
8#include <errno.h>
Scott Brandene5dcf982020-08-25 13:49:32 -07009#include <inttypes.h>
10#include <stdint.h>
Achin Gupta86f23532019-10-11 15:41:16 +010011#include <string.h>
12
13#include <arch_helpers.h>
Olivier Deprez2bae35f2020-04-16 13:39:06 +020014#include <arch/aarch64/arch_features.h>
Achin Gupta86f23532019-10-11 15:41:16 +010015#include <bl31/bl31.h>
16#include <common/debug.h>
17#include <common/runtime_svc.h>
18#include <lib/el3_runtime/context_mgmt.h>
19#include <lib/smccc.h>
20#include <lib/spinlock.h>
21#include <lib/utils.h>
Achin Gupta86f23532019-10-11 15:41:16 +010022#include <plat/common/common_def.h>
23#include <plat/common/platform.h>
24#include <platform_def.h>
J-Alves2672cde2020-05-07 18:42:25 +010025#include <services/ffa_svc.h>
Achin Gupta86f23532019-10-11 15:41:16 +010026#include <services/spmd_svc.h>
27#include <smccc_helpers.h>
28#include "spmd_private.h"
29
30/*******************************************************************************
31 * SPM Core context information.
32 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020033static spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT];
Achin Gupta86f23532019-10-11 15:41:16 +010034
35/*******************************************************************************
36 * SPM Core attribute information read from its manifest.
37 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020038static spmc_manifest_attribute_t spmc_attrs;
Achin Gupta86f23532019-10-11 15:41:16 +010039
40/*******************************************************************************
Max Shvetsov745889c2020-02-27 14:54:21 +000041 * SPM Core entry point information. Discovered on the primary core and reused
42 * on secondary cores.
43 ******************************************************************************/
44static entry_point_info_t *spmc_ep_info;
45
46/*******************************************************************************
Olivier Deprez73ef0dc2020-06-19 15:33:41 +020047 * SPM Core context on CPU based on mpidr.
48 ******************************************************************************/
49spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr)
50{
Max Shvetsovf80c64d2020-08-25 11:50:18 +010051 int core_idx = plat_core_pos_by_mpidr(mpidr);
52
53 if (core_idx < 0) {
Scott Brandene5dcf982020-08-25 13:49:32 -070054 ERROR("Invalid mpidr: %" PRIx64 ", returned ID: %d\n", mpidr, core_idx);
Max Shvetsovf80c64d2020-08-25 11:50:18 +010055 panic();
56 }
57
58 return &spm_core_context[core_idx];
Olivier Deprez73ef0dc2020-06-19 15:33:41 +020059}
60
61/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +020062 * SPM Core context on current CPU get helper.
63 ******************************************************************************/
64spmd_spm_core_context_t *spmd_get_context(void)
65{
Olivier Deprez73ef0dc2020-06-19 15:33:41 +020066 return spmd_get_context_by_mpidr(read_mpidr());
Olivier Deprez2bae35f2020-04-16 13:39:06 +020067}
68
69/*******************************************************************************
Olivier Deprezc7631a52020-03-23 09:53:06 +010070 * SPM Core ID getter.
71 ******************************************************************************/
72uint16_t spmd_spmc_id_get(void)
73{
74 return spmc_attrs.spmc_id;
75}
76
77/*******************************************************************************
Max Shvetsov745889c2020-02-27 14:54:21 +000078 * Static function declaration.
79 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +020080static int32_t spmd_init(void);
Olivier Deprez69ca84a2020-02-07 15:44:43 +010081static int spmd_spmc_init(void *pm_addr);
J-Alves2672cde2020-05-07 18:42:25 +010082static uint64_t spmd_ffa_error_return(void *handle,
Olivier Deprez2bae35f2020-04-16 13:39:06 +020083 int error_code);
84static uint64_t spmd_smc_forward(uint32_t smc_fid,
85 bool secure_origin,
86 uint64_t x1,
87 uint64_t x2,
88 uint64_t x3,
89 uint64_t x4,
90 void *handle);
Max Shvetsov745889c2020-02-27 14:54:21 +000091
92/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +020093 * This function takes an SPMC context pointer and performs a synchronous
94 * SPMC entry.
Achin Gupta86f23532019-10-11 15:41:16 +010095 ******************************************************************************/
96uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx)
97{
98 uint64_t rc;
99
100 assert(spmc_ctx != NULL);
101
102 cm_set_context(&(spmc_ctx->cpu_ctx), SECURE);
103
104 /* Restore the context assigned above */
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000105#if SPMD_SPM_AT_SEL2
Max Shvetsovbdf502d2020-02-25 13:56:19 +0000106 cm_el2_sysregs_context_restore(SECURE);
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200107#else
108 cm_el1_sysregs_context_restore(SECURE);
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000109#endif
Achin Gupta86f23532019-10-11 15:41:16 +0100110 cm_set_next_eret_context(SECURE);
111
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000112 /* Enter SPMC */
Achin Gupta86f23532019-10-11 15:41:16 +0100113 rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx);
114
115 /* Save secure state */
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000116#if SPMD_SPM_AT_SEL2
Max Shvetsovbdf502d2020-02-25 13:56:19 +0000117 cm_el2_sysregs_context_save(SECURE);
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200118#else
119 cm_el1_sysregs_context_save(SECURE);
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000120#endif
Achin Gupta86f23532019-10-11 15:41:16 +0100121
122 return rc;
123}
124
125/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200126 * This function returns to the place where spmd_spm_core_sync_entry() was
Achin Gupta86f23532019-10-11 15:41:16 +0100127 * called originally.
128 ******************************************************************************/
129__dead2 void spmd_spm_core_sync_exit(uint64_t rc)
130{
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200131 spmd_spm_core_context_t *ctx = spmd_get_context();
Achin Gupta86f23532019-10-11 15:41:16 +0100132
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200133 /* Get current CPU context from SPMC context */
Achin Gupta86f23532019-10-11 15:41:16 +0100134 assert(cm_get_context(SECURE) == &(ctx->cpu_ctx));
135
136 /*
137 * The SPMD must have initiated the original request through a
138 * synchronous entry into SPMC. Jump back to the original C runtime
139 * context with the value of rc in x0;
140 */
141 spmd_spm_core_exit(ctx->c_rt_ctx, rc);
142
143 panic();
144}
145
146/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200147 * Jump to the SPM Core for the first time.
Achin Gupta86f23532019-10-11 15:41:16 +0100148 ******************************************************************************/
149static int32_t spmd_init(void)
150{
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200151 spmd_spm_core_context_t *ctx = spmd_get_context();
152 uint64_t rc;
Achin Gupta86f23532019-10-11 15:41:16 +0100153
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200154 VERBOSE("SPM Core init start.\n");
Olivier Deprez7c016332019-10-28 09:03:13 +0000155
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200156 /* Primary boot core enters the SPMC for initialization. */
157 ctx->state = SPMC_STATE_ON_PENDING;
Achin Gupta86f23532019-10-11 15:41:16 +0100158
159 rc = spmd_spm_core_sync_entry(ctx);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200160 if (rc != 0ULL) {
Scott Brandene5dcf982020-08-25 13:49:32 -0700161 ERROR("SPMC initialisation failed 0x%" PRIx64 "\n", rc);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200162 return 0;
Achin Gupta86f23532019-10-11 15:41:16 +0100163 }
164
Olivier Deprez7c016332019-10-28 09:03:13 +0000165 ctx->state = SPMC_STATE_ON;
166
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200167 VERBOSE("SPM Core init end.\n");
Achin Gupta86f23532019-10-11 15:41:16 +0100168
169 return 1;
170}
171
172/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200173 * Loads SPMC manifest and inits SPMC.
Achin Gupta86f23532019-10-11 15:41:16 +0100174 ******************************************************************************/
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100175static int spmd_spmc_init(void *pm_addr)
Achin Gupta86f23532019-10-11 15:41:16 +0100176{
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200177 cpu_context_t *cpu_ctx;
178 unsigned int core_id;
Achin Gupta86f23532019-10-11 15:41:16 +0100179 uint32_t ep_attr;
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200180 int rc;
Achin Gupta86f23532019-10-11 15:41:16 +0100181
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200182 /* Load the SPM Core manifest */
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100183 rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr);
Max Shvetsov745889c2020-02-27 14:54:21 +0000184 if (rc != 0) {
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200185 WARN("No or invalid SPM Core manifest image provided by BL2\n");
186 return rc;
Achin Gupta86f23532019-10-11 15:41:16 +0100187 }
188
189 /*
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200190 * Ensure that the SPM Core version is compatible with the SPM
191 * Dispatcher version.
Achin Gupta86f23532019-10-11 15:41:16 +0100192 */
J-Alves2672cde2020-05-07 18:42:25 +0100193 if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) ||
194 (spmc_attrs.minor_version > FFA_VERSION_MINOR)) {
195 WARN("Unsupported FFA version (%u.%u)\n",
Achin Gupta86f23532019-10-11 15:41:16 +0100196 spmc_attrs.major_version, spmc_attrs.minor_version);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200197 return -EINVAL;
Achin Gupta86f23532019-10-11 15:41:16 +0100198 }
199
J-Alves2672cde2020-05-07 18:42:25 +0100200 VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version,
Achin Gupta86f23532019-10-11 15:41:16 +0100201 spmc_attrs.minor_version);
202
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200203 VERBOSE("SPM Core run time EL%x.\n",
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000204 SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1);
Achin Gupta86f23532019-10-11 15:41:16 +0100205
Max Shvetsove79062e2020-03-12 15:16:40 +0000206 /* Validate the SPMC ID, Ensure high bit is set */
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200207 if (((spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) &
208 SPMC_SECURE_ID_MASK) == 0U) {
209 WARN("Invalid ID (0x%x) for SPMC.\n", spmc_attrs.spmc_id);
210 return -EINVAL;
Max Shvetsove79062e2020-03-12 15:16:40 +0000211 }
212
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200213 /* Validate the SPM Core execution state */
Achin Gupta86f23532019-10-11 15:41:16 +0100214 if ((spmc_attrs.exec_state != MODE_RW_64) &&
215 (spmc_attrs.exec_state != MODE_RW_32)) {
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100216 WARN("Unsupported %s%x.\n", "SPM Core execution state 0x",
Achin Gupta86f23532019-10-11 15:41:16 +0100217 spmc_attrs.exec_state);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200218 return -EINVAL;
Achin Gupta86f23532019-10-11 15:41:16 +0100219 }
220
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100221 VERBOSE("%s%x.\n", "SPM Core execution state 0x",
222 spmc_attrs.exec_state);
Achin Gupta86f23532019-10-11 15:41:16 +0100223
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000224#if SPMD_SPM_AT_SEL2
225 /* Ensure manifest has not requested AArch32 state in S-EL2 */
226 if (spmc_attrs.exec_state == MODE_RW_32) {
227 WARN("AArch32 state at S-EL2 is not supported.\n");
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200228 return -EINVAL;
Achin Gupta86f23532019-10-11 15:41:16 +0100229 }
230
231 /*
232 * Check if S-EL2 is supported on this system if S-EL2
233 * is required for SPM
234 */
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200235 if (!is_armv8_4_sel2_present()) {
236 WARN("SPM Core run time S-EL2 is not supported.\n");
237 return -EINVAL;
Achin Gupta86f23532019-10-11 15:41:16 +0100238 }
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000239#endif /* SPMD_SPM_AT_SEL2 */
Achin Gupta86f23532019-10-11 15:41:16 +0100240
241 /* Initialise an entrypoint to set up the CPU context */
242 ep_attr = SECURE | EP_ST_ENABLE;
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200243 if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0ULL) {
Achin Gupta86f23532019-10-11 15:41:16 +0100244 ep_attr |= EP_EE_BIG;
Max Shvetsov745889c2020-02-27 14:54:21 +0000245 }
246
Achin Gupta86f23532019-10-11 15:41:16 +0100247 SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr);
Achin Gupta86f23532019-10-11 15:41:16 +0100248
249 /*
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200250 * Populate SPSR for SPM Core based upon validated parameters from the
251 * manifest.
Achin Gupta86f23532019-10-11 15:41:16 +0100252 */
253 if (spmc_attrs.exec_state == MODE_RW_32) {
254 spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM,
255 SPSR_E_LITTLE,
256 DAIF_FIQ_BIT |
257 DAIF_IRQ_BIT |
258 DAIF_ABT_BIT);
259 } else {
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000260
261#if SPMD_SPM_AT_SEL2
262 static const uint32_t runtime_el = MODE_EL2;
263#else
264 static const uint32_t runtime_el = MODE_EL1;
265#endif
266 spmc_ep_info->spsr = SPSR_64(runtime_el,
Achin Gupta86f23532019-10-11 15:41:16 +0100267 MODE_SP_ELX,
268 DISABLE_ALL_EXCEPTIONS);
269 }
270
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200271 /* Set an initial SPMC context state for all cores. */
272 for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) {
273 spm_core_context[core_id].state = SPMC_STATE_OFF;
Max Shvetsov745889c2020-02-27 14:54:21 +0000274
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200275 /* Setup an initial cpu context for the SPMC. */
276 cpu_ctx = &spm_core_context[core_id].cpu_ctx;
277 cm_setup_context(cpu_ctx, spmc_ep_info);
Achin Gupta86f23532019-10-11 15:41:16 +0100278
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200279 /*
280 * Pass the core linear ID to the SPMC through x4.
281 * (TF-A implementation defined behavior helping
282 * a legacy TOS migration to adopt FF-A).
283 */
284 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id);
285 }
Achin Gupta86f23532019-10-11 15:41:16 +0100286
Olivier Deprez9afca122019-10-28 09:15:52 +0000287 /* Register power management hooks with PSCI */
288 psci_register_spd_pm_hook(&spmd_pm);
289
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200290 /* Register init function for deferred init. */
Achin Gupta86f23532019-10-11 15:41:16 +0100291 bl31_register_bl32_init(&spmd_init);
292
Olivier Deprez4ab7a4a2021-06-21 09:47:13 +0200293 INFO("SPM Core setup done.\n");
294
Achin Gupta86f23532019-10-11 15:41:16 +0100295 return 0;
Max Shvetsov745889c2020-02-27 14:54:21 +0000296}
Achin Gupta86f23532019-10-11 15:41:16 +0100297
Max Shvetsov745889c2020-02-27 14:54:21 +0000298/*******************************************************************************
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200299 * Initialize context of SPM Core.
Max Shvetsov745889c2020-02-27 14:54:21 +0000300 ******************************************************************************/
301int spmd_setup(void)
302{
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100303 void *spmc_manifest;
Max Shvetsov745889c2020-02-27 14:54:21 +0000304 int rc;
Achin Gupta86f23532019-10-11 15:41:16 +0100305
Max Shvetsov745889c2020-02-27 14:54:21 +0000306 spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200307 if (spmc_ep_info == NULL) {
308 WARN("No SPM Core image provided by BL2 boot loader.\n");
309 return -EINVAL;
Max Shvetsov745889c2020-02-27 14:54:21 +0000310 }
311
312 /* Under no circumstances will this parameter be 0 */
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200313 assert(spmc_ep_info->pc != 0ULL);
Max Shvetsov745889c2020-02-27 14:54:21 +0000314
315 /*
316 * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200317 * be used as a manifest for the SPM Core at the next lower EL/mode.
Max Shvetsov745889c2020-02-27 14:54:21 +0000318 */
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100319 spmc_manifest = (void *)spmc_ep_info->args.arg0;
320 if (spmc_manifest == NULL) {
321 ERROR("Invalid or absent SPM Core manifest.\n");
322 return -EINVAL;
Max Shvetsov745889c2020-02-27 14:54:21 +0000323 }
324
325 /* Load manifest, init SPMC */
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100326 rc = spmd_spmc_init(spmc_manifest);
Max Shvetsov745889c2020-02-27 14:54:21 +0000327 if (rc != 0) {
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200328 WARN("Booting device without SPM initialization.\n");
Max Shvetsov745889c2020-02-27 14:54:21 +0000329 }
330
Olivier Deprez69ca84a2020-02-07 15:44:43 +0100331 return rc;
Max Shvetsov745889c2020-02-27 14:54:21 +0000332}
333
334/*******************************************************************************
335 * Forward SMC to the other security state
336 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200337static uint64_t spmd_smc_forward(uint32_t smc_fid,
338 bool secure_origin,
339 uint64_t x1,
340 uint64_t x2,
341 uint64_t x3,
342 uint64_t x4,
343 void *handle)
Max Shvetsov745889c2020-02-27 14:54:21 +0000344{
Olivier Deprezebc34772020-04-16 16:59:21 +0200345 unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE;
346 unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE;
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100347
Max Shvetsov745889c2020-02-27 14:54:21 +0000348 /* Save incoming security state */
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000349#if SPMD_SPM_AT_SEL2
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200350 if (secure_state_in == NON_SECURE) {
351 cm_el1_sysregs_context_save(secure_state_in);
352 }
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100353 cm_el2_sysregs_context_save(secure_state_in);
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200354#else
355 cm_el1_sysregs_context_save(secure_state_in);
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000356#endif
Max Shvetsov745889c2020-02-27 14:54:21 +0000357
358 /* Restore outgoing security state */
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000359#if SPMD_SPM_AT_SEL2
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200360 if (secure_state_out == NON_SECURE) {
361 cm_el1_sysregs_context_restore(secure_state_out);
362 }
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100363 cm_el2_sysregs_context_restore(secure_state_out);
Olivier Deprez9a2e5be2021-05-21 18:00:04 +0200364#else
365 cm_el1_sysregs_context_restore(secure_state_out);
Max Shvetsove7fd80e2020-02-25 13:55:00 +0000366#endif
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100367 cm_set_next_eret_context(secure_state_out);
Max Shvetsov745889c2020-02-27 14:54:21 +0000368
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100369 SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4,
Max Shvetsov745889c2020-02-27 14:54:21 +0000370 SMC_GET_GP(handle, CTX_GPREG_X5),
371 SMC_GET_GP(handle, CTX_GPREG_X6),
372 SMC_GET_GP(handle, CTX_GPREG_X7));
373}
374
375/*******************************************************************************
J-Alves2672cde2020-05-07 18:42:25 +0100376 * Return FFA_ERROR with specified error code
Max Shvetsov745889c2020-02-27 14:54:21 +0000377 ******************************************************************************/
J-Alves2672cde2020-05-07 18:42:25 +0100378static uint64_t spmd_ffa_error_return(void *handle, int error_code)
Max Shvetsov745889c2020-02-27 14:54:21 +0000379{
J-Alves64ff9932021-03-01 10:26:59 +0000380 SMC_RET8(handle, (uint32_t) FFA_ERROR,
381 FFA_TARGET_INFO_MBZ, (uint32_t)error_code,
J-Alves2672cde2020-05-07 18:42:25 +0100382 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
383 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
Achin Gupta86f23532019-10-11 15:41:16 +0100384}
385
Olivier Deprez33e44122020-04-16 17:54:27 +0200386/*******************************************************************************
387 * spmd_check_address_in_binary_image
388 ******************************************************************************/
389bool spmd_check_address_in_binary_image(uint64_t address)
390{
391 assert(!check_uptr_overflow(spmc_attrs.load_address, spmc_attrs.binary_size));
392
393 return ((address >= spmc_attrs.load_address) &&
394 (address < (spmc_attrs.load_address + spmc_attrs.binary_size)));
395}
396
Olivier Deprezebc34772020-04-16 16:59:21 +0200397/******************************************************************************
398 * spmd_is_spmc_message
399 *****************************************************************************/
400static bool spmd_is_spmc_message(unsigned int ep)
401{
402 return ((ffa_endpoint_destination(ep) == SPMD_DIRECT_MSG_ENDPOINT_ID)
403 && (ffa_endpoint_source(ep) == spmc_attrs.spmc_id));
404}
405
Olivier Deprez33e44122020-04-16 17:54:27 +0200406/******************************************************************************
407 * spmd_handle_spmc_message
408 *****************************************************************************/
Olivier Deprezc7631a52020-03-23 09:53:06 +0100409static int spmd_handle_spmc_message(unsigned long long msg,
410 unsigned long long parm1, unsigned long long parm2,
411 unsigned long long parm3, unsigned long long parm4)
Olivier Deprez33e44122020-04-16 17:54:27 +0200412{
413 VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__,
414 msg, parm1, parm2, parm3, parm4);
415
Olivier Deprez33e44122020-04-16 17:54:27 +0200416 return -EINVAL;
417}
418
Achin Gupta86f23532019-10-11 15:41:16 +0100419/*******************************************************************************
J-Alves2672cde2020-05-07 18:42:25 +0100420 * This function handles all SMCs in the range reserved for FFA. Each call is
Achin Gupta86f23532019-10-11 15:41:16 +0100421 * either forwarded to the other security state or handled by the SPM dispatcher
422 ******************************************************************************/
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200423uint64_t spmd_smc_handler(uint32_t smc_fid,
424 uint64_t x1,
425 uint64_t x2,
426 uint64_t x3,
427 uint64_t x4,
428 void *cookie,
429 void *handle,
Achin Gupta86f23532019-10-11 15:41:16 +0100430 uint64_t flags)
431{
Olivier Deprezeae45962021-01-19 15:06:47 +0100432 unsigned int linear_id = plat_my_core_pos();
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200433 spmd_spm_core_context_t *ctx = spmd_get_context();
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100434 bool secure_origin;
435 int32_t ret;
J-Alves4c95c702020-05-26 14:03:05 +0100436 uint32_t input_version;
Achin Gupta86f23532019-10-11 15:41:16 +0100437
438 /* Determine which security state this SMC originated from */
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100439 secure_origin = is_caller_secure(flags);
Achin Gupta86f23532019-10-11 15:41:16 +0100440
Scott Brandene5dcf982020-08-25 13:49:32 -0700441 VERBOSE("SPM(%u): 0x%x 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64
442 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 "\n",
443 linear_id, smc_fid, x1, x2, x3, x4,
444 SMC_GET_GP(handle, CTX_GPREG_X5),
445 SMC_GET_GP(handle, CTX_GPREG_X6),
446 SMC_GET_GP(handle, CTX_GPREG_X7));
Achin Gupta86f23532019-10-11 15:41:16 +0100447
448 switch (smc_fid) {
J-Alves2672cde2020-05-07 18:42:25 +0100449 case FFA_ERROR:
Achin Gupta86f23532019-10-11 15:41:16 +0100450 /*
451 * Check if this is the first invocation of this interface on
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200452 * this CPU. If so, then indicate that the SPM Core initialised
Achin Gupta86f23532019-10-11 15:41:16 +0100453 * unsuccessfully.
454 */
Olivier Deprez7c016332019-10-28 09:03:13 +0000455 if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
Achin Gupta86f23532019-10-11 15:41:16 +0100456 spmd_spm_core_sync_exit(x2);
Max Shvetsov745889c2020-02-27 14:54:21 +0000457 }
Achin Gupta86f23532019-10-11 15:41:16 +0100458
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100459 return spmd_smc_forward(smc_fid, secure_origin,
Max Shvetsov745889c2020-02-27 14:54:21 +0000460 x1, x2, x3, x4, handle);
Achin Gupta86f23532019-10-11 15:41:16 +0100461 break; /* not reached */
462
J-Alves2672cde2020-05-07 18:42:25 +0100463 case FFA_VERSION:
J-Alves4c95c702020-05-26 14:03:05 +0100464 input_version = (uint32_t)(0xFFFFFFFF & x1);
Achin Gupta86f23532019-10-11 15:41:16 +0100465 /*
J-Alves4c95c702020-05-26 14:03:05 +0100466 * If caller is secure and SPMC was initialized,
467 * return FFA_VERSION of SPMD.
468 * If caller is non secure and SPMC was initialized,
469 * return SPMC's version.
470 * Sanity check to "input_version".
Achin Gupta86f23532019-10-11 15:41:16 +0100471 */
J-Alves4c95c702020-05-26 14:03:05 +0100472 if ((input_version & FFA_VERSION_BIT31_MASK) ||
473 (ctx->state == SPMC_STATE_RESET)) {
474 ret = FFA_ERROR_NOT_SUPPORTED;
475 } else if (!secure_origin) {
J-Alves64ff9932021-03-01 10:26:59 +0000476 ret = MAKE_FFA_VERSION(spmc_attrs.major_version,
477 spmc_attrs.minor_version);
J-Alves4c95c702020-05-26 14:03:05 +0100478 } else {
J-Alves64ff9932021-03-01 10:26:59 +0000479 ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR,
480 FFA_VERSION_MINOR);
J-Alves4c95c702020-05-26 14:03:05 +0100481 }
482
J-Alves64ff9932021-03-01 10:26:59 +0000483 SMC_RET8(handle, (uint32_t)ret, FFA_TARGET_INFO_MBZ,
484 FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
485 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ);
Achin Gupta86f23532019-10-11 15:41:16 +0100486 break; /* not reached */
487
J-Alves2672cde2020-05-07 18:42:25 +0100488 case FFA_FEATURES:
Achin Gupta86f23532019-10-11 15:41:16 +0100489 /*
490 * This is an optional interface. Do the minimal checks and
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200491 * forward to SPM Core which will handle it if implemented.
Achin Gupta86f23532019-10-11 15:41:16 +0100492 */
493
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200494 /* Forward SMC from Normal world to the SPM Core */
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100495 if (!secure_origin) {
496 return spmd_smc_forward(smc_fid, secure_origin,
Max Shvetsov745889c2020-02-27 14:54:21 +0000497 x1, x2, x3, x4, handle);
Achin Gupta86f23532019-10-11 15:41:16 +0100498 }
Max Shvetsov745889c2020-02-27 14:54:21 +0000499
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200500 /*
501 * Return success if call was from secure world i.e. all
J-Alves2672cde2020-05-07 18:42:25 +0100502 * FFA functions are supported. This is essentially a
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200503 * nop.
504 */
J-Alves2672cde2020-05-07 18:42:25 +0100505 SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4,
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200506 SMC_GET_GP(handle, CTX_GPREG_X5),
507 SMC_GET_GP(handle, CTX_GPREG_X6),
508 SMC_GET_GP(handle, CTX_GPREG_X7));
509
Achin Gupta86f23532019-10-11 15:41:16 +0100510 break; /* not reached */
511
J-Alves2672cde2020-05-07 18:42:25 +0100512 case FFA_ID_GET:
Max Shvetsove79062e2020-03-12 15:16:40 +0000513 /*
J-Alves2672cde2020-05-07 18:42:25 +0100514 * Returns the ID of the calling FFA component.
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200515 */
Max Shvetsove79062e2020-03-12 15:16:40 +0000516 if (!secure_origin) {
J-Alves2672cde2020-05-07 18:42:25 +0100517 SMC_RET8(handle, FFA_SUCCESS_SMC32,
518 FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID,
519 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
520 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
521 FFA_PARAM_MBZ);
Max Shvetsove79062e2020-03-12 15:16:40 +0000522 }
523
J-Alves2672cde2020-05-07 18:42:25 +0100524 SMC_RET8(handle, FFA_SUCCESS_SMC32,
525 FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
526 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
527 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
528 FFA_PARAM_MBZ);
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200529
Max Shvetsove79062e2020-03-12 15:16:40 +0000530 break; /* not reached */
531
Olivier Deprezeae45962021-01-19 15:06:47 +0100532 case FFA_SECONDARY_EP_REGISTER_SMC64:
533 if (secure_origin) {
534 ret = spmd_pm_secondary_ep_register(x1);
535
536 if (ret < 0) {
537 SMC_RET8(handle, FFA_ERROR_SMC64,
538 FFA_TARGET_INFO_MBZ, ret,
539 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
540 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
541 FFA_PARAM_MBZ);
542 } else {
543 SMC_RET8(handle, FFA_SUCCESS_SMC64,
544 FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ,
545 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
546 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
547 FFA_PARAM_MBZ);
548 }
549 }
550
551 return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
552 break; /* Not reached */
553
Daniel Boulby27f35df2021-02-03 12:13:19 +0000554 case FFA_SPM_ID_GET:
555 if (MAKE_FFA_VERSION(1, 1) > FFA_VERSION_COMPILED) {
556 return spmd_ffa_error_return(handle,
557 FFA_ERROR_NOT_SUPPORTED);
558 }
559 /*
560 * Returns the ID of the SPMC or SPMD depending on the FF-A
561 * instance where this function is invoked
562 */
563 if (!secure_origin) {
564 SMC_RET8(handle, FFA_SUCCESS_SMC32,
565 FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id,
566 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
567 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
568 FFA_PARAM_MBZ);
569 }
570 SMC_RET8(handle, FFA_SUCCESS_SMC32,
571 FFA_TARGET_INFO_MBZ, SPMD_DIRECT_MSG_ENDPOINT_ID,
572 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
573 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
574 FFA_PARAM_MBZ);
575
576 break; /* not reached */
577
Olivier Deprez33e44122020-04-16 17:54:27 +0200578 case FFA_MSG_SEND_DIRECT_REQ_SMC32:
579 if (secure_origin && spmd_is_spmc_message(x1)) {
580 ret = spmd_handle_spmc_message(x3, x4,
581 SMC_GET_GP(handle, CTX_GPREG_X5),
582 SMC_GET_GP(handle, CTX_GPREG_X6),
583 SMC_GET_GP(handle, CTX_GPREG_X7));
584
585 SMC_RET8(handle, FFA_SUCCESS_SMC32,
586 FFA_TARGET_INFO_MBZ, ret,
587 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
588 FFA_PARAM_MBZ, FFA_PARAM_MBZ,
589 FFA_PARAM_MBZ);
590 } else {
591 /* Forward direct message to the other world */
592 return spmd_smc_forward(smc_fid, secure_origin,
593 x1, x2, x3, x4, handle);
594 }
595 break; /* Not reached */
596
597 case FFA_MSG_SEND_DIRECT_RESP_SMC32:
598 if (secure_origin && spmd_is_spmc_message(x1)) {
599 spmd_spm_core_sync_exit(0);
600 } else {
601 /* Forward direct message to the other world */
602 return spmd_smc_forward(smc_fid, secure_origin,
603 x1, x2, x3, x4, handle);
604 }
605 break; /* Not reached */
606
J-Alves2672cde2020-05-07 18:42:25 +0100607 case FFA_RX_RELEASE:
608 case FFA_RXTX_MAP_SMC32:
609 case FFA_RXTX_MAP_SMC64:
610 case FFA_RXTX_UNMAP:
Ruari Phipps93dff702020-07-28 10:33:35 +0100611 case FFA_PARTITION_INFO_GET:
J-Alves2621cfd2021-03-11 17:46:47 +0000612#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED
613 case FFA_NOTIFICATION_BITMAP_CREATE:
614 case FFA_NOTIFICATION_BITMAP_DESTROY:
615 case FFA_NOTIFICATION_BIND:
616 case FFA_NOTIFICATION_UNBIND:
617 case FFA_NOTIFICATION_SET:
618 case FFA_NOTIFICATION_GET:
619 case FFA_NOTIFICATION_INFO_GET:
620 case FFA_NOTIFICATION_INFO_GET_SMC64:
621#endif
Ruari Phipps93dff702020-07-28 10:33:35 +0100622 /*
J-Alves2621cfd2021-03-11 17:46:47 +0000623 * Above calls should not be forwarded from Secure world to
624 * Normal world.
Ruari Phipps93dff702020-07-28 10:33:35 +0100625 *
626 * Fall through to forward the call to the other world
627 */
J-Alves2672cde2020-05-07 18:42:25 +0100628 case FFA_MSG_RUN:
Achin Gupta86f23532019-10-11 15:41:16 +0100629 /* This interface must be invoked only by the Normal world */
Ruari Phipps93dff702020-07-28 10:33:35 +0100630
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100631 if (secure_origin) {
J-Alves2672cde2020-05-07 18:42:25 +0100632 return spmd_ffa_error_return(handle,
Ruari Phipps93dff702020-07-28 10:33:35 +0100633 FFA_ERROR_NOT_SUPPORTED);
Achin Gupta86f23532019-10-11 15:41:16 +0100634 }
635
636 /* Fall through to forward the call to the other world */
J-Alves2672cde2020-05-07 18:42:25 +0100637 case FFA_MSG_SEND:
J-Alves2672cde2020-05-07 18:42:25 +0100638 case FFA_MSG_SEND_DIRECT_REQ_SMC64:
J-Alves2672cde2020-05-07 18:42:25 +0100639 case FFA_MSG_SEND_DIRECT_RESP_SMC64:
640 case FFA_MEM_DONATE_SMC32:
641 case FFA_MEM_DONATE_SMC64:
642 case FFA_MEM_LEND_SMC32:
643 case FFA_MEM_LEND_SMC64:
644 case FFA_MEM_SHARE_SMC32:
645 case FFA_MEM_SHARE_SMC64:
646 case FFA_MEM_RETRIEVE_REQ_SMC32:
647 case FFA_MEM_RETRIEVE_REQ_SMC64:
648 case FFA_MEM_RETRIEVE_RESP:
649 case FFA_MEM_RELINQUISH:
650 case FFA_MEM_RECLAIM:
651 case FFA_SUCCESS_SMC32:
652 case FFA_SUCCESS_SMC64:
Achin Gupta86f23532019-10-11 15:41:16 +0100653 /*
654 * TODO: Assume that no requests originate from EL3 at the
655 * moment. This will change if a SP service is required in
656 * response to secure interrupts targeted to EL3. Until then
657 * simply forward the call to the Normal world.
658 */
659
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100660 return spmd_smc_forward(smc_fid, secure_origin,
Max Shvetsov745889c2020-02-27 14:54:21 +0000661 x1, x2, x3, x4, handle);
Achin Gupta86f23532019-10-11 15:41:16 +0100662 break; /* not reached */
663
J-Alves2672cde2020-05-07 18:42:25 +0100664 case FFA_MSG_WAIT:
Achin Gupta86f23532019-10-11 15:41:16 +0100665 /*
666 * Check if this is the first invocation of this interface on
667 * this CPU from the Secure world. If so, then indicate that the
Olivier Deprez2bae35f2020-04-16 13:39:06 +0200668 * SPM Core initialised successfully.
Achin Gupta86f23532019-10-11 15:41:16 +0100669 */
Olivier Deprez7c016332019-10-28 09:03:13 +0000670 if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) {
Achin Gupta86f23532019-10-11 15:41:16 +0100671 spmd_spm_core_sync_exit(0);
672 }
673
Max Shvetsov745889c2020-02-27 14:54:21 +0000674 /* Fall through to forward the call to the other world */
Olivier Deprezae18caf2021-04-02 11:09:10 +0200675 case FFA_INTERRUPT:
J-Alves2672cde2020-05-07 18:42:25 +0100676 case FFA_MSG_YIELD:
Achin Gupta86f23532019-10-11 15:41:16 +0100677 /* This interface must be invoked only by the Secure world */
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100678 if (!secure_origin) {
J-Alves2672cde2020-05-07 18:42:25 +0100679 return spmd_ffa_error_return(handle,
680 FFA_ERROR_NOT_SUPPORTED);
Achin Gupta86f23532019-10-11 15:41:16 +0100681 }
682
Olivier Deprez41ff36a2019-12-23 16:21:12 +0100683 return spmd_smc_forward(smc_fid, secure_origin,
Max Shvetsov745889c2020-02-27 14:54:21 +0000684 x1, x2, x3, x4, handle);
Achin Gupta86f23532019-10-11 15:41:16 +0100685 break; /* not reached */
686
687 default:
688 WARN("SPM: Unsupported call 0x%08x\n", smc_fid);
J-Alves2672cde2020-05-07 18:42:25 +0100689 return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
Achin Gupta86f23532019-10-11 15:41:16 +0100690 }
691}