blob: 35def25af4e81a0862e77c4cba743e925a820ea7 [file] [log] [blame]
Marc Bonnici8e1a7552021-12-01 17:57:04 +00001/*
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 <errno.h>
9
10#include <arch_helpers.h>
11#include <bl31/bl31.h>
12#include <bl31/ehf.h>
13#include <common/debug.h>
14#include <common/fdt_wrappers.h>
15#include <common/runtime_svc.h>
16#include <lib/el3_runtime/context_mgmt.h>
17#include <lib/smccc.h>
18#include <lib/utils.h>
19#include <lib/xlat_tables/xlat_tables_v2.h>
20#include <libfdt.h>
21#include <plat/common/platform.h>
Marc Bonnici9a297042022-02-14 17:06:09 +000022#include <services/el3_spmc_logical_sp.h>
Marc Bonnici8e1a7552021-12-01 17:57:04 +000023#include <services/ffa_svc.h>
24#include <services/spmc_svc.h>
25#include <services/spmd_svc.h>
26#include "spmc.h"
27
28#include <platform_def.h>
29
30/*
31 * Allocate a secure partition descriptor to describe each SP in the system that
32 * does not reside at EL3.
33 */
34static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT];
35
36/*
37 * Allocate an NS endpoint descriptor to describe each VM and the Hypervisor in
38 * the system that interacts with a SP. It is used to track the Hypervisor
39 * buffer pair, version and ID for now. It could be extended to track VM
40 * properties when the SPMC supports indirect messaging.
41 */
42static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT];
43
44/*
Marc Bonnici9a297042022-02-14 17:06:09 +000045 * Helper function to obtain the array storing the EL3
46 * Logical Partition descriptors.
47 */
48struct el3_lp_desc *get_el3_lp_array(void)
49{
50 return (struct el3_lp_desc *) EL3_LP_DESCS_START;
51}
52
53/*
Marc Bonnici8e1a7552021-12-01 17:57:04 +000054 * Helper function to obtain the descriptor of the last SP to whom control was
55 * handed to on this physical cpu. Currently, we assume there is only one SP.
56 * TODO: Expand to track multiple partitions when required.
57 */
58struct secure_partition_desc *spmc_get_current_sp_ctx(void)
59{
60 return &(sp_desc[ACTIVE_SP_DESC_INDEX]);
61}
62
63/*
64 * Helper function to obtain the execution context of an SP on the
65 * current physical cpu.
66 */
67struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp)
68{
69 return &(sp->ec[get_ec_index(sp)]);
70}
71
72/* Helper function to get pointer to SP context from its ID. */
73struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id)
74{
75 /* Check for SWd Partitions. */
76 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
77 if (sp_desc[i].sp_id == id) {
78 return &(sp_desc[i]);
79 }
80 }
81 return NULL;
82}
83
84/******************************************************************************
85 * This function returns to the place where spmc_sp_synchronous_entry() was
86 * called originally.
87 ******************************************************************************/
88__dead2 void spmc_sp_synchronous_exit(struct sp_exec_ctx *ec, uint64_t rc)
89{
90 /*
91 * The SPM must have initiated the original request through a
92 * synchronous entry into the secure partition. Jump back to the
93 * original C runtime context with the value of rc in x0;
94 */
95 spm_secure_partition_exit(ec->c_rt_ctx, rc);
96
97 panic();
98}
99
100/*******************************************************************************
101 * Return FFA_ERROR with specified error code.
102 ******************************************************************************/
103uint64_t spmc_ffa_error_return(void *handle, int error_code)
104{
105 SMC_RET8(handle, FFA_ERROR,
106 FFA_TARGET_INFO_MBZ, error_code,
107 FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ,
108 FFA_PARAM_MBZ, FFA_PARAM_MBZ);
109}
110
111/******************************************************************************
112 * Helper function to validate a secure partition ID to ensure it does not
113 * conflict with any other FF-A component and follows the convention to
114 * indicate it resides within the secure world.
115 ******************************************************************************/
116bool is_ffa_secure_id_valid(uint16_t partition_id)
117{
Marc Bonnici9a297042022-02-14 17:06:09 +0000118 struct el3_lp_desc *el3_lp_descs = get_el3_lp_array();
119
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000120 /* Ensure the ID is not the invalid partition ID. */
121 if (partition_id == INV_SP_ID) {
122 return false;
123 }
124
125 /* Ensure the ID is not the SPMD ID. */
126 if (partition_id == SPMD_DIRECT_MSG_ENDPOINT_ID) {
127 return false;
128 }
129
130 /*
131 * Ensure the ID follows the convention to indicate it resides
132 * in the secure world.
133 */
134 if (!ffa_is_secure_world_id(partition_id)) {
135 return false;
136 }
137
138 /* Ensure we don't conflict with the SPMC partition ID. */
139 if (partition_id == FFA_SPMC_ID) {
140 return false;
141 }
142
143 /* Ensure we do not already have an SP context with this ID. */
144 if (spmc_get_sp_ctx(partition_id)) {
145 return false;
146 }
147
Marc Bonnici9a297042022-02-14 17:06:09 +0000148 /* Ensure we don't clash with any Logical SP's. */
149 for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
150 if (el3_lp_descs[i].sp_id == partition_id) {
151 return false;
152 }
153 }
154
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000155 return true;
156}
157
158/*******************************************************************************
Marc Bonnici7e19db82021-11-29 17:17:29 +0000159 * This function either forwards the request to the other world or returns
160 * with an ERET depending on the source of the call.
Marc Bonnici9a297042022-02-14 17:06:09 +0000161 * We can assume that the destination is for an entity at a lower exception
162 * level as any messages destined for a logical SP resident in EL3 will have
163 * already been taken care of by the SPMC before entering this function.
Marc Bonnici7e19db82021-11-29 17:17:29 +0000164 ******************************************************************************/
165static uint64_t spmc_smc_return(uint32_t smc_fid,
166 bool secure_origin,
167 uint64_t x1,
168 uint64_t x2,
169 uint64_t x3,
170 uint64_t x4,
171 void *handle,
172 void *cookie,
173 uint64_t flags,
174 uint16_t dst_id)
175{
176 /* If the destination is in the normal world always go via the SPMD. */
177 if (ffa_is_normal_world_id(dst_id)) {
178 return spmd_smc_handler(smc_fid, x1, x2, x3, x4,
179 cookie, handle, flags);
180 }
181 /*
182 * If the caller is secure and we want to return to the secure world,
183 * ERET directly.
184 */
185 else if (secure_origin && ffa_is_secure_world_id(dst_id)) {
186 SMC_RET5(handle, smc_fid, x1, x2, x3, x4);
187 }
188 /* If we originated in the normal world then switch contexts. */
189 else if (!secure_origin && ffa_is_secure_world_id(dst_id)) {
190 return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2,
191 x3, x4, handle);
192 } else {
193 /* Unknown State. */
194 panic();
195 }
196
197 /* Shouldn't be Reached. */
198 return 0;
199}
200
201/*******************************************************************************
Marc Bonnici8eb15202021-11-29 17:05:33 +0000202 * FF-A ABI Handlers.
203 ******************************************************************************/
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000204
205/*******************************************************************************
206 * Helper function to validate arg2 as part of a direct message.
207 ******************************************************************************/
208static inline bool direct_msg_validate_arg2(uint64_t x2)
209{
210 /*
211 * We currently only support partition messages, therefore ensure x2 is
212 * not set.
213 */
214 if (x2 != (uint64_t) 0) {
215 VERBOSE("Arg2 MBZ for partition messages (0x%lx).\n", x2);
216 return false;
217 }
218 return true;
219}
220
221/*******************************************************************************
222 * Handle direct request messages and route to the appropriate destination.
223 ******************************************************************************/
224static uint64_t direct_req_smc_handler(uint32_t smc_fid,
225 bool secure_origin,
226 uint64_t x1,
227 uint64_t x2,
228 uint64_t x3,
229 uint64_t x4,
230 void *cookie,
231 void *handle,
232 uint64_t flags)
233{
234 uint16_t dst_id = ffa_endpoint_destination(x1);
Marc Bonnici9a297042022-02-14 17:06:09 +0000235 struct el3_lp_desc *el3_lp_descs;
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000236 struct secure_partition_desc *sp;
237 unsigned int idx;
238
239 /* Check if arg2 has been populated correctly based on message type. */
240 if (!direct_msg_validate_arg2(x2)) {
241 return spmc_ffa_error_return(handle,
242 FFA_ERROR_INVALID_PARAMETER);
243 }
244
Marc Bonnici9a297042022-02-14 17:06:09 +0000245 el3_lp_descs = get_el3_lp_array();
246
247 /* Check if the request is destined for a Logical Partition. */
248 for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) {
249 if (el3_lp_descs[i].sp_id == dst_id) {
250 return el3_lp_descs[i].direct_req(
251 smc_fid, secure_origin, x1, x2, x3, x4,
252 cookie, handle, flags);
253 }
254 }
255
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000256 /*
Marc Bonnici9a297042022-02-14 17:06:09 +0000257 * If the request was not targeted to a LSP and from the secure world
258 * then it is invalid since a SP cannot call into the Normal world and
259 * there is no other SP to call into. If there are other SPs in future
260 * then the partition runtime model would need to be validated as well.
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000261 */
262 if (secure_origin) {
263 VERBOSE("Direct request not supported to the Normal World.\n");
264 return spmc_ffa_error_return(handle,
265 FFA_ERROR_INVALID_PARAMETER);
266 }
267
268 /* Check if the SP ID is valid. */
269 sp = spmc_get_sp_ctx(dst_id);
270 if (sp == NULL) {
271 VERBOSE("Direct request to unknown partition ID (0x%x).\n",
272 dst_id);
273 return spmc_ffa_error_return(handle,
274 FFA_ERROR_INVALID_PARAMETER);
275 }
276
277 /*
278 * Check that the target execution context is in a waiting state before
279 * forwarding the direct request to it.
280 */
281 idx = get_ec_index(sp);
282 if (sp->ec[idx].rt_state != RT_STATE_WAITING) {
283 VERBOSE("SP context on core%u is not waiting (%u).\n",
284 idx, sp->ec[idx].rt_model);
285 return spmc_ffa_error_return(handle, FFA_ERROR_BUSY);
286 }
287
288 /*
289 * Everything checks out so forward the request to the SP after updating
290 * its state and runtime model.
291 */
292 sp->ec[idx].rt_state = RT_STATE_RUNNING;
293 sp->ec[idx].rt_model = RT_MODEL_DIR_REQ;
294 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
295 handle, cookie, flags, dst_id);
296}
297
298/*******************************************************************************
299 * Handle direct response messages and route to the appropriate destination.
300 ******************************************************************************/
301static uint64_t direct_resp_smc_handler(uint32_t smc_fid,
302 bool secure_origin,
303 uint64_t x1,
304 uint64_t x2,
305 uint64_t x3,
306 uint64_t x4,
307 void *cookie,
308 void *handle,
309 uint64_t flags)
310{
311 uint16_t dst_id = ffa_endpoint_destination(x1);
312 struct secure_partition_desc *sp;
313 unsigned int idx;
314
315 /* Check if arg2 has been populated correctly based on message type. */
316 if (!direct_msg_validate_arg2(x2)) {
317 return spmc_ffa_error_return(handle,
318 FFA_ERROR_INVALID_PARAMETER);
319 }
320
321 /* Check that the response did not originate from the Normal world. */
322 if (!secure_origin) {
323 VERBOSE("Direct Response not supported from Normal World.\n");
324 return spmc_ffa_error_return(handle,
325 FFA_ERROR_INVALID_PARAMETER);
326 }
327
328 /*
329 * Check that the response is either targeted to the Normal world or the
330 * SPMC e.g. a PM response.
331 */
332 if ((dst_id != FFA_SPMC_ID) && ffa_is_secure_world_id(dst_id)) {
333 VERBOSE("Direct response to invalid partition ID (0x%x).\n",
334 dst_id);
335 return spmc_ffa_error_return(handle,
336 FFA_ERROR_INVALID_PARAMETER);
337 }
338
339 /* Obtain the SP descriptor and update its runtime state. */
340 sp = spmc_get_sp_ctx(ffa_endpoint_source(x1));
341 if (sp == NULL) {
342 VERBOSE("Direct response to unknown partition ID (0x%x).\n",
343 dst_id);
344 return spmc_ffa_error_return(handle,
345 FFA_ERROR_INVALID_PARAMETER);
346 }
347
348 /* Sanity check state is being tracked correctly in the SPMC. */
349 idx = get_ec_index(sp);
350 assert(sp->ec[idx].rt_state == RT_STATE_RUNNING);
351
352 /* Ensure SP execution context was in the right runtime model. */
353 if (sp->ec[idx].rt_model != RT_MODEL_DIR_REQ) {
354 VERBOSE("SP context on core%u not handling direct req (%u).\n",
355 idx, sp->ec[idx].rt_model);
356 return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
357 }
358
359 /* Update the state of the SP execution context. */
360 sp->ec[idx].rt_state = RT_STATE_WAITING;
361
362 /*
363 * If the receiver is not the SPMC then forward the response to the
364 * Normal world.
365 */
366 if (dst_id == FFA_SPMC_ID) {
367 spmc_sp_synchronous_exit(&sp->ec[idx], x4);
368 /* Should not get here. */
369 panic();
370 }
371
372 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
373 handle, cookie, flags, dst_id);
374}
375
Marc Bonnici8eb15202021-11-29 17:05:33 +0000376/*******************************************************************************
377 * This function handles the FFA_MSG_WAIT SMC to allow an SP to relinquish its
378 * cycles.
379 ******************************************************************************/
380static uint64_t msg_wait_handler(uint32_t smc_fid,
381 bool secure_origin,
382 uint64_t x1,
383 uint64_t x2,
384 uint64_t x3,
385 uint64_t x4,
386 void *cookie,
387 void *handle,
388 uint64_t flags)
389{
390 struct secure_partition_desc *sp;
391 unsigned int idx;
392
393 /*
394 * Check that the response did not originate from the Normal world as
395 * only the secure world can call this ABI.
396 */
397 if (!secure_origin) {
398 VERBOSE("Normal world cannot call FFA_MSG_WAIT.\n");
399 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
400 }
401
402 /* Get the descriptor of the SP that invoked FFA_MSG_WAIT. */
403 sp = spmc_get_current_sp_ctx();
404 if (sp == NULL) {
405 return spmc_ffa_error_return(handle,
406 FFA_ERROR_INVALID_PARAMETER);
407 }
408
409 /*
410 * Get the execution context of the SP that invoked FFA_MSG_WAIT.
411 */
412 idx = get_ec_index(sp);
413
414 /* Ensure SP execution context was in the right runtime model. */
415 if (sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) {
416 return spmc_ffa_error_return(handle, FFA_ERROR_DENIED);
417 }
418
419 /* Sanity check the state is being tracked correctly in the SPMC. */
420 assert(sp->ec[idx].rt_state == RT_STATE_RUNNING);
421
422 /*
423 * Perform a synchronous exit if the partition was initialising. The
424 * state is updated after the exit.
425 */
426 if (sp->ec[idx].rt_model == RT_MODEL_INIT) {
427 spmc_sp_synchronous_exit(&sp->ec[idx], x4);
428 /* Should not get here */
429 panic();
430 }
431
432 /* Update the state of the SP execution context. */
433 sp->ec[idx].rt_state = RT_STATE_WAITING;
434
435 /* Resume normal world if a secure interrupt was handled. */
436 if (sp->ec[idx].rt_model == RT_MODEL_INTR) {
437 /* FFA_MSG_WAIT can only be called from the secure world. */
438 unsigned int secure_state_in = SECURE;
439 unsigned int secure_state_out = NON_SECURE;
440
441 cm_el1_sysregs_context_save(secure_state_in);
442 cm_el1_sysregs_context_restore(secure_state_out);
443 cm_set_next_eret_context(secure_state_out);
444 SMC_RET0(cm_get_context(secure_state_out));
445 }
446
447 /* Forward the response to the Normal world. */
448 return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4,
449 handle, cookie, flags, FFA_NWD_ID);
450}
451
Marc Bonnicib4e99842021-12-10 09:21:56 +0000452static uint64_t ffa_error_handler(uint32_t smc_fid,
453 bool secure_origin,
454 uint64_t x1,
455 uint64_t x2,
456 uint64_t x3,
457 uint64_t x4,
458 void *cookie,
459 void *handle,
460 uint64_t flags)
461{
462 struct secure_partition_desc *sp;
463 unsigned int idx;
464
465 /* Check that the response did not originate from the Normal world. */
466 if (!secure_origin) {
467 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
468 }
469
470 /* Get the descriptor of the SP that invoked FFA_ERROR. */
471 sp = spmc_get_current_sp_ctx();
472 if (sp == NULL) {
473 return spmc_ffa_error_return(handle,
474 FFA_ERROR_INVALID_PARAMETER);
475 }
476
477 /* Get the execution context of the SP that invoked FFA_ERROR. */
478 idx = get_ec_index(sp);
479
480 /*
481 * We only expect FFA_ERROR to be received during SP initialisation
482 * otherwise this is an invalid call.
483 */
484 if (sp->ec[idx].rt_model == RT_MODEL_INIT) {
485 ERROR("SP 0x%x failed to initialize.\n", sp->sp_id);
486 spmc_sp_synchronous_exit(&sp->ec[idx], x2);
487 /* Should not get here. */
488 panic();
489 }
490
491 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
492}
493
Marc Bonnici8eb15202021-11-29 17:05:33 +0000494/*******************************************************************************
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000495 * This function will parse the Secure Partition Manifest. From manifest, it
496 * will fetch details for preparing Secure partition image context and secure
497 * partition image boot arguments if any.
498 ******************************************************************************/
499static int sp_manifest_parse(void *sp_manifest, int offset,
500 struct secure_partition_desc *sp,
501 entry_point_info_t *ep_info)
502{
503 int32_t ret, node;
504 uint32_t config_32;
505
506 /*
507 * Look for the mandatory fields that are expected to be present in
508 * the SP manifests.
509 */
510 node = fdt_path_offset(sp_manifest, "/");
511 if (node < 0) {
512 ERROR("Did not find root node.\n");
513 return node;
514 }
515
Marc Bonnici21e644d2021-08-24 11:31:52 +0100516 ret = fdt_read_uint32_array(sp_manifest, node, "uuid",
517 ARRAY_SIZE(sp->uuid), sp->uuid);
518 if (ret != 0) {
519 ERROR("Missing Secure Partition UUID.\n");
520 return ret;
521 }
522
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000523 ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32);
524 if (ret != 0) {
525 ERROR("Missing SP Exception Level information.\n");
526 return ret;
527 }
528
529 sp->runtime_el = config_32;
530
531 ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32);
532 if (ret != 0) {
533 ERROR("Missing Secure Partition FF-A Version.\n");
534 return ret;
535 }
536
537 sp->ffa_version = config_32;
538
539 ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32);
540 if (ret != 0) {
541 ERROR("Missing Secure Partition Execution State.\n");
542 return ret;
543 }
544
545 sp->execution_state = config_32;
546
Marc Bonnicieec0d042021-12-09 10:51:05 +0000547 ret = fdt_read_uint32(sp_manifest, node,
548 "execution-ctx-count", &config_32);
549
550 if (ret != 0) {
551 ERROR("Missing SP Execution Context Count.\n");
552 return ret;
553 }
554
555 /*
556 * Ensure this field is set correctly in the manifest however
557 * since this is currently a hardcoded value for S-EL1 partitions
558 * we don't need to save it here, just validate.
559 */
560 if (config_32 != PLATFORM_CORE_COUNT) {
561 ERROR("SP Execution Context Count (%u) must be %u.\n",
562 config_32, PLATFORM_CORE_COUNT);
563 return -EINVAL;
564 }
565
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000566 /*
567 * Look for the optional fields that are expected to be present in
568 * an SP manifest.
569 */
570 ret = fdt_read_uint32(sp_manifest, node, "id", &config_32);
571 if (ret != 0) {
572 WARN("Missing Secure Partition ID.\n");
573 } else {
574 if (!is_ffa_secure_id_valid(config_32)) {
575 ERROR("Invalid Secure Partition ID (0x%x).\n",
576 config_32);
577 return -EINVAL;
578 }
579 sp->sp_id = config_32;
580 }
581
582 return 0;
583}
584
585/*******************************************************************************
586 * This function gets the Secure Partition Manifest base and maps the manifest
587 * region.
588 * Currently only one Secure Partition manifest is considered which is used to
589 * prepare the context for the single Secure Partition.
590 ******************************************************************************/
591static int find_and_prepare_sp_context(void)
592{
593 void *sp_manifest;
594 uintptr_t manifest_base;
595 uintptr_t manifest_base_align;
596 entry_point_info_t *next_image_ep_info;
597 int32_t ret;
598 struct secure_partition_desc *sp;
599
600 next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
601 if (next_image_ep_info == NULL) {
602 WARN("No Secure Partition image provided by BL2.\n");
603 return -ENOENT;
604 }
605
606 sp_manifest = (void *)next_image_ep_info->args.arg0;
607 if (sp_manifest == NULL) {
608 WARN("Secure Partition manifest absent.\n");
609 return -ENOENT;
610 }
611
612 manifest_base = (uintptr_t)sp_manifest;
613 manifest_base_align = page_align(manifest_base, DOWN);
614
615 /*
616 * Map the secure partition manifest region in the EL3 translation
617 * regime.
618 * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base
619 * alignment the region of 1 PAGE_SIZE from manifest align base may
620 * not completely accommodate the secure partition manifest region.
621 */
622 ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align,
623 manifest_base_align,
624 PAGE_SIZE * 2,
625 MT_RO_DATA);
626 if (ret != 0) {
627 ERROR("Error while mapping SP manifest (%d).\n", ret);
628 return ret;
629 }
630
631 ret = fdt_node_offset_by_compatible(sp_manifest, -1,
632 "arm,ffa-manifest-1.0");
633 if (ret < 0) {
634 ERROR("Error happened in SP manifest reading.\n");
635 return -EINVAL;
636 }
637
638 /*
639 * Store the size of the manifest so that it can be used later to pass
640 * the manifest as boot information later.
641 */
642 next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest);
643 INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1);
644
645 /*
646 * Select an SP descriptor for initialising the partition's execution
647 * context on the primary CPU.
648 */
649 sp = spmc_get_current_sp_ctx();
650
651 /* Initialize entry point information for the SP */
652 SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1,
653 SECURE | EP_ST_ENABLE);
654
655 /* Parse the SP manifest. */
656 ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info);
657 if (ret != 0) {
658 ERROR("Error in Secure Partition manifest parsing.\n");
659 return ret;
660 }
661
662 /* Check that the runtime EL in the manifest was correct. */
663 if (sp->runtime_el != S_EL1) {
664 ERROR("Unexpected runtime EL: %d\n", sp->runtime_el);
665 return -EINVAL;
666 }
667
668 /* Perform any common initialisation. */
669 spmc_sp_common_setup(sp, next_image_ep_info);
670
671 /* Perform any initialisation specific to S-EL1 SPs. */
672 spmc_el1_sp_setup(sp, next_image_ep_info);
673
674 /* Initialize the SP context with the required ep info. */
675 spmc_sp_common_ep_commit(sp, next_image_ep_info);
676
677 return 0;
678}
679
680/*******************************************************************************
681 * This function takes an SP context pointer and performs a synchronous entry
682 * into it.
683 ******************************************************************************/
Marc Bonnici9a297042022-02-14 17:06:09 +0000684static int32_t logical_sp_init(void)
685{
686 int32_t rc = 0;
687 struct el3_lp_desc *el3_lp_descs;
688
689 /* Perform initial validation of the Logical Partitions. */
690 rc = el3_sp_desc_validate();
691 if (rc != 0) {
692 ERROR("Logical Partition validation failed!\n");
693 return rc;
694 }
695
696 el3_lp_descs = get_el3_lp_array();
697
698 INFO("Logical Secure Partition init start.\n");
699 for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
700 rc = el3_lp_descs[i].init();
701 if (rc != 0) {
702 ERROR("Logical SP (0x%x) Failed to Initialize\n",
703 el3_lp_descs[i].sp_id);
704 return rc;
705 }
706 VERBOSE("Logical SP (0x%x) Initialized\n",
707 el3_lp_descs[i].sp_id);
708 }
709
710 INFO("Logical Secure Partition init completed.\n");
711
712 return rc;
713}
714
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000715uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec)
716{
717 uint64_t rc;
718
719 assert(ec != NULL);
720
721 /* Assign the context of the SP to this CPU */
722 cm_set_context(&(ec->cpu_ctx), SECURE);
723
724 /* Restore the context assigned above */
725 cm_el1_sysregs_context_restore(SECURE);
726 cm_set_next_eret_context(SECURE);
727
728 /* Invalidate TLBs at EL1. */
729 tlbivmalle1();
730 dsbish();
731
732 /* Enter Secure Partition */
733 rc = spm_secure_partition_enter(&ec->c_rt_ctx);
734
735 /* Save secure state */
736 cm_el1_sysregs_context_save(SECURE);
737
738 return rc;
739}
740
741/*******************************************************************************
742 * SPMC Helper Functions.
743 ******************************************************************************/
744static int32_t sp_init(void)
745{
746 uint64_t rc;
747 struct secure_partition_desc *sp;
748 struct sp_exec_ctx *ec;
749
750 sp = spmc_get_current_sp_ctx();
751 ec = spmc_get_sp_ec(sp);
752 ec->rt_model = RT_MODEL_INIT;
753 ec->rt_state = RT_STATE_RUNNING;
754
755 INFO("Secure Partition (0x%x) init start.\n", sp->sp_id);
756
757 rc = spmc_sp_synchronous_entry(ec);
758 if (rc != 0) {
759 /* Indicate SP init was not successful. */
760 ERROR("SP (0x%x) failed to initialize (%lu).\n",
761 sp->sp_id, rc);
762 return 0;
763 }
764
765 ec->rt_state = RT_STATE_WAITING;
766 INFO("Secure Partition initialized.\n");
767
768 return 1;
769}
770
771static void initalize_sp_descs(void)
772{
773 struct secure_partition_desc *sp;
774
775 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
776 sp = &sp_desc[i];
777 sp->sp_id = INV_SP_ID;
Marc Bonniciecc460a2021-09-02 13:18:41 +0100778 sp->mailbox.rx_buffer = NULL;
779 sp->mailbox.tx_buffer = NULL;
780 sp->mailbox.state = MAILBOX_STATE_EMPTY;
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000781 sp->secondary_ep = 0;
782 }
783}
784
785static void initalize_ns_ep_descs(void)
786{
787 struct ns_endpoint_desc *ns_ep;
788
789 for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) {
790 ns_ep = &ns_ep_desc[i];
791 /*
792 * Clashes with the Hypervisor ID but will not be a
793 * problem in practice.
794 */
795 ns_ep->ns_ep_id = 0;
796 ns_ep->ffa_version = 0;
Marc Bonniciecc460a2021-09-02 13:18:41 +0100797 ns_ep->mailbox.rx_buffer = NULL;
798 ns_ep->mailbox.tx_buffer = NULL;
799 ns_ep->mailbox.state = MAILBOX_STATE_EMPTY;
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000800 }
801}
802
803/*******************************************************************************
Marc Bonnici1c33cc32021-11-29 17:57:03 +0000804 * Initialize SPMC attributes for the SPMD.
805 ******************************************************************************/
806void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs)
807{
808 spmc_attrs->major_version = FFA_VERSION_MAJOR;
809 spmc_attrs->minor_version = FFA_VERSION_MINOR;
810 spmc_attrs->exec_state = MODE_RW_64;
811 spmc_attrs->spmc_id = FFA_SPMC_ID;
812}
813
814/*******************************************************************************
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000815 * Initialize contexts of all Secure Partitions.
816 ******************************************************************************/
817int32_t spmc_setup(void)
818{
819 int32_t ret;
820
821 /* Initialize endpoint descriptors */
822 initalize_sp_descs();
823 initalize_ns_ep_descs();
824
Marc Bonnici9a297042022-02-14 17:06:09 +0000825 /* Setup logical SPs. */
826 ret = logical_sp_init();
827 if (ret != 0) {
828 ERROR("Failed to initialize Logical Partitions.\n");
829 return ret;
830 }
831
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000832 /* Perform physical SP setup. */
833
834 /* Disable MMU at EL1 (initialized by BL2) */
835 disable_mmu_icache_el1();
836
837 /* Initialize context of the SP */
838 INFO("Secure Partition context setup start.\n");
839
840 ret = find_and_prepare_sp_context();
841 if (ret != 0) {
842 ERROR("Error in SP finding and context preparation.\n");
843 return ret;
844 }
845
846 /* Register init function for deferred init. */
847 bl31_register_bl32_init(&sp_init);
848
849 INFO("Secure Partition setup done.\n");
850
851 return 0;
852}
853
854/*******************************************************************************
855 * Secure Partition Manager SMC handler.
856 ******************************************************************************/
857uint64_t spmc_smc_handler(uint32_t smc_fid,
858 bool secure_origin,
859 uint64_t x1,
860 uint64_t x2,
861 uint64_t x3,
862 uint64_t x4,
863 void *cookie,
864 void *handle,
865 uint64_t flags)
866{
867 switch (smc_fid) {
868
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000869 case FFA_MSG_SEND_DIRECT_REQ_SMC32:
870 case FFA_MSG_SEND_DIRECT_REQ_SMC64:
871 return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
872 x3, x4, cookie, handle, flags);
873
874 case FFA_MSG_SEND_DIRECT_RESP_SMC32:
875 case FFA_MSG_SEND_DIRECT_RESP_SMC64:
876 return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2,
877 x3, x4, cookie, handle, flags);
878
Marc Bonnici8eb15202021-11-29 17:05:33 +0000879 case FFA_MSG_WAIT:
880 return msg_wait_handler(smc_fid, secure_origin, x1, x2, x3, x4,
881 cookie, handle, flags);
882
Marc Bonnicib4e99842021-12-10 09:21:56 +0000883 case FFA_ERROR:
884 return ffa_error_handler(smc_fid, secure_origin, x1, x2, x3, x4,
885 cookie, handle, flags);
886
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000887 default:
888 WARN("Unsupported FF-A call 0x%08x.\n", smc_fid);
889 break;
890 }
891 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
892}