Home | History | Annotate | Download | only in tsp
      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