blob: 8844f41bb13b7a3794bf7d89e0fd353f82dc459f [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{
108 uint64_t mpidr = read_mpidr();
109 uint32_t linear_id = platform_get_core_pos(mpidr);
110
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000111 /* Initialize the platform */
112 bl32_platform_setup();
113
114 /* Initialize secure/applications state here */
Achin Guptabbc33f22014-05-09 13:33:42 +0100115 tsp_generic_timer_start();
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000116
117 /* Update this cpu's statistics */
118 tsp_stats[linear_id].smc_count++;
119 tsp_stats[linear_id].eret_count++;
120 tsp_stats[linear_id].cpu_on_count++;
121
122 spin_lock(&console_lock);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100123 tf_printf("TSP %s\n\r", build_message);
Vikram Kanigirid8c9d262014-05-16 18:48:12 +0100124 INFO("Total memory base : 0x%x\n", (unsigned long)BL32_TOTAL_BASE);
125 INFO("Total memory size : 0x%x bytes\n",
126 (unsigned long)(BL32_TOTAL_LIMIT - BL32_TOTAL_BASE));
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000127 INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
128 tsp_stats[linear_id].smc_count,
129 tsp_stats[linear_id].eret_count,
130 tsp_stats[linear_id].cpu_on_count);
131 spin_unlock(&console_lock);
132
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100133 return (uint64_t) &tsp_vector_table;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000134}
135
136/*******************************************************************************
137 * This function performs any remaining book keeping in the test secure payload
138 * after this cpu's architectural state has been setup in response to an earlier
139 * psci cpu_on request.
140 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100141tsp_args_t *tsp_cpu_on_main(void)
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000142{
143 uint64_t mpidr = read_mpidr();
144 uint32_t linear_id = platform_get_core_pos(mpidr);
145
Achin Guptabbc33f22014-05-09 13:33:42 +0100146 /* Initialize secure/applications state here */
147 tsp_generic_timer_start();
148
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000149 /* Update this cpu's statistics */
150 tsp_stats[linear_id].smc_count++;
151 tsp_stats[linear_id].eret_count++;
152 tsp_stats[linear_id].cpu_on_count++;
153
154 spin_lock(&console_lock);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100155 tf_printf("SP: cpu 0x%x turned on\n\r", mpidr);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000156 INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
157 tsp_stats[linear_id].smc_count,
158 tsp_stats[linear_id].eret_count,
159 tsp_stats[linear_id].cpu_on_count);
160 spin_unlock(&console_lock);
161
162 /* Indicate to the SPD that we have completed turned ourselves on */
163 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
164}
165
166/*******************************************************************************
167 * This function performs any remaining book keeping in the test secure payload
168 * before this cpu is turned off in response to a psci cpu_off request.
169 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100170tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000171 uint64_t arg1,
172 uint64_t arg2,
173 uint64_t arg3,
174 uint64_t arg4,
175 uint64_t arg5,
176 uint64_t arg6,
177 uint64_t arg7)
178{
179 uint64_t mpidr = read_mpidr();
180 uint32_t linear_id = platform_get_core_pos(mpidr);
181
Achin Guptabbc33f22014-05-09 13:33:42 +0100182 /*
183 * This cpu is being turned off, so disable the timer to prevent the
184 * secure timer interrupt from interfering with power down. A pending
185 * interrupt will be lost but we do not care as we are turning off.
186 */
187 tsp_generic_timer_stop();
188
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000189 /* Update this cpu's statistics */
190 tsp_stats[linear_id].smc_count++;
191 tsp_stats[linear_id].eret_count++;
192 tsp_stats[linear_id].cpu_off_count++;
193
194 spin_lock(&console_lock);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100195 tf_printf("SP: cpu 0x%x off request\n\r", mpidr);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000196 INFO("cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr,
197 tsp_stats[linear_id].smc_count,
198 tsp_stats[linear_id].eret_count,
199 tsp_stats[linear_id].cpu_off_count);
200 spin_unlock(&console_lock);
201
202
Achin Gupta607084e2014-02-09 18:24:19 +0000203 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000204 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
205}
206
207/*******************************************************************************
208 * This function performs any book keeping in the test secure payload before
209 * this cpu's architectural state is saved in response to an earlier psci
210 * cpu_suspend request.
211 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100212tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000213 uint64_t arg1,
214 uint64_t arg2,
215 uint64_t arg3,
216 uint64_t arg4,
217 uint64_t arg5,
218 uint64_t arg6,
219 uint64_t arg7)
220{
221 uint64_t mpidr = read_mpidr();
222 uint32_t linear_id = platform_get_core_pos(mpidr);
223
Achin Guptabbc33f22014-05-09 13:33:42 +0100224 /*
225 * Save the time context and disable it to prevent the secure timer
226 * interrupt from interfering with wakeup from the suspend state.
227 */
228 tsp_generic_timer_save();
229 tsp_generic_timer_stop();
230
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000231 /* Update this cpu's statistics */
232 tsp_stats[linear_id].smc_count++;
233 tsp_stats[linear_id].eret_count++;
234 tsp_stats[linear_id].cpu_suspend_count++;
235
236 spin_lock(&console_lock);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100237 tf_printf("SP: cpu 0x%x suspend request. power state: 0x%x\n\r",
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000238 mpidr, power_state);
239 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr,
240 tsp_stats[linear_id].smc_count,
241 tsp_stats[linear_id].eret_count,
242 tsp_stats[linear_id].cpu_suspend_count);
243 spin_unlock(&console_lock);
244
Achin Gupta607084e2014-02-09 18:24:19 +0000245 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000246 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
247}
248
249/*******************************************************************************
250 * This function performs any book keeping in the test secure payload after this
251 * cpu's architectural state has been restored after wakeup from an earlier psci
252 * cpu_suspend request.
253 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100254tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000255 uint64_t arg1,
256 uint64_t arg2,
257 uint64_t arg3,
258 uint64_t arg4,
259 uint64_t arg5,
260 uint64_t arg6,
261 uint64_t arg7)
262{
263 uint64_t mpidr = read_mpidr();
264 uint32_t linear_id = platform_get_core_pos(mpidr);
265
Achin Guptabbc33f22014-05-09 13:33:42 +0100266 /* Restore the generic timer context */
267 tsp_generic_timer_restore();
268
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000269 /* Update this cpu's statistics */
270 tsp_stats[linear_id].smc_count++;
271 tsp_stats[linear_id].eret_count++;
272 tsp_stats[linear_id].cpu_resume_count++;
273
274 spin_lock(&console_lock);
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100275 tf_printf("SP: cpu 0x%x resumed. suspend level %d \n\r",
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000276 mpidr, suspend_level);
277 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", 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
Achin Gupta607084e2014-02-09 18:24:19 +0000283 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000284 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
285}
286
287/*******************************************************************************
288 * TSP fast smc handler. The secure monitor jumps to this function by
289 * doing the ERET after populating X0-X7 registers. The arguments are received
290 * in the function arguments in order. Once the service is rendered, this
Soby Mathew9f71f702014-05-09 20:49:17 +0100291 * function returns to Secure Monitor by raising SMC.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000292 ******************************************************************************/
Soby Mathew9f71f702014-05-09 20:49:17 +0100293tsp_args_t *tsp_smc_handler(uint64_t func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000294 uint64_t arg1,
295 uint64_t arg2,
296 uint64_t arg3,
297 uint64_t arg4,
298 uint64_t arg5,
299 uint64_t arg6,
300 uint64_t arg7)
301{
Achin Gupta916a2c12014-02-09 23:11:46 +0000302 uint64_t results[2];
303 uint64_t service_args[2];
304 uint64_t mpidr = read_mpidr();
305 uint32_t linear_id = platform_get_core_pos(mpidr);
Soby Mathew9f71f702014-05-09 20:49:17 +0100306 const char *smc_type;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000307
Achin Gupta916a2c12014-02-09 23:11:46 +0000308 /* Update this cpu's statistics */
309 tsp_stats[linear_id].smc_count++;
310 tsp_stats[linear_id].eret_count++;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000311
Soby Mathew9f71f702014-05-09 20:49:17 +0100312 smc_type = ((func >> 31) & 1) == 1 ? "fast" : "standard";
313
Soby Mathewafe7e2f2014-06-12 17:23:58 +0100314 tf_printf("SP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(), smc_type, func);
Achin Gupta916a2c12014-02-09 23:11:46 +0000315 INFO("cpu 0x%x: %d smcs, %d erets\n", mpidr,
316 tsp_stats[linear_id].smc_count,
317 tsp_stats[linear_id].eret_count);
318
319 /* Render secure services and obtain results here */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000320 results[0] = arg1;
321 results[1] = arg2;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000322
323 /*
324 * Request a service back from dispatcher/secure monitor. This call
325 * return and thereafter resume exectuion
326 */
327 tsp_get_magic(service_args);
328
329 /* Determine the function to perform based on the function ID */
Soby Mathew9f71f702014-05-09 20:49:17 +0100330 switch (TSP_BARE_FID(func)) {
331 case TSP_ADD:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000332 results[0] += service_args[0];
333 results[1] += service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000334 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100335 case TSP_SUB:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000336 results[0] -= service_args[0];
337 results[1] -= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000338 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100339 case TSP_MUL:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000340 results[0] *= service_args[0];
341 results[1] *= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000342 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100343 case TSP_DIV:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000344 results[0] /= service_args[0] ? service_args[0] : 1;
345 results[1] /= service_args[1] ? service_args[1] : 1;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000346 break;
347 default:
348 break;
349 }
350
Soby Mathew9f71f702014-05-09 20:49:17 +0100351 return set_smc_args(func, 0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000352 results[0],
353 results[1],
Soby Mathew9f71f702014-05-09 20:49:17 +0100354 0, 0, 0, 0);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000355}
356