2 * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved.
4 * SPDX-License-Identifier: BSD-3-Clause
7 #include <arch_helpers.h>
11 #include <platform_def.h>
12 #include <platform_tsp.h>
15 #include "tsp_private.h"
18 /*******************************************************************************
19 * Lock to control access to the console
20 ******************************************************************************/
21 spinlock_t console_lock
;
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
];
29 /*******************************************************************************
30 * Per cpu data structure to keep track of TSP activity
31 ******************************************************************************/
32 work_statistics_t tsp_stats
[PLATFORM_CORE_COUNT
];
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
38 ******************************************************************************/
39 #define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__)
40 #define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE)
42 static tsp_args_t
*set_smc_args(uint64_t arg0
,
52 tsp_args_t
*pcpu_smc_args
;
55 * Return to Secure Monitor by raising an SMC. The results of the
56 * service are passed as an arguments to the SMC
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
);
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)
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
);
84 uint32_t linear_id
= plat_my_core_pos();
86 /* Initialize the platform */
89 /* Initialize secure/applications state here */
90 tsp_generic_timer_start();
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
++;
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",
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
);
106 return (uint64_t) &tsp_vector_table
;
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)
116 uint32_t linear_id
= plat_my_core_pos();
118 /* Initialize secure/applications state here */
119 tsp_generic_timer_start();
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
++;
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",
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
);
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);
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
,
153 uint32_t linear_id
= plat_my_core_pos();
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.
160 tsp_generic_timer_stop();
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
++;
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",
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
);
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);
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
,
196 uint32_t linear_id
= plat_my_core_pos();
199 * Save the time context and disable it to prevent the secure timer
200 * interrupt from interfering with wakeup from the suspend state.
202 tsp_generic_timer_save();
203 tsp_generic_timer_stop();
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
++;
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",
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
);
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);
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
,
238 uint32_t linear_id
= plat_my_core_pos();
240 /* Restore the generic timer context */
241 tsp_generic_timer_restore();
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
++;
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",
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
);
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);
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
,
276 uint32_t linear_id
= plat_my_core_pos();
278 /* Update this cpu's statistics */
279 tsp_stats
[linear_id
].smc_count
++;
280 tsp_stats
[linear_id
].eret_count
++;
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
);
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);
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
,
308 uint32_t linear_id
= plat_my_core_pos();
310 /* Update this cpu's statistics */
311 tsp_stats
[linear_id
].smc_count
++;
312 tsp_stats
[linear_id
].eret_count
++;
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
);
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);
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
,
343 uint64_t service_args
[2];
344 uint32_t linear_id
= plat_my_core_pos();
346 /* Update this cpu's statistics */
347 tsp_stats
[linear_id
].smc_count
++;
348 tsp_stats
[linear_id
].eret_count
++;
350 INFO("TSP: cpu 0x%lx received %s smc 0x%lx\n", read_mpidr(),
351 ((func
>> 31) & 1) == 1 ? "fast" : "yielding",
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
);
357 /* Render secure services and obtain results here */
362 * Request a service back from dispatcher/secure monitor. This call
363 * return and thereafter resume exectuion
365 tsp_get_magic(service_args
);
367 /* Determine the function to perform based on the function ID */
368 switch (TSP_BARE_FID(func
)) {
370 results
[0] += service_args
[0];
371 results
[1] += service_args
[1];
374 results
[0] -= service_args
[0];
375 results
[1] -= service_args
[1];
378 results
[0] *= service_args
[0];
379 results
[1] *= service_args
[1];
382 results
[0] /= service_args
[0] ? service_args
[0] : 1;
383 results
[1] /= service_args
[1] ? service_args
[1] : 1;
389 return set_smc_args(func
, 0,
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
,
410 return set_smc_args(TSP_ABORT_DONE
, 0, 0, 0, 0, 0, 0, 0);