1 /* 2 * Copyright (c) 2021-2022, ProvenRun S.A.S. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 /******************************************************************************* 8 * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a 9 * plug-in component to the Secure Monitor, registered as a runtime service. The 10 * SPD is expected to be a functional extension of the Secure Payload (SP) that 11 * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting 12 * the Trusted OS/Applications range to the dispatcher. The SPD will either 13 * handle the request locally or delegate it to the Secure Payload. It is also 14 * responsible for initialising and maintaining communication with the SP. 15 ******************************************************************************/ 16 17 #include <assert.h> 18 #include <errno.h> 19 #include <stddef.h> 20 #include <string.h> 21 22 #include <arch_helpers.h> 23 #include <bl31/bl31.h> 24 #include <bl31/interrupt_mgmt.h> 25 #include <bl_common.h> 26 #include <common/debug.h> 27 #include <common/ep_info.h> 28 #include <drivers/arm/gic_common.h> 29 #include <lib/el3_runtime/context_mgmt.h> 30 #include <lib/spinlock.h> 31 #include <plat/common/platform.h> 32 #include <pnc.h> 33 #include "pncd_private.h" 34 #include <runtime_svc.h> 35 #include <tools_share/uuid.h> 36 37 /******************************************************************************* 38 * Structure to keep track of ProvenCore state 39 ******************************************************************************/ 40 static pnc_context_t pncd_sp_context; 41 42 static bool ree_info; 43 static uint64_t ree_base_addr; 44 static uint64_t ree_length; 45 static uint64_t ree_tag; 46 47 static bool pnc_initialized; 48 49 static spinlock_t smc_handler_lock; 50 51 static int pncd_init(void); 52 53 static void context_save(unsigned long security_state) 54 { 55 assert(sec_state_is_valid(security_state)); 56 57 cm_el1_sysregs_context_save((uint32_t) security_state); 58 59 #if CTX_INCLUDE_FPREGS 60 simd_ctx_save((uint32_t)security_state, false); 61 #endif 62 } 63 64 static void *context_restore(unsigned long security_state) 65 { 66 void *handle; 67 68 assert(sec_state_is_valid(security_state)); 69 70 /* Get a reference to the next context */ 71 handle = cm_get_context((uint32_t) security_state); 72 assert(handle); 73 74 /* Restore state */ 75 cm_el1_sysregs_context_restore((uint32_t) security_state); 76 77 #if CTX_INCLUDE_FPREGS 78 simd_ctx_restore((uint32_t)security_state); 79 #endif 80 81 cm_set_next_eret_context((uint32_t) security_state); 82 83 return handle; 84 } 85 86 static uint64_t pncd_sel1_interrupt_handler(uint32_t id, 87 uint32_t flags, void *handle, void *cookie); 88 89 /******************************************************************************* 90 * Switch context to the specified security state and return the targeted 91 * handle. Note that the context may remain unchanged if the switch is not 92 * allowed. 93 ******************************************************************************/ 94 void *pncd_context_switch_to(unsigned long security_state) 95 { 96 unsigned long sec_state_from = 97 security_state == SECURE ? NON_SECURE : SECURE; 98 99 assert(sec_state_is_valid(security_state)); 100 101 /* Check if this is the first world switch */ 102 if (!pnc_initialized) { 103 int rc; 104 uint32_t flags; 105 106 assert(sec_state_from == SECURE); 107 108 INFO("PnC initialization done\n"); 109 110 /* 111 * Register an interrupt handler for S-EL1 interrupts 112 * when generated during code executing in the 113 * non-secure state. 114 */ 115 flags = 0U; 116 set_interrupt_rm_flag(flags, NON_SECURE); 117 rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, 118 pncd_sel1_interrupt_handler, 119 flags); 120 if (rc != 0) { 121 ERROR("Failed to register S-EL1 interrupt handler (%d)\n", 122 rc); 123 panic(); 124 } 125 126 context_save(SECURE); 127 128 pnc_initialized = true; 129 130 /* 131 * Release the lock before restoring the EL3 context to 132 * bl31_main. 133 */ 134 spin_unlock(&smc_handler_lock); 135 136 /* 137 * SP reports completion. The SPD must have initiated 138 * the original request through a synchronous entry 139 * into the SP. Jump back to the original C runtime 140 * context. 141 */ 142 pncd_synchronous_sp_exit(&pncd_sp_context, (uint64_t) 0x0); 143 144 /* Unreachable */ 145 ERROR("Returned from pncd_synchronous_sp_exit... Should not happen\n"); 146 panic(); 147 } 148 149 /* Check that the world switch is allowed */ 150 if (read_mpidr() != pncd_sp_context.mpidr) { 151 if (sec_state_from == SECURE) { 152 /* 153 * Secure -> Non-Secure world switch initiated on a CPU where there 154 * should be no Trusted OS running 155 */ 156 WARN("Secure to Non-Secure switch requested on CPU where ProvenCore is not supposed to be running...\n"); 157 } 158 159 /* 160 * Secure or Non-Secure world wants to switch world but there is no Secure 161 * software on this core 162 */ 163 return cm_get_context((uint32_t) sec_state_from); 164 } 165 166 context_save(sec_state_from); 167 168 return context_restore(security_state); 169 } 170 171 /******************************************************************************* 172 * This function is the handler registered for S-EL1 interrupts by the PNCD. It 173 * validates the interrupt and upon success arranges entry into the PNC at 174 * 'pnc_sel1_intr_entry()' for handling the interrupt. 175 ******************************************************************************/ 176 static uint64_t pncd_sel1_interrupt_handler(uint32_t id, 177 uint32_t flags, 178 void *handle, 179 void *cookie) 180 { 181 /* Check the security state when the exception was generated */ 182 assert(get_interrupt_src_ss(flags) == NON_SECURE); 183 184 /* Sanity check the pointer to this cpu's context */ 185 assert(handle == cm_get_context(NON_SECURE)); 186 187 /* switch to PnC */ 188 handle = pncd_context_switch_to(SECURE); 189 190 assert(handle != NULL); 191 192 SMC_RET0(handle); 193 } 194 195 #pragma weak plat_pncd_setup 196 int plat_pncd_setup(void) 197 { 198 return 0; 199 } 200 201 /******************************************************************************* 202 * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type 203 * (aarch32/aarch64) if not already known and initialises the context for entry 204 * into the SP for its initialisation. 205 ******************************************************************************/ 206 static int pncd_setup(void) 207 { 208 entry_point_info_t *pnc_ep_info; 209 210 /* 211 * Get information about the Secure Payload (BL32) image. Its 212 * absence is a critical failure. 213 * 214 * TODO: Add support to conditionally include the SPD service 215 */ 216 pnc_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 217 if (!pnc_ep_info) { 218 WARN("No PNC provided by BL2 boot loader, Booting device without PNC initialization. SMC`s destined for PNC will return SMC_UNK\n"); 219 return 1; 220 } 221 222 /* 223 * If there's no valid entry point for SP, we return a non-zero value 224 * signalling failure initializing the service. We bail out without 225 * registering any handlers 226 */ 227 if (!pnc_ep_info->pc) { 228 return 1; 229 } 230 231 pncd_init_pnc_ep_state(pnc_ep_info, 232 pnc_ep_info->pc, 233 &pncd_sp_context); 234 235 /* 236 * All PNCD initialization done. Now register our init function with 237 * BL31 for deferred invocation 238 */ 239 bl31_register_bl32_init(&pncd_init); 240 bl31_set_next_image_type(NON_SECURE); 241 242 return plat_pncd_setup(); 243 } 244 245 /******************************************************************************* 246 * This function passes control to the Secure Payload image (BL32) for the first 247 * time on the primary cpu after a cold boot. It assumes that a valid secure 248 * context has already been created by pncd_setup() which can be directly used. 249 * It also assumes that a valid non-secure context has been initialised by PSCI 250 * so it does not need to save and restore any non-secure state. This function 251 * performs a synchronous entry into the Secure payload. The SP passes control 252 * back to this routine through a SMC. 253 ******************************************************************************/ 254 static int32_t pncd_init(void) 255 { 256 entry_point_info_t *pnc_entry_point; 257 uint64_t rc = 0; 258 259 /* 260 * Get information about the Secure Payload (BL32) image. Its 261 * absence is a critical failure. 262 */ 263 pnc_entry_point = bl31_plat_get_next_image_ep_info(SECURE); 264 assert(pnc_entry_point); 265 266 cm_init_my_context(pnc_entry_point); 267 268 /* 269 * Arrange for an entry into the test secure payload. It will be 270 * returned via PNC_ENTRY_DONE case 271 */ 272 rc = pncd_synchronous_sp_entry(&pncd_sp_context); 273 274 /* 275 * If everything went well at this point, the return value should be 0. 276 */ 277 return rc == 0; 278 } 279 280 #pragma weak plat_pncd_smc_handler 281 /******************************************************************************* 282 * This function is responsible for handling the platform-specific SMCs in the 283 * Trusted OS/App range as defined in the SMC Calling Convention Document. 284 ******************************************************************************/ 285 uintptr_t plat_pncd_smc_handler(uint32_t smc_fid, 286 u_register_t x1, 287 u_register_t x2, 288 u_register_t x3, 289 u_register_t x4, 290 void *cookie, 291 void *handle, 292 u_register_t flags) 293 { 294 (void) smc_fid; 295 (void) x1; 296 (void) x2; 297 (void) x3; 298 (void) x4; 299 (void) cookie; 300 (void) flags; 301 302 SMC_RET1(handle, SMC_UNK); 303 } 304 305 /******************************************************************************* 306 * This function is responsible for handling all SMCs in the Trusted OS/App 307 * range as defined in the SMC Calling Convention Document. It is also 308 * responsible for communicating with the Secure payload to delegate work and 309 * return results back to the non-secure state. Lastly it will also return any 310 * information that the secure payload needs to do the work assigned to it. 311 * 312 * It should only be called with the smc_handler_lock held. 313 ******************************************************************************/ 314 static uintptr_t pncd_smc_handler_unsafe(uint32_t smc_fid, 315 u_register_t x1, 316 u_register_t x2, 317 u_register_t x3, 318 u_register_t x4, 319 void *cookie, 320 void *handle, 321 u_register_t flags) 322 { 323 uint32_t ns; 324 325 /* Determine which security state this SMC originated from */ 326 ns = is_caller_non_secure(flags); 327 328 assert(ns != 0 || read_mpidr() == pncd_sp_context.mpidr); 329 330 switch (smc_fid) { 331 case SMC_CONFIG_SHAREDMEM: 332 if (ree_info) { 333 /* Do not Yield */ 334 SMC_RET0(handle); 335 } 336 337 /* 338 * Fetch the physical base address (x1) and size (x2) of the 339 * shared memory allocated by the Non-Secure world. This memory 340 * will be used by PNC to communicate with the Non-Secure world. 341 * Verifying the validity of these values is up to the Trusted 342 * OS. 343 */ 344 ree_base_addr = x1 | (x2 << 32); 345 ree_length = x3; 346 ree_tag = x4; 347 348 INFO("IN SMC_CONFIG_SHAREDMEM: addr=%lx, length=%lx, tag=%lx\n", 349 (unsigned long) ree_base_addr, 350 (unsigned long) ree_length, 351 (unsigned long) ree_tag); 352 353 if ((ree_base_addr % 0x200000) != 0) { 354 SMC_RET1(handle, SMC_UNK); 355 } 356 357 if ((ree_length % 0x200000) != 0) { 358 SMC_RET1(handle, SMC_UNK); 359 } 360 361 ree_info = true; 362 363 /* Do not Yield */ 364 SMC_RET4(handle, 0, 0, 0, 0); 365 366 break; 367 368 case SMC_GET_SHAREDMEM: 369 if (ree_info) { 370 x1 = (1U << 16) | ree_tag; 371 x2 = ree_base_addr & 0xFFFFFFFF; 372 x3 = (ree_base_addr >> 32) & 0xFFFFFFFF; 373 x4 = ree_length & 0xFFFFFFFF; 374 SMC_RET4(handle, x1, x2, x3, x4); 375 } else { 376 SMC_RET4(handle, 0, 0, 0, 0); 377 } 378 379 break; 380 381 case SMC_ACTION_FROM_NS: 382 if (ns == 0) { 383 SMC_RET1(handle, SMC_UNK); 384 } 385 386 if (SPD_PNCD_S_IRQ < MIN_PPI_ID) { 387 plat_ic_raise_s_el1_sgi(SPD_PNCD_S_IRQ, 388 pncd_sp_context.mpidr); 389 } else { 390 plat_ic_set_interrupt_pending(SPD_PNCD_S_IRQ); 391 } 392 393 SMC_RET0(handle); 394 395 break; 396 397 case SMC_ACTION_FROM_S: 398 if (ns != 0) { 399 SMC_RET1(handle, SMC_UNK); 400 } 401 402 if (SPD_PNCD_NS_IRQ < MIN_PPI_ID) { 403 /* 404 * NS SGI is sent to the same core as the one running 405 * PNC 406 */ 407 plat_ic_raise_ns_sgi(SPD_PNCD_NS_IRQ, read_mpidr()); 408 } else { 409 plat_ic_set_interrupt_pending(SPD_PNCD_NS_IRQ); 410 } 411 412 SMC_RET0(handle); 413 414 break; 415 416 case SMC_YIELD: 417 assert(handle == cm_get_context(ns != 0 ? NON_SECURE : SECURE)); 418 handle = pncd_context_switch_to(ns != 0 ? SECURE : NON_SECURE); 419 420 assert(handle != NULL); 421 422 SMC_RET0(handle); 423 424 break; 425 426 default: 427 INFO("Unknown smc: %x\n", smc_fid); 428 break; 429 } 430 431 return plat_pncd_smc_handler(smc_fid, x1, x2, x3, x4, 432 cookie, handle, flags); 433 } 434 435 static uintptr_t pncd_smc_handler(uint32_t smc_fid, 436 u_register_t x1, 437 u_register_t x2, 438 u_register_t x3, 439 u_register_t x4, 440 void *cookie, 441 void *handle, 442 u_register_t flags) 443 { 444 uintptr_t ret; 445 446 /* SMC handling is serialized */ 447 spin_lock(&smc_handler_lock); 448 ret = pncd_smc_handler_unsafe(smc_fid, x1, x2, x3, x4, cookie, handle, 449 flags); 450 spin_unlock(&smc_handler_lock); 451 452 return ret; 453 } 454 455 /* Define a SPD runtime service descriptor for fast SMC calls */ 456 DECLARE_RT_SVC( 457 pncd_fast, 458 OEN_TOS_START, 459 OEN_TOS_END, 460 SMC_TYPE_FAST, 461 pncd_setup, 462 pncd_smc_handler 463 ); 464 465 /* Define a SPD runtime service descriptor for standard SMC calls */ 466 DECLARE_RT_SVC( 467 pncd_std, 468 OEN_TOS_START, 469 OEN_TOS_END, 470 SMC_TYPE_YIELD, 471 NULL, 472 pncd_smc_handler 473 ); 474