1 /* 2 * Copyright (c) 2013-2024, Arm Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <assert.h> 8 #include <inttypes.h> 9 #include <stdint.h> 10 11 #include <arch_features.h> 12 #include <arch_helpers.h> 13 #include <bl32/tsp/tsp.h> 14 #include <bl32/tsp/tsp_el1_context.h> 15 #include <common/bl_common.h> 16 #include <common/build_message.h> 17 #include <common/debug.h> 18 #include <lib/spinlock.h> 19 #include <plat/common/platform.h> 20 #include <platform_tsp.h> 21 #include "tsp_private.h" 22 23 #include <platform_def.h> 24 25 /******************************************************************************* 26 * TSP main entry point where it gets the opportunity to initialize its secure 27 * state/applications. Once the state is initialized, it must return to the 28 * SPD with a pointer to the 'tsp_vector_table' jump table. 29 ******************************************************************************/ 30 uint64_t tsp_main(void) 31 { 32 NOTICE("TSP: %s\n", build_version_string); 33 NOTICE("TSP: %s\n", build_message); 34 INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); 35 INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); 36 37 uint32_t linear_id = plat_my_core_pos(); 38 39 /* Initialize the platform */ 40 tsp_platform_setup(); 41 42 /* Initialize secure/applications state here */ 43 tsp_generic_timer_start(); 44 45 /* Update this cpu's statistics */ 46 tsp_stats[linear_id].smc_count++; 47 tsp_stats[linear_id].eret_count++; 48 tsp_stats[linear_id].cpu_on_count++; 49 50 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 51 read_mpidr(), 52 tsp_stats[linear_id].smc_count, 53 tsp_stats[linear_id].eret_count, 54 tsp_stats[linear_id].cpu_on_count); 55 56 console_flush(); 57 return (uint64_t) &tsp_vector_table; 58 } 59 60 /******************************************************************************* 61 * This function performs any remaining book keeping in the test secure payload 62 * after this cpu's architectural state has been setup in response to an earlier 63 * psci cpu_on request. 64 ******************************************************************************/ 65 smc_args_t *tsp_cpu_on_main(void) 66 { 67 uint32_t linear_id = plat_my_core_pos(); 68 69 /* Initialize secure/applications state here */ 70 tsp_generic_timer_start(); 71 72 /* Update this cpu's statistics */ 73 tsp_stats[linear_id].smc_count++; 74 tsp_stats[linear_id].eret_count++; 75 tsp_stats[linear_id].cpu_on_count++; 76 77 INFO("TSP: cpu 0x%lx turned on\n", read_mpidr()); 78 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", 79 read_mpidr(), 80 tsp_stats[linear_id].smc_count, 81 tsp_stats[linear_id].eret_count, 82 tsp_stats[linear_id].cpu_on_count); 83 /* Indicate to the SPD that we have completed turned ourselves on */ 84 return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); 85 } 86 87 /******************************************************************************* 88 * This function performs any remaining book keeping in the test secure payload 89 * before this cpu is turned off in response to a psci cpu_off request. 90 ******************************************************************************/ 91 smc_args_t *tsp_cpu_off_main(uint64_t arg0, 92 uint64_t arg1, 93 uint64_t arg2, 94 uint64_t arg3, 95 uint64_t arg4, 96 uint64_t arg5, 97 uint64_t arg6, 98 uint64_t arg7) 99 { 100 uint32_t linear_id = plat_my_core_pos(); 101 102 /* 103 * This cpu is being turned off, so disable the timer to prevent the 104 * secure timer interrupt from interfering with power down. A pending 105 * interrupt will be lost but we do not care as we are turning off. 106 */ 107 tsp_generic_timer_stop(); 108 109 /* Update this cpu's statistics */ 110 tsp_stats[linear_id].smc_count++; 111 tsp_stats[linear_id].eret_count++; 112 tsp_stats[linear_id].cpu_off_count++; 113 114 INFO("TSP: cpu 0x%lx off request\n", read_mpidr()); 115 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", 116 read_mpidr(), 117 tsp_stats[linear_id].smc_count, 118 tsp_stats[linear_id].eret_count, 119 tsp_stats[linear_id].cpu_off_count); 120 121 /* Indicate to the SPD that we have completed this request */ 122 return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); 123 } 124 125 /******************************************************************************* 126 * This function performs any book keeping in the test secure payload before 127 * this cpu's architectural state is saved in response to an earlier psci 128 * cpu_suspend request. 129 ******************************************************************************/ 130 smc_args_t *tsp_cpu_suspend_main(uint64_t arg0, 131 uint64_t arg1, 132 uint64_t arg2, 133 uint64_t arg3, 134 uint64_t arg4, 135 uint64_t arg5, 136 uint64_t arg6, 137 uint64_t arg7) 138 { 139 uint32_t linear_id = plat_my_core_pos(); 140 141 /* 142 * Save the time context and disable it to prevent the secure timer 143 * interrupt from interfering with wakeup from the suspend state. 144 */ 145 tsp_generic_timer_save(); 146 tsp_generic_timer_stop(); 147 148 /* Update this cpu's statistics */ 149 tsp_stats[linear_id].smc_count++; 150 tsp_stats[linear_id].eret_count++; 151 tsp_stats[linear_id].cpu_suspend_count++; 152 153 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", 154 read_mpidr(), 155 tsp_stats[linear_id].smc_count, 156 tsp_stats[linear_id].eret_count, 157 tsp_stats[linear_id].cpu_suspend_count); 158 159 /* Indicate to the SPD that we have completed this request */ 160 return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); 161 } 162 163 /******************************************************************************* 164 * This function performs any book keeping in the test secure payload after this 165 * cpu's architectural state has been restored after wakeup from an earlier psci 166 * cpu_suspend request. 167 ******************************************************************************/ 168 smc_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, 169 uint64_t arg1, 170 uint64_t arg2, 171 uint64_t arg3, 172 uint64_t arg4, 173 uint64_t arg5, 174 uint64_t arg6, 175 uint64_t arg7) 176 { 177 uint32_t linear_id = plat_my_core_pos(); 178 179 /* Restore the generic timer context */ 180 tsp_generic_timer_restore(); 181 182 /* Update this cpu's statistics */ 183 tsp_stats[linear_id].smc_count++; 184 tsp_stats[linear_id].eret_count++; 185 tsp_stats[linear_id].cpu_resume_count++; 186 187 INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n", 188 read_mpidr(), max_off_pwrlvl); 189 INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n", 190 read_mpidr(), 191 tsp_stats[linear_id].smc_count, 192 tsp_stats[linear_id].eret_count, 193 tsp_stats[linear_id].cpu_resume_count); 194 /* Indicate to the SPD that we have completed this request */ 195 return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); 196 } 197 198 /******************************************************************************* 199 * TSP fast smc handler. The secure monitor jumps to this function by 200 * doing the ERET after populating X0-X7 registers. The arguments are received 201 * in the function arguments in order. Once the service is rendered, this 202 * function returns to Secure Monitor by raising SMC. 203 ******************************************************************************/ 204 smc_args_t *tsp_smc_handler(uint64_t func, 205 uint64_t arg1, 206 uint64_t arg2, 207 uint64_t arg3, 208 uint64_t arg4, 209 uint64_t arg5, 210 uint64_t arg6, 211 uint64_t arg7) 212 { 213 uint128_t service_args; 214 uint64_t service_arg0; 215 uint64_t service_arg1; 216 uint64_t results[2]; 217 uint32_t linear_id = plat_my_core_pos(); 218 u_register_t dit; 219 220 /* Update this cpu's statistics */ 221 tsp_stats[linear_id].smc_count++; 222 tsp_stats[linear_id].eret_count++; 223 224 INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(), 225 ((func >> 31) & 1) == 1 ? "fast" : "yielding", 226 func); 227 INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(), 228 tsp_stats[linear_id].smc_count, 229 tsp_stats[linear_id].eret_count); 230 231 /* Render secure services and obtain results here */ 232 results[0] = arg1; 233 results[1] = arg2; 234 235 /* 236 * Request a service back from dispatcher/secure monitor. 237 * This call returns and thereafter resumes execution. 238 */ 239 service_args = tsp_get_magic(); 240 service_arg0 = (uint64_t)service_args; 241 service_arg1 = (uint64_t)(service_args >> 64U); 242 243 /* 244 * Write a dummy value to an MTE2 register, to simulate usage in the 245 * secure world 246 */ 247 if (is_feat_mte2_supported()) { 248 write_gcr_el1(0x99); 249 } 250 251 /* Determine the function to perform based on the function ID */ 252 switch (TSP_BARE_FID(func)) { 253 case TSP_ADD: 254 results[0] += service_arg0; 255 results[1] += service_arg1; 256 break; 257 case TSP_SUB: 258 results[0] -= service_arg0; 259 results[1] -= service_arg1; 260 break; 261 case TSP_MUL: 262 results[0] *= service_arg0; 263 results[1] *= service_arg1; 264 break; 265 case TSP_DIV: 266 results[0] /= service_arg0 ? service_arg0 : 1; 267 results[1] /= service_arg1 ? service_arg1 : 1; 268 break; 269 case TSP_CHECK_DIT: 270 if (!is_feat_dit_supported()) { 271 ERROR("DIT not supported\n"); 272 results[0] = 0; 273 results[1] = 0xffff; 274 break; 275 } 276 dit = read_dit(); 277 results[0] = dit == service_arg0; 278 results[1] = dit; 279 /* Toggle the dit bit */ 280 write_dit(service_arg0 != 0U ? 0 : DIT_BIT); 281 break; 282 case TSP_MODIFY_EL1_CTX: 283 /* 284 * Write dummy values to EL1 context registers, to simulate 285 * their usage in the secure world. 286 */ 287 if (arg1 == TSP_CORRUPT_EL1_REGS) { 288 modify_el1_ctx_regs(TSP_CORRUPT_EL1_REGS); 289 } else { 290 modify_el1_ctx_regs(TSP_RESTORE_EL1_REGS); 291 } 292 break; 293 default: 294 break; 295 } 296 297 return set_smc_args(func, 0, 298 results[0], 299 results[1], 300 0, 0, 0, 0); 301 } 302