blob: 05737aef6f85dbc9ca3056104aed6d6d10ee47b3 [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>
33#include <bl32.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000034#include <debug.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010035#include <platform.h>
Dan Handleyed6ff952014-05-14 17:44:19 +010036#include <platform_def.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000037#include <spinlock.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010038#include <stdio.h>
39#include <tsp.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000040
41/*******************************************************************************
Vikram Kanigirid8c9d262014-05-16 18:48:12 +010042 * Declarations of linker defined symbols which will help us find the layout
43 * of trusted SRAM
44 ******************************************************************************/
45extern unsigned long __RO_START__;
46extern unsigned long __COHERENT_RAM_END__;
47
48/*******************************************************************************
Achin Gupta7c88f3f2014-02-18 18:09:12 +000049 * Lock to control access to the console
50 ******************************************************************************/
51spinlock_t console_lock;
52
53/*******************************************************************************
54 * Per cpu data structure to populate parameters for an SMC in C code and use
55 * a pointer to this structure in assembler code to populate x0-x7
56 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010057static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000058
59/*******************************************************************************
60 * Per cpu data structure to keep track of TSP activity
61 ******************************************************************************/
Achin Gupta76717892014-05-09 11:42:56 +010062work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000063
64/*******************************************************************************
Vikram Kanigirid8c9d262014-05-16 18:48:12 +010065 * The BL32 memory footprint starts with an RO sections and ends
66 * with a section for coherent RAM. Use it to find the memory size
67 ******************************************************************************/
68#define BL32_TOTAL_BASE (unsigned long)(&__RO_START__)
69
70#define BL32_TOTAL_LIMIT (unsigned long)(&__COHERENT_RAM_END__)
71
Dan Handleye2712bc2014-04-10 15:37:22 +010072static tsp_args_t *set_smc_args(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +000073 uint64_t arg1,
74 uint64_t arg2,
75 uint64_t arg3,
76 uint64_t arg4,
77 uint64_t arg5,
78 uint64_t arg6,
79 uint64_t arg7)
80{
81 uint64_t mpidr = read_mpidr();
82 uint32_t linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +010083 tsp_args_t *pcpu_smc_args;
Achin Gupta7c88f3f2014-02-18 18:09:12 +000084
85 /*
86 * Return to Secure Monitor by raising an SMC. The results of the
87 * service are passed as an arguments to the SMC
88 */
89 linear_id = platform_get_core_pos(mpidr);
90 pcpu_smc_args = &tsp_smc_args[linear_id];
91 write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
92 write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
93 write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
94 write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
95 write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
96 write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
97 write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
98 write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
99
100 return pcpu_smc_args;
101}
102
103/*******************************************************************************
104 * TSP main entry point where it gets the opportunity to initialize its secure
105 * state/applications. Once the state is initialized, it must return to the
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100106 * SPD with a pointer to the 'tsp_vector_table' jump table.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000107 ******************************************************************************/
108uint64_t tsp_main(void)
109{
110 uint64_t mpidr = read_mpidr();
111 uint32_t linear_id = platform_get_core_pos(mpidr);
112
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000113 /* Initialize the platform */
114 bl32_platform_setup();
115
116 /* Initialize secure/applications state here */
Achin Guptabbc33f22014-05-09 13:33:42 +0100117 tsp_generic_timer_start();
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000118
119 /* Update this cpu's statistics */
120 tsp_stats[linear_id].smc_count++;
121 tsp_stats[linear_id].eret_count++;
122 tsp_stats[linear_id].cpu_on_count++;
123
124 spin_lock(&console_lock);
Jon Medhurstecf0a712014-02-17 12:18:24 +0000125 printf("TSP %s\n\r", build_message);
Vikram Kanigirid8c9d262014-05-16 18:48:12 +0100126 INFO("Total memory base : 0x%x\n", (unsigned long)BL32_TOTAL_BASE);
127 INFO("Total memory size : 0x%x bytes\n",
128 (unsigned long)(BL32_TOTAL_LIMIT - BL32_TOTAL_BASE));
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000129 INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
130 tsp_stats[linear_id].smc_count,
131 tsp_stats[linear_id].eret_count,
132 tsp_stats[linear_id].cpu_on_count);
133 spin_unlock(&console_lock);
134
Andrew Thoelke891c4ca2014-05-20 21:43:27 +0100135 return (uint64_t) &tsp_vector_table;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000136}
137
138/*******************************************************************************
139 * This function performs any remaining book keeping in the test secure payload
140 * after this cpu's architectural state has been setup in response to an earlier
141 * psci cpu_on request.
142 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100143tsp_args_t *tsp_cpu_on_main(void)
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000144{
145 uint64_t mpidr = read_mpidr();
146 uint32_t linear_id = platform_get_core_pos(mpidr);
147
Achin Guptabbc33f22014-05-09 13:33:42 +0100148 /* Initialize secure/applications state here */
149 tsp_generic_timer_start();
150
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000151 /* Update this cpu's statistics */
152 tsp_stats[linear_id].smc_count++;
153 tsp_stats[linear_id].eret_count++;
154 tsp_stats[linear_id].cpu_on_count++;
155
156 spin_lock(&console_lock);
157 printf("SP: cpu 0x%x turned on\n\r", mpidr);
158 INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
159 tsp_stats[linear_id].smc_count,
160 tsp_stats[linear_id].eret_count,
161 tsp_stats[linear_id].cpu_on_count);
162 spin_unlock(&console_lock);
163
164 /* Indicate to the SPD that we have completed turned ourselves on */
165 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
166}
167
168/*******************************************************************************
169 * This function performs any remaining book keeping in the test secure payload
170 * before this cpu is turned off in response to a psci cpu_off request.
171 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100172tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000173 uint64_t arg1,
174 uint64_t arg2,
175 uint64_t arg3,
176 uint64_t arg4,
177 uint64_t arg5,
178 uint64_t arg6,
179 uint64_t arg7)
180{
181 uint64_t mpidr = read_mpidr();
182 uint32_t linear_id = platform_get_core_pos(mpidr);
183
Achin Guptabbc33f22014-05-09 13:33:42 +0100184 /*
185 * This cpu is being turned off, so disable the timer to prevent the
186 * secure timer interrupt from interfering with power down. A pending
187 * interrupt will be lost but we do not care as we are turning off.
188 */
189 tsp_generic_timer_stop();
190
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000191 /* Update this cpu's statistics */
192 tsp_stats[linear_id].smc_count++;
193 tsp_stats[linear_id].eret_count++;
194 tsp_stats[linear_id].cpu_off_count++;
195
196 spin_lock(&console_lock);
197 printf("SP: cpu 0x%x off request\n\r", mpidr);
198 INFO("cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr,
199 tsp_stats[linear_id].smc_count,
200 tsp_stats[linear_id].eret_count,
201 tsp_stats[linear_id].cpu_off_count);
202 spin_unlock(&console_lock);
203
204
Achin Gupta607084e2014-02-09 18:24:19 +0000205 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000206 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
207}
208
209/*******************************************************************************
210 * This function performs any book keeping in the test secure payload before
211 * this cpu's architectural state is saved in response to an earlier psci
212 * cpu_suspend request.
213 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100214tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000215 uint64_t arg1,
216 uint64_t arg2,
217 uint64_t arg3,
218 uint64_t arg4,
219 uint64_t arg5,
220 uint64_t arg6,
221 uint64_t arg7)
222{
223 uint64_t mpidr = read_mpidr();
224 uint32_t linear_id = platform_get_core_pos(mpidr);
225
Achin Guptabbc33f22014-05-09 13:33:42 +0100226 /*
227 * Save the time context and disable it to prevent the secure timer
228 * interrupt from interfering with wakeup from the suspend state.
229 */
230 tsp_generic_timer_save();
231 tsp_generic_timer_stop();
232
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000233 /* Update this cpu's statistics */
234 tsp_stats[linear_id].smc_count++;
235 tsp_stats[linear_id].eret_count++;
236 tsp_stats[linear_id].cpu_suspend_count++;
237
238 spin_lock(&console_lock);
239 printf("SP: cpu 0x%x suspend request. power state: 0x%x\n\r",
240 mpidr, power_state);
241 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr,
242 tsp_stats[linear_id].smc_count,
243 tsp_stats[linear_id].eret_count,
244 tsp_stats[linear_id].cpu_suspend_count);
245 spin_unlock(&console_lock);
246
Achin Gupta607084e2014-02-09 18:24:19 +0000247 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000248 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
249}
250
251/*******************************************************************************
252 * This function performs any book keeping in the test secure payload after this
253 * cpu's architectural state has been restored after wakeup from an earlier psci
254 * cpu_suspend request.
255 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100256tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000257 uint64_t arg1,
258 uint64_t arg2,
259 uint64_t arg3,
260 uint64_t arg4,
261 uint64_t arg5,
262 uint64_t arg6,
263 uint64_t arg7)
264{
265 uint64_t mpidr = read_mpidr();
266 uint32_t linear_id = platform_get_core_pos(mpidr);
267
Achin Guptabbc33f22014-05-09 13:33:42 +0100268 /* Restore the generic timer context */
269 tsp_generic_timer_restore();
270
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000271 /* Update this cpu's statistics */
272 tsp_stats[linear_id].smc_count++;
273 tsp_stats[linear_id].eret_count++;
274 tsp_stats[linear_id].cpu_resume_count++;
275
276 spin_lock(&console_lock);
277 printf("SP: cpu 0x%x resumed. suspend level %d \n\r",
278 mpidr, suspend_level);
279 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr,
280 tsp_stats[linear_id].smc_count,
281 tsp_stats[linear_id].eret_count,
282 tsp_stats[linear_id].cpu_suspend_count);
283 spin_unlock(&console_lock);
284
Achin Gupta607084e2014-02-09 18:24:19 +0000285 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000286 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
287}
288
289/*******************************************************************************
290 * TSP fast smc handler. The secure monitor jumps to this function by
291 * doing the ERET after populating X0-X7 registers. The arguments are received
292 * in the function arguments in order. Once the service is rendered, this
Soby Mathew9f71f702014-05-09 20:49:17 +0100293 * function returns to Secure Monitor by raising SMC.
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000294 ******************************************************************************/
Soby Mathew9f71f702014-05-09 20:49:17 +0100295tsp_args_t *tsp_smc_handler(uint64_t func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000296 uint64_t arg1,
297 uint64_t arg2,
298 uint64_t arg3,
299 uint64_t arg4,
300 uint64_t arg5,
301 uint64_t arg6,
302 uint64_t arg7)
303{
Achin Gupta916a2c12014-02-09 23:11:46 +0000304 uint64_t results[2];
305 uint64_t service_args[2];
306 uint64_t mpidr = read_mpidr();
307 uint32_t linear_id = platform_get_core_pos(mpidr);
Soby Mathew9f71f702014-05-09 20:49:17 +0100308 const char *smc_type;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000309
Achin Gupta916a2c12014-02-09 23:11:46 +0000310 /* Update this cpu's statistics */
311 tsp_stats[linear_id].smc_count++;
312 tsp_stats[linear_id].eret_count++;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000313
Soby Mathew9f71f702014-05-09 20:49:17 +0100314 smc_type = ((func >> 31) & 1) == 1 ? "fast" : "standard";
315
316 printf("SP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(), smc_type, func);
Achin Gupta916a2c12014-02-09 23:11:46 +0000317 INFO("cpu 0x%x: %d smcs, %d erets\n", mpidr,
318 tsp_stats[linear_id].smc_count,
319 tsp_stats[linear_id].eret_count);
320
321 /* Render secure services and obtain results here */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000322 results[0] = arg1;
323 results[1] = arg2;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000324
325 /*
326 * Request a service back from dispatcher/secure monitor. This call
327 * return and thereafter resume exectuion
328 */
329 tsp_get_magic(service_args);
330
331 /* Determine the function to perform based on the function ID */
Soby Mathew9f71f702014-05-09 20:49:17 +0100332 switch (TSP_BARE_FID(func)) {
333 case TSP_ADD:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000334 results[0] += service_args[0];
335 results[1] += service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000336 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100337 case TSP_SUB:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000338 results[0] -= service_args[0];
339 results[1] -= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000340 break;
Soby Mathew9f71f702014-05-09 20:49:17 +0100341 case TSP_MUL:
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 Mathew9f71f702014-05-09 20:49:17 +0100345 case TSP_DIV:
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000346 results[0] /= service_args[0] ? service_args[0] : 1;
347 results[1] /= service_args[1] ? service_args[1] : 1;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000348 break;
349 default:
350 break;
351 }
352
Soby Mathew9f71f702014-05-09 20:49:17 +0100353 return set_smc_args(func, 0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000354 results[0],
355 results[1],
Soby Mathew9f71f702014-05-09 20:49:17 +0100356 0, 0, 0, 0);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000357}
358