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