xref: /rk3399_ARM-atf/bl32/tsp/tsp_main.c (revision 51faada71a219a8b94cd8d8e423f0f22e9da4d8f)
1 /*
2  * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * Redistributions of source code must retain the above copyright notice, this
8  * list of conditions and the following disclaimer.
9  *
10  * Redistributions in binary form must reproduce the above copyright notice,
11  * this list of conditions and the following disclaimer in the documentation
12  * and/or other materials provided with the distribution.
13  *
14  * Neither the name of ARM nor the names of its contributors may be used
15  * to endorse or promote products derived from this software without specific
16  * prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <arch_helpers.h>
32 #include <bl_common.h>
33 #include <debug.h>
34 #include <platform.h>
35 #include <platform_def.h>
36 #include <platform_tsp.h>
37 #include <spinlock.h>
38 #include <tsp.h>
39 #include "tsp_private.h"
40 
41 
42 /*******************************************************************************
43  * Lock to control access to the console
44  ******************************************************************************/
45 spinlock_t console_lock;
46 
47 /*******************************************************************************
48  * Per cpu data structure to populate parameters for an SMC in C code and use
49  * a pointer to this structure in assembler code to populate x0-x7
50  ******************************************************************************/
51 static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
52 
53 /*******************************************************************************
54  * Per cpu data structure to keep track of TSP activity
55  ******************************************************************************/
56 work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
57 
58 /*******************************************************************************
59  * The TSP memory footprint starts at address BL32_BASE and ends with the
60  * linker symbol __BL32_END__. Use these addresses to compute the TSP image
61  * size.
62  ******************************************************************************/
63 #define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__)
64 #define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE)
65 
66 static tsp_args_t *set_smc_args(uint64_t arg0,
67 			     uint64_t arg1,
68 			     uint64_t arg2,
69 			     uint64_t arg3,
70 			     uint64_t arg4,
71 			     uint64_t arg5,
72 			     uint64_t arg6,
73 			     uint64_t arg7)
74 {
75 	uint32_t linear_id;
76 	tsp_args_t *pcpu_smc_args;
77 
78 	/*
79 	 * Return to Secure Monitor by raising an SMC. The results of the
80 	 * service are passed as an arguments to the SMC
81 	 */
82 	linear_id = plat_my_core_pos();
83 	pcpu_smc_args = &tsp_smc_args[linear_id];
84 	write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
85 	write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
86 	write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
87 	write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
88 	write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
89 	write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
90 	write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
91 	write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
92 
93 	return pcpu_smc_args;
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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 %ld\n",
275 	     read_mpidr(), max_off_pwrlvl);
276 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend 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_suspend_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  ******************************************************************************/
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  ******************************************************************************/
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  ******************************************************************************/
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 	uint64_t results[2];
367 	uint64_t service_args[2];
368 	uint32_t linear_id = plat_my_core_pos();
369 
370 	/* Update this cpu's statistics */
371 	tsp_stats[linear_id].smc_count++;
372 	tsp_stats[linear_id].eret_count++;
373 
374 	INFO("TSP: cpu 0x%lx received %s smc 0x%lx\n", read_mpidr(),
375 		((func >> 31) & 1) == 1 ? "fast" : "standard",
376 		func);
377 	INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
378 		tsp_stats[linear_id].smc_count,
379 		tsp_stats[linear_id].eret_count);
380 
381 	/* Render secure services and obtain results here */
382 	results[0] = arg1;
383 	results[1] = arg2;
384 
385 	/*
386 	 * Request a service back from dispatcher/secure monitor. This call
387 	 * return and thereafter resume exectuion
388 	 */
389 	tsp_get_magic(service_args);
390 
391 	/* Determine the function to perform based on the function ID */
392 	switch (TSP_BARE_FID(func)) {
393 	case TSP_ADD:
394 		results[0] += service_args[0];
395 		results[1] += service_args[1];
396 		break;
397 	case TSP_SUB:
398 		results[0] -= service_args[0];
399 		results[1] -= service_args[1];
400 		break;
401 	case TSP_MUL:
402 		results[0] *= service_args[0];
403 		results[1] *= service_args[1];
404 		break;
405 	case TSP_DIV:
406 		results[0] /= service_args[0] ? service_args[0] : 1;
407 		results[1] /= service_args[1] ? service_args[1] : 1;
408 		break;
409 	default:
410 		break;
411 	}
412 
413 	return set_smc_args(func, 0,
414 			    results[0],
415 			    results[1],
416 			    0, 0, 0, 0);
417 }
418 
419 /*******************************************************************************
420  * TSP smc abort handler. This function is called when aborting a preemtped
421  * standard SMC request. It should cleanup all resources owned by the SMC
422  * handler such as locks or dynamically allocated memory so following SMC
423  * request are executed in a clean environment.
424  ******************************************************************************/
425 tsp_args_t *tsp_abort_smc_handler(uint64_t func,
426 				  uint64_t arg1,
427 				  uint64_t arg2,
428 				  uint64_t arg3,
429 				  uint64_t arg4,
430 				  uint64_t arg5,
431 				  uint64_t arg6,
432 				  uint64_t arg7)
433 {
434 	return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0);
435 }
436