1 /*
2  * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved.
3  * Copyright (c) 2021, NVIDIA Corporation. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
8 #include <assert.h>
9 #include <string.h>
10 
11 #include <arch.h>
12 #include <arch_helpers.h>
13 #include <context.h>
14 #include <common/debug.h>
15 #include <lib/el3_runtime/context_mgmt.h>
16 #include <lib/xlat_tables/xlat_tables_v2.h>
17 #include <lib/utils.h>
18 #include <platform_def.h>
19 #include <plat/common/common_def.h>
20 #include <plat/common/platform.h>
21 #include <services/ffa_svc.h>
22 
23 #include "spm_common.h"
24 #include "spm_shim_private.h"
25 #include "spmc.h"
26 
27 /*
28  * We need to choose one execution context from all those available for a S-EL0
29  * SP. This execution context will be used subsequently irrespective of which
30  * physical CPU the SP runs on. The index of this context is chosen during setup
31  * on the primary cpu and stored in this variable for subsequent usage.
32  */
33 static unsigned int sel0_sp_ec_index = 0;
34 
get_ec_index(sp_desc_t * sp)35 unsigned int get_ec_index(sp_desc_t *sp)
36 {
37 	return (sp->runtime_el == EL0) ? sel0_sp_ec_index : plat_my_core_pos();
38 }
39 
40 /* Setup context of a EL0 MM Secure Partition */
spmc_el0_sp_setup(sp_desc_t * sp,entry_point_info_t * ep_info)41 void spmc_el0_sp_setup(sp_desc_t *sp, entry_point_info_t *ep_info)
42 {
43 	cpu_context_t *ctx;
44 
45 	/*
46 	 * Choose the linear of the primary core as the index of the S-EL0 SP
47 	 * execution context.
48 	 */
49 	sel0_sp_ec_index = plat_my_core_pos();
50 	ctx = &sp->ec[sel0_sp_ec_index].cpu_ctx;
51 
52 	init_xlat_tables_ctx(sp->xlat_ctx_handle);
53 
54 	/*
55 	 * MMU-related registers
56 	 * ---------------------
57 	 */
58 	xlat_ctx_t *xlat_ctx = sp->xlat_ctx_handle;
59 
60 	uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX];
61 
62 	setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table,
63 		      xlat_ctx->pa_max_address, xlat_ctx->va_max_address,
64 		      EL1_EL0_REGIME);
65 
66 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1,
67 		      mmu_cfg_params[MMU_CFG_MAIR]);
68 
69 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1,
70 		      mmu_cfg_params[MMU_CFG_TCR]);
71 
72 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1,
73 		      mmu_cfg_params[MMU_CFG_TTBR0]);
74 
75 	/* Setup SCTLR_EL1 */
76 	u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1);
77 
78 	sctlr_el1 |=
79 		/*SCTLR_EL1_RES1 |*/
80 		/* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */
81 		SCTLR_UCI_BIT							|
82 		/* RW regions at xlat regime EL1&0 are forced to be XN. */
83 		SCTLR_WXN_BIT							|
84 		/* Don't trap to EL1 execution of WFI or WFE at EL0. */
85 		SCTLR_NTWI_BIT | SCTLR_NTWE_BIT					|
86 		/* Don't trap to EL1 accesses to CTR_EL0 from EL0. */
87 		SCTLR_UCT_BIT							|
88 		/* Don't trap to EL1 execution of DZ ZVA at EL0. */
89 		SCTLR_DZE_BIT							|
90 		/* Enable SP Alignment check for EL0 */
91 		SCTLR_SA0_BIT							|
92 		/* Don't change PSTATE.PAN on taking an exception to EL1 */
93 		SCTLR_SPAN_BIT							|
94 		/* Allow cacheable data and instr. accesses to normal memory. */
95 		SCTLR_C_BIT | SCTLR_I_BIT					|
96 		/* Enable MMU. */
97 		SCTLR_M_BIT
98 	;
99 
100 	sctlr_el1 &= ~(
101 		/* Explicit data accesses at EL0 are little-endian. */
102 		SCTLR_E0E_BIT							|
103 		/*
104 		 * Alignment fault checking disabled when at EL1 and EL0 as
105 		 * the UEFI spec permits unaligned accesses.
106 		 */
107 		SCTLR_A_BIT							|
108 		/* Accesses to DAIF from EL0 are trapped to EL1. */
109 		SCTLR_UMA_BIT
110 	);
111 
112 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1);
113 
114 	/*
115 	 * Setup other system registers
116 	 * ----------------------------
117 	 */
118 
119 	/* Shim Exception Vector Base Address */
120 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1,
121 			SPM_SHIM_EXCEPTIONS_PTR);
122 
123 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1,
124 		      EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT);
125 
126 	/*
127 	 * FPEN: Allow the Secure Partition to access FP/SIMD registers.
128 	 * Note that SPM will not do any saving/restoring of these registers on
129 	 * behalf of the SP. This falls under the SP's responsibility.
130 	 * TTA: Enable access to trace registers.
131 	 * ZEN (v8.2): Trap SVE instructions and access to SVE registers.
132 	 */
133 	write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1,
134 			CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE));
135 
136 	sp->xlat_ctx_handle->xlat_regime =
137 		EL1_EL0_REGIME;
138 
139 	/* This region contains the exception vectors used at S-EL1. */
140 	mmap_region_t sel1_exception_vectors =
141 		MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START,
142 				SPM_SHIM_EXCEPTIONS_SIZE,
143 				MT_CODE | MT_SECURE | MT_PRIVILEGED);
144 	mmap_add_region_ctx(sp->xlat_ctx_handle,
145 			    &sel1_exception_vectors);
146 
147 	/*
148 	 * Save the stack base in SP_EL0 so that there is a C runtime upon the
149 	 * first ERET into the StMM SP.
150 	 */
151 	write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0,
152 		      sp->sp_stack_base + sp->sp_stack_size);
153 
154 }
155 
156 /* SEL1 partition specific initialisation. */
spmc_el1_sp_setup(sp_desc_t * sp,entry_point_info_t * ep_info)157 void spmc_el1_sp_setup(sp_desc_t *sp, entry_point_info_t *ep_info)
158 {
159 	/* Sanity check input arguments */
160 	assert(NULL != sp);
161 	assert(NULL != ep_info);
162 
163 	/*
164 	 * Lets just zero the general purpose registers for now. This would be a
165 	 * good time to let the platform enforce its own boot protocol.
166 	 */
167 	zeromem(&ep_info->args, sizeof(ep_info->args));
168 
169 	/*
170 	 * Check whether setup is being performed for the primary or a secondary
171 	 * execution context. In the latter case, indicate to the SP that this
172 	 * is a warm boot.
173 	 * TODO: This check would need to be reworked if the same entry point is
174 	 * used for both primary and secondary initialisation.
175 	 */
176 	if (sp->secondary_ep) {
177 		/*
178 		 * Sanity check that the secondary entry point is still what was
179 		 * originally set.
180 		 */
181 		assert (sp->secondary_ep == ep_info->pc);
182 
183 		write_ctx_reg(get_gpregs_ctx(&sp->ec[get_ec_index(sp)].cpu_ctx),
184 			      CTX_GPREG_X0,
185 			      FFA_WB_TYPE_S2RAM);
186 	}
187 }
188 
189 /* Common initialisation for all SPs. */
spmc_sp_common_setup(sp_desc_t * sp,entry_point_info_t * ep_info)190 void spmc_sp_common_setup(sp_desc_t *sp, entry_point_info_t *ep_info)
191 {
192 	cpu_context_t *cpu_ctx;
193 
194 	/* Assign FFA Partition ID if not already assigned */
195 	if (sp->sp_id == INV_SP_ID)
196 		sp->sp_id = FFA_SP_ID_BASE + ACTIVE_SP_DESC_INDEX;
197 
198 	/*
199 	 * The initialisation of the SPSR in the ep_info should ideally be done
200 	 * in the EL specific initialisation routines above. However,
201 	 * cm_context_setup() needs this information to initialise system
202 	 * registers correctly. So, lets do this here.
203 	 */
204 	if (sp->runtime_el == EL0)
205 		/* Setup Secure Partition SPSR for S-EL0 SP*/
206 		ep_info->spsr = SPSR_64(MODE_EL0, MODE_SP_EL0,
207 					DISABLE_ALL_EXCEPTIONS);
208 	else
209 		/* Setup Secure Partition SPSR for S-EL1 SP */
210 		ep_info->spsr =	SPSR_64(MODE_EL1, MODE_SP_ELX,
211 					DISABLE_ALL_EXCEPTIONS);
212 
213 	/*
214 	 * Initialise the SP context based upon the entrypoint information
215 	 * collected so far. We are assuming that the index of the execution
216 	 * context used for both S-EL0 and S-EL1 SPs is the linear index of the
217 	 * primary cpu. This index was saved in spmc_el0_sp_setup() as well.
218 	 */
219 	cpu_ctx = &sp->ec[plat_my_core_pos()].cpu_ctx;
220 	cm_setup_context(cpu_ctx, ep_info);
221 }
222