blob: 450dd8cddb09c631b280c8c3fb3c446af755393d [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
516 ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32);
517 if (ret != 0) {
518 ERROR("Missing SP Exception Level information.\n");
519 return ret;
520 }
521
522 sp->runtime_el = config_32;
523
524 ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32);
525 if (ret != 0) {
526 ERROR("Missing Secure Partition FF-A Version.\n");
527 return ret;
528 }
529
530 sp->ffa_version = config_32;
531
532 ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32);
533 if (ret != 0) {
534 ERROR("Missing Secure Partition Execution State.\n");
535 return ret;
536 }
537
538 sp->execution_state = config_32;
539
540 /*
541 * Look for the optional fields that are expected to be present in
542 * an SP manifest.
543 */
544 ret = fdt_read_uint32(sp_manifest, node, "id", &config_32);
545 if (ret != 0) {
546 WARN("Missing Secure Partition ID.\n");
547 } else {
548 if (!is_ffa_secure_id_valid(config_32)) {
549 ERROR("Invalid Secure Partition ID (0x%x).\n",
550 config_32);
551 return -EINVAL;
552 }
553 sp->sp_id = config_32;
554 }
555
556 return 0;
557}
558
559/*******************************************************************************
560 * This function gets the Secure Partition Manifest base and maps the manifest
561 * region.
562 * Currently only one Secure Partition manifest is considered which is used to
563 * prepare the context for the single Secure Partition.
564 ******************************************************************************/
565static int find_and_prepare_sp_context(void)
566{
567 void *sp_manifest;
568 uintptr_t manifest_base;
569 uintptr_t manifest_base_align;
570 entry_point_info_t *next_image_ep_info;
571 int32_t ret;
572 struct secure_partition_desc *sp;
573
574 next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE);
575 if (next_image_ep_info == NULL) {
576 WARN("No Secure Partition image provided by BL2.\n");
577 return -ENOENT;
578 }
579
580 sp_manifest = (void *)next_image_ep_info->args.arg0;
581 if (sp_manifest == NULL) {
582 WARN("Secure Partition manifest absent.\n");
583 return -ENOENT;
584 }
585
586 manifest_base = (uintptr_t)sp_manifest;
587 manifest_base_align = page_align(manifest_base, DOWN);
588
589 /*
590 * Map the secure partition manifest region in the EL3 translation
591 * regime.
592 * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base
593 * alignment the region of 1 PAGE_SIZE from manifest align base may
594 * not completely accommodate the secure partition manifest region.
595 */
596 ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align,
597 manifest_base_align,
598 PAGE_SIZE * 2,
599 MT_RO_DATA);
600 if (ret != 0) {
601 ERROR("Error while mapping SP manifest (%d).\n", ret);
602 return ret;
603 }
604
605 ret = fdt_node_offset_by_compatible(sp_manifest, -1,
606 "arm,ffa-manifest-1.0");
607 if (ret < 0) {
608 ERROR("Error happened in SP manifest reading.\n");
609 return -EINVAL;
610 }
611
612 /*
613 * Store the size of the manifest so that it can be used later to pass
614 * the manifest as boot information later.
615 */
616 next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest);
617 INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1);
618
619 /*
620 * Select an SP descriptor for initialising the partition's execution
621 * context on the primary CPU.
622 */
623 sp = spmc_get_current_sp_ctx();
624
625 /* Initialize entry point information for the SP */
626 SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1,
627 SECURE | EP_ST_ENABLE);
628
629 /* Parse the SP manifest. */
630 ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info);
631 if (ret != 0) {
632 ERROR("Error in Secure Partition manifest parsing.\n");
633 return ret;
634 }
635
636 /* Check that the runtime EL in the manifest was correct. */
637 if (sp->runtime_el != S_EL1) {
638 ERROR("Unexpected runtime EL: %d\n", sp->runtime_el);
639 return -EINVAL;
640 }
641
642 /* Perform any common initialisation. */
643 spmc_sp_common_setup(sp, next_image_ep_info);
644
645 /* Perform any initialisation specific to S-EL1 SPs. */
646 spmc_el1_sp_setup(sp, next_image_ep_info);
647
648 /* Initialize the SP context with the required ep info. */
649 spmc_sp_common_ep_commit(sp, next_image_ep_info);
650
651 return 0;
652}
653
654/*******************************************************************************
655 * This function takes an SP context pointer and performs a synchronous entry
656 * into it.
657 ******************************************************************************/
Marc Bonnici9a297042022-02-14 17:06:09 +0000658static int32_t logical_sp_init(void)
659{
660 int32_t rc = 0;
661 struct el3_lp_desc *el3_lp_descs;
662
663 /* Perform initial validation of the Logical Partitions. */
664 rc = el3_sp_desc_validate();
665 if (rc != 0) {
666 ERROR("Logical Partition validation failed!\n");
667 return rc;
668 }
669
670 el3_lp_descs = get_el3_lp_array();
671
672 INFO("Logical Secure Partition init start.\n");
673 for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) {
674 rc = el3_lp_descs[i].init();
675 if (rc != 0) {
676 ERROR("Logical SP (0x%x) Failed to Initialize\n",
677 el3_lp_descs[i].sp_id);
678 return rc;
679 }
680 VERBOSE("Logical SP (0x%x) Initialized\n",
681 el3_lp_descs[i].sp_id);
682 }
683
684 INFO("Logical Secure Partition init completed.\n");
685
686 return rc;
687}
688
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000689uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec)
690{
691 uint64_t rc;
692
693 assert(ec != NULL);
694
695 /* Assign the context of the SP to this CPU */
696 cm_set_context(&(ec->cpu_ctx), SECURE);
697
698 /* Restore the context assigned above */
699 cm_el1_sysregs_context_restore(SECURE);
700 cm_set_next_eret_context(SECURE);
701
702 /* Invalidate TLBs at EL1. */
703 tlbivmalle1();
704 dsbish();
705
706 /* Enter Secure Partition */
707 rc = spm_secure_partition_enter(&ec->c_rt_ctx);
708
709 /* Save secure state */
710 cm_el1_sysregs_context_save(SECURE);
711
712 return rc;
713}
714
715/*******************************************************************************
716 * SPMC Helper Functions.
717 ******************************************************************************/
718static int32_t sp_init(void)
719{
720 uint64_t rc;
721 struct secure_partition_desc *sp;
722 struct sp_exec_ctx *ec;
723
724 sp = spmc_get_current_sp_ctx();
725 ec = spmc_get_sp_ec(sp);
726 ec->rt_model = RT_MODEL_INIT;
727 ec->rt_state = RT_STATE_RUNNING;
728
729 INFO("Secure Partition (0x%x) init start.\n", sp->sp_id);
730
731 rc = spmc_sp_synchronous_entry(ec);
732 if (rc != 0) {
733 /* Indicate SP init was not successful. */
734 ERROR("SP (0x%x) failed to initialize (%lu).\n",
735 sp->sp_id, rc);
736 return 0;
737 }
738
739 ec->rt_state = RT_STATE_WAITING;
740 INFO("Secure Partition initialized.\n");
741
742 return 1;
743}
744
745static void initalize_sp_descs(void)
746{
747 struct secure_partition_desc *sp;
748
749 for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) {
750 sp = &sp_desc[i];
751 sp->sp_id = INV_SP_ID;
752 sp->secondary_ep = 0;
753 }
754}
755
756static void initalize_ns_ep_descs(void)
757{
758 struct ns_endpoint_desc *ns_ep;
759
760 for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) {
761 ns_ep = &ns_ep_desc[i];
762 /*
763 * Clashes with the Hypervisor ID but will not be a
764 * problem in practice.
765 */
766 ns_ep->ns_ep_id = 0;
767 ns_ep->ffa_version = 0;
768 }
769}
770
771/*******************************************************************************
Marc Bonnici1c33cc32021-11-29 17:57:03 +0000772 * Initialize SPMC attributes for the SPMD.
773 ******************************************************************************/
774void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs)
775{
776 spmc_attrs->major_version = FFA_VERSION_MAJOR;
777 spmc_attrs->minor_version = FFA_VERSION_MINOR;
778 spmc_attrs->exec_state = MODE_RW_64;
779 spmc_attrs->spmc_id = FFA_SPMC_ID;
780}
781
782/*******************************************************************************
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000783 * Initialize contexts of all Secure Partitions.
784 ******************************************************************************/
785int32_t spmc_setup(void)
786{
787 int32_t ret;
788
789 /* Initialize endpoint descriptors */
790 initalize_sp_descs();
791 initalize_ns_ep_descs();
792
Marc Bonnici9a297042022-02-14 17:06:09 +0000793 /* Setup logical SPs. */
794 ret = logical_sp_init();
795 if (ret != 0) {
796 ERROR("Failed to initialize Logical Partitions.\n");
797 return ret;
798 }
799
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000800 /* Perform physical SP setup. */
801
802 /* Disable MMU at EL1 (initialized by BL2) */
803 disable_mmu_icache_el1();
804
805 /* Initialize context of the SP */
806 INFO("Secure Partition context setup start.\n");
807
808 ret = find_and_prepare_sp_context();
809 if (ret != 0) {
810 ERROR("Error in SP finding and context preparation.\n");
811 return ret;
812 }
813
814 /* Register init function for deferred init. */
815 bl31_register_bl32_init(&sp_init);
816
817 INFO("Secure Partition setup done.\n");
818
819 return 0;
820}
821
822/*******************************************************************************
823 * Secure Partition Manager SMC handler.
824 ******************************************************************************/
825uint64_t spmc_smc_handler(uint32_t smc_fid,
826 bool secure_origin,
827 uint64_t x1,
828 uint64_t x2,
829 uint64_t x3,
830 uint64_t x4,
831 void *cookie,
832 void *handle,
833 uint64_t flags)
834{
835 switch (smc_fid) {
836
Marc Bonnici5eeacd52021-11-29 17:05:57 +0000837 case FFA_MSG_SEND_DIRECT_REQ_SMC32:
838 case FFA_MSG_SEND_DIRECT_REQ_SMC64:
839 return direct_req_smc_handler(smc_fid, secure_origin, x1, x2,
840 x3, x4, cookie, handle, flags);
841
842 case FFA_MSG_SEND_DIRECT_RESP_SMC32:
843 case FFA_MSG_SEND_DIRECT_RESP_SMC64:
844 return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2,
845 x3, x4, cookie, handle, flags);
846
Marc Bonnici8eb15202021-11-29 17:05:33 +0000847 case FFA_MSG_WAIT:
848 return msg_wait_handler(smc_fid, secure_origin, x1, x2, x3, x4,
849 cookie, handle, flags);
850
Marc Bonnicib4e99842021-12-10 09:21:56 +0000851 case FFA_ERROR:
852 return ffa_error_handler(smc_fid, secure_origin, x1, x2, x3, x4,
853 cookie, handle, flags);
854
Marc Bonnici8e1a7552021-12-01 17:57:04 +0000855 default:
856 WARN("Unsupported FF-A call 0x%08x.\n", smc_fid);
857 break;
858 }
859 return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED);
860}