xref: /rk3399_ARM-atf/services/std_svc/spm/el3_spmc/spmc_setup.c (revision 9bc52d330fccb0e4df22006630350a42457d3306)
1 /*
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 <string.h>
9 
10 #include <arch.h>
11 #include <arch_helpers.h>
12 #include <common/debug.h>
13 #include <context.h>
14 #include <lib/el3_runtime/context_mgmt.h>
15 #include <lib/utils.h>
16 #include <lib/xlat_tables/xlat_tables_v2.h>
17 #include <plat/common/common_def.h>
18 #include <plat/common/platform.h>
19 #include <services/ffa_svc.h>
20 #include "spm_common.h"
21 #include "spmc.h"
22 
23 #include <platform_def.h>
24 
25 /*
26  * We are assuming that the index of the execution
27  * context used is the linear index of the current physical cpu.
28  */
29 unsigned int get_ec_index(struct secure_partition_desc *sp)
30 {
31 	return plat_my_core_pos();
32 }
33 
34 /* S-EL1 partition specific initialisation. */
35 void spmc_el1_sp_setup(struct secure_partition_desc *sp,
36 		       entry_point_info_t *ep_info)
37 {
38 	/* Sanity check input arguments. */
39 	assert(sp != NULL);
40 	assert(ep_info != NULL);
41 
42 	/* Initialise the SPSR for S-EL1 SPs. */
43 	ep_info->spsr =	SPSR_64(MODE_EL1, MODE_SP_ELX,
44 				DISABLE_ALL_EXCEPTIONS);
45 
46 	/*
47 	 * TF-A Implementation defined behaviour to provide the linear
48 	 * core ID in the x4 register.
49 	 */
50 	ep_info->args.arg4 = (uintptr_t) plat_my_core_pos();
51 
52 	/*
53 	 * Check whether setup is being performed for the primary or a secondary
54 	 * execution context. In the latter case, indicate to the SP that this
55 	 * is a warm boot.
56 	 * TODO: This check would need to be reworked if the same entry point is
57 	 * used for both primary and secondary initialisation.
58 	 */
59 	if (sp->secondary_ep != 0U) {
60 		/*
61 		 * Sanity check that the secondary entry point is still what was
62 		 * originally set.
63 		 */
64 		assert(sp->secondary_ep == ep_info->pc);
65 		ep_info->args.arg0 = FFA_WB_TYPE_S2RAM;
66 	}
67 }
68 
69 /* Common initialisation for all SPs. */
70 void spmc_sp_common_setup(struct secure_partition_desc *sp,
71 			  entry_point_info_t *ep_info)
72 {
73 	uint16_t sp_id;
74 
75 	/* Assign FF-A Partition ID if not already assigned. */
76 	if (sp->sp_id == INV_SP_ID) {
77 		sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
78 		/*
79 		 * Ensure we don't clash with previously assigned partition
80 		 * IDs.
81 		 */
82 		while (!is_ffa_secure_id_valid(sp_id)) {
83 			sp_id++;
84 
85 			if (sp_id == FFA_SWD_ID_LIMIT) {
86 				ERROR("Unable to determine valid SP ID.\n");
87 				panic();
88 			}
89 		}
90 		sp->sp_id = sp_id;
91 	}
92 
93 	/*
94 	 * We currently only support S-EL1 partitions so ensure this is the
95 	 * case.
96 	 */
97 	assert(sp->runtime_el == S_EL1);
98 
99 	/*
100 	 * Clear the general purpose registers. These should be populated as
101 	 * required.
102 	 */
103 	zeromem(&ep_info->args, sizeof(ep_info->args));
104 }
105 
106 /*
107  * Initialise the SP context now we have populated the common and EL specific
108  * entrypoint information.
109  */
110 void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
111 			      entry_point_info_t *ep_info)
112 {
113 	cpu_context_t *cpu_ctx;
114 
115 	cpu_ctx = &(spmc_get_sp_ec(sp)->cpu_ctx);
116 	print_entry_point_info(ep_info);
117 	cm_setup_context(cpu_ctx, ep_info);
118 }
119