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