Merge pull request #925 from dp-arm/dp/spdx
[project/bcm63xx/atf.git] / bl32 / tsp / tsp_main.c
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
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 ******************************************************************************/
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 }