blob: 982bab2fb4a2afadd49e47f0a0175e779b482684 [file] [log] [blame]
Achin Gupta7c88f3f2014-02-18 18:09:12 +00001/*
2 * Copyright (c) 2013-2014, 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
Achin Gupta7c88f3f2014-02-18 18:09:12 +000031#include <arch_helpers.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010032#include <bl_common.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000033#include <debug.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010034#include <platform.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010035#include <platform_def.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000036#include <spinlock.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010037#include <tsp.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000038
39/*******************************************************************************
Vikram Kanigirid8c9d262014-05-16 18:48:12 +010040 * Declarations of linker defined symbols which will help us find the layout
41 * of trusted SRAM
42 ******************************************************************************/
43extern unsigned long __RO_START__;
44extern unsigned long __COHERENT_RAM_END__;
45
46/*******************************************************************************
Achin Gupta7c88f3f2014-02-18 18:09:12 +000047 * Lock to control access to the console
48 ******************************************************************************/
49spinlock_t console_lock;
50
51/*******************************************************************************
52 * Per cpu data structure to populate parameters for an SMC in C code and use
53 * a pointer to this structure in assembler code to populate x0-x7
54 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010055static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000056
57/*******************************************************************************
58 * Per cpu data structure to keep track of TSP activity
59 ******************************************************************************/
Achin Gupta76717892014-05-09 11:42:56 +010060work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000061
62/*******************************************************************************
Vikram Kanigirid8c9d262014-05-16 18:48:12 +010063 * The BL32 memory footprint starts with an RO sections and ends
64 * with a section for coherent RAM. Use it to find the memory size
65 ******************************************************************************/
66#define BL32_TOTAL_BASE (unsigned long)(&__RO_START__)
67
68#define BL32_TOTAL_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
69
Dan Handleye2712bc2014-04-10 15:37:22 +010070static tsp_args_t *set_smc_args(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +000071 uint64_t arg1,
72 uint64_t arg2,
73 uint64_t arg3,
74 uint64_t arg4,
75 uint64_t arg5,
76 uint64_t arg6,
77 uint64_t arg7)
78{
79 uint64_t mpidr = read_mpidr();
80 uint32_t linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +010081 tsp_args_t *pcpu_smc_args;
Achin Gupta7c88f3f2014-02-18 18:09:12 +000082
83 /*
84 * Return to Secure Monitor by raising an SMC. The results of the
85 * service are passed as an arguments to the SMC
86 */
87 linear_id = platform_get_core_pos(mpidr);
88 pcpu_smc_args = &tsp_smc_args[linear_id];
89 write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
90 write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
91 write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
92 write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
93 write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
94 write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
95 write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
96 write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
97
98 return pcpu_smc_args;
99}
100
101/*******************************************************************************
102 * TSP main entry point where it gets the opportunity to initialize its secure
103 * state/applications. Once the state is initialized, it must return to the
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100104 * SPD with a pointer to the 'tsp_vector_table' jump table.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000105 ******************************************************************************/
106uint64_t tsp_main(void)
107{
Dan Handley91b624e2014-07-29 17:14:00 +0100108 NOTICE("TSP: %s\n", version_string);
109 NOTICE("TSP: %s\n", build_message);
110 INFO("TSP: Total memory base : 0x%x\n", (unsigned long)BL32_TOTAL_BASE);
111 INFO("TSP: Total memory size : 0x%x bytes\n",
112 (unsigned long)(BL32_TOTAL_LIMIT - BL32_TOTAL_BASE));
113
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000114 uint64_t mpidr = read_mpidr();
115 uint32_t linear_id = platform_get_core_pos(mpidr);
116
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000117 /* Initialize the platform */
118 bl32_platform_setup();
119
120 /* Initialize secure/applications state here */
Achin Guptabbc33f22014-05-09 13:33:42 +0100121 tsp_generic_timer_start();
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000122
123 /* Update this cpu's statistics */
124 tsp_stats[linear_id].smc_count++;
125 tsp_stats[linear_id].eret_count++;
126 tsp_stats[linear_id].cpu_on_count++;
127
Dan Handley91b624e2014-07-29 17:14:00 +0100128#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000129 spin_lock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100130 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000131 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);
Dan Handley91b624e2014-07-29 17:14:00 +0100135#endif
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100136 return (uint64_t) &tsp_vector_table;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000137}
138
139/*******************************************************************************
140 * This function performs any remaining book keeping in the test secure payload
141 * after this cpu's architectural state has been setup in response to an earlier
142 * psci cpu_on request.
143 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100144tsp_args_t *tsp_cpu_on_main(void)
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000145{
146 uint64_t mpidr = read_mpidr();
147 uint32_t linear_id = platform_get_core_pos(mpidr);
148
Achin Guptabbc33f22014-05-09 13:33:42 +0100149 /* Initialize secure/applications state here */
150 tsp_generic_timer_start();
151
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000152 /* Update this cpu's statistics */
153 tsp_stats[linear_id].smc_count++;
154 tsp_stats[linear_id].eret_count++;
155 tsp_stats[linear_id].cpu_on_count++;
156
Dan Handley91b624e2014-07-29 17:14:00 +0100157#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000158 spin_lock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100159 INFO("TSP: cpu 0x%x turned on\n", mpidr);
160 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
161 tsp_stats[linear_id].smc_count,
162 tsp_stats[linear_id].eret_count,
163 tsp_stats[linear_id].cpu_on_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000164 spin_unlock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100165#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000166 /* Indicate to the SPD that we have completed turned ourselves on */
167 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
168}
169
170/*******************************************************************************
171 * This function performs any remaining book keeping in the test secure payload
172 * before this cpu is turned off in response to a psci cpu_off request.
173 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100174tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000175 uint64_t arg1,
176 uint64_t arg2,
177 uint64_t arg3,
178 uint64_t arg4,
179 uint64_t arg5,
180 uint64_t arg6,
181 uint64_t arg7)
182{
183 uint64_t mpidr = read_mpidr();
184 uint32_t linear_id = platform_get_core_pos(mpidr);
185
Achin Guptabbc33f22014-05-09 13:33:42 +0100186 /*
187 * This cpu is being turned off, so disable the timer to prevent the
188 * secure timer interrupt from interfering with power down. A pending
189 * interrupt will be lost but we do not care as we are turning off.
190 */
191 tsp_generic_timer_stop();
192
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000193 /* Update this cpu's statistics */
194 tsp_stats[linear_id].smc_count++;
195 tsp_stats[linear_id].eret_count++;
196 tsp_stats[linear_id].cpu_off_count++;
197
Dan Handley91b624e2014-07-29 17:14:00 +0100198#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000199 spin_lock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100200 INFO("TSP: cpu 0x%x off request\n", mpidr);
201 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr,
202 tsp_stats[linear_id].smc_count,
203 tsp_stats[linear_id].eret_count,
204 tsp_stats[linear_id].cpu_off_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000205 spin_unlock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100206#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000207
Achin Gupta607084e2014-02-09 18:24:19 +0000208 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000209 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
210}
211
212/*******************************************************************************
213 * This function performs any book keeping in the test secure payload before
214 * this cpu's architectural state is saved in response to an earlier psci
215 * cpu_suspend request.
216 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100217tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000218 uint64_t arg1,
219 uint64_t arg2,
220 uint64_t arg3,
221 uint64_t arg4,
222 uint64_t arg5,
223 uint64_t arg6,
224 uint64_t arg7)
225{
226 uint64_t mpidr = read_mpidr();
227 uint32_t linear_id = platform_get_core_pos(mpidr);
228
Achin Guptabbc33f22014-05-09 13:33:42 +0100229 /*
230 * Save the time context and disable it to prevent the secure timer
231 * interrupt from interfering with wakeup from the suspend state.
232 */
233 tsp_generic_timer_save();
234 tsp_generic_timer_stop();
235
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000236 /* Update this cpu's statistics */
237 tsp_stats[linear_id].smc_count++;
238 tsp_stats[linear_id].eret_count++;
239 tsp_stats[linear_id].cpu_suspend_count++;
240
Dan Handley91b624e2014-07-29 17:14:00 +0100241#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000242 spin_lock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100243 INFO("TSP: cpu 0x%x suspend request. power state: 0x%x\n",
244 mpidr, power_state);
245 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
246 mpidr,
247 tsp_stats[linear_id].smc_count,
248 tsp_stats[linear_id].eret_count,
249 tsp_stats[linear_id].cpu_suspend_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000250 spin_unlock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100251#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000252
Achin Gupta607084e2014-02-09 18:24:19 +0000253 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000254 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
255}
256
257/*******************************************************************************
258 * This function performs any book keeping in the test secure payload after this
259 * cpu's architectural state has been restored after wakeup from an earlier psci
260 * cpu_suspend request.
261 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100262tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000263 uint64_t arg1,
264 uint64_t arg2,
265 uint64_t arg3,
266 uint64_t arg4,
267 uint64_t arg5,
268 uint64_t arg6,
269 uint64_t arg7)
270{
271 uint64_t mpidr = read_mpidr();
272 uint32_t linear_id = platform_get_core_pos(mpidr);
273
Achin Guptabbc33f22014-05-09 13:33:42 +0100274 /* Restore the generic timer context */
275 tsp_generic_timer_restore();
276
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000277 /* Update this cpu's statistics */
278 tsp_stats[linear_id].smc_count++;
279 tsp_stats[linear_id].eret_count++;
280 tsp_stats[linear_id].cpu_resume_count++;
281
Dan Handley91b624e2014-07-29 17:14:00 +0100282#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000283 spin_lock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100284 INFO("TSP: cpu 0x%x resumed. suspend level %d\n",
285 mpidr, suspend_level);
286 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
287 mpidr,
288 tsp_stats[linear_id].smc_count,
289 tsp_stats[linear_id].eret_count,
290 tsp_stats[linear_id].cpu_suspend_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000291 spin_unlock(&console_lock);
Dan Handley91b624e2014-07-29 17:14:00 +0100292#endif
Achin Gupta607084e2014-02-09 18:24:19 +0000293 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000294 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
295}
296
297/*******************************************************************************
298 * TSP fast smc handler. The secure monitor jumps to this function by
299 * doing the ERET after populating X0-X7 registers. The arguments are received
300 * in the function arguments in order. Once the service is rendered, this
Soby Mathew9f71f702014-05-09 20:49:17 +0100301 * function returns to Secure Monitor by raising SMC.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000302 ******************************************************************************/
Soby Mathew9f71f702014-05-09 20:49:17 +0100303tsp_args_t *tsp_smc_handler(uint64_t func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000304 uint64_t arg1,
305 uint64_t arg2,
306 uint64_t arg3,
307 uint64_t arg4,
308 uint64_t arg5,
309 uint64_t arg6,
310 uint64_t arg7)
311{
Achin Gupta916a2c12014-02-09 23:11:46 +0000312 uint64_t results[2];
313 uint64_t service_args[2];
314 uint64_t mpidr = read_mpidr();
315 uint32_t linear_id = platform_get_core_pos(mpidr);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000316
Achin Gupta916a2c12014-02-09 23:11:46 +0000317 /* Update this cpu's statistics */
318 tsp_stats[linear_id].smc_count++;
319 tsp_stats[linear_id].eret_count++;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000320
Dan Handley91b624e2014-07-29 17:14:00 +0100321 INFO("TSP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(),
322 ((func >> 31) & 1) == 1 ? "fast" : "standard",
323 func);
324 INFO("TSP: cpu 0x%x: %d smcs, %d erets\n", mpidr,
325 tsp_stats[linear_id].smc_count,
326 tsp_stats[linear_id].eret_count);
Achin Gupta916a2c12014-02-09 23:11:46 +0000327
328 /* Render secure services and obtain results here */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000329 results[0] = arg1;
330 results[1] = arg2;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000331
332 /*
333 * Request a service back from dispatcher/secure monitor. This call
334 * return and thereafter resume exectuion
335 */
336 tsp_get_magic(service_args);
337
338 /* Determine the function to perform based on the function ID */
Soby Mathew9f71f702014-05-09 20:49:17 +0100339 switch (TSP_BARE_FID(func)) {
340 case TSP_ADD:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000341 results[0] += service_args[0];
342 results[1] += service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000343 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100344 case TSP_SUB:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000345 results[0] -= service_args[0];
346 results[1] -= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000347 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100348 case TSP_MUL:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000349 results[0] *= service_args[0];
350 results[1] *= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000351 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100352 case TSP_DIV:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000353 results[0] /= service_args[0] ? service_args[0] : 1;
354 results[1] /= service_args[1] ? service_args[1] : 1;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000355 break;
356 default:
357 break;
358 }
359
Soby Mathew9f71f702014-05-09 20:49:17 +0100360 return set_smc_args(func, 0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000361 results[0],
362 results[1],
Soby Mathew9f71f702014-05-09 20:49:17 +0100363 0, 0, 0, 0);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000364}
365