1 /* 2 * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #include <arch_helpers.h> 8 #include <assert.h> 9 #include <errno.h> 10 11 #include <bl31/bl31.h> 12 #include <bl31/ehf.h> 13 #include <common/debug.h> 14 #include <common/runtime_svc.h> 15 #include <lib/el3_runtime/context_mgmt.h> 16 #include <lib/smccc.h> 17 #include <lib/spinlock.h> 18 #include <lib/utils.h> 19 #include <lib/xlat_tables/xlat_tables_v2.h> 20 #include <plat/common/platform.h> 21 #include <services/spm_mm_partition.h> 22 #include <services/spm_mm_svc.h> 23 #include <smccc_helpers.h> 24 25 #include "spm_common.h" 26 #include "spm_mm_private.h" 27 28 /******************************************************************************* 29 * Secure Partition context information. 30 ******************************************************************************/ 31 static sp_context_t sp_ctx; 32 33 /******************************************************************************* 34 * Set state of a Secure Partition context. 35 ******************************************************************************/ 36 void sp_state_set(sp_context_t *sp_ptr, sp_state_t state) 37 { 38 spin_lock(&(sp_ptr->state_lock)); 39 sp_ptr->state = state; 40 spin_unlock(&(sp_ptr->state_lock)); 41 } 42 43 /******************************************************************************* 44 * Wait until the state of a Secure Partition is the specified one and change it 45 * to the desired state. 46 ******************************************************************************/ 47 void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) 48 { 49 int success = 0; 50 51 while (success == 0) { 52 spin_lock(&(sp_ptr->state_lock)); 53 54 if (sp_ptr->state == from) { 55 sp_ptr->state = to; 56 57 success = 1; 58 } 59 60 spin_unlock(&(sp_ptr->state_lock)); 61 } 62 } 63 64 /******************************************************************************* 65 * Check if the state of a Secure Partition is the specified one and, if so, 66 * change it to the desired state. Returns 0 on success, -1 on error. 67 ******************************************************************************/ 68 int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) 69 { 70 int ret = -1; 71 72 spin_lock(&(sp_ptr->state_lock)); 73 74 if (sp_ptr->state == from) { 75 sp_ptr->state = to; 76 77 ret = 0; 78 } 79 80 spin_unlock(&(sp_ptr->state_lock)); 81 82 return ret; 83 } 84 85 /******************************************************************************* 86 * This function takes an SP context pointer and performs a synchronous entry 87 * into it. 88 ******************************************************************************/ 89 static uint64_t spm_sp_synchronous_entry(sp_context_t *ctx) 90 { 91 uint64_t rc; 92 93 assert(ctx != NULL); 94 95 /* Assign the context of the SP to this CPU */ 96 cm_set_context(&(ctx->cpu_ctx), SECURE); 97 98 /* Restore the context assigned above */ 99 cm_el1_sysregs_context_restore(SECURE); 100 cm_set_next_eret_context(SECURE); 101 102 /* Invalidate TLBs at EL1. */ 103 tlbivmalle1(); 104 dsbish(); 105 106 /* Enter Secure Partition */ 107 rc = spm_secure_partition_enter(&ctx->c_rt_ctx); 108 109 /* Save secure state */ 110 cm_el1_sysregs_context_save(SECURE); 111 112 return rc; 113 } 114 115 /******************************************************************************* 116 * This function returns to the place where spm_sp_synchronous_entry() was 117 * called originally. 118 ******************************************************************************/ 119 __dead2 static void spm_sp_synchronous_exit(uint64_t rc) 120 { 121 sp_context_t *ctx = &sp_ctx; 122 123 /* 124 * The SPM must have initiated the original request through a 125 * synchronous entry into the secure partition. Jump back to the 126 * original C runtime context with the value of rc in x0; 127 */ 128 spm_secure_partition_exit(ctx->c_rt_ctx, rc); 129 130 panic(); 131 } 132 133 /******************************************************************************* 134 * Jump to each Secure Partition for the first time. 135 ******************************************************************************/ 136 static int32_t spm_init(void) 137 { 138 uint64_t rc; 139 sp_context_t *ctx; 140 141 INFO("Secure Partition init...\n"); 142 143 ctx = &sp_ctx; 144 145 ctx->state = SP_STATE_RESET; 146 147 rc = spm_sp_synchronous_entry(ctx); 148 assert(rc == 0); 149 150 ctx->state = SP_STATE_IDLE; 151 152 INFO("Secure Partition initialized.\n"); 153 154 return !rc; 155 } 156 157 /******************************************************************************* 158 * Initialize contexts of all Secure Partitions. 159 ******************************************************************************/ 160 int32_t spm_mm_setup(void) 161 { 162 sp_context_t *ctx; 163 164 /* Disable MMU at EL1 (initialized by BL2) */ 165 disable_mmu_icache_el1(); 166 167 /* Initialize context of the SP */ 168 INFO("Secure Partition context setup start...\n"); 169 170 ctx = &sp_ctx; 171 172 /* Assign translation tables context. */ 173 ctx->xlat_ctx_handle = spm_get_sp_xlat_context(); 174 175 spm_sp_setup(ctx); 176 177 /* Register init function for deferred init. */ 178 bl31_register_bl32_init(&spm_init); 179 180 INFO("Secure Partition setup done.\n"); 181 182 return 0; 183 } 184 185 /******************************************************************************* 186 * Function to perform a call to a Secure Partition. 187 ******************************************************************************/ 188 uint64_t spm_mm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3) 189 { 190 uint64_t rc; 191 sp_context_t *sp_ptr = &sp_ctx; 192 193 #if CTX_INCLUDE_FPREGS 194 /* 195 * SP runs to completion, no need to restore FP registers of secure context. 196 * Save FP registers only for non secure context. 197 */ 198 fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE))); 199 #endif 200 201 /* Wait until the Secure Partition is idle and set it to busy. */ 202 sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY); 203 204 /* Set values for registers on SP entry */ 205 cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx); 206 207 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); 208 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1); 209 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2); 210 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3); 211 212 /* Jump to the Secure Partition. */ 213 rc = spm_sp_synchronous_entry(sp_ptr); 214 215 /* Flag Secure Partition as idle. */ 216 assert(sp_ptr->state == SP_STATE_BUSY); 217 sp_state_set(sp_ptr, SP_STATE_IDLE); 218 219 #if CTX_INCLUDE_FPREGS 220 /* 221 * SP runs to completion, no need to save FP registers of secure context. 222 * Restore only non secure world FP registers. 223 */ 224 fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE))); 225 #endif 226 227 return rc; 228 } 229 230 /******************************************************************************* 231 * MM_COMMUNICATE handler 232 ******************************************************************************/ 233 static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, 234 uint64_t comm_buffer_address, 235 uint64_t comm_size_address, void *handle) 236 { 237 uint64_t rc; 238 239 /* Cookie. Reserved for future use. It must be zero. */ 240 if (mm_cookie != 0U) { 241 ERROR("MM_COMMUNICATE: cookie is not zero\n"); 242 SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); 243 } 244 245 if (comm_buffer_address == 0U) { 246 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n"); 247 SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); 248 } 249 250 if (comm_size_address != 0U) { 251 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n"); 252 } 253 254 /* 255 * The current secure partition design mandates 256 * - at any point, only a single core can be 257 * executing in the secure partition. 258 * - a core cannot be preempted by an interrupt 259 * while executing in secure partition. 260 * Raise the running priority of the core to the 261 * interrupt level configured for secure partition 262 * so as to block any interrupt from preempting this 263 * core. 264 */ 265 ehf_activate_priority(PLAT_SP_PRI); 266 267 /* Save the Normal world context */ 268 cm_el1_sysregs_context_save(NON_SECURE); 269 270 rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address, 271 plat_my_core_pos()); 272 273 /* Restore non-secure state */ 274 cm_el1_sysregs_context_restore(NON_SECURE); 275 cm_set_next_eret_context(NON_SECURE); 276 277 /* 278 * Exited from secure partition. This core can take 279 * interrupts now. 280 */ 281 ehf_deactivate_priority(PLAT_SP_PRI); 282 283 SMC_RET1(handle, rc); 284 } 285 286 /******************************************************************************* 287 * Secure Partition Manager SMC handler. 288 ******************************************************************************/ 289 uint64_t spm_mm_smc_handler(uint32_t smc_fid, 290 uint64_t x1, 291 uint64_t x2, 292 uint64_t x3, 293 uint64_t x4, 294 void *cookie, 295 void *handle, 296 uint64_t flags) 297 { 298 unsigned int ns; 299 300 /* Determine which security state this SMC originated from */ 301 ns = is_caller_non_secure(flags); 302 303 if (ns == SMC_FROM_SECURE) { 304 305 /* Handle SMCs from Secure world. */ 306 307 assert(handle == cm_get_context(SECURE)); 308 309 /* Make next ERET jump to S-EL0 instead of S-EL1. */ 310 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1()); 311 312 switch (smc_fid) { 313 314 case SPM_MM_VERSION_AARCH32: 315 SMC_RET1(handle, SPM_MM_VERSION_COMPILED); 316 317 case MM_SP_EVENT_COMPLETE_AARCH64: 318 spm_sp_synchronous_exit(x1); 319 320 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 321 INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); 322 323 if (sp_ctx.state != SP_STATE_RESET) { 324 WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); 325 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 326 } 327 SMC_RET1(handle, 328 spm_memory_attributes_get_smc_handler( 329 &sp_ctx, x1)); 330 331 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 332 INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); 333 334 if (sp_ctx.state != SP_STATE_RESET) { 335 WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); 336 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 337 } 338 SMC_RET1(handle, 339 spm_memory_attributes_set_smc_handler( 340 &sp_ctx, x1, x2, x3)); 341 default: 342 break; 343 } 344 } else { 345 346 /* Handle SMCs from Non-secure world. */ 347 348 assert(handle == cm_get_context(NON_SECURE)); 349 350 switch (smc_fid) { 351 352 case MM_VERSION_AARCH32: 353 SMC_RET1(handle, MM_VERSION_COMPILED); 354 355 case MM_COMMUNICATE_AARCH32: 356 case MM_COMMUNICATE_AARCH64: 357 return mm_communicate(smc_fid, x1, x2, x3, handle); 358 359 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 360 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 361 /* SMC interfaces reserved for secure callers. */ 362 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 363 364 default: 365 break; 366 } 367 } 368 369 SMC_RET1(handle, SMC_UNK); 370 } 371