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 /* Wait until the Secure Partition is idle and set it to busy. */ 194 sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY); 195 196 /* Set values for registers on SP entry */ 197 cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx); 198 199 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); 200 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1); 201 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2); 202 write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3); 203 204 /* Jump to the Secure Partition. */ 205 rc = spm_sp_synchronous_entry(sp_ptr); 206 207 /* Flag Secure Partition as idle. */ 208 assert(sp_ptr->state == SP_STATE_BUSY); 209 sp_state_set(sp_ptr, SP_STATE_IDLE); 210 211 return rc; 212 } 213 214 /******************************************************************************* 215 * MM_COMMUNICATE handler 216 ******************************************************************************/ 217 static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, 218 uint64_t comm_buffer_address, 219 uint64_t comm_size_address, void *handle) 220 { 221 uint64_t rc; 222 223 /* Cookie. Reserved for future use. It must be zero. */ 224 if (mm_cookie != 0U) { 225 ERROR("MM_COMMUNICATE: cookie is not zero\n"); 226 SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); 227 } 228 229 if (comm_buffer_address == 0U) { 230 ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n"); 231 SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); 232 } 233 234 if (comm_size_address != 0U) { 235 VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n"); 236 } 237 238 /* 239 * The current secure partition design mandates 240 * - at any point, only a single core can be 241 * executing in the secure partiton. 242 * - a core cannot be preempted by an interrupt 243 * while executing in secure partition. 244 * Raise the running priority of the core to the 245 * interrupt level configured for secure partition 246 * so as to block any interrupt from preempting this 247 * core. 248 */ 249 ehf_activate_priority(PLAT_SP_PRI); 250 251 /* Save the Normal world context */ 252 cm_el1_sysregs_context_save(NON_SECURE); 253 254 rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address, 255 plat_my_core_pos()); 256 257 /* Restore non-secure state */ 258 cm_el1_sysregs_context_restore(NON_SECURE); 259 cm_set_next_eret_context(NON_SECURE); 260 261 /* 262 * Exited from secure partition. This core can take 263 * interrupts now. 264 */ 265 ehf_deactivate_priority(PLAT_SP_PRI); 266 267 SMC_RET1(handle, rc); 268 } 269 270 /******************************************************************************* 271 * Secure Partition Manager SMC handler. 272 ******************************************************************************/ 273 uint64_t spm_mm_smc_handler(uint32_t smc_fid, 274 uint64_t x1, 275 uint64_t x2, 276 uint64_t x3, 277 uint64_t x4, 278 void *cookie, 279 void *handle, 280 uint64_t flags) 281 { 282 unsigned int ns; 283 284 /* Determine which security state this SMC originated from */ 285 ns = is_caller_non_secure(flags); 286 287 if (ns == SMC_FROM_SECURE) { 288 289 /* Handle SMCs from Secure world. */ 290 291 assert(handle == cm_get_context(SECURE)); 292 293 /* Make next ERET jump to S-EL0 instead of S-EL1. */ 294 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1()); 295 296 switch (smc_fid) { 297 298 case SPM_MM_VERSION_AARCH32: 299 SMC_RET1(handle, SPM_MM_VERSION_COMPILED); 300 301 case MM_SP_EVENT_COMPLETE_AARCH64: 302 spm_sp_synchronous_exit(x1); 303 304 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 305 INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); 306 307 if (sp_ctx.state != SP_STATE_RESET) { 308 WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); 309 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 310 } 311 SMC_RET1(handle, 312 spm_memory_attributes_get_smc_handler( 313 &sp_ctx, x1)); 314 315 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 316 INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); 317 318 if (sp_ctx.state != SP_STATE_RESET) { 319 WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); 320 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 321 } 322 SMC_RET1(handle, 323 spm_memory_attributes_set_smc_handler( 324 &sp_ctx, x1, x2, x3)); 325 default: 326 break; 327 } 328 } else { 329 330 /* Handle SMCs from Non-secure world. */ 331 332 assert(handle == cm_get_context(NON_SECURE)); 333 334 switch (smc_fid) { 335 336 case MM_VERSION_AARCH32: 337 SMC_RET1(handle, MM_VERSION_COMPILED); 338 339 case MM_COMMUNICATE_AARCH32: 340 case MM_COMMUNICATE_AARCH64: 341 return mm_communicate(smc_fid, x1, x2, x3, handle); 342 343 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 344 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 345 /* SMC interfaces reserved for secure callers. */ 346 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 347 348 default: 349 break; 350 } 351 } 352 353 SMC_RET1(handle, SMC_UNK); 354 } 355