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 int32_t ret; 316 uint32_t attr; 317 uint32_t page_count; 318 319 /* Determine which security state this SMC originated from */ 320 ns = is_caller_non_secure(flags); 321 322 if (ns == SMC_FROM_SECURE) { 323 324 /* Handle SMCs from Secure world. */ 325 326 assert(handle == cm_get_context(SECURE)); 327 328 /* Make next ERET jump to S-EL0 instead of S-EL1. */ 329 cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1()); 330 331 switch (smc_fid) { 332 333 case SPM_MM_VERSION_AARCH32: 334 SMC_RET1(handle, SPM_MM_VERSION_COMPILED); 335 336 case MM_SP_EVENT_COMPLETE_AARCH64: 337 spm_sp_synchronous_exit(x1); 338 339 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 340 INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); 341 342 if (sp_ctx.state != SP_STATE_RESET) { 343 WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); 344 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 345 } 346 347 /* x2 = page_count - 1 */ 348 page_count = x2 + 1; 349 350 ret = spm_memory_attributes_get_smc_handler( 351 &sp_ctx, x1, &page_count, &attr); 352 if (ret != SPM_MM_SUCCESS) { 353 SMC_RET1(handle, ret); 354 } else { 355 SMC_RET2(handle, attr, --page_count); 356 } 357 358 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 359 INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); 360 361 if (sp_ctx.state != SP_STATE_RESET) { 362 WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); 363 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 364 } 365 SMC_RET1(handle, 366 spm_memory_attributes_set_smc_handler( 367 &sp_ctx, x1, x2, x3)); 368 default: 369 break; 370 } 371 } else { 372 373 /* Handle SMCs from Non-secure world. */ 374 375 assert(handle == cm_get_context(NON_SECURE)); 376 377 switch (smc_fid) { 378 379 case MM_VERSION_AARCH32: 380 SMC_RET1(handle, MM_VERSION_COMPILED); 381 382 case MM_COMMUNICATE_AARCH32: 383 case MM_COMMUNICATE_AARCH64: 384 return mm_communicate(smc_fid, x1, x2, x3, handle); 385 386 case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: 387 case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: 388 /* SMC interfaces reserved for secure callers. */ 389 SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); 390 391 default: 392 break; 393 } 394 } 395 396 SMC_RET1(handle, SMC_UNK); 397 } 398