1 /* 2 * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <platform_def.h> 8 9 #include <arch_helpers.h> 10 #include <bl32/tsp/tsp.h> 11 #include <common/bl_common.h> 12 #include <common/debug.h> 13 #include <lib/spinlock.h> 14 #include <plat/common/platform.h> 15 #include <platform_tsp.h> 16 17 #include "tsp_private.h" 18 19 20 /******************************************************************************* 21 * Lock to control access to the console 22 ******************************************************************************/ 23 spinlock_t console_lock; 24 25 /******************************************************************************* 26 * Per cpu data structure to populate parameters for an SMC in C code and use 27 * a pointer to this structure in assembler code to populate x0-x7 28 ******************************************************************************/ 29 static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT]; 30 31 /******************************************************************************* 32 * Per cpu data structure to keep track of TSP activity 33 ******************************************************************************/ 34 work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; 35 36 /******************************************************************************* 37 * The TSP memory footprint starts at address BL32_BASE and ends with the 38 * linker symbol __BL32_END__. Use these addresses to compute the TSP image 39 * size. 40 ******************************************************************************/ 41 #define BL32_TOTAL_LIMIT (unsigned long)(&__BL32_END__) 42 #define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE) 43 44 static tsp_args_t *set_smc_args(uint64_t arg0, 45 uint64_t arg1, 46 uint64_t arg2, 47 uint64_t arg3, 48 uint64_t arg4, 49 uint64_t arg5, 50 uint64_t arg6, 51 uint64_t arg7) 52 { 53 uint32_t linear_id; 54 tsp_args_t *pcpu_smc_args; 55 56 /* 57 * Return to Secure Monitor by raising an SMC. The results of the 58 * service are passed as an arguments to the SMC 59 */ 60 linear_id = plat_my_core_pos(); 61 pcpu_smc_args = &tsp_smc_args[linear_id]; 62 write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0); 63 write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1); 64 write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2); 65 write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3); 66 write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4); 67 write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5); 68 write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6); 69 write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7); 70 71 return pcpu_smc_args; 72 } 73 74 /******************************************************************************* 75 * TSP main entry point where it gets the opportunity to initialize its secure 76 * state/applications. Once the state is initialized, it must return to the 77 * SPD with a pointer to the 'tsp_vector_table' jump table. 78 ******************************************************************************/ 79 uint64_t tsp_main(void) 80 { 81 NOTICE("TSP: %s\n", version_string); 82 NOTICE("TSP: %s\n", build_message); 83 INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); 84 INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); 85 86 uint32_t linear_id = plat_my_core_pos(); 87 88 /* Initialize the platform */ 89 tsp_platform_setup(); 90 91 /* Initialize secure/applications state here */ 92 tsp_generic_timer_start(); 93 94 /* Update this cpu's statistics */ 95 tsp_stats[linear_id].smc_count++; 96 tsp_stats[linear_id].eret_count++; 97 tsp_stats[linear_id].cpu_on_count++; 98 99 #if LOG_LEVEL >= LOG_LEVEL_INFO 100 spin_lock(&console_lock); 101 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 102 read_mpidr(), 103 tsp_stats[linear_id].smc_count, 104 tsp_stats[linear_id].eret_count, 105 tsp_stats[linear_id].cpu_on_count); 106 spin_unlock(&console_lock); 107 #endif 108 return (uint64_t) &tsp_vector_table; 109 } 110 111 /******************************************************************************* 112 * This function performs any remaining book keeping in the test secure payload 113 * after this cpu's architectural state has been setup in response to an earlier 114 * psci cpu_on request. 115 ******************************************************************************/ 116 tsp_args_t *tsp_cpu_on_main(void) 117 { 118 uint32_t linear_id = plat_my_core_pos(); 119 120 /* Initialize secure/applications state here */ 121 tsp_generic_timer_start(); 122 123 /* Update this cpu's statistics */ 124 tsp_stats[linear_id].smc_count++; 125 tsp_stats[linear_id].eret_count++; 126 tsp_stats[linear_id].cpu_on_count++; 127 128 #if LOG_LEVEL >= LOG_LEVEL_INFO 129 spin_lock(&console_lock); 130 INFO("TSP: cpu 0x%lx turned on\n", read_mpidr()); 131 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 132 read_mpidr(), 133 tsp_stats[linear_id].smc_count, 134 tsp_stats[linear_id].eret_count, 135 tsp_stats[linear_id].cpu_on_count); 136 spin_unlock(&console_lock); 137 #endif 138 /* Indicate to the SPD that we have completed turned ourselves on */ 139 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); 140 } 141 142 /******************************************************************************* 143 * This function performs any remaining book keeping in the test secure payload 144 * before this cpu is turned off in response to a psci cpu_off request. 145 ******************************************************************************/ 146 tsp_args_t *tsp_cpu_off_main(uint64_t arg0, 147 uint64_t arg1, 148 uint64_t arg2, 149 uint64_t arg3, 150 uint64_t arg4, 151 uint64_t arg5, 152 uint64_t arg6, 153 uint64_t arg7) 154 { 155 uint32_t linear_id = plat_my_core_pos(); 156 157 /* 158 * This cpu is being turned off, so disable the timer to prevent the 159 * secure timer interrupt from interfering with power down. A pending 160 * interrupt will be lost but we do not care as we are turning off. 161 */ 162 tsp_generic_timer_stop(); 163 164 /* Update this cpu's statistics */ 165 tsp_stats[linear_id].smc_count++; 166 tsp_stats[linear_id].eret_count++; 167 tsp_stats[linear_id].cpu_off_count++; 168 169 #if LOG_LEVEL >= LOG_LEVEL_INFO 170 spin_lock(&console_lock); 171 INFO("TSP: cpu 0x%lx off request\n", read_mpidr()); 172 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", 173 read_mpidr(), 174 tsp_stats[linear_id].smc_count, 175 tsp_stats[linear_id].eret_count, 176 tsp_stats[linear_id].cpu_off_count); 177 spin_unlock(&console_lock); 178 #endif 179 180 /* Indicate to the SPD that we have completed this request */ 181 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 182 } 183 184 /******************************************************************************* 185 * This function performs any book keeping in the test secure payload before 186 * this cpu's architectural state is saved in response to an earlier psci 187 * cpu_suspend request. 188 ******************************************************************************/ 189 tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, 190 uint64_t arg1, 191 uint64_t arg2, 192 uint64_t arg3, 193 uint64_t arg4, 194 uint64_t arg5, 195 uint64_t arg6, 196 uint64_t arg7) 197 { 198 uint32_t linear_id = plat_my_core_pos(); 199 200 /* 201 * Save the time context and disable it to prevent the secure timer 202 * interrupt from interfering with wakeup from the suspend state. 203 */ 204 tsp_generic_timer_save(); 205 tsp_generic_timer_stop(); 206 207 /* Update this cpu's statistics */ 208 tsp_stats[linear_id].smc_count++; 209 tsp_stats[linear_id].eret_count++; 210 tsp_stats[linear_id].cpu_suspend_count++; 211 212 #if LOG_LEVEL >= LOG_LEVEL_INFO 213 spin_lock(&console_lock); 214 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 215 read_mpidr(), 216 tsp_stats[linear_id].smc_count, 217 tsp_stats[linear_id].eret_count, 218 tsp_stats[linear_id].cpu_suspend_count); 219 spin_unlock(&console_lock); 220 #endif 221 222 /* Indicate to the SPD that we have completed this request */ 223 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); 224 } 225 226 /******************************************************************************* 227 * This function performs any book keeping in the test secure payload after this 228 * cpu's architectural state has been restored after wakeup from an earlier psci 229 * cpu_suspend request. 230 ******************************************************************************/ 231 tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, 232 uint64_t arg1, 233 uint64_t arg2, 234 uint64_t arg3, 235 uint64_t arg4, 236 uint64_t arg5, 237 uint64_t arg6, 238 uint64_t arg7) 239 { 240 uint32_t linear_id = plat_my_core_pos(); 241 242 /* Restore the generic timer context */ 243 tsp_generic_timer_restore(); 244 245 /* Update this cpu's statistics */ 246 tsp_stats[linear_id].smc_count++; 247 tsp_stats[linear_id].eret_count++; 248 tsp_stats[linear_id].cpu_resume_count++; 249 250 #if LOG_LEVEL >= LOG_LEVEL_INFO 251 spin_lock(&console_lock); 252 INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n", 253 read_mpidr(), max_off_pwrlvl); 254 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 255 read_mpidr(), 256 tsp_stats[linear_id].smc_count, 257 tsp_stats[linear_id].eret_count, 258 tsp_stats[linear_id].cpu_suspend_count); 259 spin_unlock(&console_lock); 260 #endif 261 /* Indicate to the SPD that we have completed this request */ 262 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); 263 } 264 265 /******************************************************************************* 266 * This function performs any remaining bookkeeping in the test secure payload 267 * before the system is switched off (in response to a psci SYSTEM_OFF request) 268 ******************************************************************************/ 269 tsp_args_t *tsp_system_off_main(uint64_t arg0, 270 uint64_t arg1, 271 uint64_t arg2, 272 uint64_t arg3, 273 uint64_t arg4, 274 uint64_t arg5, 275 uint64_t arg6, 276 uint64_t arg7) 277 { 278 uint32_t linear_id = plat_my_core_pos(); 279 280 /* Update this cpu's statistics */ 281 tsp_stats[linear_id].smc_count++; 282 tsp_stats[linear_id].eret_count++; 283 284 #if LOG_LEVEL >= LOG_LEVEL_INFO 285 spin_lock(&console_lock); 286 INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr()); 287 INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), 288 tsp_stats[linear_id].smc_count, 289 tsp_stats[linear_id].eret_count); 290 spin_unlock(&console_lock); 291 #endif 292 293 /* Indicate to the SPD that we have completed this request */ 294 return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 295 } 296 297 /******************************************************************************* 298 * This function performs any remaining bookkeeping in the test secure payload 299 * before the system is reset (in response to a psci SYSTEM_RESET request) 300 ******************************************************************************/ 301 tsp_args_t *tsp_system_reset_main(uint64_t arg0, 302 uint64_t arg1, 303 uint64_t arg2, 304 uint64_t arg3, 305 uint64_t arg4, 306 uint64_t arg5, 307 uint64_t arg6, 308 uint64_t arg7) 309 { 310 uint32_t linear_id = plat_my_core_pos(); 311 312 /* Update this cpu's statistics */ 313 tsp_stats[linear_id].smc_count++; 314 tsp_stats[linear_id].eret_count++; 315 316 #if LOG_LEVEL >= LOG_LEVEL_INFO 317 spin_lock(&console_lock); 318 INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr()); 319 INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), 320 tsp_stats[linear_id].smc_count, 321 tsp_stats[linear_id].eret_count); 322 spin_unlock(&console_lock); 323 #endif 324 325 /* Indicate to the SPD that we have completed this request */ 326 return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); 327 } 328 329 /******************************************************************************* 330 * TSP fast smc handler. The secure monitor jumps to this function by 331 * doing the ERET after populating X0-X7 registers. The arguments are received 332 * in the function arguments in order. Once the service is rendered, this 333 * function returns to Secure Monitor by raising SMC. 334 ******************************************************************************/ 335 tsp_args_t *tsp_smc_handler(uint64_t func, 336 uint64_t arg1, 337 uint64_t arg2, 338 uint64_t arg3, 339 uint64_t arg4, 340 uint64_t arg5, 341 uint64_t arg6, 342 uint64_t arg7) 343 { 344 uint64_t results[2]; 345 uint64_t service_args[2]; 346 uint32_t linear_id = plat_my_core_pos(); 347 348 /* Update this cpu's statistics */ 349 tsp_stats[linear_id].smc_count++; 350 tsp_stats[linear_id].eret_count++; 351 352 INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(), 353 ((func >> 31) & 1) == 1 ? "fast" : "yielding", 354 func); 355 INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(), 356 tsp_stats[linear_id].smc_count, 357 tsp_stats[linear_id].eret_count); 358 359 /* Render secure services and obtain results here */ 360 results[0] = arg1; 361 results[1] = arg2; 362 363 /* 364 * Request a service back from dispatcher/secure monitor. This call 365 * return and thereafter resume execution 366 */ 367 tsp_get_magic(service_args); 368 369 /* Determine the function to perform based on the function ID */ 370 switch (TSP_BARE_FID(func)) { 371 case TSP_ADD: 372 results[0] += service_args[0]; 373 results[1] += service_args[1]; 374 break; 375 case TSP_SUB: 376 results[0] -= service_args[0]; 377 results[1] -= service_args[1]; 378 break; 379 case TSP_MUL: 380 results[0] *= service_args[0]; 381 results[1] *= service_args[1]; 382 break; 383 case TSP_DIV: 384 results[0] /= service_args[0] ? service_args[0] : 1; 385 results[1] /= service_args[1] ? service_args[1] : 1; 386 break; 387 default: 388 break; 389 } 390 391 return set_smc_args(func, 0, 392 results[0], 393 results[1], 394 0, 0, 0, 0); 395 } 396 397 /******************************************************************************* 398 * TSP smc abort handler. This function is called when aborting a preempted 399 * yielding SMC request. It should cleanup all resources owned by the SMC 400 * handler such as locks or dynamically allocated memory so following SMC 401 * request are executed in a clean environment. 402 ******************************************************************************/ 403 tsp_args_t *tsp_abort_smc_handler(uint64_t func, 404 uint64_t arg1, 405 uint64_t arg2, 406 uint64_t arg3, 407 uint64_t arg4, 408 uint64_t arg5, 409 uint64_t arg6, 410 uint64_t arg7) 411 { 412 return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0); 413 } 414