• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 
9 #include <arch_features.h>
10 #include <arch_helpers.h>
11 #include <bl32/tsp/tsp.h>
12 #include <common/bl_common.h>
13 #include <common/debug.h>
14 #include <lib/spinlock.h>
15 #include <plat/common/platform.h>
16 #include <platform_def.h>
17 #include <platform_tsp.h>
18 
19 #include "tsp_private.h"
20 
21 
22 /*******************************************************************************
23  * Lock to control access to the console
24  ******************************************************************************/
25 spinlock_t console_lock;
26 
27 /*******************************************************************************
28  * Per cpu data structure to populate parameters for an SMC in C code and use
29  * a pointer to this structure in assembler code to populate x0-x7
30  ******************************************************************************/
31 static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
32 
33 /*******************************************************************************
34  * Per cpu data structure to keep track of TSP activity
35  ******************************************************************************/
36 work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
37 
38 /*******************************************************************************
39  * The TSP memory footprint starts at address BL32_BASE and ends with the
40  * linker symbol __BL32_END__. Use these addresses to compute the TSP image
41  * size.
42  ******************************************************************************/
43 #define BL32_TOTAL_LIMIT BL32_END
44 #define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE)
45 
set_smc_args(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)46 static tsp_args_t *set_smc_args(uint64_t arg0,
47 			     uint64_t arg1,
48 			     uint64_t arg2,
49 			     uint64_t arg3,
50 			     uint64_t arg4,
51 			     uint64_t arg5,
52 			     uint64_t arg6,
53 			     uint64_t arg7)
54 {
55 	uint32_t linear_id;
56 	tsp_args_t *pcpu_smc_args;
57 
58 	/*
59 	 * Return to Secure Monitor by raising an SMC. The results of the
60 	 * service are passed as an arguments to the SMC
61 	 */
62 	linear_id = plat_my_core_pos();
63 	pcpu_smc_args = &tsp_smc_args[linear_id];
64 	write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
65 	write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
66 	write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
67 	write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
68 	write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
69 	write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
70 	write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
71 	write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
72 
73 	return pcpu_smc_args;
74 }
75 
76 /*******************************************************************************
77  * Setup function for TSP.
78  ******************************************************************************/
tsp_setup(void)79 void tsp_setup(void)
80 {
81 	/* Perform early platform-specific setup */
82 	tsp_early_platform_setup();
83 
84 	/* Perform late platform-specific setup */
85 	tsp_plat_arch_setup();
86 
87 #if ENABLE_PAUTH
88 	/*
89 	 * Assert that the ARMv8.3-PAuth registers are present or an access
90 	 * fault will be triggered when they are being saved or restored.
91 	 */
92 	assert(is_armv8_3_pauth_present());
93 #endif /* ENABLE_PAUTH */
94 }
95 
96 /*******************************************************************************
97  * TSP main entry point where it gets the opportunity to initialize its secure
98  * state/applications. Once the state is initialized, it must return to the
99  * SPD with a pointer to the 'tsp_vector_table' jump table.
100  ******************************************************************************/
tsp_main(void)101 uint64_t tsp_main(void)
102 {
103 	NOTICE("TSP: %s\n", version_string);
104 	NOTICE("TSP: %s\n", build_message);
105 	INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
106 	INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
107 
108 	uint32_t linear_id = plat_my_core_pos();
109 
110 	/* Initialize the platform */
111 	tsp_platform_setup();
112 
113 	/* Initialize secure/applications state here */
114 	tsp_generic_timer_start();
115 
116 	/* Update this cpu's statistics */
117 	tsp_stats[linear_id].smc_count++;
118 	tsp_stats[linear_id].eret_count++;
119 	tsp_stats[linear_id].cpu_on_count++;
120 
121 #if LOG_LEVEL >= LOG_LEVEL_INFO
122 	spin_lock(&console_lock);
123 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
124 	     read_mpidr(),
125 	     tsp_stats[linear_id].smc_count,
126 	     tsp_stats[linear_id].eret_count,
127 	     tsp_stats[linear_id].cpu_on_count);
128 	spin_unlock(&console_lock);
129 #endif
130 	return (uint64_t) &tsp_vector_table;
131 }
132 
133 /*******************************************************************************
134  * This function performs any remaining book keeping in the test secure payload
135  * after this cpu's architectural state has been setup in response to an earlier
136  * psci cpu_on request.
137  ******************************************************************************/
tsp_cpu_on_main(void)138 tsp_args_t *tsp_cpu_on_main(void)
139 {
140 	uint32_t linear_id = plat_my_core_pos();
141 
142 	/* Initialize secure/applications state here */
143 	tsp_generic_timer_start();
144 
145 	/* Update this cpu's statistics */
146 	tsp_stats[linear_id].smc_count++;
147 	tsp_stats[linear_id].eret_count++;
148 	tsp_stats[linear_id].cpu_on_count++;
149 
150 #if LOG_LEVEL >= LOG_LEVEL_INFO
151 	spin_lock(&console_lock);
152 	INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
153 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
154 		read_mpidr(),
155 		tsp_stats[linear_id].smc_count,
156 		tsp_stats[linear_id].eret_count,
157 		tsp_stats[linear_id].cpu_on_count);
158 	spin_unlock(&console_lock);
159 #endif
160 	/* Indicate to the SPD that we have completed turned ourselves on */
161 	return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
162 }
163 
164 /*******************************************************************************
165  * This function performs any remaining book keeping in the test secure payload
166  * before this cpu is turned off in response to a psci cpu_off request.
167  ******************************************************************************/
tsp_cpu_off_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)168 tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
169 			   uint64_t arg1,
170 			   uint64_t arg2,
171 			   uint64_t arg3,
172 			   uint64_t arg4,
173 			   uint64_t arg5,
174 			   uint64_t arg6,
175 			   uint64_t arg7)
176 {
177 	uint32_t linear_id = plat_my_core_pos();
178 
179 	/*
180 	 * This cpu is being turned off, so disable the timer to prevent the
181 	 * secure timer interrupt from interfering with power down. A pending
182 	 * interrupt will be lost but we do not care as we are turning off.
183 	 */
184 	tsp_generic_timer_stop();
185 
186 	/* Update this cpu's statistics */
187 	tsp_stats[linear_id].smc_count++;
188 	tsp_stats[linear_id].eret_count++;
189 	tsp_stats[linear_id].cpu_off_count++;
190 
191 #if LOG_LEVEL >= LOG_LEVEL_INFO
192 	spin_lock(&console_lock);
193 	INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
194 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
195 		read_mpidr(),
196 		tsp_stats[linear_id].smc_count,
197 		tsp_stats[linear_id].eret_count,
198 		tsp_stats[linear_id].cpu_off_count);
199 	spin_unlock(&console_lock);
200 #endif
201 
202 	/* Indicate to the SPD that we have completed this request */
203 	return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
204 }
205 
206 /*******************************************************************************
207  * This function performs any book keeping in the test secure payload before
208  * this cpu's architectural state is saved in response to an earlier psci
209  * cpu_suspend request.
210  ******************************************************************************/
tsp_cpu_suspend_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)211 tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0,
212 			       uint64_t arg1,
213 			       uint64_t arg2,
214 			       uint64_t arg3,
215 			       uint64_t arg4,
216 			       uint64_t arg5,
217 			       uint64_t arg6,
218 			       uint64_t arg7)
219 {
220 	uint32_t linear_id = plat_my_core_pos();
221 
222 	/*
223 	 * Save the time context and disable it to prevent the secure timer
224 	 * interrupt from interfering with wakeup from the suspend state.
225 	 */
226 	tsp_generic_timer_save();
227 	tsp_generic_timer_stop();
228 
229 	/* Update this cpu's statistics */
230 	tsp_stats[linear_id].smc_count++;
231 	tsp_stats[linear_id].eret_count++;
232 	tsp_stats[linear_id].cpu_suspend_count++;
233 
234 #if LOG_LEVEL >= LOG_LEVEL_INFO
235 	spin_lock(&console_lock);
236 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
237 		read_mpidr(),
238 		tsp_stats[linear_id].smc_count,
239 		tsp_stats[linear_id].eret_count,
240 		tsp_stats[linear_id].cpu_suspend_count);
241 	spin_unlock(&console_lock);
242 #endif
243 
244 	/* Indicate to the SPD that we have completed this request */
245 	return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
246 }
247 
248 /*******************************************************************************
249  * This function performs any book keeping in the test secure payload after this
250  * cpu's architectural state has been restored after wakeup from an earlier psci
251  * cpu_suspend request.
252  ******************************************************************************/
tsp_cpu_resume_main(uint64_t max_off_pwrlvl,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)253 tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
254 			      uint64_t arg1,
255 			      uint64_t arg2,
256 			      uint64_t arg3,
257 			      uint64_t arg4,
258 			      uint64_t arg5,
259 			      uint64_t arg6,
260 			      uint64_t arg7)
261 {
262 	uint32_t linear_id = plat_my_core_pos();
263 
264 	/* Restore the generic timer context */
265 	tsp_generic_timer_restore();
266 
267 	/* Update this cpu's statistics */
268 	tsp_stats[linear_id].smc_count++;
269 	tsp_stats[linear_id].eret_count++;
270 	tsp_stats[linear_id].cpu_resume_count++;
271 
272 #if LOG_LEVEL >= LOG_LEVEL_INFO
273 	spin_lock(&console_lock);
274 	INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n",
275 	     read_mpidr(), max_off_pwrlvl);
276 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
277 		read_mpidr(),
278 		tsp_stats[linear_id].smc_count,
279 		tsp_stats[linear_id].eret_count,
280 		tsp_stats[linear_id].cpu_resume_count);
281 	spin_unlock(&console_lock);
282 #endif
283 	/* Indicate to the SPD that we have completed this request */
284 	return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
285 }
286 
287 /*******************************************************************************
288  * This function performs any remaining bookkeeping in the test secure payload
289  * before the system is switched off (in response to a psci SYSTEM_OFF request)
290  ******************************************************************************/
tsp_system_off_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)291 tsp_args_t *tsp_system_off_main(uint64_t arg0,
292 				uint64_t arg1,
293 				uint64_t arg2,
294 				uint64_t arg3,
295 				uint64_t arg4,
296 				uint64_t arg5,
297 				uint64_t arg6,
298 				uint64_t arg7)
299 {
300 	uint32_t linear_id = plat_my_core_pos();
301 
302 	/* Update this cpu's statistics */
303 	tsp_stats[linear_id].smc_count++;
304 	tsp_stats[linear_id].eret_count++;
305 
306 #if LOG_LEVEL >= LOG_LEVEL_INFO
307 	spin_lock(&console_lock);
308 	INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr());
309 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
310 	     tsp_stats[linear_id].smc_count,
311 	     tsp_stats[linear_id].eret_count);
312 	spin_unlock(&console_lock);
313 #endif
314 
315 	/* Indicate to the SPD that we have completed this request */
316 	return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
317 }
318 
319 /*******************************************************************************
320  * This function performs any remaining bookkeeping in the test secure payload
321  * before the system is reset (in response to a psci SYSTEM_RESET request)
322  ******************************************************************************/
tsp_system_reset_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)323 tsp_args_t *tsp_system_reset_main(uint64_t arg0,
324 				uint64_t arg1,
325 				uint64_t arg2,
326 				uint64_t arg3,
327 				uint64_t arg4,
328 				uint64_t arg5,
329 				uint64_t arg6,
330 				uint64_t arg7)
331 {
332 	uint32_t linear_id = plat_my_core_pos();
333 
334 	/* Update this cpu's statistics */
335 	tsp_stats[linear_id].smc_count++;
336 	tsp_stats[linear_id].eret_count++;
337 
338 #if LOG_LEVEL >= LOG_LEVEL_INFO
339 	spin_lock(&console_lock);
340 	INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr());
341 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(),
342 	     tsp_stats[linear_id].smc_count,
343 	     tsp_stats[linear_id].eret_count);
344 	spin_unlock(&console_lock);
345 #endif
346 
347 	/* Indicate to the SPD that we have completed this request */
348 	return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0);
349 }
350 
351 /*******************************************************************************
352  * TSP fast smc handler. The secure monitor jumps to this function by
353  * doing the ERET after populating X0-X7 registers. The arguments are received
354  * in the function arguments in order. Once the service is rendered, this
355  * function returns to Secure Monitor by raising SMC.
356  ******************************************************************************/
tsp_smc_handler(uint64_t func,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)357 tsp_args_t *tsp_smc_handler(uint64_t func,
358 			       uint64_t arg1,
359 			       uint64_t arg2,
360 			       uint64_t arg3,
361 			       uint64_t arg4,
362 			       uint64_t arg5,
363 			       uint64_t arg6,
364 			       uint64_t arg7)
365 {
366 	uint128_t service_args;
367 	uint64_t service_arg0;
368 	uint64_t service_arg1;
369 	uint64_t results[2];
370 	uint32_t linear_id = plat_my_core_pos();
371 
372 	/* Update this cpu's statistics */
373 	tsp_stats[linear_id].smc_count++;
374 	tsp_stats[linear_id].eret_count++;
375 
376 #if LOG_LEVEL >= LOG_LEVEL_INFO
377 	spin_lock(&console_lock);
378 	INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(),
379 		((func >> 31) & 1) == 1 ? "fast" : "yielding",
380 		func);
381 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
382 		tsp_stats[linear_id].smc_count,
383 		tsp_stats[linear_id].eret_count);
384 	spin_unlock(&console_lock);
385 #endif
386 
387 	/* Render secure services and obtain results here */
388 	results[0] = arg1;
389 	results[1] = arg2;
390 
391 	/*
392 	 * Request a service back from dispatcher/secure monitor.
393 	 * This call returns and thereafter resumes execution.
394 	 */
395 	service_args = tsp_get_magic();
396 	service_arg0 = (uint64_t)service_args;
397 	service_arg1 = (uint64_t)(service_args >> 64U);
398 
399 #if CTX_INCLUDE_MTE_REGS
400 	/*
401 	 * Write a dummy value to an MTE register, to simulate usage in the
402 	 * secure world
403 	 */
404 	write_gcr_el1(0x99);
405 #endif
406 
407 	/* Determine the function to perform based on the function ID */
408 	switch (TSP_BARE_FID(func)) {
409 	case TSP_ADD:
410 		results[0] += service_arg0;
411 		results[1] += service_arg1;
412 		break;
413 	case TSP_SUB:
414 		results[0] -= service_arg0;
415 		results[1] -= service_arg1;
416 		break;
417 	case TSP_MUL:
418 		results[0] *= service_arg0;
419 		results[1] *= service_arg1;
420 		break;
421 	case TSP_DIV:
422 		results[0] /= service_arg0 ? service_arg0 : 1;
423 		results[1] /= service_arg1 ? service_arg1 : 1;
424 		break;
425 	default:
426 		break;
427 	}
428 
429 	return set_smc_args(func, 0,
430 			    results[0],
431 			    results[1],
432 			    0, 0, 0, 0);
433 }
434 
435 /*******************************************************************************
436  * TSP smc abort handler. This function is called when aborting a preempted
437  * yielding SMC request. It should cleanup all resources owned by the SMC
438  * handler such as locks or dynamically allocated memory so following SMC
439  * request are executed in a clean environment.
440  ******************************************************************************/
tsp_abort_smc_handler(uint64_t func,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)441 tsp_args_t *tsp_abort_smc_handler(uint64_t func,
442 				  uint64_t arg1,
443 				  uint64_t arg2,
444 				  uint64_t arg3,
445 				  uint64_t arg4,
446 				  uint64_t arg5,
447 				  uint64_t arg6,
448 				  uint64_t arg7)
449 {
450 	return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0);
451 }
452