1bdd2596dSAchin Gupta /* 2cdb49d47SOlivier Deprez * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. 3bdd2596dSAchin Gupta * 4bdd2596dSAchin Gupta * SPDX-License-Identifier: BSD-3-Clause 5bdd2596dSAchin Gupta */ 6bdd2596dSAchin Gupta 7bdd2596dSAchin Gupta #include <assert.h> 8bdd2596dSAchin Gupta #include <errno.h> 94ce3e99aSScott Branden #include <inttypes.h> 104ce3e99aSScott Branden #include <stdint.h> 11bdd2596dSAchin Gupta #include <string.h> 12bdd2596dSAchin Gupta 13bdd2596dSAchin Gupta #include <arch_helpers.h> 1452696946SOlivier Deprez #include <arch/aarch64/arch_features.h> 15bdd2596dSAchin Gupta #include <bl31/bl31.h> 168cb99c3fSOlivier Deprez #include <bl31/interrupt_mgmt.h> 17bdd2596dSAchin Gupta #include <common/debug.h> 18bdd2596dSAchin Gupta #include <common/runtime_svc.h> 19bdd2596dSAchin Gupta #include <lib/el3_runtime/context_mgmt.h> 20bdd2596dSAchin Gupta #include <lib/smccc.h> 21bdd2596dSAchin Gupta #include <lib/spinlock.h> 22bdd2596dSAchin Gupta #include <lib/utils.h> 23bdd2596dSAchin Gupta #include <plat/common/common_def.h> 24bdd2596dSAchin Gupta #include <plat/common/platform.h> 25bdd2596dSAchin Gupta #include <platform_def.h> 26662af36dSJ-Alves #include <services/ffa_svc.h> 27bdd2596dSAchin Gupta #include <services/spmd_svc.h> 28bdd2596dSAchin Gupta #include <smccc_helpers.h> 29bdd2596dSAchin Gupta #include "spmd_private.h" 30bdd2596dSAchin Gupta 31bdd2596dSAchin Gupta /******************************************************************************* 32bdd2596dSAchin Gupta * SPM Core context information. 33bdd2596dSAchin Gupta ******************************************************************************/ 3452696946SOlivier Deprez static spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT]; 35bdd2596dSAchin Gupta 36bdd2596dSAchin Gupta /******************************************************************************* 37bdd2596dSAchin Gupta * SPM Core attribute information read from its manifest. 38bdd2596dSAchin Gupta ******************************************************************************/ 3952696946SOlivier Deprez static spmc_manifest_attribute_t spmc_attrs; 400f14d02fSMax Shvetsov 410f14d02fSMax Shvetsov /******************************************************************************* 420f14d02fSMax Shvetsov * SPM Core entry point information. Discovered on the primary core and reused 430f14d02fSMax Shvetsov * on secondary cores. 440f14d02fSMax Shvetsov ******************************************************************************/ 450f14d02fSMax Shvetsov static entry_point_info_t *spmc_ep_info; 460f14d02fSMax Shvetsov 470f14d02fSMax Shvetsov /******************************************************************************* 4802d50bb0SOlivier Deprez * SPM Core context on CPU based on mpidr. 4902d50bb0SOlivier Deprez ******************************************************************************/ 5002d50bb0SOlivier Deprez spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr) 5102d50bb0SOlivier Deprez { 52f7fb0bf7SMax Shvetsov int core_idx = plat_core_pos_by_mpidr(mpidr); 53f7fb0bf7SMax Shvetsov 54f7fb0bf7SMax Shvetsov if (core_idx < 0) { 554ce3e99aSScott Branden ERROR("Invalid mpidr: %" PRIx64 ", returned ID: %d\n", mpidr, core_idx); 56f7fb0bf7SMax Shvetsov panic(); 57f7fb0bf7SMax Shvetsov } 58f7fb0bf7SMax Shvetsov 59f7fb0bf7SMax Shvetsov return &spm_core_context[core_idx]; 6002d50bb0SOlivier Deprez } 6102d50bb0SOlivier Deprez 6202d50bb0SOlivier Deprez /******************************************************************************* 6352696946SOlivier Deprez * SPM Core context on current CPU get helper. 6452696946SOlivier Deprez ******************************************************************************/ 6552696946SOlivier Deprez spmd_spm_core_context_t *spmd_get_context(void) 6652696946SOlivier Deprez { 6702d50bb0SOlivier Deprez return spmd_get_context_by_mpidr(read_mpidr()); 6852696946SOlivier Deprez } 6952696946SOlivier Deprez 7052696946SOlivier Deprez /******************************************************************************* 71a92bc73bSOlivier Deprez * SPM Core ID getter. 72a92bc73bSOlivier Deprez ******************************************************************************/ 73a92bc73bSOlivier Deprez uint16_t spmd_spmc_id_get(void) 74a92bc73bSOlivier Deprez { 75a92bc73bSOlivier Deprez return spmc_attrs.spmc_id; 76a92bc73bSOlivier Deprez } 77a92bc73bSOlivier Deprez 78a92bc73bSOlivier Deprez /******************************************************************************* 790f14d02fSMax Shvetsov * Static function declaration. 800f14d02fSMax Shvetsov ******************************************************************************/ 810f14d02fSMax Shvetsov static int32_t spmd_init(void); 8223d5ba86SOlivier Deprez static int spmd_spmc_init(void *pm_addr); 83662af36dSJ-Alves static uint64_t spmd_ffa_error_return(void *handle, 8452696946SOlivier Deprez int error_code); 8552696946SOlivier Deprez static uint64_t spmd_smc_forward(uint32_t smc_fid, 8652696946SOlivier Deprez bool secure_origin, 8752696946SOlivier Deprez uint64_t x1, 8852696946SOlivier Deprez uint64_t x2, 8952696946SOlivier Deprez uint64_t x3, 9052696946SOlivier Deprez uint64_t x4, 9152696946SOlivier Deprez void *handle); 92bdd2596dSAchin Gupta 93bdd2596dSAchin Gupta /******************************************************************************* 9452696946SOlivier Deprez * This function takes an SPMC context pointer and performs a synchronous 9552696946SOlivier Deprez * SPMC entry. 96bdd2596dSAchin Gupta ******************************************************************************/ 97bdd2596dSAchin Gupta uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx) 98bdd2596dSAchin Gupta { 99bdd2596dSAchin Gupta uint64_t rc; 100bdd2596dSAchin Gupta 101bdd2596dSAchin Gupta assert(spmc_ctx != NULL); 102bdd2596dSAchin Gupta 103bdd2596dSAchin Gupta cm_set_context(&(spmc_ctx->cpu_ctx), SECURE); 104bdd2596dSAchin Gupta 105bdd2596dSAchin Gupta /* Restore the context assigned above */ 106033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 10728f39f02SMax Shvetsov cm_el2_sysregs_context_restore(SECURE); 108678ce223SOlivier Deprez #else 109678ce223SOlivier Deprez cm_el1_sysregs_context_restore(SECURE); 110033039f8SMax Shvetsov #endif 111bdd2596dSAchin Gupta cm_set_next_eret_context(SECURE); 112bdd2596dSAchin Gupta 113033039f8SMax Shvetsov /* Enter SPMC */ 114bdd2596dSAchin Gupta rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx); 115bdd2596dSAchin Gupta 116bdd2596dSAchin Gupta /* Save secure state */ 117033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 11828f39f02SMax Shvetsov cm_el2_sysregs_context_save(SECURE); 119678ce223SOlivier Deprez #else 120678ce223SOlivier Deprez cm_el1_sysregs_context_save(SECURE); 121033039f8SMax Shvetsov #endif 122bdd2596dSAchin Gupta 123bdd2596dSAchin Gupta return rc; 124bdd2596dSAchin Gupta } 125bdd2596dSAchin Gupta 126bdd2596dSAchin Gupta /******************************************************************************* 12752696946SOlivier Deprez * This function returns to the place where spmd_spm_core_sync_entry() was 128bdd2596dSAchin Gupta * called originally. 129bdd2596dSAchin Gupta ******************************************************************************/ 130bdd2596dSAchin Gupta __dead2 void spmd_spm_core_sync_exit(uint64_t rc) 131bdd2596dSAchin Gupta { 13252696946SOlivier Deprez spmd_spm_core_context_t *ctx = spmd_get_context(); 133bdd2596dSAchin Gupta 13452696946SOlivier Deprez /* Get current CPU context from SPMC context */ 135bdd2596dSAchin Gupta assert(cm_get_context(SECURE) == &(ctx->cpu_ctx)); 136bdd2596dSAchin Gupta 137bdd2596dSAchin Gupta /* 138bdd2596dSAchin Gupta * The SPMD must have initiated the original request through a 139bdd2596dSAchin Gupta * synchronous entry into SPMC. Jump back to the original C runtime 140bdd2596dSAchin Gupta * context with the value of rc in x0; 141bdd2596dSAchin Gupta */ 142bdd2596dSAchin Gupta spmd_spm_core_exit(ctx->c_rt_ctx, rc); 143bdd2596dSAchin Gupta 144bdd2596dSAchin Gupta panic(); 145bdd2596dSAchin Gupta } 146bdd2596dSAchin Gupta 147bdd2596dSAchin Gupta /******************************************************************************* 14852696946SOlivier Deprez * Jump to the SPM Core for the first time. 149bdd2596dSAchin Gupta ******************************************************************************/ 150bdd2596dSAchin Gupta static int32_t spmd_init(void) 151bdd2596dSAchin Gupta { 15252696946SOlivier Deprez spmd_spm_core_context_t *ctx = spmd_get_context(); 15352696946SOlivier Deprez uint64_t rc; 154bdd2596dSAchin Gupta 15552696946SOlivier Deprez VERBOSE("SPM Core init start.\n"); 1569dcf63ddSOlivier Deprez 157f2dcf418SOlivier Deprez /* Primary boot core enters the SPMC for initialization. */ 158f2dcf418SOlivier Deprez ctx->state = SPMC_STATE_ON_PENDING; 159bdd2596dSAchin Gupta 160bdd2596dSAchin Gupta rc = spmd_spm_core_sync_entry(ctx); 16152696946SOlivier Deprez if (rc != 0ULL) { 1624ce3e99aSScott Branden ERROR("SPMC initialisation failed 0x%" PRIx64 "\n", rc); 16352696946SOlivier Deprez return 0; 164bdd2596dSAchin Gupta } 165bdd2596dSAchin Gupta 1669dcf63ddSOlivier Deprez ctx->state = SPMC_STATE_ON; 1679dcf63ddSOlivier Deprez 16852696946SOlivier Deprez VERBOSE("SPM Core init end.\n"); 169bdd2596dSAchin Gupta 170bdd2596dSAchin Gupta return 1; 171bdd2596dSAchin Gupta } 172bdd2596dSAchin Gupta 173bdd2596dSAchin Gupta /******************************************************************************* 1748cb99c3fSOlivier Deprez * spmd_secure_interrupt_handler 1758cb99c3fSOlivier Deprez * Enter the SPMC for further handling of the secure interrupt by the SPMC 1768cb99c3fSOlivier Deprez * itself or a Secure Partition. 1778cb99c3fSOlivier Deprez ******************************************************************************/ 1788cb99c3fSOlivier Deprez static uint64_t spmd_secure_interrupt_handler(uint32_t id, 1798cb99c3fSOlivier Deprez uint32_t flags, 1808cb99c3fSOlivier Deprez void *handle, 1818cb99c3fSOlivier Deprez void *cookie) 1828cb99c3fSOlivier Deprez { 1838cb99c3fSOlivier Deprez spmd_spm_core_context_t *ctx = spmd_get_context(); 1848cb99c3fSOlivier Deprez gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 1858cb99c3fSOlivier Deprez unsigned int linear_id = plat_my_core_pos(); 1868cb99c3fSOlivier Deprez int64_t rc; 1878cb99c3fSOlivier Deprez 1888cb99c3fSOlivier Deprez /* Sanity check the security state when the exception was generated */ 1898cb99c3fSOlivier Deprez assert(get_interrupt_src_ss(flags) == NON_SECURE); 1908cb99c3fSOlivier Deprez 1918cb99c3fSOlivier Deprez /* Sanity check the pointer to this cpu's context */ 1928cb99c3fSOlivier Deprez assert(handle == cm_get_context(NON_SECURE)); 1938cb99c3fSOlivier Deprez 1948cb99c3fSOlivier Deprez /* Save the non-secure context before entering SPMC */ 1958cb99c3fSOlivier Deprez cm_el1_sysregs_context_save(NON_SECURE); 1968cb99c3fSOlivier Deprez #if SPMD_SPM_AT_SEL2 1978cb99c3fSOlivier Deprez cm_el2_sysregs_context_save(NON_SECURE); 1988cb99c3fSOlivier Deprez #endif 1998cb99c3fSOlivier Deprez 2008cb99c3fSOlivier Deprez /* Convey the event to the SPMC through the FFA_INTERRUPT interface. */ 2018cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_INTERRUPT); 2028cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X1, 0); 2038cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X2, 0); 2048cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X3, 0); 2058cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X4, 0); 2068cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X5, 0); 2078cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X6, 0); 2088cb99c3fSOlivier Deprez write_ctx_reg(gpregs, CTX_GPREG_X7, 0); 2098cb99c3fSOlivier Deprez 2108cb99c3fSOlivier Deprez /* Mark current core as handling a secure interrupt. */ 2118cb99c3fSOlivier Deprez ctx->secure_interrupt_ongoing = true; 2128cb99c3fSOlivier Deprez 2138cb99c3fSOlivier Deprez rc = spmd_spm_core_sync_entry(ctx); 2148cb99c3fSOlivier Deprez if (rc != 0ULL) { 2150c23e6f4SOlivier Deprez ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, linear_id); 2168cb99c3fSOlivier Deprez } 2178cb99c3fSOlivier Deprez 2188cb99c3fSOlivier Deprez ctx->secure_interrupt_ongoing = false; 2198cb99c3fSOlivier Deprez 2208cb99c3fSOlivier Deprez cm_el1_sysregs_context_restore(NON_SECURE); 2218cb99c3fSOlivier Deprez #if SPMD_SPM_AT_SEL2 2228cb99c3fSOlivier Deprez cm_el2_sysregs_context_restore(NON_SECURE); 2238cb99c3fSOlivier Deprez #endif 2248cb99c3fSOlivier Deprez cm_set_next_eret_context(NON_SECURE); 2258cb99c3fSOlivier Deprez 2268cb99c3fSOlivier Deprez SMC_RET0(&ctx->cpu_ctx); 2278cb99c3fSOlivier Deprez } 2288cb99c3fSOlivier Deprez 2298cb99c3fSOlivier Deprez /******************************************************************************* 23052696946SOlivier Deprez * Loads SPMC manifest and inits SPMC. 2310f14d02fSMax Shvetsov ******************************************************************************/ 23223d5ba86SOlivier Deprez static int spmd_spmc_init(void *pm_addr) 2330f14d02fSMax Shvetsov { 234f2dcf418SOlivier Deprez cpu_context_t *cpu_ctx; 235f2dcf418SOlivier Deprez unsigned int core_id; 2368cb99c3fSOlivier Deprez uint32_t ep_attr, flags; 23752696946SOlivier Deprez int rc; 2380f14d02fSMax Shvetsov 23952696946SOlivier Deprez /* Load the SPM Core manifest */ 24023d5ba86SOlivier Deprez rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr); 2410f14d02fSMax Shvetsov if (rc != 0) { 24252696946SOlivier Deprez WARN("No or invalid SPM Core manifest image provided by BL2\n"); 24352696946SOlivier Deprez return rc; 2440f14d02fSMax Shvetsov } 2450f14d02fSMax Shvetsov 2460f14d02fSMax Shvetsov /* 24752696946SOlivier Deprez * Ensure that the SPM Core version is compatible with the SPM 24852696946SOlivier Deprez * Dispatcher version. 2490f14d02fSMax Shvetsov */ 250662af36dSJ-Alves if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) || 251662af36dSJ-Alves (spmc_attrs.minor_version > FFA_VERSION_MINOR)) { 252662af36dSJ-Alves WARN("Unsupported FFA version (%u.%u)\n", 2530f14d02fSMax Shvetsov spmc_attrs.major_version, spmc_attrs.minor_version); 25452696946SOlivier Deprez return -EINVAL; 2550f14d02fSMax Shvetsov } 2560f14d02fSMax Shvetsov 257662af36dSJ-Alves VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version, 2580f14d02fSMax Shvetsov spmc_attrs.minor_version); 2590f14d02fSMax Shvetsov 26052696946SOlivier Deprez VERBOSE("SPM Core run time EL%x.\n", 261033039f8SMax Shvetsov SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1); 2620f14d02fSMax Shvetsov 263ac03ac5eSMax Shvetsov /* Validate the SPMC ID, Ensure high bit is set */ 26452696946SOlivier Deprez if (((spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) & 26552696946SOlivier Deprez SPMC_SECURE_ID_MASK) == 0U) { 26652696946SOlivier Deprez WARN("Invalid ID (0x%x) for SPMC.\n", spmc_attrs.spmc_id); 26752696946SOlivier Deprez return -EINVAL; 268ac03ac5eSMax Shvetsov } 269ac03ac5eSMax Shvetsov 27052696946SOlivier Deprez /* Validate the SPM Core execution state */ 2710f14d02fSMax Shvetsov if ((spmc_attrs.exec_state != MODE_RW_64) && 2720f14d02fSMax Shvetsov (spmc_attrs.exec_state != MODE_RW_32)) { 27323d5ba86SOlivier Deprez WARN("Unsupported %s%x.\n", "SPM Core execution state 0x", 2740f14d02fSMax Shvetsov spmc_attrs.exec_state); 27552696946SOlivier Deprez return -EINVAL; 2760f14d02fSMax Shvetsov } 2770f14d02fSMax Shvetsov 27823d5ba86SOlivier Deprez VERBOSE("%s%x.\n", "SPM Core execution state 0x", 27923d5ba86SOlivier Deprez spmc_attrs.exec_state); 2800f14d02fSMax Shvetsov 281033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 282033039f8SMax Shvetsov /* Ensure manifest has not requested AArch32 state in S-EL2 */ 283033039f8SMax Shvetsov if (spmc_attrs.exec_state == MODE_RW_32) { 284033039f8SMax Shvetsov WARN("AArch32 state at S-EL2 is not supported.\n"); 28552696946SOlivier Deprez return -EINVAL; 2860f14d02fSMax Shvetsov } 2870f14d02fSMax Shvetsov 2880f14d02fSMax Shvetsov /* 2890f14d02fSMax Shvetsov * Check if S-EL2 is supported on this system if S-EL2 2900f14d02fSMax Shvetsov * is required for SPM 2910f14d02fSMax Shvetsov */ 29252696946SOlivier Deprez if (!is_armv8_4_sel2_present()) { 29352696946SOlivier Deprez WARN("SPM Core run time S-EL2 is not supported.\n"); 29452696946SOlivier Deprez return -EINVAL; 2950f14d02fSMax Shvetsov } 296033039f8SMax Shvetsov #endif /* SPMD_SPM_AT_SEL2 */ 2970f14d02fSMax Shvetsov 2980f14d02fSMax Shvetsov /* Initialise an entrypoint to set up the CPU context */ 2990f14d02fSMax Shvetsov ep_attr = SECURE | EP_ST_ENABLE; 30052696946SOlivier Deprez if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0ULL) { 3010f14d02fSMax Shvetsov ep_attr |= EP_EE_BIG; 3020f14d02fSMax Shvetsov } 3030f14d02fSMax Shvetsov 3040f14d02fSMax Shvetsov SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr); 3050f14d02fSMax Shvetsov 3060f14d02fSMax Shvetsov /* 30752696946SOlivier Deprez * Populate SPSR for SPM Core based upon validated parameters from the 30852696946SOlivier Deprez * manifest. 3090f14d02fSMax Shvetsov */ 3100f14d02fSMax Shvetsov if (spmc_attrs.exec_state == MODE_RW_32) { 3110f14d02fSMax Shvetsov spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, 3120f14d02fSMax Shvetsov SPSR_E_LITTLE, 3130f14d02fSMax Shvetsov DAIF_FIQ_BIT | 3140f14d02fSMax Shvetsov DAIF_IRQ_BIT | 3150f14d02fSMax Shvetsov DAIF_ABT_BIT); 3160f14d02fSMax Shvetsov } else { 317033039f8SMax Shvetsov 318033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 319033039f8SMax Shvetsov static const uint32_t runtime_el = MODE_EL2; 320033039f8SMax Shvetsov #else 321033039f8SMax Shvetsov static const uint32_t runtime_el = MODE_EL1; 322033039f8SMax Shvetsov #endif 323033039f8SMax Shvetsov spmc_ep_info->spsr = SPSR_64(runtime_el, 3240f14d02fSMax Shvetsov MODE_SP_ELX, 3250f14d02fSMax Shvetsov DISABLE_ALL_EXCEPTIONS); 3260f14d02fSMax Shvetsov } 3270f14d02fSMax Shvetsov 328f2dcf418SOlivier Deprez /* Set an initial SPMC context state for all cores. */ 329f2dcf418SOlivier Deprez for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { 330f2dcf418SOlivier Deprez spm_core_context[core_id].state = SPMC_STATE_OFF; 3310f14d02fSMax Shvetsov 332f2dcf418SOlivier Deprez /* Setup an initial cpu context for the SPMC. */ 333f2dcf418SOlivier Deprez cpu_ctx = &spm_core_context[core_id].cpu_ctx; 334f2dcf418SOlivier Deprez cm_setup_context(cpu_ctx, spmc_ep_info); 3350f14d02fSMax Shvetsov 336f2dcf418SOlivier Deprez /* 337f2dcf418SOlivier Deprez * Pass the core linear ID to the SPMC through x4. 338f2dcf418SOlivier Deprez * (TF-A implementation defined behavior helping 339f2dcf418SOlivier Deprez * a legacy TOS migration to adopt FF-A). 340f2dcf418SOlivier Deprez */ 341f2dcf418SOlivier Deprez write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id); 342f2dcf418SOlivier Deprez } 3430f14d02fSMax Shvetsov 344a334c4e6SOlivier Deprez /* Register power management hooks with PSCI */ 345a334c4e6SOlivier Deprez psci_register_spd_pm_hook(&spmd_pm); 346a334c4e6SOlivier Deprez 3470f14d02fSMax Shvetsov /* Register init function for deferred init. */ 3480f14d02fSMax Shvetsov bl31_register_bl32_init(&spmd_init); 3490f14d02fSMax Shvetsov 350f2dcf418SOlivier Deprez INFO("SPM Core setup done.\n"); 351f2dcf418SOlivier Deprez 3528cb99c3fSOlivier Deprez /* 3538cb99c3fSOlivier Deprez * Register an interrupt handler routing secure interrupts to SPMD 3548cb99c3fSOlivier Deprez * while the NWd is running. 3558cb99c3fSOlivier Deprez */ 3568cb99c3fSOlivier Deprez flags = 0; 3578cb99c3fSOlivier Deprez set_interrupt_rm_flag(flags, NON_SECURE); 3588cb99c3fSOlivier Deprez rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, 3598cb99c3fSOlivier Deprez spmd_secure_interrupt_handler, 3608cb99c3fSOlivier Deprez flags); 3618cb99c3fSOlivier Deprez if (rc != 0) { 3628cb99c3fSOlivier Deprez panic(); 3638cb99c3fSOlivier Deprez } 3648cb99c3fSOlivier Deprez 3650f14d02fSMax Shvetsov return 0; 3660f14d02fSMax Shvetsov } 3670f14d02fSMax Shvetsov 3680f14d02fSMax Shvetsov /******************************************************************************* 36952696946SOlivier Deprez * Initialize context of SPM Core. 370bdd2596dSAchin Gupta ******************************************************************************/ 3710f14d02fSMax Shvetsov int spmd_setup(void) 372bdd2596dSAchin Gupta { 37323d5ba86SOlivier Deprez void *spmc_manifest; 374bdd2596dSAchin Gupta int rc; 375bdd2596dSAchin Gupta 376bdd2596dSAchin Gupta spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 37752696946SOlivier Deprez if (spmc_ep_info == NULL) { 37852696946SOlivier Deprez WARN("No SPM Core image provided by BL2 boot loader.\n"); 37952696946SOlivier Deprez return -EINVAL; 380bdd2596dSAchin Gupta } 381bdd2596dSAchin Gupta 382bdd2596dSAchin Gupta /* Under no circumstances will this parameter be 0 */ 38352696946SOlivier Deprez assert(spmc_ep_info->pc != 0ULL); 384bdd2596dSAchin Gupta 385bdd2596dSAchin Gupta /* 386bdd2596dSAchin Gupta * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will 38752696946SOlivier Deprez * be used as a manifest for the SPM Core at the next lower EL/mode. 388bdd2596dSAchin Gupta */ 38923d5ba86SOlivier Deprez spmc_manifest = (void *)spmc_ep_info->args.arg0; 39023d5ba86SOlivier Deprez if (spmc_manifest == NULL) { 39123d5ba86SOlivier Deprez ERROR("Invalid or absent SPM Core manifest.\n"); 39223d5ba86SOlivier Deprez return -EINVAL; 393bdd2596dSAchin Gupta } 394bdd2596dSAchin Gupta 3950f14d02fSMax Shvetsov /* Load manifest, init SPMC */ 39623d5ba86SOlivier Deprez rc = spmd_spmc_init(spmc_manifest); 3970f14d02fSMax Shvetsov if (rc != 0) { 39852696946SOlivier Deprez WARN("Booting device without SPM initialization.\n"); 399bdd2596dSAchin Gupta } 400bdd2596dSAchin Gupta 4010f14d02fSMax Shvetsov return rc; 4020f14d02fSMax Shvetsov } 4030f14d02fSMax Shvetsov 4040f14d02fSMax Shvetsov /******************************************************************************* 4050f14d02fSMax Shvetsov * Forward SMC to the other security state 4060f14d02fSMax Shvetsov ******************************************************************************/ 40752696946SOlivier Deprez static uint64_t spmd_smc_forward(uint32_t smc_fid, 40852696946SOlivier Deprez bool secure_origin, 40952696946SOlivier Deprez uint64_t x1, 41052696946SOlivier Deprez uint64_t x2, 41152696946SOlivier Deprez uint64_t x3, 41252696946SOlivier Deprez uint64_t x4, 41352696946SOlivier Deprez void *handle) 4140f14d02fSMax Shvetsov { 415c2901419SOlivier Deprez unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE; 416c2901419SOlivier Deprez unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE; 41793ff138bSOlivier Deprez 4180f14d02fSMax Shvetsov /* Save incoming security state */ 419033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 420678ce223SOlivier Deprez if (secure_state_in == NON_SECURE) { 421678ce223SOlivier Deprez cm_el1_sysregs_context_save(secure_state_in); 422678ce223SOlivier Deprez } 42393ff138bSOlivier Deprez cm_el2_sysregs_context_save(secure_state_in); 424678ce223SOlivier Deprez #else 425678ce223SOlivier Deprez cm_el1_sysregs_context_save(secure_state_in); 426033039f8SMax Shvetsov #endif 4270f14d02fSMax Shvetsov 4280f14d02fSMax Shvetsov /* Restore outgoing security state */ 429033039f8SMax Shvetsov #if SPMD_SPM_AT_SEL2 430678ce223SOlivier Deprez if (secure_state_out == NON_SECURE) { 431678ce223SOlivier Deprez cm_el1_sysregs_context_restore(secure_state_out); 432678ce223SOlivier Deprez } 43393ff138bSOlivier Deprez cm_el2_sysregs_context_restore(secure_state_out); 434678ce223SOlivier Deprez #else 435678ce223SOlivier Deprez cm_el1_sysregs_context_restore(secure_state_out); 436033039f8SMax Shvetsov #endif 43793ff138bSOlivier Deprez cm_set_next_eret_context(secure_state_out); 4380f14d02fSMax Shvetsov 43993ff138bSOlivier Deprez SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4, 4400f14d02fSMax Shvetsov SMC_GET_GP(handle, CTX_GPREG_X5), 4410f14d02fSMax Shvetsov SMC_GET_GP(handle, CTX_GPREG_X6), 4420f14d02fSMax Shvetsov SMC_GET_GP(handle, CTX_GPREG_X7)); 4430f14d02fSMax Shvetsov } 4440f14d02fSMax Shvetsov 4450f14d02fSMax Shvetsov /******************************************************************************* 446662af36dSJ-Alves * Return FFA_ERROR with specified error code 4470f14d02fSMax Shvetsov ******************************************************************************/ 448662af36dSJ-Alves static uint64_t spmd_ffa_error_return(void *handle, int error_code) 4490f14d02fSMax Shvetsov { 450e46b2fd2SJ-Alves SMC_RET8(handle, (uint32_t) FFA_ERROR, 451e46b2fd2SJ-Alves FFA_TARGET_INFO_MBZ, (uint32_t)error_code, 452662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, 453662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ); 454bdd2596dSAchin Gupta } 455bdd2596dSAchin Gupta 456f0d743dbSOlivier Deprez /******************************************************************************* 457f0d743dbSOlivier Deprez * spmd_check_address_in_binary_image 458f0d743dbSOlivier Deprez ******************************************************************************/ 459f0d743dbSOlivier Deprez bool spmd_check_address_in_binary_image(uint64_t address) 460f0d743dbSOlivier Deprez { 461f0d743dbSOlivier Deprez assert(!check_uptr_overflow(spmc_attrs.load_address, spmc_attrs.binary_size)); 462f0d743dbSOlivier Deprez 463f0d743dbSOlivier Deprez return ((address >= spmc_attrs.load_address) && 464f0d743dbSOlivier Deprez (address < (spmc_attrs.load_address + spmc_attrs.binary_size))); 465f0d743dbSOlivier Deprez } 466f0d743dbSOlivier Deprez 467c2901419SOlivier Deprez /****************************************************************************** 468c2901419SOlivier Deprez * spmd_is_spmc_message 469c2901419SOlivier Deprez *****************************************************************************/ 470c2901419SOlivier Deprez static bool spmd_is_spmc_message(unsigned int ep) 471c2901419SOlivier Deprez { 472c2901419SOlivier Deprez return ((ffa_endpoint_destination(ep) == SPMD_DIRECT_MSG_ENDPOINT_ID) 473c2901419SOlivier Deprez && (ffa_endpoint_source(ep) == spmc_attrs.spmc_id)); 474c2901419SOlivier Deprez } 475c2901419SOlivier Deprez 476f0d743dbSOlivier Deprez /****************************************************************************** 477f0d743dbSOlivier Deprez * spmd_handle_spmc_message 478f0d743dbSOlivier Deprez *****************************************************************************/ 479a92bc73bSOlivier Deprez static int spmd_handle_spmc_message(unsigned long long msg, 480a92bc73bSOlivier Deprez unsigned long long parm1, unsigned long long parm2, 481a92bc73bSOlivier Deprez unsigned long long parm3, unsigned long long parm4) 482f0d743dbSOlivier Deprez { 483f0d743dbSOlivier Deprez VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__, 484f0d743dbSOlivier Deprez msg, parm1, parm2, parm3, parm4); 485f0d743dbSOlivier Deprez 486f0d743dbSOlivier Deprez return -EINVAL; 487f0d743dbSOlivier Deprez } 488f0d743dbSOlivier Deprez 489bdd2596dSAchin Gupta /******************************************************************************* 490662af36dSJ-Alves * This function handles all SMCs in the range reserved for FFA. Each call is 491bdd2596dSAchin Gupta * either forwarded to the other security state or handled by the SPM dispatcher 492bdd2596dSAchin Gupta ******************************************************************************/ 49352696946SOlivier Deprez uint64_t spmd_smc_handler(uint32_t smc_fid, 49452696946SOlivier Deprez uint64_t x1, 49552696946SOlivier Deprez uint64_t x2, 49652696946SOlivier Deprez uint64_t x3, 49752696946SOlivier Deprez uint64_t x4, 49852696946SOlivier Deprez void *cookie, 49952696946SOlivier Deprez void *handle, 500bdd2596dSAchin Gupta uint64_t flags) 501bdd2596dSAchin Gupta { 502cdb49d47SOlivier Deprez unsigned int linear_id = plat_my_core_pos(); 50352696946SOlivier Deprez spmd_spm_core_context_t *ctx = spmd_get_context(); 50493ff138bSOlivier Deprez bool secure_origin; 50593ff138bSOlivier Deprez int32_t ret; 5064388f28fSJ-Alves uint32_t input_version; 507bdd2596dSAchin Gupta 508bdd2596dSAchin Gupta /* Determine which security state this SMC originated from */ 50993ff138bSOlivier Deprez secure_origin = is_caller_secure(flags); 510bdd2596dSAchin Gupta 5114ce3e99aSScott Branden VERBOSE("SPM(%u): 0x%x 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 5124ce3e99aSScott Branden " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 "\n", 513cdb49d47SOlivier Deprez linear_id, smc_fid, x1, x2, x3, x4, 514cdb49d47SOlivier Deprez SMC_GET_GP(handle, CTX_GPREG_X5), 515bdd2596dSAchin Gupta SMC_GET_GP(handle, CTX_GPREG_X6), 516bdd2596dSAchin Gupta SMC_GET_GP(handle, CTX_GPREG_X7)); 517bdd2596dSAchin Gupta 518bdd2596dSAchin Gupta switch (smc_fid) { 519662af36dSJ-Alves case FFA_ERROR: 520bdd2596dSAchin Gupta /* 521bdd2596dSAchin Gupta * Check if this is the first invocation of this interface on 52252696946SOlivier Deprez * this CPU. If so, then indicate that the SPM Core initialised 523bdd2596dSAchin Gupta * unsuccessfully. 524bdd2596dSAchin Gupta */ 5259dcf63ddSOlivier Deprez if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { 526bdd2596dSAchin Gupta spmd_spm_core_sync_exit(x2); 5270f14d02fSMax Shvetsov } 528bdd2596dSAchin Gupta 52993ff138bSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 5300f14d02fSMax Shvetsov x1, x2, x3, x4, handle); 531bdd2596dSAchin Gupta break; /* not reached */ 532bdd2596dSAchin Gupta 533662af36dSJ-Alves case FFA_VERSION: 5344388f28fSJ-Alves input_version = (uint32_t)(0xFFFFFFFF & x1); 535bdd2596dSAchin Gupta /* 5364388f28fSJ-Alves * If caller is secure and SPMC was initialized, 5374388f28fSJ-Alves * return FFA_VERSION of SPMD. 5384388f28fSJ-Alves * If caller is non secure and SPMC was initialized, 5394388f28fSJ-Alves * return SPMC's version. 5404388f28fSJ-Alves * Sanity check to "input_version". 541bdd2596dSAchin Gupta */ 5424388f28fSJ-Alves if ((input_version & FFA_VERSION_BIT31_MASK) || 5434388f28fSJ-Alves (ctx->state == SPMC_STATE_RESET)) { 5444388f28fSJ-Alves ret = FFA_ERROR_NOT_SUPPORTED; 5454388f28fSJ-Alves } else if (!secure_origin) { 546e46b2fd2SJ-Alves ret = MAKE_FFA_VERSION(spmc_attrs.major_version, 547e46b2fd2SJ-Alves spmc_attrs.minor_version); 5484388f28fSJ-Alves } else { 549e46b2fd2SJ-Alves ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, 550e46b2fd2SJ-Alves FFA_VERSION_MINOR); 5514388f28fSJ-Alves } 5524388f28fSJ-Alves 553e46b2fd2SJ-Alves SMC_RET8(handle, (uint32_t)ret, FFA_TARGET_INFO_MBZ, 554e46b2fd2SJ-Alves FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, 555e46b2fd2SJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); 556bdd2596dSAchin Gupta break; /* not reached */ 557bdd2596dSAchin Gupta 558662af36dSJ-Alves case FFA_FEATURES: 559bdd2596dSAchin Gupta /* 560bdd2596dSAchin Gupta * This is an optional interface. Do the minimal checks and 56152696946SOlivier Deprez * forward to SPM Core which will handle it if implemented. 562bdd2596dSAchin Gupta */ 563bdd2596dSAchin Gupta 56452696946SOlivier Deprez /* Forward SMC from Normal world to the SPM Core */ 56593ff138bSOlivier Deprez if (!secure_origin) { 56693ff138bSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 5670f14d02fSMax Shvetsov x1, x2, x3, x4, handle); 56852696946SOlivier Deprez } 56952696946SOlivier Deprez 570bdd2596dSAchin Gupta /* 571bdd2596dSAchin Gupta * Return success if call was from secure world i.e. all 572662af36dSJ-Alves * FFA functions are supported. This is essentially a 573bdd2596dSAchin Gupta * nop. 574bdd2596dSAchin Gupta */ 575662af36dSJ-Alves SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4, 576bdd2596dSAchin Gupta SMC_GET_GP(handle, CTX_GPREG_X5), 577bdd2596dSAchin Gupta SMC_GET_GP(handle, CTX_GPREG_X6), 578bdd2596dSAchin Gupta SMC_GET_GP(handle, CTX_GPREG_X7)); 5790f14d02fSMax Shvetsov 580bdd2596dSAchin Gupta break; /* not reached */ 581bdd2596dSAchin Gupta 582662af36dSJ-Alves case FFA_ID_GET: 583ac03ac5eSMax Shvetsov /* 584662af36dSJ-Alves * Returns the ID of the calling FFA component. 585ac03ac5eSMax Shvetsov */ 586ac03ac5eSMax Shvetsov if (!secure_origin) { 587662af36dSJ-Alves SMC_RET8(handle, FFA_SUCCESS_SMC32, 588662af36dSJ-Alves FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID, 589662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, 590662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, 591662af36dSJ-Alves FFA_PARAM_MBZ); 59252696946SOlivier Deprez } 59352696946SOlivier Deprez 594662af36dSJ-Alves SMC_RET8(handle, FFA_SUCCESS_SMC32, 595662af36dSJ-Alves FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, 596662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, 597662af36dSJ-Alves FFA_PARAM_MBZ, FFA_PARAM_MBZ, 598662af36dSJ-Alves FFA_PARAM_MBZ); 599ac03ac5eSMax Shvetsov 600ac03ac5eSMax Shvetsov break; /* not reached */ 601ac03ac5eSMax Shvetsov 602cdb49d47SOlivier Deprez case FFA_SECONDARY_EP_REGISTER_SMC64: 603cdb49d47SOlivier Deprez if (secure_origin) { 604cdb49d47SOlivier Deprez ret = spmd_pm_secondary_ep_register(x1); 605cdb49d47SOlivier Deprez 606cdb49d47SOlivier Deprez if (ret < 0) { 607cdb49d47SOlivier Deprez SMC_RET8(handle, FFA_ERROR_SMC64, 608cdb49d47SOlivier Deprez FFA_TARGET_INFO_MBZ, ret, 609cdb49d47SOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 610cdb49d47SOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 611cdb49d47SOlivier Deprez FFA_PARAM_MBZ); 612cdb49d47SOlivier Deprez } else { 613cdb49d47SOlivier Deprez SMC_RET8(handle, FFA_SUCCESS_SMC64, 614cdb49d47SOlivier Deprez FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, 615cdb49d47SOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 616cdb49d47SOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 617cdb49d47SOlivier Deprez FFA_PARAM_MBZ); 618cdb49d47SOlivier Deprez } 619cdb49d47SOlivier Deprez } 620cdb49d47SOlivier Deprez 621cdb49d47SOlivier Deprez return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 622cdb49d47SOlivier Deprez break; /* Not reached */ 623cdb49d47SOlivier Deprez 62470c121a2SDaniel Boulby case FFA_SPM_ID_GET: 62570c121a2SDaniel Boulby if (MAKE_FFA_VERSION(1, 1) > FFA_VERSION_COMPILED) { 62670c121a2SDaniel Boulby return spmd_ffa_error_return(handle, 62770c121a2SDaniel Boulby FFA_ERROR_NOT_SUPPORTED); 62870c121a2SDaniel Boulby } 62970c121a2SDaniel Boulby /* 63070c121a2SDaniel Boulby * Returns the ID of the SPMC or SPMD depending on the FF-A 63170c121a2SDaniel Boulby * instance where this function is invoked 63270c121a2SDaniel Boulby */ 63370c121a2SDaniel Boulby if (!secure_origin) { 63470c121a2SDaniel Boulby SMC_RET8(handle, FFA_SUCCESS_SMC32, 63570c121a2SDaniel Boulby FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, 63670c121a2SDaniel Boulby FFA_PARAM_MBZ, FFA_PARAM_MBZ, 63770c121a2SDaniel Boulby FFA_PARAM_MBZ, FFA_PARAM_MBZ, 63870c121a2SDaniel Boulby FFA_PARAM_MBZ); 63970c121a2SDaniel Boulby } 64070c121a2SDaniel Boulby SMC_RET8(handle, FFA_SUCCESS_SMC32, 64170c121a2SDaniel Boulby FFA_TARGET_INFO_MBZ, SPMD_DIRECT_MSG_ENDPOINT_ID, 64270c121a2SDaniel Boulby FFA_PARAM_MBZ, FFA_PARAM_MBZ, 64370c121a2SDaniel Boulby FFA_PARAM_MBZ, FFA_PARAM_MBZ, 64470c121a2SDaniel Boulby FFA_PARAM_MBZ); 64570c121a2SDaniel Boulby 64670c121a2SDaniel Boulby break; /* not reached */ 64770c121a2SDaniel Boulby 648f0d743dbSOlivier Deprez case FFA_MSG_SEND_DIRECT_REQ_SMC32: 649f0d743dbSOlivier Deprez if (secure_origin && spmd_is_spmc_message(x1)) { 650f0d743dbSOlivier Deprez ret = spmd_handle_spmc_message(x3, x4, 651f0d743dbSOlivier Deprez SMC_GET_GP(handle, CTX_GPREG_X5), 652f0d743dbSOlivier Deprez SMC_GET_GP(handle, CTX_GPREG_X6), 653f0d743dbSOlivier Deprez SMC_GET_GP(handle, CTX_GPREG_X7)); 654f0d743dbSOlivier Deprez 655f0d743dbSOlivier Deprez SMC_RET8(handle, FFA_SUCCESS_SMC32, 656f0d743dbSOlivier Deprez FFA_TARGET_INFO_MBZ, ret, 657f0d743dbSOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 658f0d743dbSOlivier Deprez FFA_PARAM_MBZ, FFA_PARAM_MBZ, 659f0d743dbSOlivier Deprez FFA_PARAM_MBZ); 660f0d743dbSOlivier Deprez } else { 661f0d743dbSOlivier Deprez /* Forward direct message to the other world */ 662f0d743dbSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 663f0d743dbSOlivier Deprez x1, x2, x3, x4, handle); 664f0d743dbSOlivier Deprez } 665f0d743dbSOlivier Deprez break; /* Not reached */ 666f0d743dbSOlivier Deprez 667f0d743dbSOlivier Deprez case FFA_MSG_SEND_DIRECT_RESP_SMC32: 668f0d743dbSOlivier Deprez if (secure_origin && spmd_is_spmc_message(x1)) { 6698cb99c3fSOlivier Deprez spmd_spm_core_sync_exit(0ULL); 670f0d743dbSOlivier Deprez } else { 671f0d743dbSOlivier Deprez /* Forward direct message to the other world */ 672f0d743dbSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 673f0d743dbSOlivier Deprez x1, x2, x3, x4, handle); 674f0d743dbSOlivier Deprez } 675f0d743dbSOlivier Deprez break; /* Not reached */ 676f0d743dbSOlivier Deprez 677662af36dSJ-Alves case FFA_RX_RELEASE: 678662af36dSJ-Alves case FFA_RXTX_MAP_SMC32: 679662af36dSJ-Alves case FFA_RXTX_MAP_SMC64: 680662af36dSJ-Alves case FFA_RXTX_UNMAP: 681545b8eb3SRuari Phipps case FFA_PARTITION_INFO_GET: 682fc3f4800SJ-Alves #if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED 683fc3f4800SJ-Alves case FFA_NOTIFICATION_BITMAP_CREATE: 684fc3f4800SJ-Alves case FFA_NOTIFICATION_BITMAP_DESTROY: 685fc3f4800SJ-Alves case FFA_NOTIFICATION_BIND: 686fc3f4800SJ-Alves case FFA_NOTIFICATION_UNBIND: 687fc3f4800SJ-Alves case FFA_NOTIFICATION_SET: 688fc3f4800SJ-Alves case FFA_NOTIFICATION_GET: 689fc3f4800SJ-Alves case FFA_NOTIFICATION_INFO_GET: 690fc3f4800SJ-Alves case FFA_NOTIFICATION_INFO_GET_SMC64: 691*c2eba07cSFederico Recanati case FFA_MSG_SEND2: 692fc3f4800SJ-Alves #endif 693662af36dSJ-Alves case FFA_MSG_RUN: 694*c2eba07cSFederico Recanati /* 695*c2eba07cSFederico Recanati * Above calls should be invoked only by the Normal world and 696*c2eba07cSFederico Recanati * must not be forwarded from Secure world to Normal world. 697*c2eba07cSFederico Recanati */ 69893ff138bSOlivier Deprez if (secure_origin) { 699662af36dSJ-Alves return spmd_ffa_error_return(handle, 700662af36dSJ-Alves FFA_ERROR_NOT_SUPPORTED); 701bdd2596dSAchin Gupta } 702bdd2596dSAchin Gupta 703bdd2596dSAchin Gupta /* Fall through to forward the call to the other world */ 704662af36dSJ-Alves case FFA_MSG_SEND: 705662af36dSJ-Alves case FFA_MSG_SEND_DIRECT_REQ_SMC64: 706662af36dSJ-Alves case FFA_MSG_SEND_DIRECT_RESP_SMC64: 707662af36dSJ-Alves case FFA_MEM_DONATE_SMC32: 708662af36dSJ-Alves case FFA_MEM_DONATE_SMC64: 709662af36dSJ-Alves case FFA_MEM_LEND_SMC32: 710662af36dSJ-Alves case FFA_MEM_LEND_SMC64: 711662af36dSJ-Alves case FFA_MEM_SHARE_SMC32: 712662af36dSJ-Alves case FFA_MEM_SHARE_SMC64: 713662af36dSJ-Alves case FFA_MEM_RETRIEVE_REQ_SMC32: 714662af36dSJ-Alves case FFA_MEM_RETRIEVE_REQ_SMC64: 715662af36dSJ-Alves case FFA_MEM_RETRIEVE_RESP: 716662af36dSJ-Alves case FFA_MEM_RELINQUISH: 717662af36dSJ-Alves case FFA_MEM_RECLAIM: 718662af36dSJ-Alves case FFA_SUCCESS_SMC32: 719662af36dSJ-Alves case FFA_SUCCESS_SMC64: 720bdd2596dSAchin Gupta /* 721bdd2596dSAchin Gupta * TODO: Assume that no requests originate from EL3 at the 722bdd2596dSAchin Gupta * moment. This will change if a SP service is required in 723bdd2596dSAchin Gupta * response to secure interrupts targeted to EL3. Until then 724bdd2596dSAchin Gupta * simply forward the call to the Normal world. 725bdd2596dSAchin Gupta */ 726bdd2596dSAchin Gupta 72793ff138bSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 7280f14d02fSMax Shvetsov x1, x2, x3, x4, handle); 729bdd2596dSAchin Gupta break; /* not reached */ 730bdd2596dSAchin Gupta 731662af36dSJ-Alves case FFA_MSG_WAIT: 732bdd2596dSAchin Gupta /* 733bdd2596dSAchin Gupta * Check if this is the first invocation of this interface on 734bdd2596dSAchin Gupta * this CPU from the Secure world. If so, then indicate that the 73552696946SOlivier Deprez * SPM Core initialised successfully. 736bdd2596dSAchin Gupta */ 7379dcf63ddSOlivier Deprez if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { 7388cb99c3fSOlivier Deprez spmd_spm_core_sync_exit(0ULL); 739bdd2596dSAchin Gupta } 740bdd2596dSAchin Gupta 7410f14d02fSMax Shvetsov /* Fall through to forward the call to the other world */ 742386dc365SOlivier Deprez case FFA_INTERRUPT: 743662af36dSJ-Alves case FFA_MSG_YIELD: 744bdd2596dSAchin Gupta /* This interface must be invoked only by the Secure world */ 74593ff138bSOlivier Deprez if (!secure_origin) { 746662af36dSJ-Alves return spmd_ffa_error_return(handle, 747662af36dSJ-Alves FFA_ERROR_NOT_SUPPORTED); 748bdd2596dSAchin Gupta } 749bdd2596dSAchin Gupta 75093ff138bSOlivier Deprez return spmd_smc_forward(smc_fid, secure_origin, 7510f14d02fSMax Shvetsov x1, x2, x3, x4, handle); 752bdd2596dSAchin Gupta break; /* not reached */ 753bdd2596dSAchin Gupta 7548cb99c3fSOlivier Deprez case FFA_NORMAL_WORLD_RESUME: 7558cb99c3fSOlivier Deprez if (secure_origin && ctx->secure_interrupt_ongoing) { 7568cb99c3fSOlivier Deprez spmd_spm_core_sync_exit(0ULL); 7578cb99c3fSOlivier Deprez } else { 7588cb99c3fSOlivier Deprez return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); 7598cb99c3fSOlivier Deprez } 7608cb99c3fSOlivier Deprez break; /* Not reached */ 7618cb99c3fSOlivier Deprez 762bdd2596dSAchin Gupta default: 763bdd2596dSAchin Gupta WARN("SPM: Unsupported call 0x%08x\n", smc_fid); 764662af36dSJ-Alves return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 765bdd2596dSAchin Gupta } 766bdd2596dSAchin Gupta } 767