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 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 * Setup function for TSP. 76 ******************************************************************************/ 77 void tsp_setup(void) 78 { 79 /* Perform early platform-specific setup */ 80 tsp_early_platform_setup(); 81 82 /* 83 * Update pointer authentication key before the MMU is enabled. It is 84 * saved in the rodata section, that can be writen before enabling the 85 * MMU. This function must be called after the console is initialized 86 * in the early platform setup. 87 */ 88 bl_handle_pauth(); 89 90 /* Perform late platform-specific setup */ 91 tsp_plat_arch_setup(); 92 } 93 94 /******************************************************************************* 95 * TSP main entry point where it gets the opportunity to initialize its secure 96 * state/applications. Once the state is initialized, it must return to the 97 * SPD with a pointer to the 'tsp_vector_table' jump table. 98 ******************************************************************************/ 99 uint64_t tsp_main(void) 100 { 101 NOTICE("TSP: %s\n", version_string); 102 NOTICE("TSP: %s\n", build_message); 103 INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); 104 INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); 105 106 uint32_t linear_id = plat_my_core_pos(); 107 108 /* Initialize the platform */ 109 tsp_platform_setup(); 110 111 /* Initialize secure/applications state here */ 112 tsp_generic_timer_start(); 113 114 /* Update this cpu's statistics */ 115 tsp_stats[linear_id].smc_count++; 116 tsp_stats[linear_id].eret_count++; 117 tsp_stats[linear_id].cpu_on_count++; 118 119 #if LOG_LEVEL >= LOG_LEVEL_INFO 120 spin_lock(&console_lock); 121 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 122 read_mpidr(), 123 tsp_stats[linear_id].smc_count, 124 tsp_stats[linear_id].eret_count, 125 tsp_stats[linear_id].cpu_on_count); 126 spin_unlock(&console_lock); 127 #endif 128 return (uint64_t) &tsp_vector_table; 129 } 130 131 /******************************************************************************* 132 * This function performs any remaining book keeping in the test secure payload 133 * after this cpu's architectural state has been setup in response to an earlier 134 * psci cpu_on request. 135 ******************************************************************************/ 136 tsp_args_t *tsp_cpu_on_main(void) 137 { 138 uint32_t linear_id = plat_my_core_pos(); 139 140 /* Initialize secure/applications state here */ 141 tsp_generic_timer_start(); 142 143 /* Update this cpu's statistics */ 144 tsp_stats[linear_id].smc_count++; 145 tsp_stats[linear_id].eret_count++; 146 tsp_stats[linear_id].cpu_on_count++; 147 148 #if LOG_LEVEL >= LOG_LEVEL_INFO 149 spin_lock(&console_lock); 150 INFO("TSP: cpu 0x%lx turned on\n", read_mpidr()); 151 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 152 read_mpidr(), 153 tsp_stats[linear_id].smc_count, 154 tsp_stats[linear_id].eret_count, 155 tsp_stats[linear_id].cpu_on_count); 156 spin_unlock(&console_lock); 157 #endif 158 /* Indicate to the SPD that we have completed turned ourselves on */ 159 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); 160 } 161 162 /******************************************************************************* 163 * This function performs any remaining book keeping in the test secure payload 164 * before this cpu is turned off in response to a psci cpu_off request. 165 ******************************************************************************/ 166 tsp_args_t *tsp_cpu_off_main(uint64_t arg0, 167 uint64_t arg1, 168 uint64_t arg2, 169 uint64_t arg3, 170 uint64_t arg4, 171 uint64_t arg5, 172 uint64_t arg6, 173 uint64_t arg7) 174 { 175 uint32_t linear_id = plat_my_core_pos(); 176 177 /* 178 * This cpu is being turned off, so disable the timer to prevent the 179 * secure timer interrupt from interfering with power down. A pending 180 * interrupt will be lost but we do not care as we are turning off. 181 */ 182 tsp_generic_timer_stop(); 183 184 /* Update this cpu's statistics */ 185 tsp_stats[linear_id].smc_count++; 186 tsp_stats[linear_id].eret_count++; 187 tsp_stats[linear_id].cpu_off_count++; 188 189 #if LOG_LEVEL >= LOG_LEVEL_INFO 190 spin_lock(&console_lock); 191 INFO("TSP: cpu 0x%lx off request\n", read_mpidr()); 192 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", 193 read_mpidr(), 194 tsp_stats[linear_id].smc_count, 195 tsp_stats[linear_id].eret_count, 196 tsp_stats[linear_id].cpu_off_count); 197 spin_unlock(&console_lock); 198 #endif 199 200 /* Indicate to the SPD that we have completed this request */ 201 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 202 } 203 204 /******************************************************************************* 205 * This function performs any book keeping in the test secure payload before 206 * this cpu's architectural state is saved in response to an earlier psci 207 * cpu_suspend request. 208 ******************************************************************************/ 209 tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, 210 uint64_t arg1, 211 uint64_t arg2, 212 uint64_t arg3, 213 uint64_t arg4, 214 uint64_t arg5, 215 uint64_t arg6, 216 uint64_t arg7) 217 { 218 uint32_t linear_id = plat_my_core_pos(); 219 220 /* 221 * Save the time context and disable it to prevent the secure timer 222 * interrupt from interfering with wakeup from the suspend state. 223 */ 224 tsp_generic_timer_save(); 225 tsp_generic_timer_stop(); 226 227 /* Update this cpu's statistics */ 228 tsp_stats[linear_id].smc_count++; 229 tsp_stats[linear_id].eret_count++; 230 tsp_stats[linear_id].cpu_suspend_count++; 231 232 #if LOG_LEVEL >= LOG_LEVEL_INFO 233 spin_lock(&console_lock); 234 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 235 read_mpidr(), 236 tsp_stats[linear_id].smc_count, 237 tsp_stats[linear_id].eret_count, 238 tsp_stats[linear_id].cpu_suspend_count); 239 spin_unlock(&console_lock); 240 #endif 241 242 /* Indicate to the SPD that we have completed this request */ 243 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); 244 } 245 246 /******************************************************************************* 247 * This function performs any book keeping in the test secure payload after this 248 * cpu's architectural state has been restored after wakeup from an earlier psci 249 * cpu_suspend request. 250 ******************************************************************************/ 251 tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, 252 uint64_t arg1, 253 uint64_t arg2, 254 uint64_t arg3, 255 uint64_t arg4, 256 uint64_t arg5, 257 uint64_t arg6, 258 uint64_t arg7) 259 { 260 uint32_t linear_id = plat_my_core_pos(); 261 262 /* Restore the generic timer context */ 263 tsp_generic_timer_restore(); 264 265 /* Update this cpu's statistics */ 266 tsp_stats[linear_id].smc_count++; 267 tsp_stats[linear_id].eret_count++; 268 tsp_stats[linear_id].cpu_resume_count++; 269 270 #if LOG_LEVEL >= LOG_LEVEL_INFO 271 spin_lock(&console_lock); 272 INFO("TSP: cpu 0x%lx resumed. maximum off power level %lld\n", 273 read_mpidr(), max_off_pwrlvl); 274 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 275 read_mpidr(), 276 tsp_stats[linear_id].smc_count, 277 tsp_stats[linear_id].eret_count, 278 tsp_stats[linear_id].cpu_suspend_count); 279 spin_unlock(&console_lock); 280 #endif 281 /* Indicate to the SPD that we have completed this request */ 282 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); 283 } 284 285 /******************************************************************************* 286 * This function performs any remaining bookkeeping in the test secure payload 287 * before the system is switched off (in response to a psci SYSTEM_OFF request) 288 ******************************************************************************/ 289 tsp_args_t *tsp_system_off_main(uint64_t arg0, 290 uint64_t arg1, 291 uint64_t arg2, 292 uint64_t arg3, 293 uint64_t arg4, 294 uint64_t arg5, 295 uint64_t arg6, 296 uint64_t arg7) 297 { 298 uint32_t linear_id = plat_my_core_pos(); 299 300 /* Update this cpu's statistics */ 301 tsp_stats[linear_id].smc_count++; 302 tsp_stats[linear_id].eret_count++; 303 304 #if LOG_LEVEL >= LOG_LEVEL_INFO 305 spin_lock(&console_lock); 306 INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr()); 307 INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), 308 tsp_stats[linear_id].smc_count, 309 tsp_stats[linear_id].eret_count); 310 spin_unlock(&console_lock); 311 #endif 312 313 /* Indicate to the SPD that we have completed this request */ 314 return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 315 } 316 317 /******************************************************************************* 318 * This function performs any remaining bookkeeping in the test secure payload 319 * before the system is reset (in response to a psci SYSTEM_RESET request) 320 ******************************************************************************/ 321 tsp_args_t *tsp_system_reset_main(uint64_t arg0, 322 uint64_t arg1, 323 uint64_t arg2, 324 uint64_t arg3, 325 uint64_t arg4, 326 uint64_t arg5, 327 uint64_t arg6, 328 uint64_t arg7) 329 { 330 uint32_t linear_id = plat_my_core_pos(); 331 332 /* Update this cpu's statistics */ 333 tsp_stats[linear_id].smc_count++; 334 tsp_stats[linear_id].eret_count++; 335 336 #if LOG_LEVEL >= LOG_LEVEL_INFO 337 spin_lock(&console_lock); 338 INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr()); 339 INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), 340 tsp_stats[linear_id].smc_count, 341 tsp_stats[linear_id].eret_count); 342 spin_unlock(&console_lock); 343 #endif 344 345 /* Indicate to the SPD that we have completed this request */ 346 return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); 347 } 348 349 /******************************************************************************* 350 * TSP fast smc handler. The secure monitor jumps to this function by 351 * doing the ERET after populating X0-X7 registers. The arguments are received 352 * in the function arguments in order. Once the service is rendered, this 353 * function returns to Secure Monitor by raising SMC. 354 ******************************************************************************/ 355 tsp_args_t *tsp_smc_handler(uint64_t func, 356 uint64_t arg1, 357 uint64_t arg2, 358 uint64_t arg3, 359 uint64_t arg4, 360 uint64_t arg5, 361 uint64_t arg6, 362 uint64_t arg7) 363 { 364 uint64_t results[2]; 365 uint64_t service_args[2]; 366 uint32_t linear_id = plat_my_core_pos(); 367 368 /* Update this cpu's statistics */ 369 tsp_stats[linear_id].smc_count++; 370 tsp_stats[linear_id].eret_count++; 371 372 INFO("TSP: cpu 0x%lx received %s smc 0x%llx\n", read_mpidr(), 373 ((func >> 31) & 1) == 1 ? "fast" : "yielding", 374 func); 375 INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(), 376 tsp_stats[linear_id].smc_count, 377 tsp_stats[linear_id].eret_count); 378 379 /* Render secure services and obtain results here */ 380 results[0] = arg1; 381 results[1] = arg2; 382 383 /* 384 * Request a service back from dispatcher/secure monitor. This call 385 * return and thereafter resume execution 386 */ 387 tsp_get_magic(service_args); 388 389 /* Determine the function to perform based on the function ID */ 390 switch (TSP_BARE_FID(func)) { 391 case TSP_ADD: 392 results[0] += service_args[0]; 393 results[1] += service_args[1]; 394 break; 395 case TSP_SUB: 396 results[0] -= service_args[0]; 397 results[1] -= service_args[1]; 398 break; 399 case TSP_MUL: 400 results[0] *= service_args[0]; 401 results[1] *= service_args[1]; 402 break; 403 case TSP_DIV: 404 results[0] /= service_args[0] ? service_args[0] : 1; 405 results[1] /= service_args[1] ? service_args[1] : 1; 406 break; 407 default: 408 break; 409 } 410 411 return set_smc_args(func, 0, 412 results[0], 413 results[1], 414 0, 0, 0, 0); 415 } 416 417 /******************************************************************************* 418 * TSP smc abort handler. This function is called when aborting a preempted 419 * yielding SMC request. It should cleanup all resources owned by the SMC 420 * handler such as locks or dynamically allocated memory so following SMC 421 * request are executed in a clean environment. 422 ******************************************************************************/ 423 tsp_args_t *tsp_abort_smc_handler(uint64_t func, 424 uint64_t arg1, 425 uint64_t arg2, 426 uint64_t arg3, 427 uint64_t arg4, 428 uint64_t arg5, 429 uint64_t arg6, 430 uint64_t arg7) 431 { 432 return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0); 433 } 434