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