blob: 31808fcfb19add77edd5f3ddcc4a769fe9ced2ad [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 Handley97043ac2014-04-09 13:14:54 +010032#include <bl_common.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000033#include <debug.h>
Dan Handley97043ac2014-04-09 13:14:54 +010034#include <platform.h>
Dan Handley5f0cdb02014-05-14 17:44:19 +010035#include <platform_def.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000036#include <spinlock.h>
Dan Handley97043ac2014-04-09 13:14:54 +010037#include <tsp.h>
Dan Handleyda0af782014-08-01 17:58:27 +010038#include "tsp_private.h"
Achin Gupta7c88f3f2014-02-18 18:09:12 +000039
40/*******************************************************************************
Vikram Kanigiri6871c5d2014-05-16 18:48:12 +010041 * Declarations of linker defined symbols which will help us find the layout
42 * of trusted SRAM
43 ******************************************************************************/
44extern unsigned long __RO_START__;
45extern unsigned long __COHERENT_RAM_END__;
46
47/*******************************************************************************
Achin Gupta7c88f3f2014-02-18 18:09:12 +000048 * Lock to control access to the console
49 ******************************************************************************/
50spinlock_t console_lock;
51
52/*******************************************************************************
53 * Per cpu data structure to populate parameters for an SMC in C code and use
54 * a pointer to this structure in assembler code to populate x0-x7
55 ******************************************************************************/
Dan Handleyfb037bf2014-04-10 15:37:22 +010056static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000057
58/*******************************************************************************
59 * Per cpu data structure to keep track of TSP activity
60 ******************************************************************************/
Achin Gupta6cf89022014-05-09 11:42:56 +010061work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000062
63/*******************************************************************************
Vikram Kanigiri6871c5d2014-05-16 18:48:12 +010064 * The BL32 memory footprint starts with an RO sections and ends
65 * with a section for coherent RAM. Use it to find the memory size
66 ******************************************************************************/
67#define BL32_TOTAL_BASE (unsigned long)(&__RO_START__)
68
69#define BL32_TOTAL_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
70
Dan Handleyfb037bf2014-04-10 15:37:22 +010071static tsp_args_t *set_smc_args(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +000072 uint64_t arg1,
73 uint64_t arg2,
74 uint64_t arg3,
75 uint64_t arg4,
76 uint64_t arg5,
77 uint64_t arg6,
78 uint64_t arg7)
79{
80 uint64_t mpidr = read_mpidr();
81 uint32_t linear_id;
Dan Handleyfb037bf2014-04-10 15:37:22 +010082 tsp_args_t *pcpu_smc_args;
Achin Gupta7c88f3f2014-02-18 18:09:12 +000083
84 /*
85 * Return to Secure Monitor by raising an SMC. The results of the
86 * service are passed as an arguments to the SMC
87 */
88 linear_id = platform_get_core_pos(mpidr);
89 pcpu_smc_args = &tsp_smc_args[linear_id];
90 write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
91 write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
92 write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
93 write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
94 write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
95 write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
96 write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
97 write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
98
99 return pcpu_smc_args;
100}
101
102/*******************************************************************************
103 * TSP main entry point where it gets the opportunity to initialize its secure
104 * state/applications. Once the state is initialized, it must return to the
Andrew Thoelke399fb082014-05-20 21:43:27 +0100105 * SPD with a pointer to the 'tsp_vector_table' jump table.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000106 ******************************************************************************/
107uint64_t tsp_main(void)
108{
Dan Handley6ad2e462014-07-29 17:14:00 +0100109 NOTICE("TSP: %s\n", version_string);
110 NOTICE("TSP: %s\n", build_message);
111 INFO("TSP: Total memory base : 0x%x\n", (unsigned long)BL32_TOTAL_BASE);
112 INFO("TSP: Total memory size : 0x%x bytes\n",
113 (unsigned long)(BL32_TOTAL_LIMIT - BL32_TOTAL_BASE));
114
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000115 uint64_t mpidr = read_mpidr();
116 uint32_t linear_id = platform_get_core_pos(mpidr);
117
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000118 /* Initialize the platform */
119 bl32_platform_setup();
120
121 /* Initialize secure/applications state here */
Achin Guptaa20a81e2014-05-09 13:33:42 +0100122 tsp_generic_timer_start();
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000123
124 /* Update this cpu's statistics */
125 tsp_stats[linear_id].smc_count++;
126 tsp_stats[linear_id].eret_count++;
127 tsp_stats[linear_id].cpu_on_count++;
128
Dan Handley6ad2e462014-07-29 17:14:00 +0100129#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000130 spin_lock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100131 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000132 tsp_stats[linear_id].smc_count,
133 tsp_stats[linear_id].eret_count,
134 tsp_stats[linear_id].cpu_on_count);
135 spin_unlock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100136#endif
Andrew Thoelke399fb082014-05-20 21:43:27 +0100137 return (uint64_t) &tsp_vector_table;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000138}
139
140/*******************************************************************************
141 * This function performs any remaining book keeping in the test secure payload
142 * after this cpu's architectural state has been setup in response to an earlier
143 * psci cpu_on request.
144 ******************************************************************************/
Dan Handleyfb037bf2014-04-10 15:37:22 +0100145tsp_args_t *tsp_cpu_on_main(void)
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000146{
147 uint64_t mpidr = read_mpidr();
148 uint32_t linear_id = platform_get_core_pos(mpidr);
149
Achin Guptaa20a81e2014-05-09 13:33:42 +0100150 /* Initialize secure/applications state here */
151 tsp_generic_timer_start();
152
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000153 /* Update this cpu's statistics */
154 tsp_stats[linear_id].smc_count++;
155 tsp_stats[linear_id].eret_count++;
156 tsp_stats[linear_id].cpu_on_count++;
157
Dan Handley6ad2e462014-07-29 17:14:00 +0100158#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000159 spin_lock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100160 INFO("TSP: cpu 0x%x turned on\n", mpidr);
161 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
162 tsp_stats[linear_id].smc_count,
163 tsp_stats[linear_id].eret_count,
164 tsp_stats[linear_id].cpu_on_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000165 spin_unlock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100166#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000167 /* Indicate to the SPD that we have completed turned ourselves on */
168 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
169}
170
171/*******************************************************************************
172 * This function performs any remaining book keeping in the test secure payload
173 * before this cpu is turned off in response to a psci cpu_off request.
174 ******************************************************************************/
Dan Handleyfb037bf2014-04-10 15:37:22 +0100175tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000176 uint64_t arg1,
177 uint64_t arg2,
178 uint64_t arg3,
179 uint64_t arg4,
180 uint64_t arg5,
181 uint64_t arg6,
182 uint64_t arg7)
183{
184 uint64_t mpidr = read_mpidr();
185 uint32_t linear_id = platform_get_core_pos(mpidr);
186
Achin Guptaa20a81e2014-05-09 13:33:42 +0100187 /*
188 * This cpu is being turned off, so disable the timer to prevent the
189 * secure timer interrupt from interfering with power down. A pending
190 * interrupt will be lost but we do not care as we are turning off.
191 */
192 tsp_generic_timer_stop();
193
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000194 /* Update this cpu's statistics */
195 tsp_stats[linear_id].smc_count++;
196 tsp_stats[linear_id].eret_count++;
197 tsp_stats[linear_id].cpu_off_count++;
198
Dan Handley6ad2e462014-07-29 17:14:00 +0100199#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000200 spin_lock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100201 INFO("TSP: cpu 0x%x off request\n", mpidr);
202 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr,
203 tsp_stats[linear_id].smc_count,
204 tsp_stats[linear_id].eret_count,
205 tsp_stats[linear_id].cpu_off_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000206 spin_unlock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100207#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000208
Achin Gupta607084e2014-02-09 18:24:19 +0000209 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000210 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
211}
212
213/*******************************************************************************
214 * This function performs any book keeping in the test secure payload before
215 * this cpu's architectural state is saved in response to an earlier psci
216 * cpu_suspend request.
217 ******************************************************************************/
Dan Handleyfb037bf2014-04-10 15:37:22 +0100218tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000219 uint64_t arg1,
220 uint64_t arg2,
221 uint64_t arg3,
222 uint64_t arg4,
223 uint64_t arg5,
224 uint64_t arg6,
225 uint64_t arg7)
226{
227 uint64_t mpidr = read_mpidr();
228 uint32_t linear_id = platform_get_core_pos(mpidr);
229
Achin Guptaa20a81e2014-05-09 13:33:42 +0100230 /*
231 * Save the time context and disable it to prevent the secure timer
232 * interrupt from interfering with wakeup from the suspend state.
233 */
234 tsp_generic_timer_save();
235 tsp_generic_timer_stop();
236
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000237 /* Update this cpu's statistics */
238 tsp_stats[linear_id].smc_count++;
239 tsp_stats[linear_id].eret_count++;
240 tsp_stats[linear_id].cpu_suspend_count++;
241
Dan Handley6ad2e462014-07-29 17:14:00 +0100242#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000243 spin_lock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100244 INFO("TSP: cpu 0x%x suspend request. power state: 0x%x\n",
245 mpidr, power_state);
246 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
247 mpidr,
248 tsp_stats[linear_id].smc_count,
249 tsp_stats[linear_id].eret_count,
250 tsp_stats[linear_id].cpu_suspend_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000251 spin_unlock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100252#endif
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000253
Achin Gupta607084e2014-02-09 18:24:19 +0000254 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000255 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
256}
257
258/*******************************************************************************
259 * This function performs any book keeping in the test secure payload after this
260 * cpu's architectural state has been restored after wakeup from an earlier psci
261 * cpu_suspend request.
262 ******************************************************************************/
Dan Handleyfb037bf2014-04-10 15:37:22 +0100263tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000264 uint64_t arg1,
265 uint64_t arg2,
266 uint64_t arg3,
267 uint64_t arg4,
268 uint64_t arg5,
269 uint64_t arg6,
270 uint64_t arg7)
271{
272 uint64_t mpidr = read_mpidr();
273 uint32_t linear_id = platform_get_core_pos(mpidr);
274
Achin Guptaa20a81e2014-05-09 13:33:42 +0100275 /* Restore the generic timer context */
276 tsp_generic_timer_restore();
277
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000278 /* Update this cpu's statistics */
279 tsp_stats[linear_id].smc_count++;
280 tsp_stats[linear_id].eret_count++;
281 tsp_stats[linear_id].cpu_resume_count++;
282
Dan Handley6ad2e462014-07-29 17:14:00 +0100283#if LOG_LEVEL >= LOG_LEVEL_INFO
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000284 spin_lock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100285 INFO("TSP: cpu 0x%x resumed. suspend level %d\n",
286 mpidr, suspend_level);
287 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n",
288 mpidr,
289 tsp_stats[linear_id].smc_count,
290 tsp_stats[linear_id].eret_count,
291 tsp_stats[linear_id].cpu_suspend_count);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000292 spin_unlock(&console_lock);
Dan Handley6ad2e462014-07-29 17:14:00 +0100293#endif
Achin Gupta607084e2014-02-09 18:24:19 +0000294 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000295 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
296}
297
298/*******************************************************************************
299 * TSP fast smc handler. The secure monitor jumps to this function by
300 * doing the ERET after populating X0-X7 registers. The arguments are received
301 * in the function arguments in order. Once the service is rendered, this
Soby Mathew239b04f2014-05-09 20:49:17 +0100302 * function returns to Secure Monitor by raising SMC.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000303 ******************************************************************************/
Soby Mathew239b04f2014-05-09 20:49:17 +0100304tsp_args_t *tsp_smc_handler(uint64_t func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000305 uint64_t arg1,
306 uint64_t arg2,
307 uint64_t arg3,
308 uint64_t arg4,
309 uint64_t arg5,
310 uint64_t arg6,
311 uint64_t arg7)
312{
Achin Gupta916a2c12014-02-09 23:11:46 +0000313 uint64_t results[2];
314 uint64_t service_args[2];
315 uint64_t mpidr = read_mpidr();
316 uint32_t linear_id = platform_get_core_pos(mpidr);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000317
Achin Gupta916a2c12014-02-09 23:11:46 +0000318 /* Update this cpu's statistics */
319 tsp_stats[linear_id].smc_count++;
320 tsp_stats[linear_id].eret_count++;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000321
Dan Handley6ad2e462014-07-29 17:14:00 +0100322 INFO("TSP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(),
323 ((func >> 31) & 1) == 1 ? "fast" : "standard",
324 func);
325 INFO("TSP: cpu 0x%x: %d smcs, %d erets\n", mpidr,
326 tsp_stats[linear_id].smc_count,
327 tsp_stats[linear_id].eret_count);
Achin Gupta916a2c12014-02-09 23:11:46 +0000328
329 /* Render secure services and obtain results here */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000330 results[0] = arg1;
331 results[1] = arg2;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000332
333 /*
334 * Request a service back from dispatcher/secure monitor. This call
335 * return and thereafter resume exectuion
336 */
337 tsp_get_magic(service_args);
338
339 /* Determine the function to perform based on the function ID */
Soby Mathew239b04f2014-05-09 20:49:17 +0100340 switch (TSP_BARE_FID(func)) {
341 case TSP_ADD:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000342 results[0] += service_args[0];
343 results[1] += service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000344 break;
Soby Mathew239b04f2014-05-09 20:49:17 +0100345 case TSP_SUB:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000346 results[0] -= service_args[0];
347 results[1] -= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000348 break;
Soby Mathew239b04f2014-05-09 20:49:17 +0100349 case TSP_MUL:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000350 results[0] *= service_args[0];
351 results[1] *= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000352 break;
Soby Mathew239b04f2014-05-09 20:49:17 +0100353 case TSP_DIV:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000354 results[0] /= service_args[0] ? service_args[0] : 1;
355 results[1] /= service_args[1] ? service_args[1] : 1;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000356 break;
357 default:
358 break;
359 }
360
Soby Mathew239b04f2014-05-09 20:49:17 +0100361 return set_smc_args(func, 0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000362 results[0],
363 results[1],
Soby Mathew239b04f2014-05-09 20:49:17 +0100364 0, 0, 0, 0);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000365}
366