1890b5088SRaghu Krishnamurthy /* 2890b5088SRaghu Krishnamurthy * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. 3890b5088SRaghu Krishnamurthy * 4890b5088SRaghu Krishnamurthy * SPDX-License-Identifier: BSD-3-Clause 5890b5088SRaghu Krishnamurthy */ 6890b5088SRaghu Krishnamurthy 7890b5088SRaghu Krishnamurthy #include <assert.h> 8890b5088SRaghu Krishnamurthy #include <errno.h> 9890b5088SRaghu Krishnamurthy #include <string.h> 10*66bdfd6eSRaghu Krishnamurthy #include "spmd_private.h" 11890b5088SRaghu Krishnamurthy 12890b5088SRaghu Krishnamurthy #include <common/debug.h> 13*66bdfd6eSRaghu Krishnamurthy #include <lib/el3_runtime/context_mgmt.h> 14890b5088SRaghu Krishnamurthy #include <services/el3_spmd_logical_sp.h> 15*66bdfd6eSRaghu Krishnamurthy #include <services/spmc_svc.h> 16*66bdfd6eSRaghu Krishnamurthy 17890b5088SRaghu Krishnamurthy 18890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP 19890b5088SRaghu Krishnamurthy static bool is_spmd_lp_inited; 20890b5088SRaghu Krishnamurthy static bool is_spmc_inited; 21890b5088SRaghu Krishnamurthy 22890b5088SRaghu Krishnamurthy /* 23890b5088SRaghu Krishnamurthy * Helper function to obtain the array storing the EL3 24890b5088SRaghu Krishnamurthy * SPMD Logical Partition descriptors. 25890b5088SRaghu Krishnamurthy */ 26890b5088SRaghu Krishnamurthy static struct spmd_lp_desc *get_spmd_el3_lp_array(void) 27890b5088SRaghu Krishnamurthy { 28890b5088SRaghu Krishnamurthy return (struct spmd_lp_desc *) SPMD_LP_DESCS_START; 29890b5088SRaghu Krishnamurthy } 30890b5088SRaghu Krishnamurthy 31890b5088SRaghu Krishnamurthy /******************************************************************************* 32890b5088SRaghu Krishnamurthy * Validate any logical partition descriptors before we initialize. 33890b5088SRaghu Krishnamurthy * Initialization of said partitions will be taken care of during SPMD boot. 34890b5088SRaghu Krishnamurthy ******************************************************************************/ 35890b5088SRaghu Krishnamurthy static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array) 36890b5088SRaghu Krishnamurthy { 37890b5088SRaghu Krishnamurthy /* Check the array bounds are valid. */ 38890b5088SRaghu Krishnamurthy assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START); 39890b5088SRaghu Krishnamurthy 40*66bdfd6eSRaghu Krishnamurthy /* 41*66bdfd6eSRaghu Krishnamurthy * No support for SPMD logical partitions when SPMC is at EL3. 42*66bdfd6eSRaghu Krishnamurthy */ 43*66bdfd6eSRaghu Krishnamurthy assert(!is_spmc_at_el3()); 44*66bdfd6eSRaghu Krishnamurthy 45890b5088SRaghu Krishnamurthy /* If no SPMD logical partitions are implemented then simply bail out. */ 46890b5088SRaghu Krishnamurthy if (SPMD_LP_DESCS_COUNT == 0U) { 47890b5088SRaghu Krishnamurthy return -1; 48890b5088SRaghu Krishnamurthy } 49890b5088SRaghu Krishnamurthy 50890b5088SRaghu Krishnamurthy for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) { 51890b5088SRaghu Krishnamurthy struct spmd_lp_desc *lp_desc = &lp_array[index]; 52890b5088SRaghu Krishnamurthy 53890b5088SRaghu Krishnamurthy /* Validate our logical partition descriptors. */ 54890b5088SRaghu Krishnamurthy if (lp_desc == NULL) { 55890b5088SRaghu Krishnamurthy ERROR("Invalid SPMD Logical SP Descriptor\n"); 56890b5088SRaghu Krishnamurthy return -EINVAL; 57890b5088SRaghu Krishnamurthy } 58890b5088SRaghu Krishnamurthy 59890b5088SRaghu Krishnamurthy /* 60890b5088SRaghu Krishnamurthy * Ensure the ID follows the convention to indicate it resides 61890b5088SRaghu Krishnamurthy * in the secure world. 62890b5088SRaghu Krishnamurthy */ 63890b5088SRaghu Krishnamurthy if (!ffa_is_secure_world_id(lp_desc->sp_id)) { 64890b5088SRaghu Krishnamurthy ERROR("Invalid SPMD Logical SP ID (0x%x)\n", 65890b5088SRaghu Krishnamurthy lp_desc->sp_id); 66890b5088SRaghu Krishnamurthy return -EINVAL; 67890b5088SRaghu Krishnamurthy } 68890b5088SRaghu Krishnamurthy 69890b5088SRaghu Krishnamurthy /* Ensure SPMD logical partition is in valid range. */ 70890b5088SRaghu Krishnamurthy if (!is_spmd_lp_id(lp_desc->sp_id)) { 71890b5088SRaghu Krishnamurthy ERROR("Invalid SPMD Logical Partition ID (0x%x)\n", 72890b5088SRaghu Krishnamurthy lp_desc->sp_id); 73890b5088SRaghu Krishnamurthy return -EINVAL; 74890b5088SRaghu Krishnamurthy } 75890b5088SRaghu Krishnamurthy 76890b5088SRaghu Krishnamurthy /* Ensure the UUID is not the NULL UUID. */ 77890b5088SRaghu Krishnamurthy if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 && 78890b5088SRaghu Krishnamurthy lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) { 79890b5088SRaghu Krishnamurthy ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n", 80890b5088SRaghu Krishnamurthy lp_desc->sp_id); 81890b5088SRaghu Krishnamurthy return -EINVAL; 82890b5088SRaghu Krishnamurthy } 83890b5088SRaghu Krishnamurthy 84890b5088SRaghu Krishnamurthy /* Ensure init function callback is registered. */ 85890b5088SRaghu Krishnamurthy if (lp_desc->init == NULL) { 86890b5088SRaghu Krishnamurthy ERROR("Missing init function for Logical SP(0x%x)\n", 87890b5088SRaghu Krishnamurthy lp_desc->sp_id); 88890b5088SRaghu Krishnamurthy return -EINVAL; 89890b5088SRaghu Krishnamurthy } 90890b5088SRaghu Krishnamurthy 91890b5088SRaghu Krishnamurthy /* Ensure that SPMD LP only supports sending direct requests. */ 92890b5088SRaghu Krishnamurthy if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) { 93890b5088SRaghu Krishnamurthy ERROR("Invalid SPMD logical partition properties (0x%x)\n", 94890b5088SRaghu Krishnamurthy lp_desc->properties); 95890b5088SRaghu Krishnamurthy return -EINVAL; 96890b5088SRaghu Krishnamurthy } 97890b5088SRaghu Krishnamurthy 98890b5088SRaghu Krishnamurthy /* Ensure that all partition IDs are unique. */ 99890b5088SRaghu Krishnamurthy for (uint32_t inner_idx = index + 1; 100890b5088SRaghu Krishnamurthy inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) { 101890b5088SRaghu Krishnamurthy if (lp_desc->sp_id == lp_array[inner_idx].sp_id) { 102890b5088SRaghu Krishnamurthy ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n", 103890b5088SRaghu Krishnamurthy lp_desc->sp_id); 104890b5088SRaghu Krishnamurthy return -EINVAL; 105890b5088SRaghu Krishnamurthy } 106890b5088SRaghu Krishnamurthy } 107890b5088SRaghu Krishnamurthy } 108890b5088SRaghu Krishnamurthy return 0; 109890b5088SRaghu Krishnamurthy } 110*66bdfd6eSRaghu Krishnamurthy 111*66bdfd6eSRaghu Krishnamurthy static void spmd_encode_ffa_error(struct ffa_value *retval, int32_t error_code) 112*66bdfd6eSRaghu Krishnamurthy { 113*66bdfd6eSRaghu Krishnamurthy retval->func = FFA_ERROR; 114*66bdfd6eSRaghu Krishnamurthy retval->arg1 = FFA_TARGET_INFO_MBZ; 115*66bdfd6eSRaghu Krishnamurthy retval->arg2 = (uint32_t)error_code; 116*66bdfd6eSRaghu Krishnamurthy retval->arg3 = FFA_TARGET_INFO_MBZ; 117*66bdfd6eSRaghu Krishnamurthy retval->arg4 = FFA_TARGET_INFO_MBZ; 118*66bdfd6eSRaghu Krishnamurthy retval->arg5 = FFA_TARGET_INFO_MBZ; 119*66bdfd6eSRaghu Krishnamurthy retval->arg6 = FFA_TARGET_INFO_MBZ; 120*66bdfd6eSRaghu Krishnamurthy retval->arg7 = FFA_TARGET_INFO_MBZ; 121*66bdfd6eSRaghu Krishnamurthy } 122*66bdfd6eSRaghu Krishnamurthy 123*66bdfd6eSRaghu Krishnamurthy static void spmd_build_direct_message_req(spmd_spm_core_context_t *ctx, 124*66bdfd6eSRaghu Krishnamurthy uint64_t x1, uint64_t x2, 125*66bdfd6eSRaghu Krishnamurthy uint64_t x3, uint64_t x4) 126*66bdfd6eSRaghu Krishnamurthy { 127*66bdfd6eSRaghu Krishnamurthy gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 128*66bdfd6eSRaghu Krishnamurthy 129*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); 130*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X1, x1); 131*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X2, x2); 132*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X3, x3); 133*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X4, x4); 134*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X5, 0U); 135*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X6, 0U); 136*66bdfd6eSRaghu Krishnamurthy write_ctx_reg(gpregs, CTX_GPREG_X7, 0U); 137*66bdfd6eSRaghu Krishnamurthy } 138*66bdfd6eSRaghu Krishnamurthy 139*66bdfd6eSRaghu Krishnamurthy static void spmd_encode_ctx_to_ffa_value(spmd_spm_core_context_t *ctx, 140*66bdfd6eSRaghu Krishnamurthy struct ffa_value *retval) 141*66bdfd6eSRaghu Krishnamurthy { 142*66bdfd6eSRaghu Krishnamurthy gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 143*66bdfd6eSRaghu Krishnamurthy 144*66bdfd6eSRaghu Krishnamurthy retval->func = read_ctx_reg(gpregs, CTX_GPREG_X0); 145*66bdfd6eSRaghu Krishnamurthy retval->arg1 = read_ctx_reg(gpregs, CTX_GPREG_X1); 146*66bdfd6eSRaghu Krishnamurthy retval->arg2 = read_ctx_reg(gpregs, CTX_GPREG_X2); 147*66bdfd6eSRaghu Krishnamurthy retval->arg3 = read_ctx_reg(gpregs, CTX_GPREG_X3); 148*66bdfd6eSRaghu Krishnamurthy retval->arg4 = read_ctx_reg(gpregs, CTX_GPREG_X4); 149*66bdfd6eSRaghu Krishnamurthy retval->arg5 = read_ctx_reg(gpregs, CTX_GPREG_X5); 150*66bdfd6eSRaghu Krishnamurthy retval->arg6 = read_ctx_reg(gpregs, CTX_GPREG_X6); 151*66bdfd6eSRaghu Krishnamurthy retval->arg7 = read_ctx_reg(gpregs, CTX_GPREG_X7); 152*66bdfd6eSRaghu Krishnamurthy } 153*66bdfd6eSRaghu Krishnamurthy 154*66bdfd6eSRaghu Krishnamurthy static void spmd_logical_sp_set_dir_req_ongoing(spmd_spm_core_context_t *ctx) 155*66bdfd6eSRaghu Krishnamurthy { 156*66bdfd6eSRaghu Krishnamurthy ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_DIR_REQ_ONGOING; 157*66bdfd6eSRaghu Krishnamurthy } 158*66bdfd6eSRaghu Krishnamurthy 159*66bdfd6eSRaghu Krishnamurthy static void spmd_logical_sp_reset_dir_req_ongoing(spmd_spm_core_context_t *ctx) 160*66bdfd6eSRaghu Krishnamurthy { 161*66bdfd6eSRaghu Krishnamurthy ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_DIR_REQ_ONGOING; 162*66bdfd6eSRaghu Krishnamurthy } 163*66bdfd6eSRaghu Krishnamurthy 164890b5088SRaghu Krishnamurthy #endif 165890b5088SRaghu Krishnamurthy 166890b5088SRaghu Krishnamurthy /* 167890b5088SRaghu Krishnamurthy * Initialize SPMD logical partitions. This function assumes that it is called 168890b5088SRaghu Krishnamurthy * only after the SPMC has successfully initialized. 169890b5088SRaghu Krishnamurthy */ 170890b5088SRaghu Krishnamurthy int32_t spmd_logical_sp_init(void) 171890b5088SRaghu Krishnamurthy { 172890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP 173890b5088SRaghu Krishnamurthy int32_t rc = 0; 174890b5088SRaghu Krishnamurthy struct spmd_lp_desc *spmd_lp_descs; 175890b5088SRaghu Krishnamurthy 176890b5088SRaghu Krishnamurthy if (is_spmd_lp_inited == true) { 177890b5088SRaghu Krishnamurthy return 0; 178890b5088SRaghu Krishnamurthy } 179890b5088SRaghu Krishnamurthy 180890b5088SRaghu Krishnamurthy if (is_spmc_inited == false) { 181890b5088SRaghu Krishnamurthy return -1; 182890b5088SRaghu Krishnamurthy } 183890b5088SRaghu Krishnamurthy 184890b5088SRaghu Krishnamurthy spmd_lp_descs = get_spmd_el3_lp_array(); 185890b5088SRaghu Krishnamurthy 186890b5088SRaghu Krishnamurthy /* Perform initial validation of the SPMD Logical Partitions. */ 187890b5088SRaghu Krishnamurthy rc = el3_spmd_sp_desc_validate(spmd_lp_descs); 188890b5088SRaghu Krishnamurthy if (rc != 0) { 189890b5088SRaghu Krishnamurthy ERROR("Logical SPMD Partition validation failed!\n"); 190890b5088SRaghu Krishnamurthy return rc; 191890b5088SRaghu Krishnamurthy } 192890b5088SRaghu Krishnamurthy 193890b5088SRaghu Krishnamurthy VERBOSE("SPMD Logical Secure Partition init start.\n"); 194890b5088SRaghu Krishnamurthy for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) { 195890b5088SRaghu Krishnamurthy rc = spmd_lp_descs[i].init(); 196890b5088SRaghu Krishnamurthy if (rc != 0) { 197890b5088SRaghu Krishnamurthy ERROR("SPMD Logical SP (0x%x) failed to initialize\n", 198890b5088SRaghu Krishnamurthy spmd_lp_descs[i].sp_id); 199890b5088SRaghu Krishnamurthy return rc; 200890b5088SRaghu Krishnamurthy } 201890b5088SRaghu Krishnamurthy VERBOSE("SPMD Logical SP (0x%x) Initialized\n", 202890b5088SRaghu Krishnamurthy spmd_lp_descs[i].sp_id); 203890b5088SRaghu Krishnamurthy } 204890b5088SRaghu Krishnamurthy 205890b5088SRaghu Krishnamurthy INFO("SPMD Logical Secure Partition init completed.\n"); 206890b5088SRaghu Krishnamurthy if (rc == 0) { 207890b5088SRaghu Krishnamurthy is_spmd_lp_inited = true; 208890b5088SRaghu Krishnamurthy } 209890b5088SRaghu Krishnamurthy return rc; 210890b5088SRaghu Krishnamurthy #else 211890b5088SRaghu Krishnamurthy return 0; 212890b5088SRaghu Krishnamurthy #endif 213890b5088SRaghu Krishnamurthy } 214890b5088SRaghu Krishnamurthy 215890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_initialized(void) 216890b5088SRaghu Krishnamurthy { 217890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP 218890b5088SRaghu Krishnamurthy is_spmc_inited = true; 219890b5088SRaghu Krishnamurthy #endif 220890b5088SRaghu Krishnamurthy } 221890b5088SRaghu Krishnamurthy 222890b5088SRaghu Krishnamurthy void spmd_logical_sp_set_spmc_failure(void) 223890b5088SRaghu Krishnamurthy { 224890b5088SRaghu Krishnamurthy #if ENABLE_SPMD_LP 225890b5088SRaghu Krishnamurthy is_spmc_inited = false; 226890b5088SRaghu Krishnamurthy #endif 227890b5088SRaghu Krishnamurthy } 228*66bdfd6eSRaghu Krishnamurthy 229*66bdfd6eSRaghu Krishnamurthy /******************************************************************************* 230*66bdfd6eSRaghu Krishnamurthy * This function sends an FF-A Direct Request from a partition in EL3 to a 231*66bdfd6eSRaghu Krishnamurthy * partition that may reside under an SPMC (only lower ELs supported). The main 232*66bdfd6eSRaghu Krishnamurthy * use of this API is for SPMD logical partitions. 233*66bdfd6eSRaghu Krishnamurthy * The API is expected to be used when there are platform specific SMCs that 234*66bdfd6eSRaghu Krishnamurthy * need to be routed to a secure partition that is FF-A compliant or when 235*66bdfd6eSRaghu Krishnamurthy * there are group 0 interrupts that need to be handled first in EL3 and then 236*66bdfd6eSRaghu Krishnamurthy * forwarded to an FF-A compliant secure partition. Therefore, it is expected 237*66bdfd6eSRaghu Krishnamurthy * that the handle to the context provided belongs to the non-secure context. 238*66bdfd6eSRaghu Krishnamurthy * This also means that interrupts/SMCs that trap to EL3 during secure execution 239*66bdfd6eSRaghu Krishnamurthy * cannot use this API. 240*66bdfd6eSRaghu Krishnamurthy * x1, x2, x3 and x4 are encoded as specified in the FF-A specification. 241*66bdfd6eSRaghu Krishnamurthy * retval is used to pass the direct response values to the caller. 242*66bdfd6eSRaghu Krishnamurthy * The function returns true if retval has valid values, and false otherwise. 243*66bdfd6eSRaghu Krishnamurthy ******************************************************************************/ 244*66bdfd6eSRaghu Krishnamurthy bool spmd_el3_ffa_msg_direct_req(uint64_t x1, 245*66bdfd6eSRaghu Krishnamurthy uint64_t x2, 246*66bdfd6eSRaghu Krishnamurthy uint64_t x3, 247*66bdfd6eSRaghu Krishnamurthy uint64_t x4, 248*66bdfd6eSRaghu Krishnamurthy void *handle, 249*66bdfd6eSRaghu Krishnamurthy struct ffa_value *retval) 250*66bdfd6eSRaghu Krishnamurthy { 251*66bdfd6eSRaghu Krishnamurthy #if ENABLE_SPMD_LP 252*66bdfd6eSRaghu Krishnamurthy 253*66bdfd6eSRaghu Krishnamurthy uint64_t rc = UINT64_MAX; 254*66bdfd6eSRaghu Krishnamurthy spmd_spm_core_context_t *ctx = spmd_get_context(); 255*66bdfd6eSRaghu Krishnamurthy 256*66bdfd6eSRaghu Krishnamurthy if (retval == NULL) { 257*66bdfd6eSRaghu Krishnamurthy return false; 258*66bdfd6eSRaghu Krishnamurthy } 259*66bdfd6eSRaghu Krishnamurthy 260*66bdfd6eSRaghu Krishnamurthy memset(retval, 0, sizeof(*retval)); 261*66bdfd6eSRaghu Krishnamurthy 262*66bdfd6eSRaghu Krishnamurthy if (!is_spmd_lp_inited || !is_spmc_inited) { 263*66bdfd6eSRaghu Krishnamurthy VERBOSE("Cannot send SPMD logical partition direct message," 264*66bdfd6eSRaghu Krishnamurthy " Partitions not initialized or SPMC not initialized.\n"); 265*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 266*66bdfd6eSRaghu Krishnamurthy return true; 267*66bdfd6eSRaghu Krishnamurthy } 268*66bdfd6eSRaghu Krishnamurthy 269*66bdfd6eSRaghu Krishnamurthy /* 270*66bdfd6eSRaghu Krishnamurthy * x2 must be zero, since there is no support for framework message via 271*66bdfd6eSRaghu Krishnamurthy * an SPMD logical partition. This is sort of a useless check and it is 272*66bdfd6eSRaghu Krishnamurthy * possible to not take parameter. However, as the framework extends it 273*66bdfd6eSRaghu Krishnamurthy * may be useful to have x2 and extend this function later with 274*66bdfd6eSRaghu Krishnamurthy * functionality based on x2. 275*66bdfd6eSRaghu Krishnamurthy */ 276*66bdfd6eSRaghu Krishnamurthy if (x2 != 0) { 277*66bdfd6eSRaghu Krishnamurthy VERBOSE("x2 must be zero. Cannot send framework message.\n"); 278*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 279*66bdfd6eSRaghu Krishnamurthy return true; 280*66bdfd6eSRaghu Krishnamurthy } 281*66bdfd6eSRaghu Krishnamurthy 282*66bdfd6eSRaghu Krishnamurthy /* 283*66bdfd6eSRaghu Krishnamurthy * Current context must be non-secure. API is expected to be used 284*66bdfd6eSRaghu Krishnamurthy * when entry into EL3 and the SPMD logical partition is via an 285*66bdfd6eSRaghu Krishnamurthy * interrupt that occurs when execution is in normal world and 286*66bdfd6eSRaghu Krishnamurthy * SMCs from normal world. FF-A compliant SPMCs are expected to 287*66bdfd6eSRaghu Krishnamurthy * trap interrupts during secure execution in lower ELs since they 288*66bdfd6eSRaghu Krishnamurthy * are usually not re-entrant and SMCs from secure world can be 289*66bdfd6eSRaghu Krishnamurthy * handled synchronously. There is no known use case for an SPMD 290*66bdfd6eSRaghu Krishnamurthy * logical partition to send a direct message to another partition 291*66bdfd6eSRaghu Krishnamurthy * in response to a secure interrupt or SMCs from secure world. 292*66bdfd6eSRaghu Krishnamurthy */ 293*66bdfd6eSRaghu Krishnamurthy if (handle != cm_get_context(NON_SECURE)) { 294*66bdfd6eSRaghu Krishnamurthy VERBOSE("Handle must be for the non-secure context.\n"); 295*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 296*66bdfd6eSRaghu Krishnamurthy return true; 297*66bdfd6eSRaghu Krishnamurthy } 298*66bdfd6eSRaghu Krishnamurthy 299*66bdfd6eSRaghu Krishnamurthy if (!is_spmd_lp_id(ffa_endpoint_source(x1))) { 300*66bdfd6eSRaghu Krishnamurthy VERBOSE("Source ID must be valid SPMD logical partition" 301*66bdfd6eSRaghu Krishnamurthy " ID.\n"); 302*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, 303*66bdfd6eSRaghu Krishnamurthy FFA_ERROR_INVALID_PARAMETER); 304*66bdfd6eSRaghu Krishnamurthy return true; 305*66bdfd6eSRaghu Krishnamurthy } 306*66bdfd6eSRaghu Krishnamurthy 307*66bdfd6eSRaghu Krishnamurthy if (is_spmd_lp_id(ffa_endpoint_destination(x1))) { 308*66bdfd6eSRaghu Krishnamurthy VERBOSE("Destination ID must not be SPMD logical partition" 309*66bdfd6eSRaghu Krishnamurthy " ID.\n"); 310*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, 311*66bdfd6eSRaghu Krishnamurthy FFA_ERROR_INVALID_PARAMETER); 312*66bdfd6eSRaghu Krishnamurthy return true; 313*66bdfd6eSRaghu Krishnamurthy } 314*66bdfd6eSRaghu Krishnamurthy 315*66bdfd6eSRaghu Krishnamurthy if (!ffa_is_secure_world_id(ffa_endpoint_destination(x1))) { 316*66bdfd6eSRaghu Krishnamurthy VERBOSE("Destination ID must be secure world ID.\n"); 317*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, 318*66bdfd6eSRaghu Krishnamurthy FFA_ERROR_INVALID_PARAMETER); 319*66bdfd6eSRaghu Krishnamurthy return true; 320*66bdfd6eSRaghu Krishnamurthy } 321*66bdfd6eSRaghu Krishnamurthy 322*66bdfd6eSRaghu Krishnamurthy if (ffa_endpoint_destination(x1) == SPMD_DIRECT_MSG_ENDPOINT_ID) { 323*66bdfd6eSRaghu Krishnamurthy VERBOSE("Destination ID must not be SPMD ID.\n"); 324*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, 325*66bdfd6eSRaghu Krishnamurthy FFA_ERROR_INVALID_PARAMETER); 326*66bdfd6eSRaghu Krishnamurthy return true; 327*66bdfd6eSRaghu Krishnamurthy } 328*66bdfd6eSRaghu Krishnamurthy 329*66bdfd6eSRaghu Krishnamurthy if (ffa_endpoint_destination(x1) == spmd_spmc_id_get()) { 330*66bdfd6eSRaghu Krishnamurthy VERBOSE("Destination ID must not be SPMC ID.\n"); 331*66bdfd6eSRaghu Krishnamurthy spmd_encode_ffa_error(retval, 332*66bdfd6eSRaghu Krishnamurthy FFA_ERROR_INVALID_PARAMETER); 333*66bdfd6eSRaghu Krishnamurthy return true; 334*66bdfd6eSRaghu Krishnamurthy } 335*66bdfd6eSRaghu Krishnamurthy 336*66bdfd6eSRaghu Krishnamurthy /* Save the non-secure context before entering SPMC */ 337*66bdfd6eSRaghu Krishnamurthy cm_el1_sysregs_context_save(NON_SECURE); 338*66bdfd6eSRaghu Krishnamurthy #if SPMD_SPM_AT_SEL2 339*66bdfd6eSRaghu Krishnamurthy cm_el2_sysregs_context_save(NON_SECURE); 340*66bdfd6eSRaghu Krishnamurthy #endif 341*66bdfd6eSRaghu Krishnamurthy 342*66bdfd6eSRaghu Krishnamurthy /* 343*66bdfd6eSRaghu Krishnamurthy * Perform synchronous entry into the SPMC. Synchronous entry is 344*66bdfd6eSRaghu Krishnamurthy * required because the spec requires that a direct message request 345*66bdfd6eSRaghu Krishnamurthy * from an SPMD LP look like a function call from it's perspective. 346*66bdfd6eSRaghu Krishnamurthy */ 347*66bdfd6eSRaghu Krishnamurthy spmd_build_direct_message_req(ctx, x1, x2, x3, x4); 348*66bdfd6eSRaghu Krishnamurthy spmd_logical_sp_set_dir_req_ongoing(ctx); 349*66bdfd6eSRaghu Krishnamurthy 350*66bdfd6eSRaghu Krishnamurthy rc = spmd_spm_core_sync_entry(ctx); 351*66bdfd6eSRaghu Krishnamurthy 352*66bdfd6eSRaghu Krishnamurthy spmd_logical_sp_reset_dir_req_ongoing(ctx); 353*66bdfd6eSRaghu Krishnamurthy 354*66bdfd6eSRaghu Krishnamurthy if (rc != 0ULL) { 355*66bdfd6eSRaghu Krishnamurthy ERROR("%s failed (%lx) on CPU%u\n", __func__, rc, 356*66bdfd6eSRaghu Krishnamurthy plat_my_core_pos()); 357*66bdfd6eSRaghu Krishnamurthy panic(); 358*66bdfd6eSRaghu Krishnamurthy } else { 359*66bdfd6eSRaghu Krishnamurthy spmd_encode_ctx_to_ffa_value(ctx, retval); 360*66bdfd6eSRaghu Krishnamurthy 361*66bdfd6eSRaghu Krishnamurthy /* 362*66bdfd6eSRaghu Krishnamurthy * Only expect error or direct response, 363*66bdfd6eSRaghu Krishnamurthy * spmd_spm_core_sync_exit should not be called on other paths. 364*66bdfd6eSRaghu Krishnamurthy * Checks are asserts since the LSP can fail gracefully if the 365*66bdfd6eSRaghu Krishnamurthy * source or destination ids are not the same. Panic'ing would 366*66bdfd6eSRaghu Krishnamurthy * not provide any benefit. 367*66bdfd6eSRaghu Krishnamurthy */ 368*66bdfd6eSRaghu Krishnamurthy assert(is_ffa_error(retval) || is_ffa_direct_msg_resp(retval)); 369*66bdfd6eSRaghu Krishnamurthy assert(is_ffa_error(retval) || 370*66bdfd6eSRaghu Krishnamurthy (ffa_endpoint_destination(retval->arg1) == 371*66bdfd6eSRaghu Krishnamurthy ffa_endpoint_source(x1))); 372*66bdfd6eSRaghu Krishnamurthy assert(is_ffa_error(retval) || 373*66bdfd6eSRaghu Krishnamurthy (ffa_endpoint_source(retval->arg1) == 374*66bdfd6eSRaghu Krishnamurthy ffa_endpoint_destination(x1))); 375*66bdfd6eSRaghu Krishnamurthy } 376*66bdfd6eSRaghu Krishnamurthy 377*66bdfd6eSRaghu Krishnamurthy cm_el1_sysregs_context_restore(NON_SECURE); 378*66bdfd6eSRaghu Krishnamurthy #if SPMD_SPM_AT_SEL2 379*66bdfd6eSRaghu Krishnamurthy cm_el2_sysregs_context_restore(NON_SECURE); 380*66bdfd6eSRaghu Krishnamurthy #endif 381*66bdfd6eSRaghu Krishnamurthy cm_set_next_eret_context(NON_SECURE); 382*66bdfd6eSRaghu Krishnamurthy 383*66bdfd6eSRaghu Krishnamurthy return true; 384*66bdfd6eSRaghu Krishnamurthy #else 385*66bdfd6eSRaghu Krishnamurthy return false; 386*66bdfd6eSRaghu Krishnamurthy #endif 387*66bdfd6eSRaghu Krishnamurthy } 388*66bdfd6eSRaghu Krishnamurthy 389*66bdfd6eSRaghu Krishnamurthy bool is_spmd_logical_sp_dir_req_in_progress( 390*66bdfd6eSRaghu Krishnamurthy spmd_spm_core_context_t *ctx) 391*66bdfd6eSRaghu Krishnamurthy { 392*66bdfd6eSRaghu Krishnamurthy #if ENABLE_SPMD_LP 393*66bdfd6eSRaghu Krishnamurthy return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_DIR_REQ_ONGOING) 394*66bdfd6eSRaghu Krishnamurthy == SPMD_LP_FFA_DIR_REQ_ONGOING); 395*66bdfd6eSRaghu Krishnamurthy #else 396*66bdfd6eSRaghu Krishnamurthy return false; 397*66bdfd6eSRaghu Krishnamurthy #endif 398*66bdfd6eSRaghu Krishnamurthy } 399