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 __COHERENT_RAM_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 a section for coherent RAM. 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)(&__COHERENT_RAM_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 power_state, 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 suspend request. power state: 0x%x\n", 246 mpidr, power_state); 247 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", 248 mpidr, 249 tsp_stats[linear_id].smc_count, 250 tsp_stats[linear_id].eret_count, 251 tsp_stats[linear_id].cpu_suspend_count); 252 spin_unlock(&console_lock); 253 #endif 254 255 /* Indicate to the SPD that we have completed this request */ 256 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); 257 } 258 259 /******************************************************************************* 260 * This function performs any book keeping in the test secure payload after this 261 * cpu's architectural state has been restored after wakeup from an earlier psci 262 * cpu_suspend request. 263 ******************************************************************************/ 264 tsp_args_t *tsp_cpu_resume_main(uint64_t suspend_level, 265 uint64_t arg1, 266 uint64_t arg2, 267 uint64_t arg3, 268 uint64_t arg4, 269 uint64_t arg5, 270 uint64_t arg6, 271 uint64_t arg7) 272 { 273 uint64_t mpidr = read_mpidr(); 274 uint32_t linear_id = platform_get_core_pos(mpidr); 275 276 /* Restore the generic timer context */ 277 tsp_generic_timer_restore(); 278 279 /* Update this cpu's statistics */ 280 tsp_stats[linear_id].smc_count++; 281 tsp_stats[linear_id].eret_count++; 282 tsp_stats[linear_id].cpu_resume_count++; 283 284 #if LOG_LEVEL >= LOG_LEVEL_INFO 285 spin_lock(&console_lock); 286 INFO("TSP: cpu 0x%x resumed. suspend level %d\n", 287 mpidr, suspend_level); 288 INFO("TSP: cpu 0x%x: %d smcs, %d erets %d cpu suspend requests\n", 289 mpidr, 290 tsp_stats[linear_id].smc_count, 291 tsp_stats[linear_id].eret_count, 292 tsp_stats[linear_id].cpu_suspend_count); 293 spin_unlock(&console_lock); 294 #endif 295 /* Indicate to the SPD that we have completed this request */ 296 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); 297 } 298 299 /******************************************************************************* 300 * This function performs any remaining bookkeeping in the test secure payload 301 * before the system is switched off (in response to a psci SYSTEM_OFF request) 302 ******************************************************************************/ 303 tsp_args_t *tsp_system_off_main(uint64_t arg0, 304 uint64_t arg1, 305 uint64_t arg2, 306 uint64_t arg3, 307 uint64_t arg4, 308 uint64_t arg5, 309 uint64_t arg6, 310 uint64_t arg7) 311 { 312 uint64_t mpidr = read_mpidr(); 313 uint32_t linear_id = platform_get_core_pos(mpidr); 314 315 /* Update this cpu's statistics */ 316 tsp_stats[linear_id].smc_count++; 317 tsp_stats[linear_id].eret_count++; 318 319 #if LOG_LEVEL >= LOG_LEVEL_INFO 320 spin_lock(&console_lock); 321 INFO("TSP: cpu 0x%x SYSTEM_OFF request\n", mpidr); 322 INFO("TSP: cpu 0x%x: %d smcs, %d erets requests\n", mpidr, 323 tsp_stats[linear_id].smc_count, 324 tsp_stats[linear_id].eret_count); 325 spin_unlock(&console_lock); 326 #endif 327 328 /* Indicate to the SPD that we have completed this request */ 329 return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 330 } 331 332 /******************************************************************************* 333 * This function performs any remaining bookkeeping in the test secure payload 334 * before the system is reset (in response to a psci SYSTEM_RESET request) 335 ******************************************************************************/ 336 tsp_args_t *tsp_system_reset_main(uint64_t arg0, 337 uint64_t arg1, 338 uint64_t arg2, 339 uint64_t arg3, 340 uint64_t arg4, 341 uint64_t arg5, 342 uint64_t arg6, 343 uint64_t arg7) 344 { 345 uint64_t mpidr = read_mpidr(); 346 uint32_t linear_id = platform_get_core_pos(mpidr); 347 348 /* Update this cpu's statistics */ 349 tsp_stats[linear_id].smc_count++; 350 tsp_stats[linear_id].eret_count++; 351 352 #if LOG_LEVEL >= LOG_LEVEL_INFO 353 spin_lock(&console_lock); 354 INFO("TSP: cpu 0x%x SYSTEM_RESET request\n", mpidr); 355 INFO("TSP: cpu 0x%x: %d smcs, %d erets requests\n", mpidr, 356 tsp_stats[linear_id].smc_count, 357 tsp_stats[linear_id].eret_count); 358 spin_unlock(&console_lock); 359 #endif 360 361 /* Indicate to the SPD that we have completed this request */ 362 return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); 363 } 364 365 /******************************************************************************* 366 * TSP fast smc handler. The secure monitor jumps to this function by 367 * doing the ERET after populating X0-X7 registers. The arguments are received 368 * in the function arguments in order. Once the service is rendered, this 369 * function returns to Secure Monitor by raising SMC. 370 ******************************************************************************/ 371 tsp_args_t *tsp_smc_handler(uint64_t func, 372 uint64_t arg1, 373 uint64_t arg2, 374 uint64_t arg3, 375 uint64_t arg4, 376 uint64_t arg5, 377 uint64_t arg6, 378 uint64_t arg7) 379 { 380 uint64_t results[2]; 381 uint64_t service_args[2]; 382 uint64_t mpidr = read_mpidr(); 383 uint32_t linear_id = platform_get_core_pos(mpidr); 384 385 /* Update this cpu's statistics */ 386 tsp_stats[linear_id].smc_count++; 387 tsp_stats[linear_id].eret_count++; 388 389 INFO("TSP: cpu 0x%x received %s smc 0x%x\n", read_mpidr(), 390 ((func >> 31) & 1) == 1 ? "fast" : "standard", 391 func); 392 INFO("TSP: cpu 0x%x: %d smcs, %d erets\n", mpidr, 393 tsp_stats[linear_id].smc_count, 394 tsp_stats[linear_id].eret_count); 395 396 /* Render secure services and obtain results here */ 397 results[0] = arg1; 398 results[1] = arg2; 399 400 /* 401 * Request a service back from dispatcher/secure monitor. This call 402 * return and thereafter resume exectuion 403 */ 404 tsp_get_magic(service_args); 405 406 /* Determine the function to perform based on the function ID */ 407 switch (TSP_BARE_FID(func)) { 408 case TSP_ADD: 409 results[0] += service_args[0]; 410 results[1] += service_args[1]; 411 break; 412 case TSP_SUB: 413 results[0] -= service_args[0]; 414 results[1] -= service_args[1]; 415 break; 416 case TSP_MUL: 417 results[0] *= service_args[0]; 418 results[1] *= service_args[1]; 419 break; 420 case TSP_DIV: 421 results[0] /= service_args[0] ? service_args[0] : 1; 422 results[1] /= service_args[1] ? service_args[1] : 1; 423 break; 424 default: 425 break; 426 } 427 428 return set_smc_args(func, 0, 429 results[0], 430 results[1], 431 0, 0, 0, 0); 432 } 433 434