xref: /rk3399_ARM-atf/bl32/tsp/tsp_main.c (revision da0af78aa230d3a873923e05643071f761f593e2)
1 /*
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 
31 #include <arch_helpers.h>
32 #include <bl_common.h>
33 #include <debug.h>
34 #include <platform.h>
35 #include <platform_def.h>
36 #include <spinlock.h>
37 #include <tsp.h>
38 #include "tsp_private.h"
39 
40 /*******************************************************************************
41  * Declarations of linker defined symbols which will help us find the layout
42  * of trusted SRAM
43  ******************************************************************************/
44 extern unsigned long __RO_START__;
45 extern unsigned long __COHERENT_RAM_END__;
46 
47 /*******************************************************************************
48  * Lock to control access to the console
49  ******************************************************************************/
50 spinlock_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  ******************************************************************************/
56 static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT];
57 
58 /*******************************************************************************
59  * Per cpu data structure to keep track of TSP activity
60  ******************************************************************************/
61 work_statistics_t tsp_stats[PLATFORM_CORE_COUNT];
62 
63 /*******************************************************************************
64  * 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 
71 static tsp_args_t *set_smc_args(uint64_t arg0,
72 			     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;
82 	tsp_args_t *pcpu_smc_args;
83 
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
105  * SPD with a pointer to the 'tsp_vector_table' jump table.
106  ******************************************************************************/
107 uint64_t tsp_main(void)
108 {
109 	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 
115 	uint64_t mpidr = read_mpidr();
116 	uint32_t linear_id = platform_get_core_pos(mpidr);
117 
118 	/* Initialize the platform */
119 	bl32_platform_setup();
120 
121 	/* Initialize secure/applications state here */
122 	tsp_generic_timer_start();
123 
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 
129 #if LOG_LEVEL >= LOG_LEVEL_INFO
130 	spin_lock(&console_lock);
131 	INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu on requests\n", mpidr,
132 	     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);
136 #endif
137 	return (uint64_t) &tsp_vector_table;
138 }
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  ******************************************************************************/
145 tsp_args_t *tsp_cpu_on_main(void)
146 {
147 	uint64_t mpidr = read_mpidr();
148 	uint32_t linear_id = platform_get_core_pos(mpidr);
149 
150 	/* Initialize secure/applications state here */
151 	tsp_generic_timer_start();
152 
153 	/* 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 
158 #if LOG_LEVEL >= LOG_LEVEL_INFO
159 	spin_lock(&console_lock);
160 	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);
165 	spin_unlock(&console_lock);
166 #endif
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  ******************************************************************************/
175 tsp_args_t *tsp_cpu_off_main(uint64_t arg0,
176 			   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 	/*
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 
194 	/* 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 
199 #if LOG_LEVEL >= LOG_LEVEL_INFO
200 	spin_lock(&console_lock);
201 	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);
206 	spin_unlock(&console_lock);
207 #endif
208 
209 	/* Indicate to the SPD that we have completed this request */
210 	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  ******************************************************************************/
218 tsp_args_t *tsp_cpu_suspend_main(uint64_t power_state,
219 			       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 
230 	/*
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 
237 	/* 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 
242 #if LOG_LEVEL >= LOG_LEVEL_INFO
243 	spin_lock(&console_lock);
244 	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);
251 	spin_unlock(&console_lock);
252 #endif
253 
254 	/* Indicate to the SPD that we have completed this request */
255 	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  ******************************************************************************/
263 tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level,
264 			      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 
275 	/* Restore the generic timer context */
276 	tsp_generic_timer_restore();
277 
278 	/* 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 
283 #if LOG_LEVEL >= LOG_LEVEL_INFO
284 	spin_lock(&console_lock);
285 	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);
292 	spin_unlock(&console_lock);
293 #endif
294 	/* Indicate to the SPD that we have completed this request */
295 	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
302  * function returns to Secure Monitor by raising SMC.
303  ******************************************************************************/
304 tsp_args_t *tsp_smc_handler(uint64_t func,
305 			       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 {
313 	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);
317 
318 	/* Update this cpu's statistics */
319 	tsp_stats[linear_id].smc_count++;
320 	tsp_stats[linear_id].eret_count++;
321 
322 	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);
328 
329 	/* Render secure services and obtain results here */
330 	results[0] = arg1;
331 	results[1] = arg2;
332 
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 */
340 	switch (TSP_BARE_FID(func)) {
341 	case TSP_ADD:
342 		results[0] += service_args[0];
343 		results[1] += service_args[1];
344 		break;
345 	case TSP_SUB:
346 		results[0] -= service_args[0];
347 		results[1] -= service_args[1];
348 		break;
349 	case TSP_MUL:
350 		results[0] *= service_args[0];
351 		results[1] *= service_args[1];
352 		break;
353 	case TSP_DIV:
354 		results[0] /= service_args[0] ? service_args[0] : 1;
355 		results[1] /= service_args[1] ? service_args[1] : 1;
356 		break;
357 	default:
358 		break;
359 	}
360 
361 	return set_smc_args(func, 0,
362 			    results[0],
363 			    results[1],
364 			    0, 0, 0, 0);
365 }
366 
367