1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <inttypes.h> 10*91f16700Schasinglulu #include <stdint.h> 11*91f16700Schasinglulu #include <string.h> 12*91f16700Schasinglulu 13*91f16700Schasinglulu #include <arch_helpers.h> 14*91f16700Schasinglulu #include <arch_features.h> 15*91f16700Schasinglulu #include <bl31/bl31.h> 16*91f16700Schasinglulu #include <common/debug.h> 17*91f16700Schasinglulu #include <common/runtime_svc.h> 18*91f16700Schasinglulu #include <context.h> 19*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 20*91f16700Schasinglulu #include <lib/el3_runtime/cpu_data.h> 21*91f16700Schasinglulu #include <lib/el3_runtime/pubsub.h> 22*91f16700Schasinglulu #include <lib/extensions/pmuv3.h> 23*91f16700Schasinglulu #include <lib/extensions/sys_reg_trace.h> 24*91f16700Schasinglulu #include <lib/gpt_rme/gpt_rme.h> 25*91f16700Schasinglulu 26*91f16700Schasinglulu #include <lib/spinlock.h> 27*91f16700Schasinglulu #include <lib/utils.h> 28*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h> 29*91f16700Schasinglulu #include <plat/common/common_def.h> 30*91f16700Schasinglulu #include <plat/common/platform.h> 31*91f16700Schasinglulu #include <platform_def.h> 32*91f16700Schasinglulu #include <services/rmmd_svc.h> 33*91f16700Schasinglulu #include <smccc_helpers.h> 34*91f16700Schasinglulu #include <lib/extensions/sme.h> 35*91f16700Schasinglulu #include <lib/extensions/sve.h> 36*91f16700Schasinglulu #include "rmmd_initial_context.h" 37*91f16700Schasinglulu #include "rmmd_private.h" 38*91f16700Schasinglulu 39*91f16700Schasinglulu /******************************************************************************* 40*91f16700Schasinglulu * RMM boot failure flag 41*91f16700Schasinglulu ******************************************************************************/ 42*91f16700Schasinglulu static bool rmm_boot_failed; 43*91f16700Schasinglulu 44*91f16700Schasinglulu /******************************************************************************* 45*91f16700Schasinglulu * RMM context information. 46*91f16700Schasinglulu ******************************************************************************/ 47*91f16700Schasinglulu rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT]; 48*91f16700Schasinglulu 49*91f16700Schasinglulu /******************************************************************************* 50*91f16700Schasinglulu * RMM entry point information. Discovered on the primary core and reused 51*91f16700Schasinglulu * on secondary cores. 52*91f16700Schasinglulu ******************************************************************************/ 53*91f16700Schasinglulu static entry_point_info_t *rmm_ep_info; 54*91f16700Schasinglulu 55*91f16700Schasinglulu /******************************************************************************* 56*91f16700Schasinglulu * Static function declaration. 57*91f16700Schasinglulu ******************************************************************************/ 58*91f16700Schasinglulu static int32_t rmm_init(void); 59*91f16700Schasinglulu 60*91f16700Schasinglulu /******************************************************************************* 61*91f16700Schasinglulu * This function takes an RMM context pointer and performs a synchronous entry 62*91f16700Schasinglulu * into it. 63*91f16700Schasinglulu ******************************************************************************/ 64*91f16700Schasinglulu uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx) 65*91f16700Schasinglulu { 66*91f16700Schasinglulu uint64_t rc; 67*91f16700Schasinglulu 68*91f16700Schasinglulu assert(rmm_ctx != NULL); 69*91f16700Schasinglulu 70*91f16700Schasinglulu cm_set_context(&(rmm_ctx->cpu_ctx), REALM); 71*91f16700Schasinglulu 72*91f16700Schasinglulu /* Restore the realm context assigned above */ 73*91f16700Schasinglulu cm_el1_sysregs_context_restore(REALM); 74*91f16700Schasinglulu cm_el2_sysregs_context_restore(REALM); 75*91f16700Schasinglulu cm_set_next_eret_context(REALM); 76*91f16700Schasinglulu 77*91f16700Schasinglulu /* Enter RMM */ 78*91f16700Schasinglulu rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx); 79*91f16700Schasinglulu 80*91f16700Schasinglulu /* 81*91f16700Schasinglulu * Save realm context. EL1 and EL2 Non-secure 82*91f16700Schasinglulu * contexts will be restored before exiting to 83*91f16700Schasinglulu * Non-secure world, therefore there is no need 84*91f16700Schasinglulu * to clear EL1 and EL2 context registers. 85*91f16700Schasinglulu */ 86*91f16700Schasinglulu cm_el1_sysregs_context_save(REALM); 87*91f16700Schasinglulu cm_el2_sysregs_context_save(REALM); 88*91f16700Schasinglulu 89*91f16700Schasinglulu return rc; 90*91f16700Schasinglulu } 91*91f16700Schasinglulu 92*91f16700Schasinglulu /******************************************************************************* 93*91f16700Schasinglulu * This function returns to the place where rmmd_rmm_sync_entry() was 94*91f16700Schasinglulu * called originally. 95*91f16700Schasinglulu ******************************************************************************/ 96*91f16700Schasinglulu __dead2 void rmmd_rmm_sync_exit(uint64_t rc) 97*91f16700Schasinglulu { 98*91f16700Schasinglulu rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; 99*91f16700Schasinglulu 100*91f16700Schasinglulu /* Get context of the RMM in use by this CPU. */ 101*91f16700Schasinglulu assert(cm_get_context(REALM) == &(ctx->cpu_ctx)); 102*91f16700Schasinglulu 103*91f16700Schasinglulu /* 104*91f16700Schasinglulu * The RMMD must have initiated the original request through a 105*91f16700Schasinglulu * synchronous entry into RMM. Jump back to the original C runtime 106*91f16700Schasinglulu * context with the value of rc in x0; 107*91f16700Schasinglulu */ 108*91f16700Schasinglulu rmmd_rmm_exit(ctx->c_rt_ctx, rc); 109*91f16700Schasinglulu 110*91f16700Schasinglulu panic(); 111*91f16700Schasinglulu } 112*91f16700Schasinglulu 113*91f16700Schasinglulu static void rmm_el2_context_init(el2_sysregs_t *regs) 114*91f16700Schasinglulu { 115*91f16700Schasinglulu regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2; 116*91f16700Schasinglulu regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1; 117*91f16700Schasinglulu } 118*91f16700Schasinglulu 119*91f16700Schasinglulu /******************************************************************************* 120*91f16700Schasinglulu * Enable architecture extensions on first entry to Realm world. 121*91f16700Schasinglulu ******************************************************************************/ 122*91f16700Schasinglulu 123*91f16700Schasinglulu static void manage_extensions_realm(cpu_context_t *ctx) 124*91f16700Schasinglulu { 125*91f16700Schasinglulu pmuv3_enable(ctx); 126*91f16700Schasinglulu 127*91f16700Schasinglulu /* 128*91f16700Schasinglulu * Enable access to TPIDR2_EL0 if SME/SME2 is enabled for Non Secure world. 129*91f16700Schasinglulu */ 130*91f16700Schasinglulu if (is_feat_sme_supported()) { 131*91f16700Schasinglulu sme_enable(ctx); 132*91f16700Schasinglulu } 133*91f16700Schasinglulu } 134*91f16700Schasinglulu 135*91f16700Schasinglulu static void manage_extensions_realm_per_world(void) 136*91f16700Schasinglulu { 137*91f16700Schasinglulu if (is_feat_sve_supported()) { 138*91f16700Schasinglulu /* 139*91f16700Schasinglulu * Enable SVE and FPU in realm context when it is enabled for NS. 140*91f16700Schasinglulu * Realm manager must ensure that the SVE and FPU register 141*91f16700Schasinglulu * contexts are properly managed. 142*91f16700Schasinglulu */ 143*91f16700Schasinglulu sve_enable_per_world(&per_world_context[CPU_CONTEXT_REALM]); 144*91f16700Schasinglulu } 145*91f16700Schasinglulu 146*91f16700Schasinglulu /* NS can access this but Realm shouldn't */ 147*91f16700Schasinglulu if (is_feat_sys_reg_trace_supported()) { 148*91f16700Schasinglulu sys_reg_trace_disable_per_world(&per_world_context[CPU_CONTEXT_REALM]); 149*91f16700Schasinglulu } 150*91f16700Schasinglulu 151*91f16700Schasinglulu /* 152*91f16700Schasinglulu * If SME/SME2 is supported and enabled for NS world, then disable trapping 153*91f16700Schasinglulu * of SME instructions for Realm world. RMM will save/restore required 154*91f16700Schasinglulu * registers that are shared with SVE/FPU so that Realm can use FPU or SVE. 155*91f16700Schasinglulu */ 156*91f16700Schasinglulu if (is_feat_sme_supported()) { 157*91f16700Schasinglulu sme_enable_per_world(&per_world_context[CPU_CONTEXT_REALM]); 158*91f16700Schasinglulu } 159*91f16700Schasinglulu } 160*91f16700Schasinglulu 161*91f16700Schasinglulu /******************************************************************************* 162*91f16700Schasinglulu * Jump to the RMM for the first time. 163*91f16700Schasinglulu ******************************************************************************/ 164*91f16700Schasinglulu static int32_t rmm_init(void) 165*91f16700Schasinglulu { 166*91f16700Schasinglulu long rc; 167*91f16700Schasinglulu rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; 168*91f16700Schasinglulu 169*91f16700Schasinglulu INFO("RMM init start.\n"); 170*91f16700Schasinglulu 171*91f16700Schasinglulu /* Enable architecture extensions */ 172*91f16700Schasinglulu manage_extensions_realm(&ctx->cpu_ctx); 173*91f16700Schasinglulu 174*91f16700Schasinglulu manage_extensions_realm_per_world(); 175*91f16700Schasinglulu 176*91f16700Schasinglulu /* Initialize RMM EL2 context. */ 177*91f16700Schasinglulu rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); 178*91f16700Schasinglulu 179*91f16700Schasinglulu rc = rmmd_rmm_sync_entry(ctx); 180*91f16700Schasinglulu if (rc != E_RMM_BOOT_SUCCESS) { 181*91f16700Schasinglulu ERROR("RMM init failed: %ld\n", rc); 182*91f16700Schasinglulu /* Mark the boot as failed for all the CPUs */ 183*91f16700Schasinglulu rmm_boot_failed = true; 184*91f16700Schasinglulu return 0; 185*91f16700Schasinglulu } 186*91f16700Schasinglulu 187*91f16700Schasinglulu INFO("RMM init end.\n"); 188*91f16700Schasinglulu 189*91f16700Schasinglulu return 1; 190*91f16700Schasinglulu } 191*91f16700Schasinglulu 192*91f16700Schasinglulu /******************************************************************************* 193*91f16700Schasinglulu * Load and read RMM manifest, setup RMM. 194*91f16700Schasinglulu ******************************************************************************/ 195*91f16700Schasinglulu int rmmd_setup(void) 196*91f16700Schasinglulu { 197*91f16700Schasinglulu size_t shared_buf_size __unused; 198*91f16700Schasinglulu uintptr_t shared_buf_base; 199*91f16700Schasinglulu uint32_t ep_attr; 200*91f16700Schasinglulu unsigned int linear_id = plat_my_core_pos(); 201*91f16700Schasinglulu rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id]; 202*91f16700Schasinglulu struct rmm_manifest *manifest; 203*91f16700Schasinglulu int rc; 204*91f16700Schasinglulu 205*91f16700Schasinglulu /* Make sure RME is supported. */ 206*91f16700Schasinglulu assert(get_armv9_2_feat_rme_support() != 0U); 207*91f16700Schasinglulu 208*91f16700Schasinglulu rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM); 209*91f16700Schasinglulu if (rmm_ep_info == NULL) { 210*91f16700Schasinglulu WARN("No RMM image provided by BL2 boot loader, Booting " 211*91f16700Schasinglulu "device without RMM initialization. SMCs destined for " 212*91f16700Schasinglulu "RMM will return SMC_UNK\n"); 213*91f16700Schasinglulu return -ENOENT; 214*91f16700Schasinglulu } 215*91f16700Schasinglulu 216*91f16700Schasinglulu /* Under no circumstances will this parameter be 0 */ 217*91f16700Schasinglulu assert(rmm_ep_info->pc == RMM_BASE); 218*91f16700Schasinglulu 219*91f16700Schasinglulu /* Initialise an entrypoint to set up the CPU context */ 220*91f16700Schasinglulu ep_attr = EP_REALM; 221*91f16700Schasinglulu if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) { 222*91f16700Schasinglulu ep_attr |= EP_EE_BIG; 223*91f16700Schasinglulu } 224*91f16700Schasinglulu 225*91f16700Schasinglulu SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr); 226*91f16700Schasinglulu rmm_ep_info->spsr = SPSR_64(MODE_EL2, 227*91f16700Schasinglulu MODE_SP_ELX, 228*91f16700Schasinglulu DISABLE_ALL_EXCEPTIONS); 229*91f16700Schasinglulu 230*91f16700Schasinglulu shared_buf_size = 231*91f16700Schasinglulu plat_rmmd_get_el3_rmm_shared_mem(&shared_buf_base); 232*91f16700Schasinglulu 233*91f16700Schasinglulu assert((shared_buf_size == SZ_4K) && 234*91f16700Schasinglulu ((void *)shared_buf_base != NULL)); 235*91f16700Schasinglulu 236*91f16700Schasinglulu /* Load the boot manifest at the beginning of the shared area */ 237*91f16700Schasinglulu manifest = (struct rmm_manifest *)shared_buf_base; 238*91f16700Schasinglulu rc = plat_rmmd_load_manifest(manifest); 239*91f16700Schasinglulu if (rc != 0) { 240*91f16700Schasinglulu ERROR("Error loading RMM Boot Manifest (%i)\n", rc); 241*91f16700Schasinglulu return rc; 242*91f16700Schasinglulu } 243*91f16700Schasinglulu flush_dcache_range((uintptr_t)shared_buf_base, shared_buf_size); 244*91f16700Schasinglulu 245*91f16700Schasinglulu /* 246*91f16700Schasinglulu * Prepare coldboot arguments for RMM: 247*91f16700Schasinglulu * arg0: This CPUID (primary processor). 248*91f16700Schasinglulu * arg1: Version for this Boot Interface. 249*91f16700Schasinglulu * arg2: PLATFORM_CORE_COUNT. 250*91f16700Schasinglulu * arg3: Base address for the EL3 <-> RMM shared area. The boot 251*91f16700Schasinglulu * manifest will be stored at the beginning of this area. 252*91f16700Schasinglulu */ 253*91f16700Schasinglulu rmm_ep_info->args.arg0 = linear_id; 254*91f16700Schasinglulu rmm_ep_info->args.arg1 = RMM_EL3_INTERFACE_VERSION; 255*91f16700Schasinglulu rmm_ep_info->args.arg2 = PLATFORM_CORE_COUNT; 256*91f16700Schasinglulu rmm_ep_info->args.arg3 = shared_buf_base; 257*91f16700Schasinglulu 258*91f16700Schasinglulu /* Initialise RMM context with this entry point information */ 259*91f16700Schasinglulu cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info); 260*91f16700Schasinglulu 261*91f16700Schasinglulu INFO("RMM setup done.\n"); 262*91f16700Schasinglulu 263*91f16700Schasinglulu /* Register init function for deferred init. */ 264*91f16700Schasinglulu bl31_register_rmm_init(&rmm_init); 265*91f16700Schasinglulu 266*91f16700Schasinglulu return 0; 267*91f16700Schasinglulu } 268*91f16700Schasinglulu 269*91f16700Schasinglulu /******************************************************************************* 270*91f16700Schasinglulu * Forward SMC to the other security state 271*91f16700Schasinglulu ******************************************************************************/ 272*91f16700Schasinglulu static uint64_t rmmd_smc_forward(uint32_t src_sec_state, 273*91f16700Schasinglulu uint32_t dst_sec_state, uint64_t x0, 274*91f16700Schasinglulu uint64_t x1, uint64_t x2, uint64_t x3, 275*91f16700Schasinglulu uint64_t x4, void *handle) 276*91f16700Schasinglulu { 277*91f16700Schasinglulu cpu_context_t *ctx = cm_get_context(dst_sec_state); 278*91f16700Schasinglulu 279*91f16700Schasinglulu /* Save incoming security state */ 280*91f16700Schasinglulu cm_el1_sysregs_context_save(src_sec_state); 281*91f16700Schasinglulu cm_el2_sysregs_context_save(src_sec_state); 282*91f16700Schasinglulu 283*91f16700Schasinglulu /* Restore outgoing security state */ 284*91f16700Schasinglulu cm_el1_sysregs_context_restore(dst_sec_state); 285*91f16700Schasinglulu cm_el2_sysregs_context_restore(dst_sec_state); 286*91f16700Schasinglulu cm_set_next_eret_context(dst_sec_state); 287*91f16700Schasinglulu 288*91f16700Schasinglulu /* 289*91f16700Schasinglulu * As per SMCCCv1.2, we need to preserve x4 to x7 unless 290*91f16700Schasinglulu * being used as return args. Hence we differentiate the 291*91f16700Schasinglulu * onward and backward path. Support upto 8 args in the 292*91f16700Schasinglulu * onward path and 4 args in return path. 293*91f16700Schasinglulu * Register x4 will be preserved by RMM in case it is not 294*91f16700Schasinglulu * used in return path. 295*91f16700Schasinglulu */ 296*91f16700Schasinglulu if (src_sec_state == NON_SECURE) { 297*91f16700Schasinglulu SMC_RET8(ctx, x0, x1, x2, x3, x4, 298*91f16700Schasinglulu SMC_GET_GP(handle, CTX_GPREG_X5), 299*91f16700Schasinglulu SMC_GET_GP(handle, CTX_GPREG_X6), 300*91f16700Schasinglulu SMC_GET_GP(handle, CTX_GPREG_X7)); 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu SMC_RET5(ctx, x0, x1, x2, x3, x4); 304*91f16700Schasinglulu } 305*91f16700Schasinglulu 306*91f16700Schasinglulu /******************************************************************************* 307*91f16700Schasinglulu * This function handles all SMCs in the range reserved for RMI. Each call is 308*91f16700Schasinglulu * either forwarded to the other security state or handled by the RMM dispatcher 309*91f16700Schasinglulu ******************************************************************************/ 310*91f16700Schasinglulu uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, 311*91f16700Schasinglulu uint64_t x3, uint64_t x4, void *cookie, 312*91f16700Schasinglulu void *handle, uint64_t flags) 313*91f16700Schasinglulu { 314*91f16700Schasinglulu uint32_t src_sec_state; 315*91f16700Schasinglulu 316*91f16700Schasinglulu /* If RMM failed to boot, treat any RMI SMC as unknown */ 317*91f16700Schasinglulu if (rmm_boot_failed) { 318*91f16700Schasinglulu WARN("RMMD: Failed to boot up RMM. Ignoring RMI call\n"); 319*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 320*91f16700Schasinglulu } 321*91f16700Schasinglulu 322*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 323*91f16700Schasinglulu src_sec_state = caller_sec_state(flags); 324*91f16700Schasinglulu 325*91f16700Schasinglulu /* RMI must not be invoked by the Secure world */ 326*91f16700Schasinglulu if (src_sec_state == SMC_FROM_SECURE) { 327*91f16700Schasinglulu WARN("RMMD: RMI invoked by secure world.\n"); 328*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 329*91f16700Schasinglulu } 330*91f16700Schasinglulu 331*91f16700Schasinglulu /* 332*91f16700Schasinglulu * Forward an RMI call from the Normal world to the Realm world as it 333*91f16700Schasinglulu * is. 334*91f16700Schasinglulu */ 335*91f16700Schasinglulu if (src_sec_state == SMC_FROM_NON_SECURE) { 336*91f16700Schasinglulu /* 337*91f16700Schasinglulu * If SVE hint bit is set in the flags then update the SMC 338*91f16700Schasinglulu * function id and pass it on to the lower EL. 339*91f16700Schasinglulu */ 340*91f16700Schasinglulu if (is_sve_hint_set(flags)) { 341*91f16700Schasinglulu smc_fid |= (FUNCID_SVE_HINT_MASK << 342*91f16700Schasinglulu FUNCID_SVE_HINT_SHIFT); 343*91f16700Schasinglulu } 344*91f16700Schasinglulu VERBOSE("RMMD: RMI call from non-secure world.\n"); 345*91f16700Schasinglulu return rmmd_smc_forward(NON_SECURE, REALM, smc_fid, 346*91f16700Schasinglulu x1, x2, x3, x4, handle); 347*91f16700Schasinglulu } 348*91f16700Schasinglulu 349*91f16700Schasinglulu if (src_sec_state != SMC_FROM_REALM) { 350*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 351*91f16700Schasinglulu } 352*91f16700Schasinglulu 353*91f16700Schasinglulu switch (smc_fid) { 354*91f16700Schasinglulu case RMM_RMI_REQ_COMPLETE: { 355*91f16700Schasinglulu uint64_t x5 = SMC_GET_GP(handle, CTX_GPREG_X5); 356*91f16700Schasinglulu 357*91f16700Schasinglulu return rmmd_smc_forward(REALM, NON_SECURE, x1, 358*91f16700Schasinglulu x2, x3, x4, x5, handle); 359*91f16700Schasinglulu } 360*91f16700Schasinglulu default: 361*91f16700Schasinglulu WARN("RMMD: Unsupported RMM call 0x%08x\n", smc_fid); 362*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 363*91f16700Schasinglulu } 364*91f16700Schasinglulu } 365*91f16700Schasinglulu 366*91f16700Schasinglulu /******************************************************************************* 367*91f16700Schasinglulu * This cpu has been turned on. Enter RMM to initialise R-EL2. Entry into RMM 368*91f16700Schasinglulu * is done after initialising minimal architectural state that guarantees safe 369*91f16700Schasinglulu * execution. 370*91f16700Schasinglulu ******************************************************************************/ 371*91f16700Schasinglulu static void *rmmd_cpu_on_finish_handler(const void *arg) 372*91f16700Schasinglulu { 373*91f16700Schasinglulu long rc; 374*91f16700Schasinglulu uint32_t linear_id = plat_my_core_pos(); 375*91f16700Schasinglulu rmmd_rmm_context_t *ctx = &rmm_context[linear_id]; 376*91f16700Schasinglulu 377*91f16700Schasinglulu if (rmm_boot_failed) { 378*91f16700Schasinglulu /* RMM Boot failed on a previous CPU. Abort. */ 379*91f16700Schasinglulu ERROR("RMM Failed to initialize. Ignoring for CPU%d\n", 380*91f16700Schasinglulu linear_id); 381*91f16700Schasinglulu return NULL; 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu /* 385*91f16700Schasinglulu * Prepare warmboot arguments for RMM: 386*91f16700Schasinglulu * arg0: This CPUID. 387*91f16700Schasinglulu * arg1 to arg3: Not used. 388*91f16700Schasinglulu */ 389*91f16700Schasinglulu rmm_ep_info->args.arg0 = linear_id; 390*91f16700Schasinglulu rmm_ep_info->args.arg1 = 0ULL; 391*91f16700Schasinglulu rmm_ep_info->args.arg2 = 0ULL; 392*91f16700Schasinglulu rmm_ep_info->args.arg3 = 0ULL; 393*91f16700Schasinglulu 394*91f16700Schasinglulu /* Initialise RMM context with this entry point information */ 395*91f16700Schasinglulu cm_setup_context(&ctx->cpu_ctx, rmm_ep_info); 396*91f16700Schasinglulu 397*91f16700Schasinglulu /* Enable architecture extensions */ 398*91f16700Schasinglulu manage_extensions_realm(&ctx->cpu_ctx); 399*91f16700Schasinglulu 400*91f16700Schasinglulu /* Initialize RMM EL2 context. */ 401*91f16700Schasinglulu rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); 402*91f16700Schasinglulu 403*91f16700Schasinglulu rc = rmmd_rmm_sync_entry(ctx); 404*91f16700Schasinglulu 405*91f16700Schasinglulu if (rc != E_RMM_BOOT_SUCCESS) { 406*91f16700Schasinglulu ERROR("RMM init failed on CPU%d: %ld\n", linear_id, rc); 407*91f16700Schasinglulu /* Mark the boot as failed for any other booting CPU */ 408*91f16700Schasinglulu rmm_boot_failed = true; 409*91f16700Schasinglulu } 410*91f16700Schasinglulu 411*91f16700Schasinglulu return NULL; 412*91f16700Schasinglulu } 413*91f16700Schasinglulu 414*91f16700Schasinglulu /* Subscribe to PSCI CPU on to initialize RMM on secondary */ 415*91f16700Schasinglulu SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler); 416*91f16700Schasinglulu 417*91f16700Schasinglulu /* Convert GPT lib error to RMMD GTS error */ 418*91f16700Schasinglulu static int gpt_to_gts_error(int error, uint32_t smc_fid, uint64_t address) 419*91f16700Schasinglulu { 420*91f16700Schasinglulu int ret; 421*91f16700Schasinglulu 422*91f16700Schasinglulu if (error == 0) { 423*91f16700Schasinglulu return E_RMM_OK; 424*91f16700Schasinglulu } 425*91f16700Schasinglulu 426*91f16700Schasinglulu if (error == -EINVAL) { 427*91f16700Schasinglulu ret = E_RMM_BAD_ADDR; 428*91f16700Schasinglulu } else { 429*91f16700Schasinglulu /* This is the only other error code we expect */ 430*91f16700Schasinglulu assert(error == -EPERM); 431*91f16700Schasinglulu ret = E_RMM_BAD_PAS; 432*91f16700Schasinglulu } 433*91f16700Schasinglulu 434*91f16700Schasinglulu ERROR("RMMD: PAS Transition failed. GPT ret = %d, PA: 0x%"PRIx64 ", FID = 0x%x\n", 435*91f16700Schasinglulu error, address, smc_fid); 436*91f16700Schasinglulu return ret; 437*91f16700Schasinglulu } 438*91f16700Schasinglulu 439*91f16700Schasinglulu /******************************************************************************* 440*91f16700Schasinglulu * This function handles RMM-EL3 interface SMCs 441*91f16700Schasinglulu ******************************************************************************/ 442*91f16700Schasinglulu uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, 443*91f16700Schasinglulu uint64_t x3, uint64_t x4, void *cookie, 444*91f16700Schasinglulu void *handle, uint64_t flags) 445*91f16700Schasinglulu { 446*91f16700Schasinglulu uint32_t src_sec_state; 447*91f16700Schasinglulu int ret; 448*91f16700Schasinglulu 449*91f16700Schasinglulu /* If RMM failed to boot, treat any RMM-EL3 interface SMC as unknown */ 450*91f16700Schasinglulu if (rmm_boot_failed) { 451*91f16700Schasinglulu WARN("RMMD: Failed to boot up RMM. Ignoring RMM-EL3 call\n"); 452*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 453*91f16700Schasinglulu } 454*91f16700Schasinglulu 455*91f16700Schasinglulu /* Determine which security state this SMC originated from */ 456*91f16700Schasinglulu src_sec_state = caller_sec_state(flags); 457*91f16700Schasinglulu 458*91f16700Schasinglulu if (src_sec_state != SMC_FROM_REALM) { 459*91f16700Schasinglulu WARN("RMMD: RMM-EL3 call originated from secure or normal world\n"); 460*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 461*91f16700Schasinglulu } 462*91f16700Schasinglulu 463*91f16700Schasinglulu switch (smc_fid) { 464*91f16700Schasinglulu case RMM_GTSI_DELEGATE: 465*91f16700Schasinglulu ret = gpt_delegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); 466*91f16700Schasinglulu SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); 467*91f16700Schasinglulu case RMM_GTSI_UNDELEGATE: 468*91f16700Schasinglulu ret = gpt_undelegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); 469*91f16700Schasinglulu SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); 470*91f16700Schasinglulu case RMM_ATTEST_GET_PLAT_TOKEN: 471*91f16700Schasinglulu ret = rmmd_attest_get_platform_token(x1, &x2, x3); 472*91f16700Schasinglulu SMC_RET2(handle, ret, x2); 473*91f16700Schasinglulu case RMM_ATTEST_GET_REALM_KEY: 474*91f16700Schasinglulu ret = rmmd_attest_get_signing_key(x1, &x2, x3); 475*91f16700Schasinglulu SMC_RET2(handle, ret, x2); 476*91f16700Schasinglulu 477*91f16700Schasinglulu case RMM_BOOT_COMPLETE: 478*91f16700Schasinglulu VERBOSE("RMMD: running rmmd_rmm_sync_exit\n"); 479*91f16700Schasinglulu rmmd_rmm_sync_exit(x1); 480*91f16700Schasinglulu 481*91f16700Schasinglulu default: 482*91f16700Schasinglulu WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid); 483*91f16700Schasinglulu SMC_RET1(handle, SMC_UNK); 484*91f16700Schasinglulu } 485*91f16700Schasinglulu } 486