1 /*
2 * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <inttypes.h>
9 #include <stdint.h>
10
11 #include <arch_features.h>
12 #include <arch_helpers.h>
13 #include <bl32/tsp/tsp.h>
14 #include <common/bl_common.h>
15 #include <common/build_message.h>
16 #include <common/debug.h>
17 #include <lib/spinlock.h>
18 #include <plat/common/platform.h>
19 #include <platform_tsp.h>
20 #include "tsp_private.h"
21
22 #include <platform_def.h>
23
24 /*******************************************************************************
25 * TSP main entry point where it gets the opportunity to initialize its secure
26 * state/applications. Once the state is initialized, it must return to the
27 * SPD with a pointer to the 'tsp_vector_table' jump table.
28 ******************************************************************************/
tsp_main(void)29 uint64_t tsp_main(void)
30 {
31 NOTICE("TSP: %s\n", build_version_string);
32 NOTICE("TSP: %s\n", build_message);
33 INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE);
34 INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE);
35
36 uint32_t linear_id = plat_my_core_pos();
37
38 /* Initialize the platform */
39 tsp_platform_setup();
40
41 /* Initialize secure/applications state here */
42 tsp_generic_timer_start();
43
44 /* Update this cpu's statistics */
45 tsp_stats[linear_id].smc_count++;
46 tsp_stats[linear_id].eret_count++;
47 tsp_stats[linear_id].cpu_on_count++;
48
49 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
50 read_mpidr(),
51 tsp_stats[linear_id].smc_count,
52 tsp_stats[linear_id].eret_count,
53 tsp_stats[linear_id].cpu_on_count);
54
55 console_flush();
56 return (uint64_t) &tsp_vector_table;
57 }
58
59 /*******************************************************************************
60 * This function performs any remaining book keeping in the test secure payload
61 * after this cpu's architectural state has been setup in response to an earlier
62 * psci cpu_on request.
63 ******************************************************************************/
tsp_cpu_on_main(void)64 smc_args_t *tsp_cpu_on_main(void)
65 {
66 uint32_t linear_id = plat_my_core_pos();
67
68 /* Initialize secure/applications state here */
69 tsp_generic_timer_start();
70
71 /* Update this cpu's statistics */
72 tsp_stats[linear_id].smc_count++;
73 tsp_stats[linear_id].eret_count++;
74 tsp_stats[linear_id].cpu_on_count++;
75
76 INFO("TSP: cpu 0x%lx turned on\n", read_mpidr());
77 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n",
78 read_mpidr(),
79 tsp_stats[linear_id].smc_count,
80 tsp_stats[linear_id].eret_count,
81 tsp_stats[linear_id].cpu_on_count);
82 /* Indicate to the SPD that we have completed turned ourselves on */
83 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0);
84 }
85
86 /*******************************************************************************
87 * This function performs any remaining book keeping in the test secure payload
88 * before this cpu is turned off in response to a psci cpu_off request.
89 ******************************************************************************/
tsp_cpu_off_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)90 smc_args_t *tsp_cpu_off_main(uint64_t arg0,
91 uint64_t arg1,
92 uint64_t arg2,
93 uint64_t arg3,
94 uint64_t arg4,
95 uint64_t arg5,
96 uint64_t arg6,
97 uint64_t arg7)
98 {
99 uint32_t linear_id = plat_my_core_pos();
100
101 /*
102 * This cpu is being turned off, so disable the timer to prevent the
103 * secure timer interrupt from interfering with power down. A pending
104 * interrupt will be lost but we do not care as we are turning off.
105 */
106 tsp_generic_timer_stop();
107
108 /* Update this cpu's statistics */
109 tsp_stats[linear_id].smc_count++;
110 tsp_stats[linear_id].eret_count++;
111 tsp_stats[linear_id].cpu_off_count++;
112
113 INFO("TSP: cpu 0x%lx off request\n", read_mpidr());
114 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n",
115 read_mpidr(),
116 tsp_stats[linear_id].smc_count,
117 tsp_stats[linear_id].eret_count,
118 tsp_stats[linear_id].cpu_off_count);
119
120 /* Indicate to the SPD that we have completed this request */
121 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0);
122 }
123
124 /*******************************************************************************
125 * This function performs any book keeping in the test secure payload before
126 * this cpu's architectural state is saved in response to an earlier psci
127 * cpu_suspend request.
128 ******************************************************************************/
tsp_cpu_suspend_main(uint64_t arg0,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)129 smc_args_t *tsp_cpu_suspend_main(uint64_t arg0,
130 uint64_t arg1,
131 uint64_t arg2,
132 uint64_t arg3,
133 uint64_t arg4,
134 uint64_t arg5,
135 uint64_t arg6,
136 uint64_t arg7)
137 {
138 uint32_t linear_id = plat_my_core_pos();
139
140 /*
141 * Save the time context and disable it to prevent the secure timer
142 * interrupt from interfering with wakeup from the suspend state.
143 */
144 tsp_generic_timer_save();
145 tsp_generic_timer_stop();
146
147 /* Update this cpu's statistics */
148 tsp_stats[linear_id].smc_count++;
149 tsp_stats[linear_id].eret_count++;
150 tsp_stats[linear_id].cpu_suspend_count++;
151
152 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n",
153 read_mpidr(),
154 tsp_stats[linear_id].smc_count,
155 tsp_stats[linear_id].eret_count,
156 tsp_stats[linear_id].cpu_suspend_count);
157
158 /* Indicate to the SPD that we have completed this request */
159 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0);
160 }
161
162 /*******************************************************************************
163 * This function performs any book keeping in the test secure payload after this
164 * cpu's architectural state has been restored after wakeup from an earlier psci
165 * cpu_suspend request.
166 ******************************************************************************/
tsp_cpu_resume_main(uint64_t max_off_pwrlvl,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)167 smc_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl,
168 uint64_t arg1,
169 uint64_t arg2,
170 uint64_t arg3,
171 uint64_t arg4,
172 uint64_t arg5,
173 uint64_t arg6,
174 uint64_t arg7)
175 {
176 uint32_t linear_id = plat_my_core_pos();
177
178 /* Restore the generic timer context */
179 tsp_generic_timer_restore();
180
181 /* Update this cpu's statistics */
182 tsp_stats[linear_id].smc_count++;
183 tsp_stats[linear_id].eret_count++;
184 tsp_stats[linear_id].cpu_resume_count++;
185
186 INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n",
187 read_mpidr(), max_off_pwrlvl);
188 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n",
189 read_mpidr(),
190 tsp_stats[linear_id].smc_count,
191 tsp_stats[linear_id].eret_count,
192 tsp_stats[linear_id].cpu_resume_count);
193 /* Indicate to the SPD that we have completed this request */
194 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0);
195 }
196
197 /*******************************************************************************
198 * TSP fast smc handler. The secure monitor jumps to this function by
199 * doing the ERET after populating X0-X7 registers. The arguments are received
200 * in the function arguments in order. Once the service is rendered, this
201 * function returns to Secure Monitor by raising SMC.
202 ******************************************************************************/
tsp_smc_handler(uint64_t func,uint64_t arg1,uint64_t arg2,uint64_t arg3,uint64_t arg4,uint64_t arg5,uint64_t arg6,uint64_t arg7)203 smc_args_t *tsp_smc_handler(uint64_t func,
204 uint64_t arg1,
205 uint64_t arg2,
206 uint64_t arg3,
207 uint64_t arg4,
208 uint64_t arg5,
209 uint64_t arg6,
210 uint64_t arg7)
211 {
212 uint128_t service_args;
213 uint64_t service_arg0;
214 uint64_t service_arg1;
215 uint64_t results[2];
216 uint32_t linear_id = plat_my_core_pos();
217 u_register_t dit;
218
219 /* Update this cpu's statistics */
220 tsp_stats[linear_id].smc_count++;
221 tsp_stats[linear_id].eret_count++;
222
223 INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(),
224 ((func >> 31) & 1) == 1 ? "fast" : "yielding",
225 func);
226 INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(),
227 tsp_stats[linear_id].smc_count,
228 tsp_stats[linear_id].eret_count);
229
230 /* Render secure services and obtain results here */
231 results[0] = arg1;
232 results[1] = arg2;
233
234 /*
235 * Request a service back from dispatcher/secure monitor.
236 * This call returns and thereafter resumes execution.
237 */
238 service_args = tsp_get_magic();
239 service_arg0 = (uint64_t)service_args;
240 service_arg1 = (uint64_t)(service_args >> 64U);
241
242 /*
243 * Write a dummy value to an MTE2 register, to simulate usage in the
244 * secure world
245 */
246 if (is_feat_mte2_supported()) {
247 write_gcr_el1(0x99);
248 }
249
250 /* Determine the function to perform based on the function ID */
251 switch (TSP_BARE_FID(func)) {
252 case TSP_ADD:
253 results[0] += service_arg0;
254 results[1] += service_arg1;
255 break;
256 case TSP_SUB:
257 results[0] -= service_arg0;
258 results[1] -= service_arg1;
259 break;
260 case TSP_MUL:
261 results[0] *= service_arg0;
262 results[1] *= service_arg1;
263 break;
264 case TSP_DIV:
265 results[0] /= service_arg0 ? service_arg0 : 1;
266 results[1] /= service_arg1 ? service_arg1 : 1;
267 break;
268 case TSP_CHECK_DIT:
269 if (!is_feat_dit_supported()) {
270 ERROR("DIT not supported\n");
271 results[0] = 0;
272 results[1] = 0xffff;
273 break;
274 }
275 dit = read_dit();
276 results[0] = dit == service_arg0;
277 results[1] = dit;
278 /* Toggle the dit bit */
279 write_dit(service_arg0 != 0U ? 0 : DIT_BIT);
280 break;
281 default:
282 break;
283 }
284
285 return set_smc_args(func, 0,
286 results[0],
287 results[1],
288 0, 0, 0, 0);
289 }
290