blob: a667ffc23ad6f3fbba9a962483cdfe3d5aedc9fb [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>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000036#include <spinlock.h>
Dan Handley2bd4ef22014-04-09 13:14:54 +010037#include <stdio.h>
38#include <tsp.h>
Achin Gupta7c88f3f2014-02-18 18:09:12 +000039
40/*******************************************************************************
41 * Lock to control access to the console
42 ******************************************************************************/
43spinlock_t console_lock;
44
45/*******************************************************************************
46 * Per cpu data structure to populate parameters for an SMC in C code and use
47 * a pointer to this structure in assembler code to populate x0-x7
48 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010049static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000050
51/*******************************************************************************
52 * Per cpu data structure to keep track of TSP activity
53 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010054static work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
Achin Gupta7c88f3f2014-02-18 18:09:12 +000055
56/*******************************************************************************
57 * Single reference to the various entry points exported by the test secure
58 * payload. A single copy should suffice for all cpus as they are not expected
59 * to change.
60 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +010061static const entry_info_t tsp_entry_info = {
Achin Gupta7c88f3f2014-02-18 18:09:12 +000062 tsp_fast_smc_entry,
63 tsp_cpu_on_entry,
64 tsp_cpu_off_entry,
65 tsp_cpu_resume_entry,
66 tsp_cpu_suspend_entry,
67};
68
Dan Handleye2712bc2014-04-10 15:37:22 +010069static tsp_args_t *set_smc_args(uint64_t arg0,
Achin Gupta7c88f3f2014-02-18 18:09:12 +000070 uint64_t arg1,
71 uint64_t arg2,
72 uint64_t arg3,
73 uint64_t arg4,
74 uint64_t arg5,
75 uint64_t arg6,
76 uint64_t arg7)
77{
78 uint64_t mpidr = read_mpidr();
79 uint32_t linear_id;
Dan Handleye2712bc2014-04-10 15:37:22 +010080 tsp_args_t *pcpu_smc_args;
Achin Gupta7c88f3f2014-02-18 18:09:12 +000081
82 /*
83 * Return to Secure Monitor by raising an SMC. The results of the
84 * service are passed as an arguments to the SMC
85 */
86 linear_id = platform_get_core_pos(mpidr);
87 pcpu_smc_args = &tsp_smc_args[linear_id];
88 write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0);
89 write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1);
90 write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2);
91 write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3);
92 write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4);
93 write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5);
94 write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6);
95 write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7);
96
97 return pcpu_smc_args;
98}
99
100/*******************************************************************************
101 * TSP main entry point where it gets the opportunity to initialize its secure
102 * state/applications. Once the state is initialized, it must return to the
103 * SPD with a pointer to the 'tsp_entry_info' structure.
104 ******************************************************************************/
105uint64_t tsp_main(void)
106{
107 uint64_t mpidr = read_mpidr();
108 uint32_t linear_id = platform_get_core_pos(mpidr);
109
110#if DEBUG
Dan Handleye2712bc2014-04-10 15:37:22 +0100111 meminfo_t *mem_layout = bl32_plat_sec_mem_layout();
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000112#endif
113
114 /* Initialize the platform */
115 bl32_platform_setup();
116
117 /* Initialize secure/applications state here */
118
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);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000126 INFO("Total memory base : 0x%x\n", mem_layout->total_base);
127 INFO("Total memory size : 0x%x bytes\n", mem_layout->total_size);
128 INFO("Free memory base : 0x%x\n", mem_layout->free_base);
129 INFO("Free memory size : 0x%x bytes\n", mem_layout->free_size);
130 INFO("cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
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);
135
136 /*
137 * TODO: There is a massive assumption that the SPD and SP can see each
138 * other's memory without issues so it is safe to pass pointers to
139 * internal memory. Replace this with a shared communication buffer.
140 */
141 return (uint64_t) &tsp_entry_info;
142}
143
144/*******************************************************************************
145 * This function performs any remaining book keeping in the test secure payload
146 * after this cpu's architectural state has been setup in response to an earlier
147 * psci cpu_on request.
148 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100149tsp_args_t *tsp_cpu_on_main(void)
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000150{
151 uint64_t mpidr = read_mpidr();
152 uint32_t linear_id = platform_get_core_pos(mpidr);
153
154 /* Update this cpu's statistics */
155 tsp_stats[linear_id].smc_count++;
156 tsp_stats[linear_id].eret_count++;
157 tsp_stats[linear_id].cpu_on_count++;
158
159 spin_lock(&console_lock);
160 printf("SP: cpu 0x%x turned on\n\r", mpidr);
161 INFO("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);
165 spin_unlock(&console_lock);
166
167 /* 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 Handleye2712bc2014-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
187 /* Update this cpu's statistics */
188 tsp_stats[linear_id].smc_count++;
189 tsp_stats[linear_id].eret_count++;
190 tsp_stats[linear_id].cpu_off_count++;
191
192 spin_lock(&console_lock);
193 printf("SP: cpu 0x%x off request\n\r", mpidr);
194 INFO("cpu 0x%x: %d smcs, %d erets %d cpu off requests\n", mpidr,
195 tsp_stats[linear_id].smc_count,
196 tsp_stats[linear_id].eret_count,
197 tsp_stats[linear_id].cpu_off_count);
198 spin_unlock(&console_lock);
199
200
Achin Gupta607084e2014-02-09 18:24:19 +0000201 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000202 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
203}
204
205/*******************************************************************************
206 * This function performs any book keeping in the test secure payload before
207 * this cpu's architectural state is saved in response to an earlier psci
208 * cpu_suspend request.
209 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100210tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000211 uint64_t arg1,
212 uint64_t arg2,
213 uint64_t arg3,
214 uint64_t arg4,
215 uint64_t arg5,
216 uint64_t arg6,
217 uint64_t arg7)
218{
219 uint64_t mpidr = read_mpidr();
220 uint32_t linear_id = platform_get_core_pos(mpidr);
221
222 /* Update this cpu's statistics */
223 tsp_stats[linear_id].smc_count++;
224 tsp_stats[linear_id].eret_count++;
225 tsp_stats[linear_id].cpu_suspend_count++;
226
227 spin_lock(&console_lock);
228 printf("SP: cpu 0x%x suspend request. power state: 0x%x\n\r",
229 mpidr, power_state);
230 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr,
231 tsp_stats[linear_id].smc_count,
232 tsp_stats[linear_id].eret_count,
233 tsp_stats[linear_id].cpu_suspend_count);
234 spin_unlock(&console_lock);
235
Achin Gupta607084e2014-02-09 18:24:19 +0000236 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000237 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
238}
239
240/*******************************************************************************
241 * This function performs any book keeping in the test secure payload after this
242 * cpu's architectural state has been restored after wakeup from an earlier psci
243 * cpu_suspend request.
244 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100245tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000246 uint64_t arg1,
247 uint64_t arg2,
248 uint64_t arg3,
249 uint64_t arg4,
250 uint64_t arg5,
251 uint64_t arg6,
252 uint64_t arg7)
253{
254 uint64_t mpidr = read_mpidr();
255 uint32_t linear_id = platform_get_core_pos(mpidr);
256
257 /* Update this cpu's statistics */
258 tsp_stats[linear_id].smc_count++;
259 tsp_stats[linear_id].eret_count++;
260 tsp_stats[linear_id].cpu_resume_count++;
261
262 spin_lock(&console_lock);
263 printf("SP: cpu 0x%x resumed. suspend level %d \n\r",
264 mpidr, suspend_level);
265 INFO("cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", mpidr,
266 tsp_stats[linear_id].smc_count,
267 tsp_stats[linear_id].eret_count,
268 tsp_stats[linear_id].cpu_suspend_count);
269 spin_unlock(&console_lock);
270
Achin Gupta607084e2014-02-09 18:24:19 +0000271 /* Indicate to the SPD that we have completed this request */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000272 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
273}
274
275/*******************************************************************************
276 * TSP fast smc handler. The secure monitor jumps to this function by
277 * doing the ERET after populating X0-X7 registers. The arguments are received
278 * in the function arguments in order. Once the service is rendered, this
279 * function returns to Secure Monitor by raising SMC
280 ******************************************************************************/
Dan Handleye2712bc2014-04-10 15:37:22 +0100281tsp_args_t *tsp_fast_smc_handler(uint64_t func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000282 uint64_t arg1,
283 uint64_t arg2,
284 uint64_t arg3,
285 uint64_t arg4,
286 uint64_t arg5,
287 uint64_t arg6,
288 uint64_t arg7)
289{
Achin Gupta916a2c12014-02-09 23:11:46 +0000290 uint64_t results[2];
291 uint64_t service_args[2];
292 uint64_t mpidr = read_mpidr();
293 uint32_t linear_id = platform_get_core_pos(mpidr);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000294
Achin Gupta916a2c12014-02-09 23:11:46 +0000295 /* Update this cpu's statistics */
296 tsp_stats[linear_id].smc_count++;
297 tsp_stats[linear_id].eret_count++;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000298
Achin Gupta916a2c12014-02-09 23:11:46 +0000299 printf("SP: cpu 0x%x received fast smc 0x%x\n", read_mpidr(), func);
300 INFO("cpu 0x%x: %d smcs, %d erets\n", mpidr,
301 tsp_stats[linear_id].smc_count,
302 tsp_stats[linear_id].eret_count);
303
304 /* Render secure services and obtain results here */
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000305
306 results[0] = arg1;
307 results[1] = arg2;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000308
309 /*
310 * Request a service back from dispatcher/secure monitor. This call
311 * return and thereafter resume exectuion
312 */
313 tsp_get_magic(service_args);
314
315 /* Determine the function to perform based on the function ID */
316 switch (func) {
317 case TSP_FID_ADD:
318 results[0] += service_args[0];
319 results[1] += service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000320 break;
321 case TSP_FID_SUB:
322 results[0] -= service_args[0];
323 results[1] -= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000324 break;
325 case TSP_FID_MUL:
326 results[0] *= service_args[0];
327 results[1] *= service_args[1];
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000328 break;
329 case TSP_FID_DIV:
330 results[0] /= service_args[0] ? service_args[0] : 1;
331 results[1] /= service_args[1] ? service_args[1] : 1;
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000332 break;
333 default:
334 break;
335 }
336
Achin Gupta916a2c12014-02-09 23:11:46 +0000337 return set_smc_args(func,
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000338 results[0],
339 results[1],
Achin Gupta916a2c12014-02-09 23:11:46 +0000340 0, 0, 0, 0, 0);
Achin Gupta7c88f3f2014-02-18 18:09:12 +0000341}
342