1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2022, 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 10*91f16700Schasinglulu #include <arch_helpers.h> 11*91f16700Schasinglulu #include <bl31/bl31.h> 12*91f16700Schasinglulu #include <bl31/ehf.h> 13*91f16700Schasinglulu #include <bl31/interrupt_mgmt.h> 14*91f16700Schasinglulu #include <common/debug.h> 15*91f16700Schasinglulu #include <common/fdt_wrappers.h> 16*91f16700Schasinglulu #include <common/runtime_svc.h> 17*91f16700Schasinglulu #include <common/uuid.h> 18*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 19*91f16700Schasinglulu #include <lib/smccc.h> 20*91f16700Schasinglulu #include <lib/utils.h> 21*91f16700Schasinglulu #include <lib/xlat_tables/xlat_tables_v2.h> 22*91f16700Schasinglulu #include <libfdt.h> 23*91f16700Schasinglulu #include <plat/common/platform.h> 24*91f16700Schasinglulu #include <services/el3_spmc_logical_sp.h> 25*91f16700Schasinglulu #include <services/ffa_svc.h> 26*91f16700Schasinglulu #include <services/spmc_svc.h> 27*91f16700Schasinglulu #include <services/spmd_svc.h> 28*91f16700Schasinglulu #include "spmc.h" 29*91f16700Schasinglulu #include "spmc_shared_mem.h" 30*91f16700Schasinglulu 31*91f16700Schasinglulu #include <platform_def.h> 32*91f16700Schasinglulu 33*91f16700Schasinglulu /* Declare the maximum number of SPs and El3 LPs. */ 34*91f16700Schasinglulu #define MAX_SP_LP_PARTITIONS SECURE_PARTITION_COUNT + MAX_EL3_LP_DESCS_COUNT 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* 37*91f16700Schasinglulu * Allocate a secure partition descriptor to describe each SP in the system that 38*91f16700Schasinglulu * does not reside at EL3. 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu static struct secure_partition_desc sp_desc[SECURE_PARTITION_COUNT]; 41*91f16700Schasinglulu 42*91f16700Schasinglulu /* 43*91f16700Schasinglulu * Allocate an NS endpoint descriptor to describe each VM and the Hypervisor in 44*91f16700Schasinglulu * the system that interacts with a SP. It is used to track the Hypervisor 45*91f16700Schasinglulu * buffer pair, version and ID for now. It could be extended to track VM 46*91f16700Schasinglulu * properties when the SPMC supports indirect messaging. 47*91f16700Schasinglulu */ 48*91f16700Schasinglulu static struct ns_endpoint_desc ns_ep_desc[NS_PARTITION_COUNT]; 49*91f16700Schasinglulu 50*91f16700Schasinglulu static uint64_t spmc_sp_interrupt_handler(uint32_t id, 51*91f16700Schasinglulu uint32_t flags, 52*91f16700Schasinglulu void *handle, 53*91f16700Schasinglulu void *cookie); 54*91f16700Schasinglulu 55*91f16700Schasinglulu /* 56*91f16700Schasinglulu * Helper function to obtain the array storing the EL3 57*91f16700Schasinglulu * Logical Partition descriptors. 58*91f16700Schasinglulu */ 59*91f16700Schasinglulu struct el3_lp_desc *get_el3_lp_array(void) 60*91f16700Schasinglulu { 61*91f16700Schasinglulu return (struct el3_lp_desc *) EL3_LP_DESCS_START; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu /* 65*91f16700Schasinglulu * Helper function to obtain the descriptor of the last SP to whom control was 66*91f16700Schasinglulu * handed to on this physical cpu. Currently, we assume there is only one SP. 67*91f16700Schasinglulu * TODO: Expand to track multiple partitions when required. 68*91f16700Schasinglulu */ 69*91f16700Schasinglulu struct secure_partition_desc *spmc_get_current_sp_ctx(void) 70*91f16700Schasinglulu { 71*91f16700Schasinglulu return &(sp_desc[ACTIVE_SP_DESC_INDEX]); 72*91f16700Schasinglulu } 73*91f16700Schasinglulu 74*91f16700Schasinglulu /* 75*91f16700Schasinglulu * Helper function to obtain the execution context of an SP on the 76*91f16700Schasinglulu * current physical cpu. 77*91f16700Schasinglulu */ 78*91f16700Schasinglulu struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp) 79*91f16700Schasinglulu { 80*91f16700Schasinglulu return &(sp->ec[get_ec_index(sp)]); 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* Helper function to get pointer to SP context from its ID. */ 84*91f16700Schasinglulu struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id) 85*91f16700Schasinglulu { 86*91f16700Schasinglulu /* Check for Secure World Partitions. */ 87*91f16700Schasinglulu for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 88*91f16700Schasinglulu if (sp_desc[i].sp_id == id) { 89*91f16700Schasinglulu return &(sp_desc[i]); 90*91f16700Schasinglulu } 91*91f16700Schasinglulu } 92*91f16700Schasinglulu return NULL; 93*91f16700Schasinglulu } 94*91f16700Schasinglulu 95*91f16700Schasinglulu /* 96*91f16700Schasinglulu * Helper function to obtain the descriptor of the Hypervisor or OS kernel. 97*91f16700Schasinglulu * We assume that the first descriptor is reserved for this entity. 98*91f16700Schasinglulu */ 99*91f16700Schasinglulu struct ns_endpoint_desc *spmc_get_hyp_ctx(void) 100*91f16700Schasinglulu { 101*91f16700Schasinglulu return &(ns_ep_desc[0]); 102*91f16700Schasinglulu } 103*91f16700Schasinglulu 104*91f16700Schasinglulu /* 105*91f16700Schasinglulu * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor 106*91f16700Schasinglulu * or OS kernel in the normal world or the last SP that was run. 107*91f16700Schasinglulu */ 108*91f16700Schasinglulu struct mailbox *spmc_get_mbox_desc(bool secure_origin) 109*91f16700Schasinglulu { 110*91f16700Schasinglulu /* Obtain the RX/TX buffer pair descriptor. */ 111*91f16700Schasinglulu if (secure_origin) { 112*91f16700Schasinglulu return &(spmc_get_current_sp_ctx()->mailbox); 113*91f16700Schasinglulu } else { 114*91f16700Schasinglulu return &(spmc_get_hyp_ctx()->mailbox); 115*91f16700Schasinglulu } 116*91f16700Schasinglulu } 117*91f16700Schasinglulu 118*91f16700Schasinglulu /****************************************************************************** 119*91f16700Schasinglulu * This function returns to the place where spmc_sp_synchronous_entry() was 120*91f16700Schasinglulu * called originally. 121*91f16700Schasinglulu ******************************************************************************/ 122*91f16700Schasinglulu __dead2 void spmc_sp_synchronous_exit(struct sp_exec_ctx *ec, uint64_t rc) 123*91f16700Schasinglulu { 124*91f16700Schasinglulu /* 125*91f16700Schasinglulu * The SPM must have initiated the original request through a 126*91f16700Schasinglulu * synchronous entry into the secure partition. Jump back to the 127*91f16700Schasinglulu * original C runtime context with the value of rc in x0; 128*91f16700Schasinglulu */ 129*91f16700Schasinglulu spm_secure_partition_exit(ec->c_rt_ctx, rc); 130*91f16700Schasinglulu 131*91f16700Schasinglulu panic(); 132*91f16700Schasinglulu } 133*91f16700Schasinglulu 134*91f16700Schasinglulu /******************************************************************************* 135*91f16700Schasinglulu * Return FFA_ERROR with specified error code. 136*91f16700Schasinglulu ******************************************************************************/ 137*91f16700Schasinglulu uint64_t spmc_ffa_error_return(void *handle, int error_code) 138*91f16700Schasinglulu { 139*91f16700Schasinglulu SMC_RET8(handle, FFA_ERROR, 140*91f16700Schasinglulu FFA_TARGET_INFO_MBZ, error_code, 141*91f16700Schasinglulu FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, 142*91f16700Schasinglulu FFA_PARAM_MBZ, FFA_PARAM_MBZ); 143*91f16700Schasinglulu } 144*91f16700Schasinglulu 145*91f16700Schasinglulu /****************************************************************************** 146*91f16700Schasinglulu * Helper function to validate a secure partition ID to ensure it does not 147*91f16700Schasinglulu * conflict with any other FF-A component and follows the convention to 148*91f16700Schasinglulu * indicate it resides within the secure world. 149*91f16700Schasinglulu ******************************************************************************/ 150*91f16700Schasinglulu bool is_ffa_secure_id_valid(uint16_t partition_id) 151*91f16700Schasinglulu { 152*91f16700Schasinglulu struct el3_lp_desc *el3_lp_descs = get_el3_lp_array(); 153*91f16700Schasinglulu 154*91f16700Schasinglulu /* Ensure the ID is not the invalid partition ID. */ 155*91f16700Schasinglulu if (partition_id == INV_SP_ID) { 156*91f16700Schasinglulu return false; 157*91f16700Schasinglulu } 158*91f16700Schasinglulu 159*91f16700Schasinglulu /* Ensure the ID is not the SPMD ID. */ 160*91f16700Schasinglulu if (partition_id == SPMD_DIRECT_MSG_ENDPOINT_ID) { 161*91f16700Schasinglulu return false; 162*91f16700Schasinglulu } 163*91f16700Schasinglulu 164*91f16700Schasinglulu /* 165*91f16700Schasinglulu * Ensure the ID follows the convention to indicate it resides 166*91f16700Schasinglulu * in the secure world. 167*91f16700Schasinglulu */ 168*91f16700Schasinglulu if (!ffa_is_secure_world_id(partition_id)) { 169*91f16700Schasinglulu return false; 170*91f16700Schasinglulu } 171*91f16700Schasinglulu 172*91f16700Schasinglulu /* Ensure we don't conflict with the SPMC partition ID. */ 173*91f16700Schasinglulu if (partition_id == FFA_SPMC_ID) { 174*91f16700Schasinglulu return false; 175*91f16700Schasinglulu } 176*91f16700Schasinglulu 177*91f16700Schasinglulu /* Ensure we do not already have an SP context with this ID. */ 178*91f16700Schasinglulu if (spmc_get_sp_ctx(partition_id)) { 179*91f16700Schasinglulu return false; 180*91f16700Schasinglulu } 181*91f16700Schasinglulu 182*91f16700Schasinglulu /* Ensure we don't clash with any Logical SP's. */ 183*91f16700Schasinglulu for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) { 184*91f16700Schasinglulu if (el3_lp_descs[i].sp_id == partition_id) { 185*91f16700Schasinglulu return false; 186*91f16700Schasinglulu } 187*91f16700Schasinglulu } 188*91f16700Schasinglulu 189*91f16700Schasinglulu return true; 190*91f16700Schasinglulu } 191*91f16700Schasinglulu 192*91f16700Schasinglulu /******************************************************************************* 193*91f16700Schasinglulu * This function either forwards the request to the other world or returns 194*91f16700Schasinglulu * with an ERET depending on the source of the call. 195*91f16700Schasinglulu * We can assume that the destination is for an entity at a lower exception 196*91f16700Schasinglulu * level as any messages destined for a logical SP resident in EL3 will have 197*91f16700Schasinglulu * already been taken care of by the SPMC before entering this function. 198*91f16700Schasinglulu ******************************************************************************/ 199*91f16700Schasinglulu static uint64_t spmc_smc_return(uint32_t smc_fid, 200*91f16700Schasinglulu bool secure_origin, 201*91f16700Schasinglulu uint64_t x1, 202*91f16700Schasinglulu uint64_t x2, 203*91f16700Schasinglulu uint64_t x3, 204*91f16700Schasinglulu uint64_t x4, 205*91f16700Schasinglulu void *handle, 206*91f16700Schasinglulu void *cookie, 207*91f16700Schasinglulu uint64_t flags, 208*91f16700Schasinglulu uint16_t dst_id) 209*91f16700Schasinglulu { 210*91f16700Schasinglulu /* If the destination is in the normal world always go via the SPMD. */ 211*91f16700Schasinglulu if (ffa_is_normal_world_id(dst_id)) { 212*91f16700Schasinglulu return spmd_smc_handler(smc_fid, x1, x2, x3, x4, 213*91f16700Schasinglulu cookie, handle, flags); 214*91f16700Schasinglulu } 215*91f16700Schasinglulu /* 216*91f16700Schasinglulu * If the caller is secure and we want to return to the secure world, 217*91f16700Schasinglulu * ERET directly. 218*91f16700Schasinglulu */ 219*91f16700Schasinglulu else if (secure_origin && ffa_is_secure_world_id(dst_id)) { 220*91f16700Schasinglulu SMC_RET5(handle, smc_fid, x1, x2, x3, x4); 221*91f16700Schasinglulu } 222*91f16700Schasinglulu /* If we originated in the normal world then switch contexts. */ 223*91f16700Schasinglulu else if (!secure_origin && ffa_is_secure_world_id(dst_id)) { 224*91f16700Schasinglulu return spmd_smc_switch_state(smc_fid, secure_origin, x1, x2, 225*91f16700Schasinglulu x3, x4, handle); 226*91f16700Schasinglulu } else { 227*91f16700Schasinglulu /* Unknown State. */ 228*91f16700Schasinglulu panic(); 229*91f16700Schasinglulu } 230*91f16700Schasinglulu 231*91f16700Schasinglulu /* Shouldn't be Reached. */ 232*91f16700Schasinglulu return 0; 233*91f16700Schasinglulu } 234*91f16700Schasinglulu 235*91f16700Schasinglulu /******************************************************************************* 236*91f16700Schasinglulu * FF-A ABI Handlers. 237*91f16700Schasinglulu ******************************************************************************/ 238*91f16700Schasinglulu 239*91f16700Schasinglulu /******************************************************************************* 240*91f16700Schasinglulu * Helper function to validate arg2 as part of a direct message. 241*91f16700Schasinglulu ******************************************************************************/ 242*91f16700Schasinglulu static inline bool direct_msg_validate_arg2(uint64_t x2) 243*91f16700Schasinglulu { 244*91f16700Schasinglulu /* Check message type. */ 245*91f16700Schasinglulu if (x2 & FFA_FWK_MSG_BIT) { 246*91f16700Schasinglulu /* We have a framework message, ensure it is a known message. */ 247*91f16700Schasinglulu if (x2 & ~(FFA_FWK_MSG_MASK | FFA_FWK_MSG_BIT)) { 248*91f16700Schasinglulu VERBOSE("Invalid message format 0x%lx.\n", x2); 249*91f16700Schasinglulu return false; 250*91f16700Schasinglulu } 251*91f16700Schasinglulu } else { 252*91f16700Schasinglulu /* We have a partition messages, ensure x2 is not set. */ 253*91f16700Schasinglulu if (x2 != (uint64_t) 0) { 254*91f16700Schasinglulu VERBOSE("Arg2 MBZ for partition messages. (0x%lx).\n", 255*91f16700Schasinglulu x2); 256*91f16700Schasinglulu return false; 257*91f16700Schasinglulu } 258*91f16700Schasinglulu } 259*91f16700Schasinglulu return true; 260*91f16700Schasinglulu } 261*91f16700Schasinglulu 262*91f16700Schasinglulu /******************************************************************************* 263*91f16700Schasinglulu * Helper function to validate the destination ID of a direct response. 264*91f16700Schasinglulu ******************************************************************************/ 265*91f16700Schasinglulu static bool direct_msg_validate_dst_id(uint16_t dst_id) 266*91f16700Schasinglulu { 267*91f16700Schasinglulu struct secure_partition_desc *sp; 268*91f16700Schasinglulu 269*91f16700Schasinglulu /* Check if we're targeting a normal world partition. */ 270*91f16700Schasinglulu if (ffa_is_normal_world_id(dst_id)) { 271*91f16700Schasinglulu return true; 272*91f16700Schasinglulu } 273*91f16700Schasinglulu 274*91f16700Schasinglulu /* Or directed to the SPMC itself.*/ 275*91f16700Schasinglulu if (dst_id == FFA_SPMC_ID) { 276*91f16700Schasinglulu return true; 277*91f16700Schasinglulu } 278*91f16700Schasinglulu 279*91f16700Schasinglulu /* Otherwise ensure the SP exists. */ 280*91f16700Schasinglulu sp = spmc_get_sp_ctx(dst_id); 281*91f16700Schasinglulu if (sp != NULL) { 282*91f16700Schasinglulu return true; 283*91f16700Schasinglulu } 284*91f16700Schasinglulu 285*91f16700Schasinglulu return false; 286*91f16700Schasinglulu } 287*91f16700Schasinglulu 288*91f16700Schasinglulu /******************************************************************************* 289*91f16700Schasinglulu * Helper function to validate the response from a Logical Partition. 290*91f16700Schasinglulu ******************************************************************************/ 291*91f16700Schasinglulu static bool direct_msg_validate_lp_resp(uint16_t origin_id, uint16_t lp_id, 292*91f16700Schasinglulu void *handle) 293*91f16700Schasinglulu { 294*91f16700Schasinglulu /* Retrieve populated Direct Response Arguments. */ 295*91f16700Schasinglulu uint64_t x1 = SMC_GET_GP(handle, CTX_GPREG_X1); 296*91f16700Schasinglulu uint64_t x2 = SMC_GET_GP(handle, CTX_GPREG_X2); 297*91f16700Schasinglulu uint16_t src_id = ffa_endpoint_source(x1); 298*91f16700Schasinglulu uint16_t dst_id = ffa_endpoint_destination(x1); 299*91f16700Schasinglulu 300*91f16700Schasinglulu if (src_id != lp_id) { 301*91f16700Schasinglulu ERROR("Invalid EL3 LP source ID (0x%x).\n", src_id); 302*91f16700Schasinglulu return false; 303*91f16700Schasinglulu } 304*91f16700Schasinglulu 305*91f16700Schasinglulu /* 306*91f16700Schasinglulu * Check the destination ID is valid and ensure the LP is responding to 307*91f16700Schasinglulu * the original request. 308*91f16700Schasinglulu */ 309*91f16700Schasinglulu if ((!direct_msg_validate_dst_id(dst_id)) || (dst_id != origin_id)) { 310*91f16700Schasinglulu ERROR("Invalid EL3 LP destination ID (0x%x).\n", dst_id); 311*91f16700Schasinglulu return false; 312*91f16700Schasinglulu } 313*91f16700Schasinglulu 314*91f16700Schasinglulu if (!direct_msg_validate_arg2(x2)) { 315*91f16700Schasinglulu ERROR("Invalid EL3 LP message encoding.\n"); 316*91f16700Schasinglulu return false; 317*91f16700Schasinglulu } 318*91f16700Schasinglulu return true; 319*91f16700Schasinglulu } 320*91f16700Schasinglulu 321*91f16700Schasinglulu /******************************************************************************* 322*91f16700Schasinglulu * Handle direct request messages and route to the appropriate destination. 323*91f16700Schasinglulu ******************************************************************************/ 324*91f16700Schasinglulu static uint64_t direct_req_smc_handler(uint32_t smc_fid, 325*91f16700Schasinglulu bool secure_origin, 326*91f16700Schasinglulu uint64_t x1, 327*91f16700Schasinglulu uint64_t x2, 328*91f16700Schasinglulu uint64_t x3, 329*91f16700Schasinglulu uint64_t x4, 330*91f16700Schasinglulu void *cookie, 331*91f16700Schasinglulu void *handle, 332*91f16700Schasinglulu uint64_t flags) 333*91f16700Schasinglulu { 334*91f16700Schasinglulu uint16_t src_id = ffa_endpoint_source(x1); 335*91f16700Schasinglulu uint16_t dst_id = ffa_endpoint_destination(x1); 336*91f16700Schasinglulu struct el3_lp_desc *el3_lp_descs; 337*91f16700Schasinglulu struct secure_partition_desc *sp; 338*91f16700Schasinglulu unsigned int idx; 339*91f16700Schasinglulu 340*91f16700Schasinglulu /* Check if arg2 has been populated correctly based on message type. */ 341*91f16700Schasinglulu if (!direct_msg_validate_arg2(x2)) { 342*91f16700Schasinglulu return spmc_ffa_error_return(handle, 343*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 344*91f16700Schasinglulu } 345*91f16700Schasinglulu 346*91f16700Schasinglulu /* Validate Sender is either the current SP or from the normal world. */ 347*91f16700Schasinglulu if ((secure_origin && src_id != spmc_get_current_sp_ctx()->sp_id) || 348*91f16700Schasinglulu (!secure_origin && !ffa_is_normal_world_id(src_id))) { 349*91f16700Schasinglulu ERROR("Invalid direct request source ID (0x%x).\n", src_id); 350*91f16700Schasinglulu return spmc_ffa_error_return(handle, 351*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 352*91f16700Schasinglulu } 353*91f16700Schasinglulu 354*91f16700Schasinglulu el3_lp_descs = get_el3_lp_array(); 355*91f16700Schasinglulu 356*91f16700Schasinglulu /* Check if the request is destined for a Logical Partition. */ 357*91f16700Schasinglulu for (unsigned int i = 0U; i < MAX_EL3_LP_DESCS_COUNT; i++) { 358*91f16700Schasinglulu if (el3_lp_descs[i].sp_id == dst_id) { 359*91f16700Schasinglulu uint64_t ret = el3_lp_descs[i].direct_req( 360*91f16700Schasinglulu smc_fid, secure_origin, x1, x2, 361*91f16700Schasinglulu x3, x4, cookie, handle, flags); 362*91f16700Schasinglulu if (!direct_msg_validate_lp_resp(src_id, dst_id, 363*91f16700Schasinglulu handle)) { 364*91f16700Schasinglulu panic(); 365*91f16700Schasinglulu } 366*91f16700Schasinglulu 367*91f16700Schasinglulu /* Message checks out. */ 368*91f16700Schasinglulu return ret; 369*91f16700Schasinglulu } 370*91f16700Schasinglulu } 371*91f16700Schasinglulu 372*91f16700Schasinglulu /* 373*91f16700Schasinglulu * If the request was not targeted to a LSP and from the secure world 374*91f16700Schasinglulu * then it is invalid since a SP cannot call into the Normal world and 375*91f16700Schasinglulu * there is no other SP to call into. If there are other SPs in future 376*91f16700Schasinglulu * then the partition runtime model would need to be validated as well. 377*91f16700Schasinglulu */ 378*91f16700Schasinglulu if (secure_origin) { 379*91f16700Schasinglulu VERBOSE("Direct request not supported to the Normal World.\n"); 380*91f16700Schasinglulu return spmc_ffa_error_return(handle, 381*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 382*91f16700Schasinglulu } 383*91f16700Schasinglulu 384*91f16700Schasinglulu /* Check if the SP ID is valid. */ 385*91f16700Schasinglulu sp = spmc_get_sp_ctx(dst_id); 386*91f16700Schasinglulu if (sp == NULL) { 387*91f16700Schasinglulu VERBOSE("Direct request to unknown partition ID (0x%x).\n", 388*91f16700Schasinglulu dst_id); 389*91f16700Schasinglulu return spmc_ffa_error_return(handle, 390*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 391*91f16700Schasinglulu } 392*91f16700Schasinglulu 393*91f16700Schasinglulu /* 394*91f16700Schasinglulu * Check that the target execution context is in a waiting state before 395*91f16700Schasinglulu * forwarding the direct request to it. 396*91f16700Schasinglulu */ 397*91f16700Schasinglulu idx = get_ec_index(sp); 398*91f16700Schasinglulu if (sp->ec[idx].rt_state != RT_STATE_WAITING) { 399*91f16700Schasinglulu VERBOSE("SP context on core%u is not waiting (%u).\n", 400*91f16700Schasinglulu idx, sp->ec[idx].rt_model); 401*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_BUSY); 402*91f16700Schasinglulu } 403*91f16700Schasinglulu 404*91f16700Schasinglulu /* 405*91f16700Schasinglulu * Everything checks out so forward the request to the SP after updating 406*91f16700Schasinglulu * its state and runtime model. 407*91f16700Schasinglulu */ 408*91f16700Schasinglulu sp->ec[idx].rt_state = RT_STATE_RUNNING; 409*91f16700Schasinglulu sp->ec[idx].rt_model = RT_MODEL_DIR_REQ; 410*91f16700Schasinglulu sp->ec[idx].dir_req_origin_id = src_id; 411*91f16700Schasinglulu return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 412*91f16700Schasinglulu handle, cookie, flags, dst_id); 413*91f16700Schasinglulu } 414*91f16700Schasinglulu 415*91f16700Schasinglulu /******************************************************************************* 416*91f16700Schasinglulu * Handle direct response messages and route to the appropriate destination. 417*91f16700Schasinglulu ******************************************************************************/ 418*91f16700Schasinglulu static uint64_t direct_resp_smc_handler(uint32_t smc_fid, 419*91f16700Schasinglulu bool secure_origin, 420*91f16700Schasinglulu uint64_t x1, 421*91f16700Schasinglulu uint64_t x2, 422*91f16700Schasinglulu uint64_t x3, 423*91f16700Schasinglulu uint64_t x4, 424*91f16700Schasinglulu void *cookie, 425*91f16700Schasinglulu void *handle, 426*91f16700Schasinglulu uint64_t flags) 427*91f16700Schasinglulu { 428*91f16700Schasinglulu uint16_t dst_id = ffa_endpoint_destination(x1); 429*91f16700Schasinglulu struct secure_partition_desc *sp; 430*91f16700Schasinglulu unsigned int idx; 431*91f16700Schasinglulu 432*91f16700Schasinglulu /* Check if arg2 has been populated correctly based on message type. */ 433*91f16700Schasinglulu if (!direct_msg_validate_arg2(x2)) { 434*91f16700Schasinglulu return spmc_ffa_error_return(handle, 435*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 436*91f16700Schasinglulu } 437*91f16700Schasinglulu 438*91f16700Schasinglulu /* Check that the response did not originate from the Normal world. */ 439*91f16700Schasinglulu if (!secure_origin) { 440*91f16700Schasinglulu VERBOSE("Direct Response not supported from Normal World.\n"); 441*91f16700Schasinglulu return spmc_ffa_error_return(handle, 442*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 443*91f16700Schasinglulu } 444*91f16700Schasinglulu 445*91f16700Schasinglulu /* 446*91f16700Schasinglulu * Check that the response is either targeted to the Normal world or the 447*91f16700Schasinglulu * SPMC e.g. a PM response. 448*91f16700Schasinglulu */ 449*91f16700Schasinglulu if (!direct_msg_validate_dst_id(dst_id)) { 450*91f16700Schasinglulu VERBOSE("Direct response to invalid partition ID (0x%x).\n", 451*91f16700Schasinglulu dst_id); 452*91f16700Schasinglulu return spmc_ffa_error_return(handle, 453*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 454*91f16700Schasinglulu } 455*91f16700Schasinglulu 456*91f16700Schasinglulu /* Obtain the SP descriptor and update its runtime state. */ 457*91f16700Schasinglulu sp = spmc_get_sp_ctx(ffa_endpoint_source(x1)); 458*91f16700Schasinglulu if (sp == NULL) { 459*91f16700Schasinglulu VERBOSE("Direct response to unknown partition ID (0x%x).\n", 460*91f16700Schasinglulu dst_id); 461*91f16700Schasinglulu return spmc_ffa_error_return(handle, 462*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 463*91f16700Schasinglulu } 464*91f16700Schasinglulu 465*91f16700Schasinglulu /* Sanity check state is being tracked correctly in the SPMC. */ 466*91f16700Schasinglulu idx = get_ec_index(sp); 467*91f16700Schasinglulu assert(sp->ec[idx].rt_state == RT_STATE_RUNNING); 468*91f16700Schasinglulu 469*91f16700Schasinglulu /* Ensure SP execution context was in the right runtime model. */ 470*91f16700Schasinglulu if (sp->ec[idx].rt_model != RT_MODEL_DIR_REQ) { 471*91f16700Schasinglulu VERBOSE("SP context on core%u not handling direct req (%u).\n", 472*91f16700Schasinglulu idx, sp->ec[idx].rt_model); 473*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 474*91f16700Schasinglulu } 475*91f16700Schasinglulu 476*91f16700Schasinglulu if (sp->ec[idx].dir_req_origin_id != dst_id) { 477*91f16700Schasinglulu WARN("Invalid direct resp partition ID 0x%x != 0x%x on core%u.\n", 478*91f16700Schasinglulu dst_id, sp->ec[idx].dir_req_origin_id, idx); 479*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 480*91f16700Schasinglulu } 481*91f16700Schasinglulu 482*91f16700Schasinglulu /* Update the state of the SP execution context. */ 483*91f16700Schasinglulu sp->ec[idx].rt_state = RT_STATE_WAITING; 484*91f16700Schasinglulu 485*91f16700Schasinglulu /* Clear the ongoing direct request ID. */ 486*91f16700Schasinglulu sp->ec[idx].dir_req_origin_id = INV_SP_ID; 487*91f16700Schasinglulu 488*91f16700Schasinglulu /* 489*91f16700Schasinglulu * If the receiver is not the SPMC then forward the response to the 490*91f16700Schasinglulu * Normal world. 491*91f16700Schasinglulu */ 492*91f16700Schasinglulu if (dst_id == FFA_SPMC_ID) { 493*91f16700Schasinglulu spmc_sp_synchronous_exit(&sp->ec[idx], x4); 494*91f16700Schasinglulu /* Should not get here. */ 495*91f16700Schasinglulu panic(); 496*91f16700Schasinglulu } 497*91f16700Schasinglulu 498*91f16700Schasinglulu return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 499*91f16700Schasinglulu handle, cookie, flags, dst_id); 500*91f16700Schasinglulu } 501*91f16700Schasinglulu 502*91f16700Schasinglulu /******************************************************************************* 503*91f16700Schasinglulu * This function handles the FFA_MSG_WAIT SMC to allow an SP to relinquish its 504*91f16700Schasinglulu * cycles. 505*91f16700Schasinglulu ******************************************************************************/ 506*91f16700Schasinglulu static uint64_t msg_wait_handler(uint32_t smc_fid, 507*91f16700Schasinglulu bool secure_origin, 508*91f16700Schasinglulu uint64_t x1, 509*91f16700Schasinglulu uint64_t x2, 510*91f16700Schasinglulu uint64_t x3, 511*91f16700Schasinglulu uint64_t x4, 512*91f16700Schasinglulu void *cookie, 513*91f16700Schasinglulu void *handle, 514*91f16700Schasinglulu uint64_t flags) 515*91f16700Schasinglulu { 516*91f16700Schasinglulu struct secure_partition_desc *sp; 517*91f16700Schasinglulu unsigned int idx; 518*91f16700Schasinglulu 519*91f16700Schasinglulu /* 520*91f16700Schasinglulu * Check that the response did not originate from the Normal world as 521*91f16700Schasinglulu * only the secure world can call this ABI. 522*91f16700Schasinglulu */ 523*91f16700Schasinglulu if (!secure_origin) { 524*91f16700Schasinglulu VERBOSE("Normal world cannot call FFA_MSG_WAIT.\n"); 525*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 526*91f16700Schasinglulu } 527*91f16700Schasinglulu 528*91f16700Schasinglulu /* Get the descriptor of the SP that invoked FFA_MSG_WAIT. */ 529*91f16700Schasinglulu sp = spmc_get_current_sp_ctx(); 530*91f16700Schasinglulu if (sp == NULL) { 531*91f16700Schasinglulu return spmc_ffa_error_return(handle, 532*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 533*91f16700Schasinglulu } 534*91f16700Schasinglulu 535*91f16700Schasinglulu /* 536*91f16700Schasinglulu * Get the execution context of the SP that invoked FFA_MSG_WAIT. 537*91f16700Schasinglulu */ 538*91f16700Schasinglulu idx = get_ec_index(sp); 539*91f16700Schasinglulu 540*91f16700Schasinglulu /* Ensure SP execution context was in the right runtime model. */ 541*91f16700Schasinglulu if (sp->ec[idx].rt_model == RT_MODEL_DIR_REQ) { 542*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 543*91f16700Schasinglulu } 544*91f16700Schasinglulu 545*91f16700Schasinglulu /* Sanity check the state is being tracked correctly in the SPMC. */ 546*91f16700Schasinglulu assert(sp->ec[idx].rt_state == RT_STATE_RUNNING); 547*91f16700Schasinglulu 548*91f16700Schasinglulu /* 549*91f16700Schasinglulu * Perform a synchronous exit if the partition was initialising. The 550*91f16700Schasinglulu * state is updated after the exit. 551*91f16700Schasinglulu */ 552*91f16700Schasinglulu if (sp->ec[idx].rt_model == RT_MODEL_INIT) { 553*91f16700Schasinglulu spmc_sp_synchronous_exit(&sp->ec[idx], x4); 554*91f16700Schasinglulu /* Should not get here */ 555*91f16700Schasinglulu panic(); 556*91f16700Schasinglulu } 557*91f16700Schasinglulu 558*91f16700Schasinglulu /* Update the state of the SP execution context. */ 559*91f16700Schasinglulu sp->ec[idx].rt_state = RT_STATE_WAITING; 560*91f16700Schasinglulu 561*91f16700Schasinglulu /* Resume normal world if a secure interrupt was handled. */ 562*91f16700Schasinglulu if (sp->ec[idx].rt_model == RT_MODEL_INTR) { 563*91f16700Schasinglulu /* FFA_MSG_WAIT can only be called from the secure world. */ 564*91f16700Schasinglulu unsigned int secure_state_in = SECURE; 565*91f16700Schasinglulu unsigned int secure_state_out = NON_SECURE; 566*91f16700Schasinglulu 567*91f16700Schasinglulu cm_el1_sysregs_context_save(secure_state_in); 568*91f16700Schasinglulu cm_el1_sysregs_context_restore(secure_state_out); 569*91f16700Schasinglulu cm_set_next_eret_context(secure_state_out); 570*91f16700Schasinglulu SMC_RET0(cm_get_context(secure_state_out)); 571*91f16700Schasinglulu } 572*91f16700Schasinglulu 573*91f16700Schasinglulu /* Forward the response to the Normal world. */ 574*91f16700Schasinglulu return spmc_smc_return(smc_fid, secure_origin, x1, x2, x3, x4, 575*91f16700Schasinglulu handle, cookie, flags, FFA_NWD_ID); 576*91f16700Schasinglulu } 577*91f16700Schasinglulu 578*91f16700Schasinglulu static uint64_t ffa_error_handler(uint32_t smc_fid, 579*91f16700Schasinglulu bool secure_origin, 580*91f16700Schasinglulu uint64_t x1, 581*91f16700Schasinglulu uint64_t x2, 582*91f16700Schasinglulu uint64_t x3, 583*91f16700Schasinglulu uint64_t x4, 584*91f16700Schasinglulu void *cookie, 585*91f16700Schasinglulu void *handle, 586*91f16700Schasinglulu uint64_t flags) 587*91f16700Schasinglulu { 588*91f16700Schasinglulu struct secure_partition_desc *sp; 589*91f16700Schasinglulu unsigned int idx; 590*91f16700Schasinglulu 591*91f16700Schasinglulu /* Check that the response did not originate from the Normal world. */ 592*91f16700Schasinglulu if (!secure_origin) { 593*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 594*91f16700Schasinglulu } 595*91f16700Schasinglulu 596*91f16700Schasinglulu /* Get the descriptor of the SP that invoked FFA_ERROR. */ 597*91f16700Schasinglulu sp = spmc_get_current_sp_ctx(); 598*91f16700Schasinglulu if (sp == NULL) { 599*91f16700Schasinglulu return spmc_ffa_error_return(handle, 600*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 601*91f16700Schasinglulu } 602*91f16700Schasinglulu 603*91f16700Schasinglulu /* Get the execution context of the SP that invoked FFA_ERROR. */ 604*91f16700Schasinglulu idx = get_ec_index(sp); 605*91f16700Schasinglulu 606*91f16700Schasinglulu /* 607*91f16700Schasinglulu * We only expect FFA_ERROR to be received during SP initialisation 608*91f16700Schasinglulu * otherwise this is an invalid call. 609*91f16700Schasinglulu */ 610*91f16700Schasinglulu if (sp->ec[idx].rt_model == RT_MODEL_INIT) { 611*91f16700Schasinglulu ERROR("SP 0x%x failed to initialize.\n", sp->sp_id); 612*91f16700Schasinglulu spmc_sp_synchronous_exit(&sp->ec[idx], x2); 613*91f16700Schasinglulu /* Should not get here. */ 614*91f16700Schasinglulu panic(); 615*91f16700Schasinglulu } 616*91f16700Schasinglulu 617*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 618*91f16700Schasinglulu } 619*91f16700Schasinglulu 620*91f16700Schasinglulu static uint64_t ffa_version_handler(uint32_t smc_fid, 621*91f16700Schasinglulu bool secure_origin, 622*91f16700Schasinglulu uint64_t x1, 623*91f16700Schasinglulu uint64_t x2, 624*91f16700Schasinglulu uint64_t x3, 625*91f16700Schasinglulu uint64_t x4, 626*91f16700Schasinglulu void *cookie, 627*91f16700Schasinglulu void *handle, 628*91f16700Schasinglulu uint64_t flags) 629*91f16700Schasinglulu { 630*91f16700Schasinglulu uint32_t requested_version = x1 & FFA_VERSION_MASK; 631*91f16700Schasinglulu 632*91f16700Schasinglulu if (requested_version & FFA_VERSION_BIT31_MASK) { 633*91f16700Schasinglulu /* Invalid encoding, return an error. */ 634*91f16700Schasinglulu SMC_RET1(handle, FFA_ERROR_NOT_SUPPORTED); 635*91f16700Schasinglulu /* Execution stops here. */ 636*91f16700Schasinglulu } 637*91f16700Schasinglulu 638*91f16700Schasinglulu /* Determine the caller to store the requested version. */ 639*91f16700Schasinglulu if (secure_origin) { 640*91f16700Schasinglulu /* 641*91f16700Schasinglulu * Ensure that the SP is reporting the same version as 642*91f16700Schasinglulu * specified in its manifest. If these do not match there is 643*91f16700Schasinglulu * something wrong with the SP. 644*91f16700Schasinglulu * TODO: Should we abort the SP? For now assert this is not 645*91f16700Schasinglulu * case. 646*91f16700Schasinglulu */ 647*91f16700Schasinglulu assert(requested_version == 648*91f16700Schasinglulu spmc_get_current_sp_ctx()->ffa_version); 649*91f16700Schasinglulu } else { 650*91f16700Schasinglulu /* 651*91f16700Schasinglulu * If this is called by the normal world, record this 652*91f16700Schasinglulu * information in its descriptor. 653*91f16700Schasinglulu */ 654*91f16700Schasinglulu spmc_get_hyp_ctx()->ffa_version = requested_version; 655*91f16700Schasinglulu } 656*91f16700Schasinglulu 657*91f16700Schasinglulu SMC_RET1(handle, MAKE_FFA_VERSION(FFA_VERSION_MAJOR, 658*91f16700Schasinglulu FFA_VERSION_MINOR)); 659*91f16700Schasinglulu } 660*91f16700Schasinglulu 661*91f16700Schasinglulu /******************************************************************************* 662*91f16700Schasinglulu * Helper function to obtain the FF-A version of the calling partition. 663*91f16700Schasinglulu ******************************************************************************/ 664*91f16700Schasinglulu uint32_t get_partition_ffa_version(bool secure_origin) 665*91f16700Schasinglulu { 666*91f16700Schasinglulu if (secure_origin) { 667*91f16700Schasinglulu return spmc_get_current_sp_ctx()->ffa_version; 668*91f16700Schasinglulu } else { 669*91f16700Schasinglulu return spmc_get_hyp_ctx()->ffa_version; 670*91f16700Schasinglulu } 671*91f16700Schasinglulu } 672*91f16700Schasinglulu 673*91f16700Schasinglulu static uint64_t rxtx_map_handler(uint32_t smc_fid, 674*91f16700Schasinglulu bool secure_origin, 675*91f16700Schasinglulu uint64_t x1, 676*91f16700Schasinglulu uint64_t x2, 677*91f16700Schasinglulu uint64_t x3, 678*91f16700Schasinglulu uint64_t x4, 679*91f16700Schasinglulu void *cookie, 680*91f16700Schasinglulu void *handle, 681*91f16700Schasinglulu uint64_t flags) 682*91f16700Schasinglulu { 683*91f16700Schasinglulu int ret; 684*91f16700Schasinglulu uint32_t error_code; 685*91f16700Schasinglulu uint32_t mem_atts = secure_origin ? MT_SECURE : MT_NS; 686*91f16700Schasinglulu struct mailbox *mbox; 687*91f16700Schasinglulu uintptr_t tx_address = x1; 688*91f16700Schasinglulu uintptr_t rx_address = x2; 689*91f16700Schasinglulu uint32_t page_count = x3 & FFA_RXTX_PAGE_COUNT_MASK; /* Bits [5:0] */ 690*91f16700Schasinglulu uint32_t buf_size = page_count * FFA_PAGE_SIZE; 691*91f16700Schasinglulu 692*91f16700Schasinglulu /* 693*91f16700Schasinglulu * The SPMC does not support mapping of VM RX/TX pairs to facilitate 694*91f16700Schasinglulu * indirect messaging with SPs. Check if the Hypervisor has invoked this 695*91f16700Schasinglulu * ABI on behalf of a VM and reject it if this is the case. 696*91f16700Schasinglulu */ 697*91f16700Schasinglulu if (tx_address == 0 || rx_address == 0) { 698*91f16700Schasinglulu WARN("Mapping RX/TX Buffers on behalf of VM not supported.\n"); 699*91f16700Schasinglulu return spmc_ffa_error_return(handle, 700*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 701*91f16700Schasinglulu } 702*91f16700Schasinglulu 703*91f16700Schasinglulu /* Ensure the specified buffers are not the same. */ 704*91f16700Schasinglulu if (tx_address == rx_address) { 705*91f16700Schasinglulu WARN("TX Buffer must not be the same as RX Buffer.\n"); 706*91f16700Schasinglulu return spmc_ffa_error_return(handle, 707*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 708*91f16700Schasinglulu } 709*91f16700Schasinglulu 710*91f16700Schasinglulu /* Ensure the buffer size is not 0. */ 711*91f16700Schasinglulu if (buf_size == 0U) { 712*91f16700Schasinglulu WARN("Buffer size must not be 0\n"); 713*91f16700Schasinglulu return spmc_ffa_error_return(handle, 714*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 715*91f16700Schasinglulu } 716*91f16700Schasinglulu 717*91f16700Schasinglulu /* 718*91f16700Schasinglulu * Ensure the buffer size is a multiple of the translation granule size 719*91f16700Schasinglulu * in TF-A. 720*91f16700Schasinglulu */ 721*91f16700Schasinglulu if (buf_size % PAGE_SIZE != 0U) { 722*91f16700Schasinglulu WARN("Buffer size must be aligned to translation granule.\n"); 723*91f16700Schasinglulu return spmc_ffa_error_return(handle, 724*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 725*91f16700Schasinglulu } 726*91f16700Schasinglulu 727*91f16700Schasinglulu /* Obtain the RX/TX buffer pair descriptor. */ 728*91f16700Schasinglulu mbox = spmc_get_mbox_desc(secure_origin); 729*91f16700Schasinglulu 730*91f16700Schasinglulu spin_lock(&mbox->lock); 731*91f16700Schasinglulu 732*91f16700Schasinglulu /* Check if buffers have already been mapped. */ 733*91f16700Schasinglulu if (mbox->rx_buffer != 0 || mbox->tx_buffer != 0) { 734*91f16700Schasinglulu WARN("RX/TX Buffers already mapped (%p/%p)\n", 735*91f16700Schasinglulu (void *) mbox->rx_buffer, (void *)mbox->tx_buffer); 736*91f16700Schasinglulu error_code = FFA_ERROR_DENIED; 737*91f16700Schasinglulu goto err; 738*91f16700Schasinglulu } 739*91f16700Schasinglulu 740*91f16700Schasinglulu /* memmap the TX buffer as read only. */ 741*91f16700Schasinglulu ret = mmap_add_dynamic_region(tx_address, /* PA */ 742*91f16700Schasinglulu tx_address, /* VA */ 743*91f16700Schasinglulu buf_size, /* size */ 744*91f16700Schasinglulu mem_atts | MT_RO_DATA); /* attrs */ 745*91f16700Schasinglulu if (ret != 0) { 746*91f16700Schasinglulu /* Return the correct error code. */ 747*91f16700Schasinglulu error_code = (ret == -ENOMEM) ? FFA_ERROR_NO_MEMORY : 748*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER; 749*91f16700Schasinglulu WARN("Unable to map TX buffer: %d\n", error_code); 750*91f16700Schasinglulu goto err; 751*91f16700Schasinglulu } 752*91f16700Schasinglulu 753*91f16700Schasinglulu /* memmap the RX buffer as read write. */ 754*91f16700Schasinglulu ret = mmap_add_dynamic_region(rx_address, /* PA */ 755*91f16700Schasinglulu rx_address, /* VA */ 756*91f16700Schasinglulu buf_size, /* size */ 757*91f16700Schasinglulu mem_atts | MT_RW_DATA); /* attrs */ 758*91f16700Schasinglulu 759*91f16700Schasinglulu if (ret != 0) { 760*91f16700Schasinglulu error_code = (ret == -ENOMEM) ? FFA_ERROR_NO_MEMORY : 761*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER; 762*91f16700Schasinglulu WARN("Unable to map RX buffer: %d\n", error_code); 763*91f16700Schasinglulu /* Unmap the TX buffer again. */ 764*91f16700Schasinglulu mmap_remove_dynamic_region(tx_address, buf_size); 765*91f16700Schasinglulu goto err; 766*91f16700Schasinglulu } 767*91f16700Schasinglulu 768*91f16700Schasinglulu mbox->tx_buffer = (void *) tx_address; 769*91f16700Schasinglulu mbox->rx_buffer = (void *) rx_address; 770*91f16700Schasinglulu mbox->rxtx_page_count = page_count; 771*91f16700Schasinglulu spin_unlock(&mbox->lock); 772*91f16700Schasinglulu 773*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 774*91f16700Schasinglulu /* Execution stops here. */ 775*91f16700Schasinglulu err: 776*91f16700Schasinglulu spin_unlock(&mbox->lock); 777*91f16700Schasinglulu return spmc_ffa_error_return(handle, error_code); 778*91f16700Schasinglulu } 779*91f16700Schasinglulu 780*91f16700Schasinglulu static uint64_t rxtx_unmap_handler(uint32_t smc_fid, 781*91f16700Schasinglulu bool secure_origin, 782*91f16700Schasinglulu uint64_t x1, 783*91f16700Schasinglulu uint64_t x2, 784*91f16700Schasinglulu uint64_t x3, 785*91f16700Schasinglulu uint64_t x4, 786*91f16700Schasinglulu void *cookie, 787*91f16700Schasinglulu void *handle, 788*91f16700Schasinglulu uint64_t flags) 789*91f16700Schasinglulu { 790*91f16700Schasinglulu struct mailbox *mbox = spmc_get_mbox_desc(secure_origin); 791*91f16700Schasinglulu uint32_t buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE; 792*91f16700Schasinglulu 793*91f16700Schasinglulu /* 794*91f16700Schasinglulu * The SPMC does not support mapping of VM RX/TX pairs to facilitate 795*91f16700Schasinglulu * indirect messaging with SPs. Check if the Hypervisor has invoked this 796*91f16700Schasinglulu * ABI on behalf of a VM and reject it if this is the case. 797*91f16700Schasinglulu */ 798*91f16700Schasinglulu if (x1 != 0UL) { 799*91f16700Schasinglulu return spmc_ffa_error_return(handle, 800*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 801*91f16700Schasinglulu } 802*91f16700Schasinglulu 803*91f16700Schasinglulu spin_lock(&mbox->lock); 804*91f16700Schasinglulu 805*91f16700Schasinglulu /* Check if buffers are currently mapped. */ 806*91f16700Schasinglulu if (mbox->rx_buffer == 0 || mbox->tx_buffer == 0) { 807*91f16700Schasinglulu spin_unlock(&mbox->lock); 808*91f16700Schasinglulu return spmc_ffa_error_return(handle, 809*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 810*91f16700Schasinglulu } 811*91f16700Schasinglulu 812*91f16700Schasinglulu /* Unmap RX Buffer */ 813*91f16700Schasinglulu if (mmap_remove_dynamic_region((uintptr_t) mbox->rx_buffer, 814*91f16700Schasinglulu buf_size) != 0) { 815*91f16700Schasinglulu WARN("Unable to unmap RX buffer!\n"); 816*91f16700Schasinglulu } 817*91f16700Schasinglulu 818*91f16700Schasinglulu mbox->rx_buffer = 0; 819*91f16700Schasinglulu 820*91f16700Schasinglulu /* Unmap TX Buffer */ 821*91f16700Schasinglulu if (mmap_remove_dynamic_region((uintptr_t) mbox->tx_buffer, 822*91f16700Schasinglulu buf_size) != 0) { 823*91f16700Schasinglulu WARN("Unable to unmap TX buffer!\n"); 824*91f16700Schasinglulu } 825*91f16700Schasinglulu 826*91f16700Schasinglulu mbox->tx_buffer = 0; 827*91f16700Schasinglulu mbox->rxtx_page_count = 0; 828*91f16700Schasinglulu 829*91f16700Schasinglulu spin_unlock(&mbox->lock); 830*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 831*91f16700Schasinglulu } 832*91f16700Schasinglulu 833*91f16700Schasinglulu /* 834*91f16700Schasinglulu * Helper function to populate the properties field of a Partition Info Get 835*91f16700Schasinglulu * descriptor. 836*91f16700Schasinglulu */ 837*91f16700Schasinglulu static uint32_t 838*91f16700Schasinglulu partition_info_get_populate_properties(uint32_t sp_properties, 839*91f16700Schasinglulu enum sp_execution_state sp_ec_state) 840*91f16700Schasinglulu { 841*91f16700Schasinglulu uint32_t properties = sp_properties; 842*91f16700Schasinglulu uint32_t ec_state; 843*91f16700Schasinglulu 844*91f16700Schasinglulu /* Determine the execution state of the SP. */ 845*91f16700Schasinglulu ec_state = sp_ec_state == SP_STATE_AARCH64 ? 846*91f16700Schasinglulu FFA_PARTITION_INFO_GET_AARCH64_STATE : 847*91f16700Schasinglulu FFA_PARTITION_INFO_GET_AARCH32_STATE; 848*91f16700Schasinglulu 849*91f16700Schasinglulu properties |= ec_state << FFA_PARTITION_INFO_GET_EXEC_STATE_SHIFT; 850*91f16700Schasinglulu 851*91f16700Schasinglulu return properties; 852*91f16700Schasinglulu } 853*91f16700Schasinglulu 854*91f16700Schasinglulu /* 855*91f16700Schasinglulu * Collate the partition information in a v1.1 partition information 856*91f16700Schasinglulu * descriptor format, this will be converter later if required. 857*91f16700Schasinglulu */ 858*91f16700Schasinglulu static int partition_info_get_handler_v1_1(uint32_t *uuid, 859*91f16700Schasinglulu struct ffa_partition_info_v1_1 860*91f16700Schasinglulu *partitions, 861*91f16700Schasinglulu uint32_t max_partitions, 862*91f16700Schasinglulu uint32_t *partition_count) 863*91f16700Schasinglulu { 864*91f16700Schasinglulu uint32_t index; 865*91f16700Schasinglulu struct ffa_partition_info_v1_1 *desc; 866*91f16700Schasinglulu bool null_uuid = is_null_uuid(uuid); 867*91f16700Schasinglulu struct el3_lp_desc *el3_lp_descs = get_el3_lp_array(); 868*91f16700Schasinglulu 869*91f16700Schasinglulu /* Deal with Logical Partitions. */ 870*91f16700Schasinglulu for (index = 0U; index < EL3_LP_DESCS_COUNT; index++) { 871*91f16700Schasinglulu if (null_uuid || uuid_match(uuid, el3_lp_descs[index].uuid)) { 872*91f16700Schasinglulu /* Found a matching UUID, populate appropriately. */ 873*91f16700Schasinglulu if (*partition_count >= max_partitions) { 874*91f16700Schasinglulu return FFA_ERROR_NO_MEMORY; 875*91f16700Schasinglulu } 876*91f16700Schasinglulu 877*91f16700Schasinglulu desc = &partitions[*partition_count]; 878*91f16700Schasinglulu desc->ep_id = el3_lp_descs[index].sp_id; 879*91f16700Schasinglulu desc->execution_ctx_count = PLATFORM_CORE_COUNT; 880*91f16700Schasinglulu /* LSPs must be AArch64. */ 881*91f16700Schasinglulu desc->properties = 882*91f16700Schasinglulu partition_info_get_populate_properties( 883*91f16700Schasinglulu el3_lp_descs[index].properties, 884*91f16700Schasinglulu SP_STATE_AARCH64); 885*91f16700Schasinglulu 886*91f16700Schasinglulu if (null_uuid) { 887*91f16700Schasinglulu copy_uuid(desc->uuid, el3_lp_descs[index].uuid); 888*91f16700Schasinglulu } 889*91f16700Schasinglulu (*partition_count)++; 890*91f16700Schasinglulu } 891*91f16700Schasinglulu } 892*91f16700Schasinglulu 893*91f16700Schasinglulu /* Deal with physical SP's. */ 894*91f16700Schasinglulu for (index = 0U; index < SECURE_PARTITION_COUNT; index++) { 895*91f16700Schasinglulu if (null_uuid || uuid_match(uuid, sp_desc[index].uuid)) { 896*91f16700Schasinglulu /* Found a matching UUID, populate appropriately. */ 897*91f16700Schasinglulu if (*partition_count >= max_partitions) { 898*91f16700Schasinglulu return FFA_ERROR_NO_MEMORY; 899*91f16700Schasinglulu } 900*91f16700Schasinglulu 901*91f16700Schasinglulu desc = &partitions[*partition_count]; 902*91f16700Schasinglulu desc->ep_id = sp_desc[index].sp_id; 903*91f16700Schasinglulu /* 904*91f16700Schasinglulu * Execution context count must match No. cores for 905*91f16700Schasinglulu * S-EL1 SPs. 906*91f16700Schasinglulu */ 907*91f16700Schasinglulu desc->execution_ctx_count = PLATFORM_CORE_COUNT; 908*91f16700Schasinglulu desc->properties = 909*91f16700Schasinglulu partition_info_get_populate_properties( 910*91f16700Schasinglulu sp_desc[index].properties, 911*91f16700Schasinglulu sp_desc[index].execution_state); 912*91f16700Schasinglulu 913*91f16700Schasinglulu if (null_uuid) { 914*91f16700Schasinglulu copy_uuid(desc->uuid, sp_desc[index].uuid); 915*91f16700Schasinglulu } 916*91f16700Schasinglulu (*partition_count)++; 917*91f16700Schasinglulu } 918*91f16700Schasinglulu } 919*91f16700Schasinglulu return 0; 920*91f16700Schasinglulu } 921*91f16700Schasinglulu 922*91f16700Schasinglulu /* 923*91f16700Schasinglulu * Handle the case where that caller only wants the count of partitions 924*91f16700Schasinglulu * matching a given UUID and does not want the corresponding descriptors 925*91f16700Schasinglulu * populated. 926*91f16700Schasinglulu */ 927*91f16700Schasinglulu static uint32_t partition_info_get_handler_count_only(uint32_t *uuid) 928*91f16700Schasinglulu { 929*91f16700Schasinglulu uint32_t index = 0; 930*91f16700Schasinglulu uint32_t partition_count = 0; 931*91f16700Schasinglulu bool null_uuid = is_null_uuid(uuid); 932*91f16700Schasinglulu struct el3_lp_desc *el3_lp_descs = get_el3_lp_array(); 933*91f16700Schasinglulu 934*91f16700Schasinglulu /* Deal with Logical Partitions. */ 935*91f16700Schasinglulu for (index = 0U; index < EL3_LP_DESCS_COUNT; index++) { 936*91f16700Schasinglulu if (null_uuid || 937*91f16700Schasinglulu uuid_match(uuid, el3_lp_descs[index].uuid)) { 938*91f16700Schasinglulu (partition_count)++; 939*91f16700Schasinglulu } 940*91f16700Schasinglulu } 941*91f16700Schasinglulu 942*91f16700Schasinglulu /* Deal with physical SP's. */ 943*91f16700Schasinglulu for (index = 0U; index < SECURE_PARTITION_COUNT; index++) { 944*91f16700Schasinglulu if (null_uuid || uuid_match(uuid, sp_desc[index].uuid)) { 945*91f16700Schasinglulu (partition_count)++; 946*91f16700Schasinglulu } 947*91f16700Schasinglulu } 948*91f16700Schasinglulu return partition_count; 949*91f16700Schasinglulu } 950*91f16700Schasinglulu 951*91f16700Schasinglulu /* 952*91f16700Schasinglulu * If the caller of the PARTITION_INFO_GET ABI was a v1.0 caller, populate 953*91f16700Schasinglulu * the corresponding descriptor format from the v1.1 descriptor array. 954*91f16700Schasinglulu */ 955*91f16700Schasinglulu static uint64_t partition_info_populate_v1_0(struct ffa_partition_info_v1_1 956*91f16700Schasinglulu *partitions, 957*91f16700Schasinglulu struct mailbox *mbox, 958*91f16700Schasinglulu int partition_count) 959*91f16700Schasinglulu { 960*91f16700Schasinglulu uint32_t index; 961*91f16700Schasinglulu uint32_t buf_size; 962*91f16700Schasinglulu uint32_t descriptor_size; 963*91f16700Schasinglulu struct ffa_partition_info_v1_0 *v1_0_partitions = 964*91f16700Schasinglulu (struct ffa_partition_info_v1_0 *) mbox->rx_buffer; 965*91f16700Schasinglulu 966*91f16700Schasinglulu buf_size = mbox->rxtx_page_count * FFA_PAGE_SIZE; 967*91f16700Schasinglulu descriptor_size = partition_count * 968*91f16700Schasinglulu sizeof(struct ffa_partition_info_v1_0); 969*91f16700Schasinglulu 970*91f16700Schasinglulu if (descriptor_size > buf_size) { 971*91f16700Schasinglulu return FFA_ERROR_NO_MEMORY; 972*91f16700Schasinglulu } 973*91f16700Schasinglulu 974*91f16700Schasinglulu for (index = 0U; index < partition_count; index++) { 975*91f16700Schasinglulu v1_0_partitions[index].ep_id = partitions[index].ep_id; 976*91f16700Schasinglulu v1_0_partitions[index].execution_ctx_count = 977*91f16700Schasinglulu partitions[index].execution_ctx_count; 978*91f16700Schasinglulu /* Only report v1.0 properties. */ 979*91f16700Schasinglulu v1_0_partitions[index].properties = 980*91f16700Schasinglulu (partitions[index].properties & 981*91f16700Schasinglulu FFA_PARTITION_INFO_GET_PROPERTIES_V1_0_MASK); 982*91f16700Schasinglulu } 983*91f16700Schasinglulu return 0; 984*91f16700Schasinglulu } 985*91f16700Schasinglulu 986*91f16700Schasinglulu /* 987*91f16700Schasinglulu * Main handler for FFA_PARTITION_INFO_GET which supports both FF-A v1.1 and 988*91f16700Schasinglulu * v1.0 implementations. 989*91f16700Schasinglulu */ 990*91f16700Schasinglulu static uint64_t partition_info_get_handler(uint32_t smc_fid, 991*91f16700Schasinglulu bool secure_origin, 992*91f16700Schasinglulu uint64_t x1, 993*91f16700Schasinglulu uint64_t x2, 994*91f16700Schasinglulu uint64_t x3, 995*91f16700Schasinglulu uint64_t x4, 996*91f16700Schasinglulu void *cookie, 997*91f16700Schasinglulu void *handle, 998*91f16700Schasinglulu uint64_t flags) 999*91f16700Schasinglulu { 1000*91f16700Schasinglulu int ret; 1001*91f16700Schasinglulu uint32_t partition_count = 0; 1002*91f16700Schasinglulu uint32_t size = 0; 1003*91f16700Schasinglulu uint32_t ffa_version = get_partition_ffa_version(secure_origin); 1004*91f16700Schasinglulu struct mailbox *mbox; 1005*91f16700Schasinglulu uint64_t info_get_flags; 1006*91f16700Schasinglulu bool count_only; 1007*91f16700Schasinglulu uint32_t uuid[4]; 1008*91f16700Schasinglulu 1009*91f16700Schasinglulu uuid[0] = x1; 1010*91f16700Schasinglulu uuid[1] = x2; 1011*91f16700Schasinglulu uuid[2] = x3; 1012*91f16700Schasinglulu uuid[3] = x4; 1013*91f16700Schasinglulu 1014*91f16700Schasinglulu /* Determine if the Partition descriptors should be populated. */ 1015*91f16700Schasinglulu info_get_flags = SMC_GET_GP(handle, CTX_GPREG_X5); 1016*91f16700Schasinglulu count_only = (info_get_flags & FFA_PARTITION_INFO_GET_COUNT_FLAG_MASK); 1017*91f16700Schasinglulu 1018*91f16700Schasinglulu /* Handle the case where we don't need to populate the descriptors. */ 1019*91f16700Schasinglulu if (count_only) { 1020*91f16700Schasinglulu partition_count = partition_info_get_handler_count_only(uuid); 1021*91f16700Schasinglulu if (partition_count == 0) { 1022*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1023*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1024*91f16700Schasinglulu } 1025*91f16700Schasinglulu } else { 1026*91f16700Schasinglulu struct ffa_partition_info_v1_1 partitions[MAX_SP_LP_PARTITIONS]; 1027*91f16700Schasinglulu 1028*91f16700Schasinglulu /* 1029*91f16700Schasinglulu * Handle the case where the partition descriptors are required, 1030*91f16700Schasinglulu * check we have the buffers available and populate the 1031*91f16700Schasinglulu * appropriate structure version. 1032*91f16700Schasinglulu */ 1033*91f16700Schasinglulu 1034*91f16700Schasinglulu /* Obtain the v1.1 format of the descriptors. */ 1035*91f16700Schasinglulu ret = partition_info_get_handler_v1_1(uuid, partitions, 1036*91f16700Schasinglulu MAX_SP_LP_PARTITIONS, 1037*91f16700Schasinglulu &partition_count); 1038*91f16700Schasinglulu 1039*91f16700Schasinglulu /* Check if an error occurred during discovery. */ 1040*91f16700Schasinglulu if (ret != 0) { 1041*91f16700Schasinglulu goto err; 1042*91f16700Schasinglulu } 1043*91f16700Schasinglulu 1044*91f16700Schasinglulu /* If we didn't find any matches the UUID is unknown. */ 1045*91f16700Schasinglulu if (partition_count == 0) { 1046*91f16700Schasinglulu ret = FFA_ERROR_INVALID_PARAMETER; 1047*91f16700Schasinglulu goto err; 1048*91f16700Schasinglulu } 1049*91f16700Schasinglulu 1050*91f16700Schasinglulu /* Obtain the partition mailbox RX/TX buffer pair descriptor. */ 1051*91f16700Schasinglulu mbox = spmc_get_mbox_desc(secure_origin); 1052*91f16700Schasinglulu 1053*91f16700Schasinglulu /* 1054*91f16700Schasinglulu * If the caller has not bothered registering its RX/TX pair 1055*91f16700Schasinglulu * then return an error code. 1056*91f16700Schasinglulu */ 1057*91f16700Schasinglulu spin_lock(&mbox->lock); 1058*91f16700Schasinglulu if (mbox->rx_buffer == NULL) { 1059*91f16700Schasinglulu ret = FFA_ERROR_BUSY; 1060*91f16700Schasinglulu goto err_unlock; 1061*91f16700Schasinglulu } 1062*91f16700Schasinglulu 1063*91f16700Schasinglulu /* Ensure the RX buffer is currently free. */ 1064*91f16700Schasinglulu if (mbox->state != MAILBOX_STATE_EMPTY) { 1065*91f16700Schasinglulu ret = FFA_ERROR_BUSY; 1066*91f16700Schasinglulu goto err_unlock; 1067*91f16700Schasinglulu } 1068*91f16700Schasinglulu 1069*91f16700Schasinglulu /* Zero the RX buffer before populating. */ 1070*91f16700Schasinglulu (void)memset(mbox->rx_buffer, 0, 1071*91f16700Schasinglulu mbox->rxtx_page_count * FFA_PAGE_SIZE); 1072*91f16700Schasinglulu 1073*91f16700Schasinglulu /* 1074*91f16700Schasinglulu * Depending on the FF-A version of the requesting partition 1075*91f16700Schasinglulu * we may need to convert to a v1.0 format otherwise we can copy 1076*91f16700Schasinglulu * directly. 1077*91f16700Schasinglulu */ 1078*91f16700Schasinglulu if (ffa_version == MAKE_FFA_VERSION(U(1), U(0))) { 1079*91f16700Schasinglulu ret = partition_info_populate_v1_0(partitions, 1080*91f16700Schasinglulu mbox, 1081*91f16700Schasinglulu partition_count); 1082*91f16700Schasinglulu if (ret != 0) { 1083*91f16700Schasinglulu goto err_unlock; 1084*91f16700Schasinglulu } 1085*91f16700Schasinglulu } else { 1086*91f16700Schasinglulu uint32_t buf_size = mbox->rxtx_page_count * 1087*91f16700Schasinglulu FFA_PAGE_SIZE; 1088*91f16700Schasinglulu 1089*91f16700Schasinglulu /* Ensure the descriptor will fit in the buffer. */ 1090*91f16700Schasinglulu size = sizeof(struct ffa_partition_info_v1_1); 1091*91f16700Schasinglulu if (partition_count * size > buf_size) { 1092*91f16700Schasinglulu ret = FFA_ERROR_NO_MEMORY; 1093*91f16700Schasinglulu goto err_unlock; 1094*91f16700Schasinglulu } 1095*91f16700Schasinglulu memcpy(mbox->rx_buffer, partitions, 1096*91f16700Schasinglulu partition_count * size); 1097*91f16700Schasinglulu } 1098*91f16700Schasinglulu 1099*91f16700Schasinglulu mbox->state = MAILBOX_STATE_FULL; 1100*91f16700Schasinglulu spin_unlock(&mbox->lock); 1101*91f16700Schasinglulu } 1102*91f16700Schasinglulu SMC_RET4(handle, FFA_SUCCESS_SMC32, 0, partition_count, size); 1103*91f16700Schasinglulu 1104*91f16700Schasinglulu err_unlock: 1105*91f16700Schasinglulu spin_unlock(&mbox->lock); 1106*91f16700Schasinglulu err: 1107*91f16700Schasinglulu return spmc_ffa_error_return(handle, ret); 1108*91f16700Schasinglulu } 1109*91f16700Schasinglulu 1110*91f16700Schasinglulu static uint64_t ffa_feature_success(void *handle, uint32_t arg2) 1111*91f16700Schasinglulu { 1112*91f16700Schasinglulu SMC_RET3(handle, FFA_SUCCESS_SMC32, 0, arg2); 1113*91f16700Schasinglulu } 1114*91f16700Schasinglulu 1115*91f16700Schasinglulu static uint64_t ffa_features_retrieve_request(bool secure_origin, 1116*91f16700Schasinglulu uint32_t input_properties, 1117*91f16700Schasinglulu void *handle) 1118*91f16700Schasinglulu { 1119*91f16700Schasinglulu /* 1120*91f16700Schasinglulu * If we're called by the normal world we don't support any 1121*91f16700Schasinglulu * additional features. 1122*91f16700Schasinglulu */ 1123*91f16700Schasinglulu if (!secure_origin) { 1124*91f16700Schasinglulu if ((input_properties & FFA_FEATURES_RET_REQ_NS_BIT) != 0U) { 1125*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1126*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1127*91f16700Schasinglulu } 1128*91f16700Schasinglulu 1129*91f16700Schasinglulu } else { 1130*91f16700Schasinglulu struct secure_partition_desc *sp = spmc_get_current_sp_ctx(); 1131*91f16700Schasinglulu /* 1132*91f16700Schasinglulu * If v1.1 the NS bit must be set otherwise it is an invalid 1133*91f16700Schasinglulu * call. If v1.0 check and store whether the SP has requested 1134*91f16700Schasinglulu * the use of the NS bit. 1135*91f16700Schasinglulu */ 1136*91f16700Schasinglulu if (sp->ffa_version == MAKE_FFA_VERSION(1, 1)) { 1137*91f16700Schasinglulu if ((input_properties & 1138*91f16700Schasinglulu FFA_FEATURES_RET_REQ_NS_BIT) == 0U) { 1139*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1140*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1141*91f16700Schasinglulu } 1142*91f16700Schasinglulu return ffa_feature_success(handle, 1143*91f16700Schasinglulu FFA_FEATURES_RET_REQ_NS_BIT); 1144*91f16700Schasinglulu } else { 1145*91f16700Schasinglulu sp->ns_bit_requested = (input_properties & 1146*91f16700Schasinglulu FFA_FEATURES_RET_REQ_NS_BIT) != 1147*91f16700Schasinglulu 0U; 1148*91f16700Schasinglulu } 1149*91f16700Schasinglulu if (sp->ns_bit_requested) { 1150*91f16700Schasinglulu return ffa_feature_success(handle, 1151*91f16700Schasinglulu FFA_FEATURES_RET_REQ_NS_BIT); 1152*91f16700Schasinglulu } 1153*91f16700Schasinglulu } 1154*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1155*91f16700Schasinglulu } 1156*91f16700Schasinglulu 1157*91f16700Schasinglulu static uint64_t ffa_features_handler(uint32_t smc_fid, 1158*91f16700Schasinglulu bool secure_origin, 1159*91f16700Schasinglulu uint64_t x1, 1160*91f16700Schasinglulu uint64_t x2, 1161*91f16700Schasinglulu uint64_t x3, 1162*91f16700Schasinglulu uint64_t x4, 1163*91f16700Schasinglulu void *cookie, 1164*91f16700Schasinglulu void *handle, 1165*91f16700Schasinglulu uint64_t flags) 1166*91f16700Schasinglulu { 1167*91f16700Schasinglulu uint32_t function_id = (uint32_t) x1; 1168*91f16700Schasinglulu uint32_t input_properties = (uint32_t) x2; 1169*91f16700Schasinglulu 1170*91f16700Schasinglulu /* Check if a Feature ID was requested. */ 1171*91f16700Schasinglulu if ((function_id & FFA_FEATURES_BIT31_MASK) == 0U) { 1172*91f16700Schasinglulu /* We currently don't support any additional features. */ 1173*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 1174*91f16700Schasinglulu } 1175*91f16700Schasinglulu 1176*91f16700Schasinglulu /* 1177*91f16700Schasinglulu * Handle the cases where we have separate handlers due to additional 1178*91f16700Schasinglulu * properties. 1179*91f16700Schasinglulu */ 1180*91f16700Schasinglulu switch (function_id) { 1181*91f16700Schasinglulu case FFA_MEM_RETRIEVE_REQ_SMC32: 1182*91f16700Schasinglulu case FFA_MEM_RETRIEVE_REQ_SMC64: 1183*91f16700Schasinglulu return ffa_features_retrieve_request(secure_origin, 1184*91f16700Schasinglulu input_properties, 1185*91f16700Schasinglulu handle); 1186*91f16700Schasinglulu } 1187*91f16700Schasinglulu 1188*91f16700Schasinglulu /* 1189*91f16700Schasinglulu * We don't currently support additional input properties for these 1190*91f16700Schasinglulu * other ABIs therefore ensure this value is set to 0. 1191*91f16700Schasinglulu */ 1192*91f16700Schasinglulu if (input_properties != 0U) { 1193*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1194*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1195*91f16700Schasinglulu } 1196*91f16700Schasinglulu 1197*91f16700Schasinglulu /* Report if any other FF-A ABI is supported. */ 1198*91f16700Schasinglulu switch (function_id) { 1199*91f16700Schasinglulu /* Supported features from both worlds. */ 1200*91f16700Schasinglulu case FFA_ERROR: 1201*91f16700Schasinglulu case FFA_SUCCESS_SMC32: 1202*91f16700Schasinglulu case FFA_INTERRUPT: 1203*91f16700Schasinglulu case FFA_SPM_ID_GET: 1204*91f16700Schasinglulu case FFA_ID_GET: 1205*91f16700Schasinglulu case FFA_FEATURES: 1206*91f16700Schasinglulu case FFA_VERSION: 1207*91f16700Schasinglulu case FFA_RX_RELEASE: 1208*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_REQ_SMC32: 1209*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_REQ_SMC64: 1210*91f16700Schasinglulu case FFA_PARTITION_INFO_GET: 1211*91f16700Schasinglulu case FFA_RXTX_MAP_SMC32: 1212*91f16700Schasinglulu case FFA_RXTX_MAP_SMC64: 1213*91f16700Schasinglulu case FFA_RXTX_UNMAP: 1214*91f16700Schasinglulu case FFA_MEM_FRAG_TX: 1215*91f16700Schasinglulu case FFA_MSG_RUN: 1216*91f16700Schasinglulu 1217*91f16700Schasinglulu /* 1218*91f16700Schasinglulu * We are relying on the fact that the other registers 1219*91f16700Schasinglulu * will be set to 0 as these values align with the 1220*91f16700Schasinglulu * currently implemented features of the SPMC. If this 1221*91f16700Schasinglulu * changes this function must be extended to handle 1222*91f16700Schasinglulu * reporting the additional functionality. 1223*91f16700Schasinglulu */ 1224*91f16700Schasinglulu 1225*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1226*91f16700Schasinglulu /* Execution stops here. */ 1227*91f16700Schasinglulu 1228*91f16700Schasinglulu /* Supported ABIs only from the secure world. */ 1229*91f16700Schasinglulu case FFA_SECONDARY_EP_REGISTER_SMC64: 1230*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_RESP_SMC32: 1231*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_RESP_SMC64: 1232*91f16700Schasinglulu case FFA_MEM_RELINQUISH: 1233*91f16700Schasinglulu case FFA_MSG_WAIT: 1234*91f16700Schasinglulu 1235*91f16700Schasinglulu if (!secure_origin) { 1236*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1237*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1238*91f16700Schasinglulu } 1239*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1240*91f16700Schasinglulu /* Execution stops here. */ 1241*91f16700Schasinglulu 1242*91f16700Schasinglulu /* Supported features only from the normal world. */ 1243*91f16700Schasinglulu case FFA_MEM_SHARE_SMC32: 1244*91f16700Schasinglulu case FFA_MEM_SHARE_SMC64: 1245*91f16700Schasinglulu case FFA_MEM_LEND_SMC32: 1246*91f16700Schasinglulu case FFA_MEM_LEND_SMC64: 1247*91f16700Schasinglulu case FFA_MEM_RECLAIM: 1248*91f16700Schasinglulu case FFA_MEM_FRAG_RX: 1249*91f16700Schasinglulu 1250*91f16700Schasinglulu if (secure_origin) { 1251*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1252*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1253*91f16700Schasinglulu } 1254*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1255*91f16700Schasinglulu /* Execution stops here. */ 1256*91f16700Schasinglulu 1257*91f16700Schasinglulu default: 1258*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1259*91f16700Schasinglulu FFA_ERROR_NOT_SUPPORTED); 1260*91f16700Schasinglulu } 1261*91f16700Schasinglulu } 1262*91f16700Schasinglulu 1263*91f16700Schasinglulu static uint64_t ffa_id_get_handler(uint32_t smc_fid, 1264*91f16700Schasinglulu bool secure_origin, 1265*91f16700Schasinglulu uint64_t x1, 1266*91f16700Schasinglulu uint64_t x2, 1267*91f16700Schasinglulu uint64_t x3, 1268*91f16700Schasinglulu uint64_t x4, 1269*91f16700Schasinglulu void *cookie, 1270*91f16700Schasinglulu void *handle, 1271*91f16700Schasinglulu uint64_t flags) 1272*91f16700Schasinglulu { 1273*91f16700Schasinglulu if (secure_origin) { 1274*91f16700Schasinglulu SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0, 1275*91f16700Schasinglulu spmc_get_current_sp_ctx()->sp_id); 1276*91f16700Schasinglulu } else { 1277*91f16700Schasinglulu SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0, 1278*91f16700Schasinglulu spmc_get_hyp_ctx()->ns_ep_id); 1279*91f16700Schasinglulu } 1280*91f16700Schasinglulu } 1281*91f16700Schasinglulu 1282*91f16700Schasinglulu /* 1283*91f16700Schasinglulu * Enable an SP to query the ID assigned to the SPMC. 1284*91f16700Schasinglulu */ 1285*91f16700Schasinglulu static uint64_t ffa_spm_id_get_handler(uint32_t smc_fid, 1286*91f16700Schasinglulu bool secure_origin, 1287*91f16700Schasinglulu uint64_t x1, 1288*91f16700Schasinglulu uint64_t x2, 1289*91f16700Schasinglulu uint64_t x3, 1290*91f16700Schasinglulu uint64_t x4, 1291*91f16700Schasinglulu void *cookie, 1292*91f16700Schasinglulu void *handle, 1293*91f16700Schasinglulu uint64_t flags) 1294*91f16700Schasinglulu { 1295*91f16700Schasinglulu assert(x1 == 0UL); 1296*91f16700Schasinglulu assert(x2 == 0UL); 1297*91f16700Schasinglulu assert(x3 == 0UL); 1298*91f16700Schasinglulu assert(x4 == 0UL); 1299*91f16700Schasinglulu assert(SMC_GET_GP(handle, CTX_GPREG_X5) == 0UL); 1300*91f16700Schasinglulu assert(SMC_GET_GP(handle, CTX_GPREG_X6) == 0UL); 1301*91f16700Schasinglulu assert(SMC_GET_GP(handle, CTX_GPREG_X7) == 0UL); 1302*91f16700Schasinglulu 1303*91f16700Schasinglulu SMC_RET3(handle, FFA_SUCCESS_SMC32, 0x0, FFA_SPMC_ID); 1304*91f16700Schasinglulu } 1305*91f16700Schasinglulu 1306*91f16700Schasinglulu static uint64_t ffa_run_handler(uint32_t smc_fid, 1307*91f16700Schasinglulu bool secure_origin, 1308*91f16700Schasinglulu uint64_t x1, 1309*91f16700Schasinglulu uint64_t x2, 1310*91f16700Schasinglulu uint64_t x3, 1311*91f16700Schasinglulu uint64_t x4, 1312*91f16700Schasinglulu void *cookie, 1313*91f16700Schasinglulu void *handle, 1314*91f16700Schasinglulu uint64_t flags) 1315*91f16700Schasinglulu { 1316*91f16700Schasinglulu struct secure_partition_desc *sp; 1317*91f16700Schasinglulu uint16_t target_id = FFA_RUN_EP_ID(x1); 1318*91f16700Schasinglulu uint16_t vcpu_id = FFA_RUN_VCPU_ID(x1); 1319*91f16700Schasinglulu unsigned int idx; 1320*91f16700Schasinglulu unsigned int *rt_state; 1321*91f16700Schasinglulu unsigned int *rt_model; 1322*91f16700Schasinglulu 1323*91f16700Schasinglulu /* Can only be called from the normal world. */ 1324*91f16700Schasinglulu if (secure_origin) { 1325*91f16700Schasinglulu ERROR("FFA_RUN can only be called from NWd.\n"); 1326*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1327*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1328*91f16700Schasinglulu } 1329*91f16700Schasinglulu 1330*91f16700Schasinglulu /* Cannot run a Normal world partition. */ 1331*91f16700Schasinglulu if (ffa_is_normal_world_id(target_id)) { 1332*91f16700Schasinglulu ERROR("Cannot run a NWd partition (0x%x).\n", target_id); 1333*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1334*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1335*91f16700Schasinglulu } 1336*91f16700Schasinglulu 1337*91f16700Schasinglulu /* Check that the target SP exists. */ 1338*91f16700Schasinglulu sp = spmc_get_sp_ctx(target_id); 1339*91f16700Schasinglulu ERROR("Unknown partition ID (0x%x).\n", target_id); 1340*91f16700Schasinglulu if (sp == NULL) { 1341*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1342*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1343*91f16700Schasinglulu } 1344*91f16700Schasinglulu 1345*91f16700Schasinglulu idx = get_ec_index(sp); 1346*91f16700Schasinglulu if (idx != vcpu_id) { 1347*91f16700Schasinglulu ERROR("Cannot run vcpu %d != %d.\n", idx, vcpu_id); 1348*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1349*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1350*91f16700Schasinglulu } 1351*91f16700Schasinglulu rt_state = &((sp->ec[idx]).rt_state); 1352*91f16700Schasinglulu rt_model = &((sp->ec[idx]).rt_model); 1353*91f16700Schasinglulu if (*rt_state == RT_STATE_RUNNING) { 1354*91f16700Schasinglulu ERROR("Partition (0x%x) is already running.\n", target_id); 1355*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_BUSY); 1356*91f16700Schasinglulu } 1357*91f16700Schasinglulu 1358*91f16700Schasinglulu /* 1359*91f16700Schasinglulu * Sanity check that if the execution context was not waiting then it 1360*91f16700Schasinglulu * was either in the direct request or the run partition runtime model. 1361*91f16700Schasinglulu */ 1362*91f16700Schasinglulu if (*rt_state == RT_STATE_PREEMPTED || *rt_state == RT_STATE_BLOCKED) { 1363*91f16700Schasinglulu assert(*rt_model == RT_MODEL_RUN || 1364*91f16700Schasinglulu *rt_model == RT_MODEL_DIR_REQ); 1365*91f16700Schasinglulu } 1366*91f16700Schasinglulu 1367*91f16700Schasinglulu /* 1368*91f16700Schasinglulu * If the context was waiting then update the partition runtime model. 1369*91f16700Schasinglulu */ 1370*91f16700Schasinglulu if (*rt_state == RT_STATE_WAITING) { 1371*91f16700Schasinglulu *rt_model = RT_MODEL_RUN; 1372*91f16700Schasinglulu } 1373*91f16700Schasinglulu 1374*91f16700Schasinglulu /* 1375*91f16700Schasinglulu * Forward the request to the correct SP vCPU after updating 1376*91f16700Schasinglulu * its state. 1377*91f16700Schasinglulu */ 1378*91f16700Schasinglulu *rt_state = RT_STATE_RUNNING; 1379*91f16700Schasinglulu 1380*91f16700Schasinglulu return spmc_smc_return(smc_fid, secure_origin, x1, 0, 0, 0, 1381*91f16700Schasinglulu handle, cookie, flags, target_id); 1382*91f16700Schasinglulu } 1383*91f16700Schasinglulu 1384*91f16700Schasinglulu static uint64_t rx_release_handler(uint32_t smc_fid, 1385*91f16700Schasinglulu bool secure_origin, 1386*91f16700Schasinglulu uint64_t x1, 1387*91f16700Schasinglulu uint64_t x2, 1388*91f16700Schasinglulu uint64_t x3, 1389*91f16700Schasinglulu uint64_t x4, 1390*91f16700Schasinglulu void *cookie, 1391*91f16700Schasinglulu void *handle, 1392*91f16700Schasinglulu uint64_t flags) 1393*91f16700Schasinglulu { 1394*91f16700Schasinglulu struct mailbox *mbox = spmc_get_mbox_desc(secure_origin); 1395*91f16700Schasinglulu 1396*91f16700Schasinglulu spin_lock(&mbox->lock); 1397*91f16700Schasinglulu 1398*91f16700Schasinglulu if (mbox->state != MAILBOX_STATE_FULL) { 1399*91f16700Schasinglulu spin_unlock(&mbox->lock); 1400*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 1401*91f16700Schasinglulu } 1402*91f16700Schasinglulu 1403*91f16700Schasinglulu mbox->state = MAILBOX_STATE_EMPTY; 1404*91f16700Schasinglulu spin_unlock(&mbox->lock); 1405*91f16700Schasinglulu 1406*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1407*91f16700Schasinglulu } 1408*91f16700Schasinglulu 1409*91f16700Schasinglulu /* 1410*91f16700Schasinglulu * Perform initial validation on the provided secondary entry point. 1411*91f16700Schasinglulu * For now ensure it does not lie within the BL31 Image or the SP's 1412*91f16700Schasinglulu * RX/TX buffers as these are mapped within EL3. 1413*91f16700Schasinglulu * TODO: perform validation for additional invalid memory regions. 1414*91f16700Schasinglulu */ 1415*91f16700Schasinglulu static int validate_secondary_ep(uintptr_t ep, struct secure_partition_desc *sp) 1416*91f16700Schasinglulu { 1417*91f16700Schasinglulu struct mailbox *mb; 1418*91f16700Schasinglulu uintptr_t buffer_size; 1419*91f16700Schasinglulu uintptr_t sp_rx_buffer; 1420*91f16700Schasinglulu uintptr_t sp_tx_buffer; 1421*91f16700Schasinglulu uintptr_t sp_rx_buffer_limit; 1422*91f16700Schasinglulu uintptr_t sp_tx_buffer_limit; 1423*91f16700Schasinglulu 1424*91f16700Schasinglulu mb = &sp->mailbox; 1425*91f16700Schasinglulu buffer_size = (uintptr_t) (mb->rxtx_page_count * FFA_PAGE_SIZE); 1426*91f16700Schasinglulu sp_rx_buffer = (uintptr_t) mb->rx_buffer; 1427*91f16700Schasinglulu sp_tx_buffer = (uintptr_t) mb->tx_buffer; 1428*91f16700Schasinglulu sp_rx_buffer_limit = sp_rx_buffer + buffer_size; 1429*91f16700Schasinglulu sp_tx_buffer_limit = sp_tx_buffer + buffer_size; 1430*91f16700Schasinglulu 1431*91f16700Schasinglulu /* 1432*91f16700Schasinglulu * Check if the entry point lies within BL31, or the 1433*91f16700Schasinglulu * SP's RX or TX buffer. 1434*91f16700Schasinglulu */ 1435*91f16700Schasinglulu if ((ep >= BL31_BASE && ep < BL31_LIMIT) || 1436*91f16700Schasinglulu (ep >= sp_rx_buffer && ep < sp_rx_buffer_limit) || 1437*91f16700Schasinglulu (ep >= sp_tx_buffer && ep < sp_tx_buffer_limit)) { 1438*91f16700Schasinglulu return -EINVAL; 1439*91f16700Schasinglulu } 1440*91f16700Schasinglulu return 0; 1441*91f16700Schasinglulu } 1442*91f16700Schasinglulu 1443*91f16700Schasinglulu /******************************************************************************* 1444*91f16700Schasinglulu * This function handles the FFA_SECONDARY_EP_REGISTER SMC to allow an SP to 1445*91f16700Schasinglulu * register an entry point for initialization during a secondary cold boot. 1446*91f16700Schasinglulu ******************************************************************************/ 1447*91f16700Schasinglulu static uint64_t ffa_sec_ep_register_handler(uint32_t smc_fid, 1448*91f16700Schasinglulu bool secure_origin, 1449*91f16700Schasinglulu uint64_t x1, 1450*91f16700Schasinglulu uint64_t x2, 1451*91f16700Schasinglulu uint64_t x3, 1452*91f16700Schasinglulu uint64_t x4, 1453*91f16700Schasinglulu void *cookie, 1454*91f16700Schasinglulu void *handle, 1455*91f16700Schasinglulu uint64_t flags) 1456*91f16700Schasinglulu { 1457*91f16700Schasinglulu struct secure_partition_desc *sp; 1458*91f16700Schasinglulu struct sp_exec_ctx *sp_ctx; 1459*91f16700Schasinglulu 1460*91f16700Schasinglulu /* This request cannot originate from the Normal world. */ 1461*91f16700Schasinglulu if (!secure_origin) { 1462*91f16700Schasinglulu WARN("%s: Can only be called from SWd.\n", __func__); 1463*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 1464*91f16700Schasinglulu } 1465*91f16700Schasinglulu 1466*91f16700Schasinglulu /* Get the context of the current SP. */ 1467*91f16700Schasinglulu sp = spmc_get_current_sp_ctx(); 1468*91f16700Schasinglulu if (sp == NULL) { 1469*91f16700Schasinglulu WARN("%s: Cannot find SP context.\n", __func__); 1470*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1471*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1472*91f16700Schasinglulu } 1473*91f16700Schasinglulu 1474*91f16700Schasinglulu /* Only an S-EL1 SP should be invoking this ABI. */ 1475*91f16700Schasinglulu if (sp->runtime_el != S_EL1) { 1476*91f16700Schasinglulu WARN("%s: Can only be called for a S-EL1 SP.\n", __func__); 1477*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 1478*91f16700Schasinglulu } 1479*91f16700Schasinglulu 1480*91f16700Schasinglulu /* Ensure the SP is in its initialization state. */ 1481*91f16700Schasinglulu sp_ctx = spmc_get_sp_ec(sp); 1482*91f16700Schasinglulu if (sp_ctx->rt_model != RT_MODEL_INIT) { 1483*91f16700Schasinglulu WARN("%s: Can only be called during SP initialization.\n", 1484*91f16700Schasinglulu __func__); 1485*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_DENIED); 1486*91f16700Schasinglulu } 1487*91f16700Schasinglulu 1488*91f16700Schasinglulu /* Perform initial validation of the secondary entry point. */ 1489*91f16700Schasinglulu if (validate_secondary_ep(x1, sp)) { 1490*91f16700Schasinglulu WARN("%s: Invalid entry point provided (0x%lx).\n", 1491*91f16700Schasinglulu __func__, x1); 1492*91f16700Schasinglulu return spmc_ffa_error_return(handle, 1493*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 1494*91f16700Schasinglulu } 1495*91f16700Schasinglulu 1496*91f16700Schasinglulu /* 1497*91f16700Schasinglulu * Update the secondary entrypoint in SP context. 1498*91f16700Schasinglulu * We don't need a lock here as during partition initialization there 1499*91f16700Schasinglulu * will only be a single core online. 1500*91f16700Schasinglulu */ 1501*91f16700Schasinglulu sp->secondary_ep = x1; 1502*91f16700Schasinglulu VERBOSE("%s: 0x%lx\n", __func__, sp->secondary_ep); 1503*91f16700Schasinglulu 1504*91f16700Schasinglulu SMC_RET1(handle, FFA_SUCCESS_SMC32); 1505*91f16700Schasinglulu } 1506*91f16700Schasinglulu 1507*91f16700Schasinglulu /******************************************************************************* 1508*91f16700Schasinglulu * This function will parse the Secure Partition Manifest. From manifest, it 1509*91f16700Schasinglulu * will fetch details for preparing Secure partition image context and secure 1510*91f16700Schasinglulu * partition image boot arguments if any. 1511*91f16700Schasinglulu ******************************************************************************/ 1512*91f16700Schasinglulu static int sp_manifest_parse(void *sp_manifest, int offset, 1513*91f16700Schasinglulu struct secure_partition_desc *sp, 1514*91f16700Schasinglulu entry_point_info_t *ep_info, 1515*91f16700Schasinglulu int32_t *boot_info_reg) 1516*91f16700Schasinglulu { 1517*91f16700Schasinglulu int32_t ret, node; 1518*91f16700Schasinglulu uint32_t config_32; 1519*91f16700Schasinglulu 1520*91f16700Schasinglulu /* 1521*91f16700Schasinglulu * Look for the mandatory fields that are expected to be present in 1522*91f16700Schasinglulu * the SP manifests. 1523*91f16700Schasinglulu */ 1524*91f16700Schasinglulu node = fdt_path_offset(sp_manifest, "/"); 1525*91f16700Schasinglulu if (node < 0) { 1526*91f16700Schasinglulu ERROR("Did not find root node.\n"); 1527*91f16700Schasinglulu return node; 1528*91f16700Schasinglulu } 1529*91f16700Schasinglulu 1530*91f16700Schasinglulu ret = fdt_read_uint32_array(sp_manifest, node, "uuid", 1531*91f16700Schasinglulu ARRAY_SIZE(sp->uuid), sp->uuid); 1532*91f16700Schasinglulu if (ret != 0) { 1533*91f16700Schasinglulu ERROR("Missing Secure Partition UUID.\n"); 1534*91f16700Schasinglulu return ret; 1535*91f16700Schasinglulu } 1536*91f16700Schasinglulu 1537*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, "exception-level", &config_32); 1538*91f16700Schasinglulu if (ret != 0) { 1539*91f16700Schasinglulu ERROR("Missing SP Exception Level information.\n"); 1540*91f16700Schasinglulu return ret; 1541*91f16700Schasinglulu } 1542*91f16700Schasinglulu 1543*91f16700Schasinglulu sp->runtime_el = config_32; 1544*91f16700Schasinglulu 1545*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, "ffa-version", &config_32); 1546*91f16700Schasinglulu if (ret != 0) { 1547*91f16700Schasinglulu ERROR("Missing Secure Partition FF-A Version.\n"); 1548*91f16700Schasinglulu return ret; 1549*91f16700Schasinglulu } 1550*91f16700Schasinglulu 1551*91f16700Schasinglulu sp->ffa_version = config_32; 1552*91f16700Schasinglulu 1553*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, "execution-state", &config_32); 1554*91f16700Schasinglulu if (ret != 0) { 1555*91f16700Schasinglulu ERROR("Missing Secure Partition Execution State.\n"); 1556*91f16700Schasinglulu return ret; 1557*91f16700Schasinglulu } 1558*91f16700Schasinglulu 1559*91f16700Schasinglulu sp->execution_state = config_32; 1560*91f16700Schasinglulu 1561*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, 1562*91f16700Schasinglulu "messaging-method", &config_32); 1563*91f16700Schasinglulu if (ret != 0) { 1564*91f16700Schasinglulu ERROR("Missing Secure Partition messaging method.\n"); 1565*91f16700Schasinglulu return ret; 1566*91f16700Schasinglulu } 1567*91f16700Schasinglulu 1568*91f16700Schasinglulu /* Validate this entry, we currently only support direct messaging. */ 1569*91f16700Schasinglulu if ((config_32 & ~(FFA_PARTITION_DIRECT_REQ_RECV | 1570*91f16700Schasinglulu FFA_PARTITION_DIRECT_REQ_SEND)) != 0U) { 1571*91f16700Schasinglulu WARN("Invalid Secure Partition messaging method (0x%x)\n", 1572*91f16700Schasinglulu config_32); 1573*91f16700Schasinglulu return -EINVAL; 1574*91f16700Schasinglulu } 1575*91f16700Schasinglulu 1576*91f16700Schasinglulu sp->properties = config_32; 1577*91f16700Schasinglulu 1578*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, 1579*91f16700Schasinglulu "execution-ctx-count", &config_32); 1580*91f16700Schasinglulu 1581*91f16700Schasinglulu if (ret != 0) { 1582*91f16700Schasinglulu ERROR("Missing SP Execution Context Count.\n"); 1583*91f16700Schasinglulu return ret; 1584*91f16700Schasinglulu } 1585*91f16700Schasinglulu 1586*91f16700Schasinglulu /* 1587*91f16700Schasinglulu * Ensure this field is set correctly in the manifest however 1588*91f16700Schasinglulu * since this is currently a hardcoded value for S-EL1 partitions 1589*91f16700Schasinglulu * we don't need to save it here, just validate. 1590*91f16700Schasinglulu */ 1591*91f16700Schasinglulu if (config_32 != PLATFORM_CORE_COUNT) { 1592*91f16700Schasinglulu ERROR("SP Execution Context Count (%u) must be %u.\n", 1593*91f16700Schasinglulu config_32, PLATFORM_CORE_COUNT); 1594*91f16700Schasinglulu return -EINVAL; 1595*91f16700Schasinglulu } 1596*91f16700Schasinglulu 1597*91f16700Schasinglulu /* 1598*91f16700Schasinglulu * Look for the optional fields that are expected to be present in 1599*91f16700Schasinglulu * an SP manifest. 1600*91f16700Schasinglulu */ 1601*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, "id", &config_32); 1602*91f16700Schasinglulu if (ret != 0) { 1603*91f16700Schasinglulu WARN("Missing Secure Partition ID.\n"); 1604*91f16700Schasinglulu } else { 1605*91f16700Schasinglulu if (!is_ffa_secure_id_valid(config_32)) { 1606*91f16700Schasinglulu ERROR("Invalid Secure Partition ID (0x%x).\n", 1607*91f16700Schasinglulu config_32); 1608*91f16700Schasinglulu return -EINVAL; 1609*91f16700Schasinglulu } 1610*91f16700Schasinglulu sp->sp_id = config_32; 1611*91f16700Schasinglulu } 1612*91f16700Schasinglulu 1613*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, 1614*91f16700Schasinglulu "power-management-messages", &config_32); 1615*91f16700Schasinglulu if (ret != 0) { 1616*91f16700Schasinglulu WARN("Missing Power Management Messages entry.\n"); 1617*91f16700Schasinglulu } else { 1618*91f16700Schasinglulu /* 1619*91f16700Schasinglulu * Ensure only the currently supported power messages have 1620*91f16700Schasinglulu * been requested. 1621*91f16700Schasinglulu */ 1622*91f16700Schasinglulu if (config_32 & ~(FFA_PM_MSG_SUB_CPU_OFF | 1623*91f16700Schasinglulu FFA_PM_MSG_SUB_CPU_SUSPEND | 1624*91f16700Schasinglulu FFA_PM_MSG_SUB_CPU_SUSPEND_RESUME)) { 1625*91f16700Schasinglulu ERROR("Requested unsupported PM messages (%x)\n", 1626*91f16700Schasinglulu config_32); 1627*91f16700Schasinglulu return -EINVAL; 1628*91f16700Schasinglulu } 1629*91f16700Schasinglulu sp->pwr_mgmt_msgs = config_32; 1630*91f16700Schasinglulu } 1631*91f16700Schasinglulu 1632*91f16700Schasinglulu ret = fdt_read_uint32(sp_manifest, node, 1633*91f16700Schasinglulu "gp-register-num", &config_32); 1634*91f16700Schasinglulu if (ret != 0) { 1635*91f16700Schasinglulu WARN("Missing boot information register.\n"); 1636*91f16700Schasinglulu } else { 1637*91f16700Schasinglulu /* Check if a register number between 0-3 is specified. */ 1638*91f16700Schasinglulu if (config_32 < 4) { 1639*91f16700Schasinglulu *boot_info_reg = config_32; 1640*91f16700Schasinglulu } else { 1641*91f16700Schasinglulu WARN("Incorrect boot information register (%u).\n", 1642*91f16700Schasinglulu config_32); 1643*91f16700Schasinglulu } 1644*91f16700Schasinglulu } 1645*91f16700Schasinglulu 1646*91f16700Schasinglulu return 0; 1647*91f16700Schasinglulu } 1648*91f16700Schasinglulu 1649*91f16700Schasinglulu /******************************************************************************* 1650*91f16700Schasinglulu * This function gets the Secure Partition Manifest base and maps the manifest 1651*91f16700Schasinglulu * region. 1652*91f16700Schasinglulu * Currently only one Secure Partition manifest is considered which is used to 1653*91f16700Schasinglulu * prepare the context for the single Secure Partition. 1654*91f16700Schasinglulu ******************************************************************************/ 1655*91f16700Schasinglulu static int find_and_prepare_sp_context(void) 1656*91f16700Schasinglulu { 1657*91f16700Schasinglulu void *sp_manifest; 1658*91f16700Schasinglulu uintptr_t manifest_base; 1659*91f16700Schasinglulu uintptr_t manifest_base_align; 1660*91f16700Schasinglulu entry_point_info_t *next_image_ep_info; 1661*91f16700Schasinglulu int32_t ret, boot_info_reg = -1; 1662*91f16700Schasinglulu struct secure_partition_desc *sp; 1663*91f16700Schasinglulu 1664*91f16700Schasinglulu next_image_ep_info = bl31_plat_get_next_image_ep_info(SECURE); 1665*91f16700Schasinglulu if (next_image_ep_info == NULL) { 1666*91f16700Schasinglulu WARN("No Secure Partition image provided by BL2.\n"); 1667*91f16700Schasinglulu return -ENOENT; 1668*91f16700Schasinglulu } 1669*91f16700Schasinglulu 1670*91f16700Schasinglulu sp_manifest = (void *)next_image_ep_info->args.arg0; 1671*91f16700Schasinglulu if (sp_manifest == NULL) { 1672*91f16700Schasinglulu WARN("Secure Partition manifest absent.\n"); 1673*91f16700Schasinglulu return -ENOENT; 1674*91f16700Schasinglulu } 1675*91f16700Schasinglulu 1676*91f16700Schasinglulu manifest_base = (uintptr_t)sp_manifest; 1677*91f16700Schasinglulu manifest_base_align = page_align(manifest_base, DOWN); 1678*91f16700Schasinglulu 1679*91f16700Schasinglulu /* 1680*91f16700Schasinglulu * Map the secure partition manifest region in the EL3 translation 1681*91f16700Schasinglulu * regime. 1682*91f16700Schasinglulu * Map an area equal to (2 * PAGE_SIZE) for now. During manifest base 1683*91f16700Schasinglulu * alignment the region of 1 PAGE_SIZE from manifest align base may 1684*91f16700Schasinglulu * not completely accommodate the secure partition manifest region. 1685*91f16700Schasinglulu */ 1686*91f16700Schasinglulu ret = mmap_add_dynamic_region((unsigned long long)manifest_base_align, 1687*91f16700Schasinglulu manifest_base_align, 1688*91f16700Schasinglulu PAGE_SIZE * 2, 1689*91f16700Schasinglulu MT_RO_DATA); 1690*91f16700Schasinglulu if (ret != 0) { 1691*91f16700Schasinglulu ERROR("Error while mapping SP manifest (%d).\n", ret); 1692*91f16700Schasinglulu return ret; 1693*91f16700Schasinglulu } 1694*91f16700Schasinglulu 1695*91f16700Schasinglulu ret = fdt_node_offset_by_compatible(sp_manifest, -1, 1696*91f16700Schasinglulu "arm,ffa-manifest-1.0"); 1697*91f16700Schasinglulu if (ret < 0) { 1698*91f16700Schasinglulu ERROR("Error happened in SP manifest reading.\n"); 1699*91f16700Schasinglulu return -EINVAL; 1700*91f16700Schasinglulu } 1701*91f16700Schasinglulu 1702*91f16700Schasinglulu /* 1703*91f16700Schasinglulu * Store the size of the manifest so that it can be used later to pass 1704*91f16700Schasinglulu * the manifest as boot information later. 1705*91f16700Schasinglulu */ 1706*91f16700Schasinglulu next_image_ep_info->args.arg1 = fdt_totalsize(sp_manifest); 1707*91f16700Schasinglulu INFO("Manifest size = %lu bytes.\n", next_image_ep_info->args.arg1); 1708*91f16700Schasinglulu 1709*91f16700Schasinglulu /* 1710*91f16700Schasinglulu * Select an SP descriptor for initialising the partition's execution 1711*91f16700Schasinglulu * context on the primary CPU. 1712*91f16700Schasinglulu */ 1713*91f16700Schasinglulu sp = spmc_get_current_sp_ctx(); 1714*91f16700Schasinglulu 1715*91f16700Schasinglulu /* Initialize entry point information for the SP */ 1716*91f16700Schasinglulu SET_PARAM_HEAD(next_image_ep_info, PARAM_EP, VERSION_1, 1717*91f16700Schasinglulu SECURE | EP_ST_ENABLE); 1718*91f16700Schasinglulu 1719*91f16700Schasinglulu /* Parse the SP manifest. */ 1720*91f16700Schasinglulu ret = sp_manifest_parse(sp_manifest, ret, sp, next_image_ep_info, 1721*91f16700Schasinglulu &boot_info_reg); 1722*91f16700Schasinglulu if (ret != 0) { 1723*91f16700Schasinglulu ERROR("Error in Secure Partition manifest parsing.\n"); 1724*91f16700Schasinglulu return ret; 1725*91f16700Schasinglulu } 1726*91f16700Schasinglulu 1727*91f16700Schasinglulu /* Check that the runtime EL in the manifest was correct. */ 1728*91f16700Schasinglulu if (sp->runtime_el != S_EL1) { 1729*91f16700Schasinglulu ERROR("Unexpected runtime EL: %d\n", sp->runtime_el); 1730*91f16700Schasinglulu return -EINVAL; 1731*91f16700Schasinglulu } 1732*91f16700Schasinglulu 1733*91f16700Schasinglulu /* Perform any common initialisation. */ 1734*91f16700Schasinglulu spmc_sp_common_setup(sp, next_image_ep_info, boot_info_reg); 1735*91f16700Schasinglulu 1736*91f16700Schasinglulu /* Perform any initialisation specific to S-EL1 SPs. */ 1737*91f16700Schasinglulu spmc_el1_sp_setup(sp, next_image_ep_info); 1738*91f16700Schasinglulu 1739*91f16700Schasinglulu /* Initialize the SP context with the required ep info. */ 1740*91f16700Schasinglulu spmc_sp_common_ep_commit(sp, next_image_ep_info); 1741*91f16700Schasinglulu 1742*91f16700Schasinglulu return 0; 1743*91f16700Schasinglulu } 1744*91f16700Schasinglulu 1745*91f16700Schasinglulu /******************************************************************************* 1746*91f16700Schasinglulu * This function takes an SP context pointer and performs a synchronous entry 1747*91f16700Schasinglulu * into it. 1748*91f16700Schasinglulu ******************************************************************************/ 1749*91f16700Schasinglulu static int32_t logical_sp_init(void) 1750*91f16700Schasinglulu { 1751*91f16700Schasinglulu int32_t rc = 0; 1752*91f16700Schasinglulu struct el3_lp_desc *el3_lp_descs; 1753*91f16700Schasinglulu 1754*91f16700Schasinglulu /* Perform initial validation of the Logical Partitions. */ 1755*91f16700Schasinglulu rc = el3_sp_desc_validate(); 1756*91f16700Schasinglulu if (rc != 0) { 1757*91f16700Schasinglulu ERROR("Logical Partition validation failed!\n"); 1758*91f16700Schasinglulu return rc; 1759*91f16700Schasinglulu } 1760*91f16700Schasinglulu 1761*91f16700Schasinglulu el3_lp_descs = get_el3_lp_array(); 1762*91f16700Schasinglulu 1763*91f16700Schasinglulu INFO("Logical Secure Partition init start.\n"); 1764*91f16700Schasinglulu for (unsigned int i = 0U; i < EL3_LP_DESCS_COUNT; i++) { 1765*91f16700Schasinglulu rc = el3_lp_descs[i].init(); 1766*91f16700Schasinglulu if (rc != 0) { 1767*91f16700Schasinglulu ERROR("Logical SP (0x%x) Failed to Initialize\n", 1768*91f16700Schasinglulu el3_lp_descs[i].sp_id); 1769*91f16700Schasinglulu return rc; 1770*91f16700Schasinglulu } 1771*91f16700Schasinglulu VERBOSE("Logical SP (0x%x) Initialized\n", 1772*91f16700Schasinglulu el3_lp_descs[i].sp_id); 1773*91f16700Schasinglulu } 1774*91f16700Schasinglulu 1775*91f16700Schasinglulu INFO("Logical Secure Partition init completed.\n"); 1776*91f16700Schasinglulu 1777*91f16700Schasinglulu return rc; 1778*91f16700Schasinglulu } 1779*91f16700Schasinglulu 1780*91f16700Schasinglulu uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec) 1781*91f16700Schasinglulu { 1782*91f16700Schasinglulu uint64_t rc; 1783*91f16700Schasinglulu 1784*91f16700Schasinglulu assert(ec != NULL); 1785*91f16700Schasinglulu 1786*91f16700Schasinglulu /* Assign the context of the SP to this CPU */ 1787*91f16700Schasinglulu cm_set_context(&(ec->cpu_ctx), SECURE); 1788*91f16700Schasinglulu 1789*91f16700Schasinglulu /* Restore the context assigned above */ 1790*91f16700Schasinglulu cm_el1_sysregs_context_restore(SECURE); 1791*91f16700Schasinglulu cm_set_next_eret_context(SECURE); 1792*91f16700Schasinglulu 1793*91f16700Schasinglulu /* Invalidate TLBs at EL1. */ 1794*91f16700Schasinglulu tlbivmalle1(); 1795*91f16700Schasinglulu dsbish(); 1796*91f16700Schasinglulu 1797*91f16700Schasinglulu /* Enter Secure Partition */ 1798*91f16700Schasinglulu rc = spm_secure_partition_enter(&ec->c_rt_ctx); 1799*91f16700Schasinglulu 1800*91f16700Schasinglulu /* Save secure state */ 1801*91f16700Schasinglulu cm_el1_sysregs_context_save(SECURE); 1802*91f16700Schasinglulu 1803*91f16700Schasinglulu return rc; 1804*91f16700Schasinglulu } 1805*91f16700Schasinglulu 1806*91f16700Schasinglulu /******************************************************************************* 1807*91f16700Schasinglulu * SPMC Helper Functions. 1808*91f16700Schasinglulu ******************************************************************************/ 1809*91f16700Schasinglulu static int32_t sp_init(void) 1810*91f16700Schasinglulu { 1811*91f16700Schasinglulu uint64_t rc; 1812*91f16700Schasinglulu struct secure_partition_desc *sp; 1813*91f16700Schasinglulu struct sp_exec_ctx *ec; 1814*91f16700Schasinglulu 1815*91f16700Schasinglulu sp = spmc_get_current_sp_ctx(); 1816*91f16700Schasinglulu ec = spmc_get_sp_ec(sp); 1817*91f16700Schasinglulu ec->rt_model = RT_MODEL_INIT; 1818*91f16700Schasinglulu ec->rt_state = RT_STATE_RUNNING; 1819*91f16700Schasinglulu 1820*91f16700Schasinglulu INFO("Secure Partition (0x%x) init start.\n", sp->sp_id); 1821*91f16700Schasinglulu 1822*91f16700Schasinglulu rc = spmc_sp_synchronous_entry(ec); 1823*91f16700Schasinglulu if (rc != 0) { 1824*91f16700Schasinglulu /* Indicate SP init was not successful. */ 1825*91f16700Schasinglulu ERROR("SP (0x%x) failed to initialize (%lu).\n", 1826*91f16700Schasinglulu sp->sp_id, rc); 1827*91f16700Schasinglulu return 0; 1828*91f16700Schasinglulu } 1829*91f16700Schasinglulu 1830*91f16700Schasinglulu ec->rt_state = RT_STATE_WAITING; 1831*91f16700Schasinglulu INFO("Secure Partition initialized.\n"); 1832*91f16700Schasinglulu 1833*91f16700Schasinglulu return 1; 1834*91f16700Schasinglulu } 1835*91f16700Schasinglulu 1836*91f16700Schasinglulu static void initalize_sp_descs(void) 1837*91f16700Schasinglulu { 1838*91f16700Schasinglulu struct secure_partition_desc *sp; 1839*91f16700Schasinglulu 1840*91f16700Schasinglulu for (unsigned int i = 0U; i < SECURE_PARTITION_COUNT; i++) { 1841*91f16700Schasinglulu sp = &sp_desc[i]; 1842*91f16700Schasinglulu sp->sp_id = INV_SP_ID; 1843*91f16700Schasinglulu sp->mailbox.rx_buffer = NULL; 1844*91f16700Schasinglulu sp->mailbox.tx_buffer = NULL; 1845*91f16700Schasinglulu sp->mailbox.state = MAILBOX_STATE_EMPTY; 1846*91f16700Schasinglulu sp->secondary_ep = 0; 1847*91f16700Schasinglulu } 1848*91f16700Schasinglulu } 1849*91f16700Schasinglulu 1850*91f16700Schasinglulu static void initalize_ns_ep_descs(void) 1851*91f16700Schasinglulu { 1852*91f16700Schasinglulu struct ns_endpoint_desc *ns_ep; 1853*91f16700Schasinglulu 1854*91f16700Schasinglulu for (unsigned int i = 0U; i < NS_PARTITION_COUNT; i++) { 1855*91f16700Schasinglulu ns_ep = &ns_ep_desc[i]; 1856*91f16700Schasinglulu /* 1857*91f16700Schasinglulu * Clashes with the Hypervisor ID but will not be a 1858*91f16700Schasinglulu * problem in practice. 1859*91f16700Schasinglulu */ 1860*91f16700Schasinglulu ns_ep->ns_ep_id = 0; 1861*91f16700Schasinglulu ns_ep->ffa_version = 0; 1862*91f16700Schasinglulu ns_ep->mailbox.rx_buffer = NULL; 1863*91f16700Schasinglulu ns_ep->mailbox.tx_buffer = NULL; 1864*91f16700Schasinglulu ns_ep->mailbox.state = MAILBOX_STATE_EMPTY; 1865*91f16700Schasinglulu } 1866*91f16700Schasinglulu } 1867*91f16700Schasinglulu 1868*91f16700Schasinglulu /******************************************************************************* 1869*91f16700Schasinglulu * Initialize SPMC attributes for the SPMD. 1870*91f16700Schasinglulu ******************************************************************************/ 1871*91f16700Schasinglulu void spmc_populate_attrs(spmc_manifest_attribute_t *spmc_attrs) 1872*91f16700Schasinglulu { 1873*91f16700Schasinglulu spmc_attrs->major_version = FFA_VERSION_MAJOR; 1874*91f16700Schasinglulu spmc_attrs->minor_version = FFA_VERSION_MINOR; 1875*91f16700Schasinglulu spmc_attrs->exec_state = MODE_RW_64; 1876*91f16700Schasinglulu spmc_attrs->spmc_id = FFA_SPMC_ID; 1877*91f16700Schasinglulu } 1878*91f16700Schasinglulu 1879*91f16700Schasinglulu /******************************************************************************* 1880*91f16700Schasinglulu * Initialize contexts of all Secure Partitions. 1881*91f16700Schasinglulu ******************************************************************************/ 1882*91f16700Schasinglulu int32_t spmc_setup(void) 1883*91f16700Schasinglulu { 1884*91f16700Schasinglulu int32_t ret; 1885*91f16700Schasinglulu uint32_t flags; 1886*91f16700Schasinglulu 1887*91f16700Schasinglulu /* Initialize endpoint descriptors */ 1888*91f16700Schasinglulu initalize_sp_descs(); 1889*91f16700Schasinglulu initalize_ns_ep_descs(); 1890*91f16700Schasinglulu 1891*91f16700Schasinglulu /* 1892*91f16700Schasinglulu * Retrieve the information of the datastore for tracking shared memory 1893*91f16700Schasinglulu * requests allocated by platform code and zero the region if available. 1894*91f16700Schasinglulu */ 1895*91f16700Schasinglulu ret = plat_spmc_shmem_datastore_get(&spmc_shmem_obj_state.data, 1896*91f16700Schasinglulu &spmc_shmem_obj_state.data_size); 1897*91f16700Schasinglulu if (ret != 0) { 1898*91f16700Schasinglulu ERROR("Failed to obtain memory descriptor backing store!\n"); 1899*91f16700Schasinglulu return ret; 1900*91f16700Schasinglulu } 1901*91f16700Schasinglulu memset(spmc_shmem_obj_state.data, 0, spmc_shmem_obj_state.data_size); 1902*91f16700Schasinglulu 1903*91f16700Schasinglulu /* Setup logical SPs. */ 1904*91f16700Schasinglulu ret = logical_sp_init(); 1905*91f16700Schasinglulu if (ret != 0) { 1906*91f16700Schasinglulu ERROR("Failed to initialize Logical Partitions.\n"); 1907*91f16700Schasinglulu return ret; 1908*91f16700Schasinglulu } 1909*91f16700Schasinglulu 1910*91f16700Schasinglulu /* Perform physical SP setup. */ 1911*91f16700Schasinglulu 1912*91f16700Schasinglulu /* Disable MMU at EL1 (initialized by BL2) */ 1913*91f16700Schasinglulu disable_mmu_icache_el1(); 1914*91f16700Schasinglulu 1915*91f16700Schasinglulu /* Initialize context of the SP */ 1916*91f16700Schasinglulu INFO("Secure Partition context setup start.\n"); 1917*91f16700Schasinglulu 1918*91f16700Schasinglulu ret = find_and_prepare_sp_context(); 1919*91f16700Schasinglulu if (ret != 0) { 1920*91f16700Schasinglulu ERROR("Error in SP finding and context preparation.\n"); 1921*91f16700Schasinglulu return ret; 1922*91f16700Schasinglulu } 1923*91f16700Schasinglulu 1924*91f16700Schasinglulu /* Register power management hooks with PSCI */ 1925*91f16700Schasinglulu psci_register_spd_pm_hook(&spmc_pm); 1926*91f16700Schasinglulu 1927*91f16700Schasinglulu /* 1928*91f16700Schasinglulu * Register an interrupt handler for S-EL1 interrupts 1929*91f16700Schasinglulu * when generated during code executing in the 1930*91f16700Schasinglulu * non-secure state. 1931*91f16700Schasinglulu */ 1932*91f16700Schasinglulu flags = 0; 1933*91f16700Schasinglulu set_interrupt_rm_flag(flags, NON_SECURE); 1934*91f16700Schasinglulu ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, 1935*91f16700Schasinglulu spmc_sp_interrupt_handler, 1936*91f16700Schasinglulu flags); 1937*91f16700Schasinglulu if (ret != 0) { 1938*91f16700Schasinglulu ERROR("Failed to register interrupt handler! (%d)\n", ret); 1939*91f16700Schasinglulu panic(); 1940*91f16700Schasinglulu } 1941*91f16700Schasinglulu 1942*91f16700Schasinglulu /* Register init function for deferred init. */ 1943*91f16700Schasinglulu bl31_register_bl32_init(&sp_init); 1944*91f16700Schasinglulu 1945*91f16700Schasinglulu INFO("Secure Partition setup done.\n"); 1946*91f16700Schasinglulu 1947*91f16700Schasinglulu return 0; 1948*91f16700Schasinglulu } 1949*91f16700Schasinglulu 1950*91f16700Schasinglulu /******************************************************************************* 1951*91f16700Schasinglulu * Secure Partition Manager SMC handler. 1952*91f16700Schasinglulu ******************************************************************************/ 1953*91f16700Schasinglulu uint64_t spmc_smc_handler(uint32_t smc_fid, 1954*91f16700Schasinglulu bool secure_origin, 1955*91f16700Schasinglulu uint64_t x1, 1956*91f16700Schasinglulu uint64_t x2, 1957*91f16700Schasinglulu uint64_t x3, 1958*91f16700Schasinglulu uint64_t x4, 1959*91f16700Schasinglulu void *cookie, 1960*91f16700Schasinglulu void *handle, 1961*91f16700Schasinglulu uint64_t flags) 1962*91f16700Schasinglulu { 1963*91f16700Schasinglulu switch (smc_fid) { 1964*91f16700Schasinglulu 1965*91f16700Schasinglulu case FFA_VERSION: 1966*91f16700Schasinglulu return ffa_version_handler(smc_fid, secure_origin, x1, x2, x3, 1967*91f16700Schasinglulu x4, cookie, handle, flags); 1968*91f16700Schasinglulu 1969*91f16700Schasinglulu case FFA_SPM_ID_GET: 1970*91f16700Schasinglulu return ffa_spm_id_get_handler(smc_fid, secure_origin, x1, x2, 1971*91f16700Schasinglulu x3, x4, cookie, handle, flags); 1972*91f16700Schasinglulu 1973*91f16700Schasinglulu case FFA_ID_GET: 1974*91f16700Schasinglulu return ffa_id_get_handler(smc_fid, secure_origin, x1, x2, x3, 1975*91f16700Schasinglulu x4, cookie, handle, flags); 1976*91f16700Schasinglulu 1977*91f16700Schasinglulu case FFA_FEATURES: 1978*91f16700Schasinglulu return ffa_features_handler(smc_fid, secure_origin, x1, x2, x3, 1979*91f16700Schasinglulu x4, cookie, handle, flags); 1980*91f16700Schasinglulu 1981*91f16700Schasinglulu case FFA_SECONDARY_EP_REGISTER_SMC64: 1982*91f16700Schasinglulu return ffa_sec_ep_register_handler(smc_fid, secure_origin, x1, 1983*91f16700Schasinglulu x2, x3, x4, cookie, handle, 1984*91f16700Schasinglulu flags); 1985*91f16700Schasinglulu 1986*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_REQ_SMC32: 1987*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_REQ_SMC64: 1988*91f16700Schasinglulu return direct_req_smc_handler(smc_fid, secure_origin, x1, x2, 1989*91f16700Schasinglulu x3, x4, cookie, handle, flags); 1990*91f16700Schasinglulu 1991*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_RESP_SMC32: 1992*91f16700Schasinglulu case FFA_MSG_SEND_DIRECT_RESP_SMC64: 1993*91f16700Schasinglulu return direct_resp_smc_handler(smc_fid, secure_origin, x1, x2, 1994*91f16700Schasinglulu x3, x4, cookie, handle, flags); 1995*91f16700Schasinglulu 1996*91f16700Schasinglulu case FFA_RXTX_MAP_SMC32: 1997*91f16700Schasinglulu case FFA_RXTX_MAP_SMC64: 1998*91f16700Schasinglulu return rxtx_map_handler(smc_fid, secure_origin, x1, x2, x3, x4, 1999*91f16700Schasinglulu cookie, handle, flags); 2000*91f16700Schasinglulu 2001*91f16700Schasinglulu case FFA_RXTX_UNMAP: 2002*91f16700Schasinglulu return rxtx_unmap_handler(smc_fid, secure_origin, x1, x2, x3, 2003*91f16700Schasinglulu x4, cookie, handle, flags); 2004*91f16700Schasinglulu 2005*91f16700Schasinglulu case FFA_PARTITION_INFO_GET: 2006*91f16700Schasinglulu return partition_info_get_handler(smc_fid, secure_origin, x1, 2007*91f16700Schasinglulu x2, x3, x4, cookie, handle, 2008*91f16700Schasinglulu flags); 2009*91f16700Schasinglulu 2010*91f16700Schasinglulu case FFA_RX_RELEASE: 2011*91f16700Schasinglulu return rx_release_handler(smc_fid, secure_origin, x1, x2, x3, 2012*91f16700Schasinglulu x4, cookie, handle, flags); 2013*91f16700Schasinglulu 2014*91f16700Schasinglulu case FFA_MSG_WAIT: 2015*91f16700Schasinglulu return msg_wait_handler(smc_fid, secure_origin, x1, x2, x3, x4, 2016*91f16700Schasinglulu cookie, handle, flags); 2017*91f16700Schasinglulu 2018*91f16700Schasinglulu case FFA_ERROR: 2019*91f16700Schasinglulu return ffa_error_handler(smc_fid, secure_origin, x1, x2, x3, x4, 2020*91f16700Schasinglulu cookie, handle, flags); 2021*91f16700Schasinglulu 2022*91f16700Schasinglulu case FFA_MSG_RUN: 2023*91f16700Schasinglulu return ffa_run_handler(smc_fid, secure_origin, x1, x2, x3, x4, 2024*91f16700Schasinglulu cookie, handle, flags); 2025*91f16700Schasinglulu 2026*91f16700Schasinglulu case FFA_MEM_SHARE_SMC32: 2027*91f16700Schasinglulu case FFA_MEM_SHARE_SMC64: 2028*91f16700Schasinglulu case FFA_MEM_LEND_SMC32: 2029*91f16700Schasinglulu case FFA_MEM_LEND_SMC64: 2030*91f16700Schasinglulu return spmc_ffa_mem_send(smc_fid, secure_origin, x1, x2, x3, x4, 2031*91f16700Schasinglulu cookie, handle, flags); 2032*91f16700Schasinglulu 2033*91f16700Schasinglulu case FFA_MEM_FRAG_TX: 2034*91f16700Schasinglulu return spmc_ffa_mem_frag_tx(smc_fid, secure_origin, x1, x2, x3, 2035*91f16700Schasinglulu x4, cookie, handle, flags); 2036*91f16700Schasinglulu 2037*91f16700Schasinglulu case FFA_MEM_FRAG_RX: 2038*91f16700Schasinglulu return spmc_ffa_mem_frag_rx(smc_fid, secure_origin, x1, x2, x3, 2039*91f16700Schasinglulu x4, cookie, handle, flags); 2040*91f16700Schasinglulu 2041*91f16700Schasinglulu case FFA_MEM_RETRIEVE_REQ_SMC32: 2042*91f16700Schasinglulu case FFA_MEM_RETRIEVE_REQ_SMC64: 2043*91f16700Schasinglulu return spmc_ffa_mem_retrieve_req(smc_fid, secure_origin, x1, x2, 2044*91f16700Schasinglulu x3, x4, cookie, handle, flags); 2045*91f16700Schasinglulu 2046*91f16700Schasinglulu case FFA_MEM_RELINQUISH: 2047*91f16700Schasinglulu return spmc_ffa_mem_relinquish(smc_fid, secure_origin, x1, x2, 2048*91f16700Schasinglulu x3, x4, cookie, handle, flags); 2049*91f16700Schasinglulu 2050*91f16700Schasinglulu case FFA_MEM_RECLAIM: 2051*91f16700Schasinglulu return spmc_ffa_mem_reclaim(smc_fid, secure_origin, x1, x2, x3, 2052*91f16700Schasinglulu x4, cookie, handle, flags); 2053*91f16700Schasinglulu 2054*91f16700Schasinglulu default: 2055*91f16700Schasinglulu WARN("Unsupported FF-A call 0x%08x.\n", smc_fid); 2056*91f16700Schasinglulu break; 2057*91f16700Schasinglulu } 2058*91f16700Schasinglulu return spmc_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 2059*91f16700Schasinglulu } 2060*91f16700Schasinglulu 2061*91f16700Schasinglulu /******************************************************************************* 2062*91f16700Schasinglulu * This function is the handler registered for S-EL1 interrupts by the SPMC. It 2063*91f16700Schasinglulu * validates the interrupt and upon success arranges entry into the SP for 2064*91f16700Schasinglulu * handling the interrupt. 2065*91f16700Schasinglulu ******************************************************************************/ 2066*91f16700Schasinglulu static uint64_t spmc_sp_interrupt_handler(uint32_t id, 2067*91f16700Schasinglulu uint32_t flags, 2068*91f16700Schasinglulu void *handle, 2069*91f16700Schasinglulu void *cookie) 2070*91f16700Schasinglulu { 2071*91f16700Schasinglulu struct secure_partition_desc *sp = spmc_get_current_sp_ctx(); 2072*91f16700Schasinglulu struct sp_exec_ctx *ec; 2073*91f16700Schasinglulu uint32_t linear_id = plat_my_core_pos(); 2074*91f16700Schasinglulu 2075*91f16700Schasinglulu /* Sanity check for a NULL pointer dereference. */ 2076*91f16700Schasinglulu assert(sp != NULL); 2077*91f16700Schasinglulu 2078*91f16700Schasinglulu /* Check the security state when the exception was generated. */ 2079*91f16700Schasinglulu assert(get_interrupt_src_ss(flags) == NON_SECURE); 2080*91f16700Schasinglulu 2081*91f16700Schasinglulu /* Panic if not an S-EL1 Partition. */ 2082*91f16700Schasinglulu if (sp->runtime_el != S_EL1) { 2083*91f16700Schasinglulu ERROR("Interrupt received for a non S-EL1 SP on core%u.\n", 2084*91f16700Schasinglulu linear_id); 2085*91f16700Schasinglulu panic(); 2086*91f16700Schasinglulu } 2087*91f16700Schasinglulu 2088*91f16700Schasinglulu /* Obtain a reference to the SP execution context. */ 2089*91f16700Schasinglulu ec = spmc_get_sp_ec(sp); 2090*91f16700Schasinglulu 2091*91f16700Schasinglulu /* Ensure that the execution context is in waiting state else panic. */ 2092*91f16700Schasinglulu if (ec->rt_state != RT_STATE_WAITING) { 2093*91f16700Schasinglulu ERROR("SP EC on core%u is not waiting (%u), it is (%u).\n", 2094*91f16700Schasinglulu linear_id, RT_STATE_WAITING, ec->rt_state); 2095*91f16700Schasinglulu panic(); 2096*91f16700Schasinglulu } 2097*91f16700Schasinglulu 2098*91f16700Schasinglulu /* Update the runtime model and state of the partition. */ 2099*91f16700Schasinglulu ec->rt_model = RT_MODEL_INTR; 2100*91f16700Schasinglulu ec->rt_state = RT_STATE_RUNNING; 2101*91f16700Schasinglulu 2102*91f16700Schasinglulu VERBOSE("SP (0x%x) interrupt start on core%u.\n", sp->sp_id, linear_id); 2103*91f16700Schasinglulu 2104*91f16700Schasinglulu /* 2105*91f16700Schasinglulu * Forward the interrupt to the S-EL1 SP. The interrupt ID is not 2106*91f16700Schasinglulu * populated as the SP can determine this by itself. 2107*91f16700Schasinglulu */ 2108*91f16700Schasinglulu return spmd_smc_switch_state(FFA_INTERRUPT, false, 2109*91f16700Schasinglulu FFA_PARAM_MBZ, FFA_PARAM_MBZ, 2110*91f16700Schasinglulu FFA_PARAM_MBZ, FFA_PARAM_MBZ, 2111*91f16700Schasinglulu handle); 2112*91f16700Schasinglulu } 2113