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