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