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