1*91f16700Schasinglulu /* 2*91f16700Schasinglulu * Copyright (c) 2023, Arm Limited and Contributors. All rights reserved. 3*91f16700Schasinglulu * 4*91f16700Schasinglulu * SPDX-License-Identifier: BSD-3-Clause 5*91f16700Schasinglulu */ 6*91f16700Schasinglulu 7*91f16700Schasinglulu #include <assert.h> 8*91f16700Schasinglulu #include <errno.h> 9*91f16700Schasinglulu #include <string.h> 10*91f16700Schasinglulu #include "spmd_private.h" 11*91f16700Schasinglulu 12*91f16700Schasinglulu #include <common/debug.h> 13*91f16700Schasinglulu #include <common/uuid.h> 14*91f16700Schasinglulu #include <lib/el3_runtime/context_mgmt.h> 15*91f16700Schasinglulu #include <services/el3_spmd_logical_sp.h> 16*91f16700Schasinglulu #include <services/spmc_svc.h> 17*91f16700Schasinglulu #include <smccc_helpers.h> 18*91f16700Schasinglulu 19*91f16700Schasinglulu 20*91f16700Schasinglulu /* 21*91f16700Schasinglulu * Maximum ffa_partition_info entries that can be returned by an invocation 22*91f16700Schasinglulu * of FFA_PARTITION_INFO_GET_REGS_64 is size in bytes, of available 23*91f16700Schasinglulu * registers/args in struct ffa_value divided by size of struct 24*91f16700Schasinglulu * ffa_partition_info. For this ABI, arg3-arg17 in ffa_value can be used, i.e. 25*91f16700Schasinglulu * 15 uint64_t fields. For FF-A v1.1, this value should be 5. 26*91f16700Schasinglulu */ 27*91f16700Schasinglulu #define MAX_INFO_REGS_ENTRIES_PER_CALL \ 28*91f16700Schasinglulu (uint8_t)((15 * sizeof(uint64_t)) / \ 29*91f16700Schasinglulu sizeof(struct ffa_partition_info_v1_1)) 30*91f16700Schasinglulu CASSERT(MAX_INFO_REGS_ENTRIES_PER_CALL == 5, assert_too_many_info_reg_entries); 31*91f16700Schasinglulu 32*91f16700Schasinglulu #if ENABLE_SPMD_LP 33*91f16700Schasinglulu static bool is_spmd_lp_inited; 34*91f16700Schasinglulu static bool is_spmc_inited; 35*91f16700Schasinglulu 36*91f16700Schasinglulu /* 37*91f16700Schasinglulu * Helper function to obtain the array storing the EL3 38*91f16700Schasinglulu * SPMD Logical Partition descriptors. 39*91f16700Schasinglulu */ 40*91f16700Schasinglulu static struct spmd_lp_desc *get_spmd_el3_lp_array(void) 41*91f16700Schasinglulu { 42*91f16700Schasinglulu return (struct spmd_lp_desc *) SPMD_LP_DESCS_START; 43*91f16700Schasinglulu } 44*91f16700Schasinglulu 45*91f16700Schasinglulu /******************************************************************************* 46*91f16700Schasinglulu * Validate any logical partition descriptors before we initialize. 47*91f16700Schasinglulu * Initialization of said partitions will be taken care of during SPMD boot. 48*91f16700Schasinglulu ******************************************************************************/ 49*91f16700Schasinglulu static int el3_spmd_sp_desc_validate(struct spmd_lp_desc *lp_array) 50*91f16700Schasinglulu { 51*91f16700Schasinglulu /* Check the array bounds are valid. */ 52*91f16700Schasinglulu assert(SPMD_LP_DESCS_END > SPMD_LP_DESCS_START); 53*91f16700Schasinglulu 54*91f16700Schasinglulu /* 55*91f16700Schasinglulu * No support for SPMD logical partitions when SPMC is at EL3. 56*91f16700Schasinglulu */ 57*91f16700Schasinglulu assert(!is_spmc_at_el3()); 58*91f16700Schasinglulu 59*91f16700Schasinglulu /* If no SPMD logical partitions are implemented then simply bail out. */ 60*91f16700Schasinglulu if (SPMD_LP_DESCS_COUNT == 0U) { 61*91f16700Schasinglulu return -1; 62*91f16700Schasinglulu } 63*91f16700Schasinglulu 64*91f16700Schasinglulu for (uint32_t index = 0U; index < SPMD_LP_DESCS_COUNT; index++) { 65*91f16700Schasinglulu struct spmd_lp_desc *lp_desc = &lp_array[index]; 66*91f16700Schasinglulu 67*91f16700Schasinglulu /* Validate our logical partition descriptors. */ 68*91f16700Schasinglulu if (lp_desc == NULL) { 69*91f16700Schasinglulu ERROR("Invalid SPMD Logical SP Descriptor\n"); 70*91f16700Schasinglulu return -EINVAL; 71*91f16700Schasinglulu } 72*91f16700Schasinglulu 73*91f16700Schasinglulu /* 74*91f16700Schasinglulu * Ensure the ID follows the convention to indicate it resides 75*91f16700Schasinglulu * in the secure world. 76*91f16700Schasinglulu */ 77*91f16700Schasinglulu if (!ffa_is_secure_world_id(lp_desc->sp_id)) { 78*91f16700Schasinglulu ERROR("Invalid SPMD Logical SP ID (0x%x)\n", 79*91f16700Schasinglulu lp_desc->sp_id); 80*91f16700Schasinglulu return -EINVAL; 81*91f16700Schasinglulu } 82*91f16700Schasinglulu 83*91f16700Schasinglulu /* Ensure SPMD logical partition is in valid range. */ 84*91f16700Schasinglulu if (!is_spmd_lp_id(lp_desc->sp_id)) { 85*91f16700Schasinglulu ERROR("Invalid SPMD Logical Partition ID (0x%x)\n", 86*91f16700Schasinglulu lp_desc->sp_id); 87*91f16700Schasinglulu return -EINVAL; 88*91f16700Schasinglulu } 89*91f16700Schasinglulu 90*91f16700Schasinglulu /* Ensure the UUID is not the NULL UUID. */ 91*91f16700Schasinglulu if (lp_desc->uuid[0] == 0 && lp_desc->uuid[1] == 0 && 92*91f16700Schasinglulu lp_desc->uuid[2] == 0 && lp_desc->uuid[3] == 0) { 93*91f16700Schasinglulu ERROR("Invalid UUID for SPMD Logical SP (0x%x)\n", 94*91f16700Schasinglulu lp_desc->sp_id); 95*91f16700Schasinglulu return -EINVAL; 96*91f16700Schasinglulu } 97*91f16700Schasinglulu 98*91f16700Schasinglulu /* Ensure init function callback is registered. */ 99*91f16700Schasinglulu if (lp_desc->init == NULL) { 100*91f16700Schasinglulu ERROR("Missing init function for Logical SP(0x%x)\n", 101*91f16700Schasinglulu lp_desc->sp_id); 102*91f16700Schasinglulu return -EINVAL; 103*91f16700Schasinglulu } 104*91f16700Schasinglulu 105*91f16700Schasinglulu /* Ensure that SPMD LP only supports sending direct requests. */ 106*91f16700Schasinglulu if (lp_desc->properties != FFA_PARTITION_DIRECT_REQ_SEND) { 107*91f16700Schasinglulu ERROR("Invalid SPMD logical partition properties (0x%x)\n", 108*91f16700Schasinglulu lp_desc->properties); 109*91f16700Schasinglulu return -EINVAL; 110*91f16700Schasinglulu } 111*91f16700Schasinglulu 112*91f16700Schasinglulu /* Ensure that all partition IDs are unique. */ 113*91f16700Schasinglulu for (uint32_t inner_idx = index + 1; 114*91f16700Schasinglulu inner_idx < SPMD_LP_DESCS_COUNT; inner_idx++) { 115*91f16700Schasinglulu if (lp_desc->sp_id == lp_array[inner_idx].sp_id) { 116*91f16700Schasinglulu ERROR("Duplicate SPMD logical SP ID Detected (0x%x)\n", 117*91f16700Schasinglulu lp_desc->sp_id); 118*91f16700Schasinglulu return -EINVAL; 119*91f16700Schasinglulu } 120*91f16700Schasinglulu } 121*91f16700Schasinglulu } 122*91f16700Schasinglulu return 0; 123*91f16700Schasinglulu } 124*91f16700Schasinglulu 125*91f16700Schasinglulu static void spmd_encode_ffa_error(struct ffa_value *retval, int32_t error_code) 126*91f16700Schasinglulu { 127*91f16700Schasinglulu retval->func = FFA_ERROR; 128*91f16700Schasinglulu retval->arg1 = FFA_TARGET_INFO_MBZ; 129*91f16700Schasinglulu retval->arg2 = (uint32_t)error_code; 130*91f16700Schasinglulu retval->arg3 = FFA_TARGET_INFO_MBZ; 131*91f16700Schasinglulu retval->arg4 = FFA_TARGET_INFO_MBZ; 132*91f16700Schasinglulu retval->arg5 = FFA_TARGET_INFO_MBZ; 133*91f16700Schasinglulu retval->arg6 = FFA_TARGET_INFO_MBZ; 134*91f16700Schasinglulu retval->arg7 = FFA_TARGET_INFO_MBZ; 135*91f16700Schasinglulu } 136*91f16700Schasinglulu 137*91f16700Schasinglulu static void spmd_build_direct_message_req(spmd_spm_core_context_t *ctx, 138*91f16700Schasinglulu uint64_t x1, uint64_t x2, 139*91f16700Schasinglulu uint64_t x3, uint64_t x4) 140*91f16700Schasinglulu { 141*91f16700Schasinglulu gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 142*91f16700Schasinglulu 143*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); 144*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X1, x1); 145*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X2, x2); 146*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X3, x3); 147*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X4, x4); 148*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X5, 0U); 149*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X6, 0U); 150*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X7, 0U); 151*91f16700Schasinglulu } 152*91f16700Schasinglulu 153*91f16700Schasinglulu static void spmd_encode_ctx_to_ffa_value(spmd_spm_core_context_t *ctx, 154*91f16700Schasinglulu struct ffa_value *retval) 155*91f16700Schasinglulu { 156*91f16700Schasinglulu gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 157*91f16700Schasinglulu 158*91f16700Schasinglulu retval->func = read_ctx_reg(gpregs, CTX_GPREG_X0); 159*91f16700Schasinglulu retval->arg1 = read_ctx_reg(gpregs, CTX_GPREG_X1); 160*91f16700Schasinglulu retval->arg2 = read_ctx_reg(gpregs, CTX_GPREG_X2); 161*91f16700Schasinglulu retval->arg3 = read_ctx_reg(gpregs, CTX_GPREG_X3); 162*91f16700Schasinglulu retval->arg4 = read_ctx_reg(gpregs, CTX_GPREG_X4); 163*91f16700Schasinglulu retval->arg5 = read_ctx_reg(gpregs, CTX_GPREG_X5); 164*91f16700Schasinglulu retval->arg6 = read_ctx_reg(gpregs, CTX_GPREG_X6); 165*91f16700Schasinglulu retval->arg7 = read_ctx_reg(gpregs, CTX_GPREG_X7); 166*91f16700Schasinglulu retval->arg8 = read_ctx_reg(gpregs, CTX_GPREG_X8); 167*91f16700Schasinglulu retval->arg9 = read_ctx_reg(gpregs, CTX_GPREG_X9); 168*91f16700Schasinglulu retval->arg10 = read_ctx_reg(gpregs, CTX_GPREG_X10); 169*91f16700Schasinglulu retval->arg11 = read_ctx_reg(gpregs, CTX_GPREG_X11); 170*91f16700Schasinglulu retval->arg12 = read_ctx_reg(gpregs, CTX_GPREG_X12); 171*91f16700Schasinglulu retval->arg13 = read_ctx_reg(gpregs, CTX_GPREG_X13); 172*91f16700Schasinglulu retval->arg14 = read_ctx_reg(gpregs, CTX_GPREG_X14); 173*91f16700Schasinglulu retval->arg15 = read_ctx_reg(gpregs, CTX_GPREG_X15); 174*91f16700Schasinglulu retval->arg16 = read_ctx_reg(gpregs, CTX_GPREG_X16); 175*91f16700Schasinglulu retval->arg17 = read_ctx_reg(gpregs, CTX_GPREG_X17); 176*91f16700Schasinglulu } 177*91f16700Schasinglulu 178*91f16700Schasinglulu static void spmd_logical_sp_set_dir_req_ongoing(spmd_spm_core_context_t *ctx) 179*91f16700Schasinglulu { 180*91f16700Schasinglulu ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_DIR_REQ_ONGOING; 181*91f16700Schasinglulu } 182*91f16700Schasinglulu 183*91f16700Schasinglulu static void spmd_logical_sp_reset_dir_req_ongoing(spmd_spm_core_context_t *ctx) 184*91f16700Schasinglulu { 185*91f16700Schasinglulu ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_DIR_REQ_ONGOING; 186*91f16700Schasinglulu } 187*91f16700Schasinglulu 188*91f16700Schasinglulu static void spmd_build_ffa_info_get_regs(spmd_spm_core_context_t *ctx, 189*91f16700Schasinglulu const uint32_t uuid[4], 190*91f16700Schasinglulu const uint16_t start_index, 191*91f16700Schasinglulu const uint16_t tag) 192*91f16700Schasinglulu { 193*91f16700Schasinglulu gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); 194*91f16700Schasinglulu 195*91f16700Schasinglulu uint64_t arg1 = (uint64_t)uuid[1] << 32 | uuid[0]; 196*91f16700Schasinglulu uint64_t arg2 = (uint64_t)uuid[3] << 32 | uuid[2]; 197*91f16700Schasinglulu uint64_t arg3 = start_index | (uint64_t)tag << 16; 198*91f16700Schasinglulu 199*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_PARTITION_INFO_GET_REGS_SMC64); 200*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X1, arg1); 201*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X2, arg2); 202*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X3, arg3); 203*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X4, 0U); 204*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X5, 0U); 205*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X6, 0U); 206*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X7, 0U); 207*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X8, 0U); 208*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X9, 0U); 209*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X10, 0U); 210*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X11, 0U); 211*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X12, 0U); 212*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X13, 0U); 213*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X14, 0U); 214*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X15, 0U); 215*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X16, 0U); 216*91f16700Schasinglulu write_ctx_reg(gpregs, CTX_GPREG_X17, 0U); 217*91f16700Schasinglulu } 218*91f16700Schasinglulu 219*91f16700Schasinglulu static void spmd_logical_sp_set_info_regs_ongoing(spmd_spm_core_context_t *ctx) 220*91f16700Schasinglulu { 221*91f16700Schasinglulu ctx->spmd_lp_sync_req_ongoing |= SPMD_LP_FFA_INFO_GET_REG_ONGOING; 222*91f16700Schasinglulu } 223*91f16700Schasinglulu 224*91f16700Schasinglulu static void spmd_logical_sp_reset_info_regs_ongoing( 225*91f16700Schasinglulu spmd_spm_core_context_t *ctx) 226*91f16700Schasinglulu { 227*91f16700Schasinglulu ctx->spmd_lp_sync_req_ongoing &= ~SPMD_LP_FFA_INFO_GET_REG_ONGOING; 228*91f16700Schasinglulu } 229*91f16700Schasinglulu 230*91f16700Schasinglulu static void spmd_fill_lp_info_array( 231*91f16700Schasinglulu struct ffa_partition_info_v1_1 (*partitions)[EL3_SPMD_MAX_NUM_LP], 232*91f16700Schasinglulu uint32_t uuid[4], uint16_t *lp_count_out) 233*91f16700Schasinglulu { 234*91f16700Schasinglulu uint16_t lp_count = 0; 235*91f16700Schasinglulu struct spmd_lp_desc *lp_array; 236*91f16700Schasinglulu bool uuid_is_null = is_null_uuid(uuid); 237*91f16700Schasinglulu 238*91f16700Schasinglulu if (SPMD_LP_DESCS_COUNT == 0U) { 239*91f16700Schasinglulu *lp_count_out = 0; 240*91f16700Schasinglulu return; 241*91f16700Schasinglulu } 242*91f16700Schasinglulu 243*91f16700Schasinglulu lp_array = get_spmd_el3_lp_array(); 244*91f16700Schasinglulu for (uint16_t index = 0; index < SPMD_LP_DESCS_COUNT; ++index) { 245*91f16700Schasinglulu struct spmd_lp_desc *lp = &lp_array[index]; 246*91f16700Schasinglulu 247*91f16700Schasinglulu if (uuid_is_null || uuid_match(uuid, lp->uuid)) { 248*91f16700Schasinglulu uint16_t array_index = lp_count; 249*91f16700Schasinglulu 250*91f16700Schasinglulu ++lp_count; 251*91f16700Schasinglulu 252*91f16700Schasinglulu (*partitions)[array_index].ep_id = lp->sp_id; 253*91f16700Schasinglulu (*partitions)[array_index].execution_ctx_count = 1; 254*91f16700Schasinglulu (*partitions)[array_index].properties = lp->properties; 255*91f16700Schasinglulu (*partitions)[array_index].properties |= 256*91f16700Schasinglulu (FFA_PARTITION_INFO_GET_AARCH64_STATE << 257*91f16700Schasinglulu FFA_PARTITION_INFO_GET_EXEC_STATE_SHIFT); 258*91f16700Schasinglulu if (uuid_is_null) { 259*91f16700Schasinglulu memcpy(&((*partitions)[array_index].uuid), 260*91f16700Schasinglulu &lp->uuid, sizeof(lp->uuid)); 261*91f16700Schasinglulu } 262*91f16700Schasinglulu } 263*91f16700Schasinglulu } 264*91f16700Schasinglulu 265*91f16700Schasinglulu *lp_count_out = lp_count; 266*91f16700Schasinglulu } 267*91f16700Schasinglulu 268*91f16700Schasinglulu static inline void spmd_pack_lp_count_props( 269*91f16700Schasinglulu uint64_t *xn, uint16_t ep_id, uint16_t vcpu_count, 270*91f16700Schasinglulu uint32_t properties) 271*91f16700Schasinglulu { 272*91f16700Schasinglulu *xn = (uint64_t)ep_id; 273*91f16700Schasinglulu *xn |= (uint64_t)vcpu_count << 16; 274*91f16700Schasinglulu *xn |= (uint64_t)properties << 32; 275*91f16700Schasinglulu } 276*91f16700Schasinglulu 277*91f16700Schasinglulu static inline void spmd_pack_lp_uuid(uint64_t *xn_1, uint64_t *xn_2, 278*91f16700Schasinglulu uint32_t uuid[4]) 279*91f16700Schasinglulu { 280*91f16700Schasinglulu *xn_1 = (uint64_t)uuid[0]; 281*91f16700Schasinglulu *xn_1 |= (uint64_t)uuid[1] << 32; 282*91f16700Schasinglulu *xn_2 = (uint64_t)uuid[2]; 283*91f16700Schasinglulu *xn_2 |= (uint64_t)uuid[3] << 32; 284*91f16700Schasinglulu } 285*91f16700Schasinglulu #endif 286*91f16700Schasinglulu 287*91f16700Schasinglulu /* 288*91f16700Schasinglulu * Initialize SPMD logical partitions. This function assumes that it is called 289*91f16700Schasinglulu * only after the SPMC has successfully initialized. 290*91f16700Schasinglulu */ 291*91f16700Schasinglulu int32_t spmd_logical_sp_init(void) 292*91f16700Schasinglulu { 293*91f16700Schasinglulu #if ENABLE_SPMD_LP 294*91f16700Schasinglulu int32_t rc = 0; 295*91f16700Schasinglulu struct spmd_lp_desc *spmd_lp_descs; 296*91f16700Schasinglulu 297*91f16700Schasinglulu assert(SPMD_LP_DESCS_COUNT <= EL3_SPMD_MAX_NUM_LP); 298*91f16700Schasinglulu 299*91f16700Schasinglulu if (is_spmd_lp_inited == true) { 300*91f16700Schasinglulu return 0; 301*91f16700Schasinglulu } 302*91f16700Schasinglulu 303*91f16700Schasinglulu if (is_spmc_inited == false) { 304*91f16700Schasinglulu return -1; 305*91f16700Schasinglulu } 306*91f16700Schasinglulu 307*91f16700Schasinglulu spmd_lp_descs = get_spmd_el3_lp_array(); 308*91f16700Schasinglulu 309*91f16700Schasinglulu /* Perform initial validation of the SPMD Logical Partitions. */ 310*91f16700Schasinglulu rc = el3_spmd_sp_desc_validate(spmd_lp_descs); 311*91f16700Schasinglulu if (rc != 0) { 312*91f16700Schasinglulu ERROR("Logical SPMD Partition validation failed!\n"); 313*91f16700Schasinglulu return rc; 314*91f16700Schasinglulu } 315*91f16700Schasinglulu 316*91f16700Schasinglulu VERBOSE("SPMD Logical Secure Partition init start.\n"); 317*91f16700Schasinglulu for (unsigned int i = 0U; i < SPMD_LP_DESCS_COUNT; i++) { 318*91f16700Schasinglulu rc = spmd_lp_descs[i].init(); 319*91f16700Schasinglulu if (rc != 0) { 320*91f16700Schasinglulu ERROR("SPMD Logical SP (0x%x) failed to initialize\n", 321*91f16700Schasinglulu spmd_lp_descs[i].sp_id); 322*91f16700Schasinglulu return rc; 323*91f16700Schasinglulu } 324*91f16700Schasinglulu VERBOSE("SPMD Logical SP (0x%x) Initialized\n", 325*91f16700Schasinglulu spmd_lp_descs[i].sp_id); 326*91f16700Schasinglulu } 327*91f16700Schasinglulu 328*91f16700Schasinglulu INFO("SPMD Logical Secure Partition init completed.\n"); 329*91f16700Schasinglulu if (rc == 0) { 330*91f16700Schasinglulu is_spmd_lp_inited = true; 331*91f16700Schasinglulu } 332*91f16700Schasinglulu return rc; 333*91f16700Schasinglulu #else 334*91f16700Schasinglulu return 0; 335*91f16700Schasinglulu #endif 336*91f16700Schasinglulu } 337*91f16700Schasinglulu 338*91f16700Schasinglulu void spmd_logical_sp_set_spmc_initialized(void) 339*91f16700Schasinglulu { 340*91f16700Schasinglulu #if ENABLE_SPMD_LP 341*91f16700Schasinglulu is_spmc_inited = true; 342*91f16700Schasinglulu #endif 343*91f16700Schasinglulu } 344*91f16700Schasinglulu 345*91f16700Schasinglulu void spmd_logical_sp_set_spmc_failure(void) 346*91f16700Schasinglulu { 347*91f16700Schasinglulu #if ENABLE_SPMD_LP 348*91f16700Schasinglulu is_spmc_inited = false; 349*91f16700Schasinglulu #endif 350*91f16700Schasinglulu } 351*91f16700Schasinglulu 352*91f16700Schasinglulu /* 353*91f16700Schasinglulu * This function takes an ffa_value structure populated with partition 354*91f16700Schasinglulu * information from an FFA_PARTITION_INFO_GET_REGS ABI call, extracts 355*91f16700Schasinglulu * the values and writes it into a ffa_partition_info_v1_1 structure for 356*91f16700Schasinglulu * other code to consume. 357*91f16700Schasinglulu */ 358*91f16700Schasinglulu bool ffa_partition_info_regs_get_part_info( 359*91f16700Schasinglulu struct ffa_value *args, uint8_t idx, 360*91f16700Schasinglulu struct ffa_partition_info_v1_1 *partition_info) 361*91f16700Schasinglulu { 362*91f16700Schasinglulu uint64_t *arg_ptrs; 363*91f16700Schasinglulu uint64_t info, uuid_lo, uuid_high; 364*91f16700Schasinglulu 365*91f16700Schasinglulu /* 366*91f16700Schasinglulu * Each partition information is encoded in 3 registers, so there can be 367*91f16700Schasinglulu * a maximum of 5 entries. 368*91f16700Schasinglulu */ 369*91f16700Schasinglulu if (idx >= 5 || partition_info == NULL) { 370*91f16700Schasinglulu return false; 371*91f16700Schasinglulu } 372*91f16700Schasinglulu 373*91f16700Schasinglulu /* 374*91f16700Schasinglulu * List of pointers to args in return value. arg0/func encodes ff-a 375*91f16700Schasinglulu * function, arg1 is reserved, arg2 encodes indices. arg3 and greater 376*91f16700Schasinglulu * values reflect partition properties. 377*91f16700Schasinglulu */ 378*91f16700Schasinglulu arg_ptrs = (uint64_t *)args + ((idx * 3) + 3); 379*91f16700Schasinglulu info = *arg_ptrs; 380*91f16700Schasinglulu 381*91f16700Schasinglulu arg_ptrs++; 382*91f16700Schasinglulu uuid_lo = *arg_ptrs; 383*91f16700Schasinglulu 384*91f16700Schasinglulu arg_ptrs++; 385*91f16700Schasinglulu uuid_high = *arg_ptrs; 386*91f16700Schasinglulu 387*91f16700Schasinglulu partition_info->ep_id = (uint16_t)(info & 0xFFFFU); 388*91f16700Schasinglulu partition_info->execution_ctx_count = (uint16_t)((info >> 16) & 0xFFFFU); 389*91f16700Schasinglulu partition_info->properties = (uint32_t)(info >> 32); 390*91f16700Schasinglulu partition_info->uuid[0] = (uint32_t)(uuid_lo & 0xFFFFFFFFU); 391*91f16700Schasinglulu partition_info->uuid[1] = (uint32_t)((uuid_lo >> 32) & 0xFFFFFFFFU); 392*91f16700Schasinglulu partition_info->uuid[2] = (uint32_t)(uuid_high & 0xFFFFFFFFU); 393*91f16700Schasinglulu partition_info->uuid[3] = (uint32_t)((uuid_high >> 32) & 0xFFFFFFFFU); 394*91f16700Schasinglulu 395*91f16700Schasinglulu return true; 396*91f16700Schasinglulu } 397*91f16700Schasinglulu 398*91f16700Schasinglulu /* 399*91f16700Schasinglulu * This function is called by the SPMD in response to 400*91f16700Schasinglulu * an FFA_PARTITION_INFO_GET_REG ABI invocation by the SPMC. Secure partitions 401*91f16700Schasinglulu * are allowed to discover the presence of EL3 SPMD logical partitions by 402*91f16700Schasinglulu * invoking the aforementioned ABI and this function populates the required 403*91f16700Schasinglulu * information about EL3 SPMD logical partitions. 404*91f16700Schasinglulu */ 405*91f16700Schasinglulu uint64_t spmd_el3_populate_logical_partition_info(void *handle, uint64_t x1, 406*91f16700Schasinglulu uint64_t x2, uint64_t x3) 407*91f16700Schasinglulu { 408*91f16700Schasinglulu #if ENABLE_SPMD_LP 409*91f16700Schasinglulu uint32_t target_uuid[4] = { 0 }; 410*91f16700Schasinglulu uint32_t w0; 411*91f16700Schasinglulu uint32_t w1; 412*91f16700Schasinglulu uint32_t w2; 413*91f16700Schasinglulu uint32_t w3; 414*91f16700Schasinglulu uint16_t start_index; 415*91f16700Schasinglulu uint16_t tag; 416*91f16700Schasinglulu static struct ffa_partition_info_v1_1 partitions[EL3_SPMD_MAX_NUM_LP]; 417*91f16700Schasinglulu uint16_t lp_count = 0; 418*91f16700Schasinglulu uint16_t max_idx = 0; 419*91f16700Schasinglulu uint16_t curr_idx = 0; 420*91f16700Schasinglulu uint8_t num_entries_to_ret = 0; 421*91f16700Schasinglulu struct ffa_value ret = { 0 }; 422*91f16700Schasinglulu uint64_t *arg_ptrs = (uint64_t *)&ret + 3; 423*91f16700Schasinglulu 424*91f16700Schasinglulu w0 = (uint32_t)(x1 & 0xFFFFFFFFU); 425*91f16700Schasinglulu w1 = (uint32_t)(x1 >> 32); 426*91f16700Schasinglulu w2 = (uint32_t)(x2 & 0xFFFFFFFFU); 427*91f16700Schasinglulu w3 = (uint32_t)(x2 >> 32); 428*91f16700Schasinglulu 429*91f16700Schasinglulu target_uuid[0] = w0; 430*91f16700Schasinglulu target_uuid[1] = w1; 431*91f16700Schasinglulu target_uuid[2] = w2; 432*91f16700Schasinglulu target_uuid[3] = w3; 433*91f16700Schasinglulu 434*91f16700Schasinglulu start_index = (uint16_t)(x3 & 0xFFFFU); 435*91f16700Schasinglulu tag = (uint16_t)((x3 >> 16) & 0xFFFFU); 436*91f16700Schasinglulu 437*91f16700Schasinglulu assert(handle == cm_get_context(SECURE)); 438*91f16700Schasinglulu 439*91f16700Schasinglulu if (tag != 0) { 440*91f16700Schasinglulu VERBOSE("Tag is not 0. Cannot return partition info.\n"); 441*91f16700Schasinglulu return spmd_ffa_error_return(handle, FFA_ERROR_RETRY); 442*91f16700Schasinglulu } 443*91f16700Schasinglulu 444*91f16700Schasinglulu memset(&partitions, 0, sizeof(partitions)); 445*91f16700Schasinglulu 446*91f16700Schasinglulu spmd_fill_lp_info_array(&partitions, target_uuid, &lp_count); 447*91f16700Schasinglulu 448*91f16700Schasinglulu if (lp_count == 0) { 449*91f16700Schasinglulu VERBOSE("No SPDM EL3 logical partitions exist.\n"); 450*91f16700Schasinglulu return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 451*91f16700Schasinglulu } 452*91f16700Schasinglulu 453*91f16700Schasinglulu if (start_index >= lp_count) { 454*91f16700Schasinglulu VERBOSE("start_index = %d, lp_count = %d (start index must be" 455*91f16700Schasinglulu " less than partition count.\n", 456*91f16700Schasinglulu start_index, lp_count); 457*91f16700Schasinglulu return spmd_ffa_error_return(handle, 458*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 459*91f16700Schasinglulu } 460*91f16700Schasinglulu 461*91f16700Schasinglulu max_idx = lp_count - 1; 462*91f16700Schasinglulu num_entries_to_ret = (max_idx - start_index) + 1; 463*91f16700Schasinglulu num_entries_to_ret = 464*91f16700Schasinglulu MIN(num_entries_to_ret, MAX_INFO_REGS_ENTRIES_PER_CALL); 465*91f16700Schasinglulu curr_idx = start_index + num_entries_to_ret - 1; 466*91f16700Schasinglulu assert(curr_idx <= max_idx); 467*91f16700Schasinglulu 468*91f16700Schasinglulu ret.func = FFA_SUCCESS_SMC64; 469*91f16700Schasinglulu ret.arg2 = (uint64_t)((sizeof(struct ffa_partition_info_v1_1) & 0xFFFFU) << 48); 470*91f16700Schasinglulu ret.arg2 |= (uint64_t)(curr_idx << 16); 471*91f16700Schasinglulu ret.arg2 |= (uint64_t)max_idx; 472*91f16700Schasinglulu 473*91f16700Schasinglulu for (uint16_t idx = start_index; idx <= curr_idx; ++idx) { 474*91f16700Schasinglulu spmd_pack_lp_count_props(arg_ptrs, partitions[idx].ep_id, 475*91f16700Schasinglulu partitions[idx].execution_ctx_count, 476*91f16700Schasinglulu partitions[idx].properties); 477*91f16700Schasinglulu arg_ptrs++; 478*91f16700Schasinglulu if (is_null_uuid(target_uuid)) { 479*91f16700Schasinglulu spmd_pack_lp_uuid(arg_ptrs, (arg_ptrs + 1), 480*91f16700Schasinglulu partitions[idx].uuid); 481*91f16700Schasinglulu } 482*91f16700Schasinglulu arg_ptrs += 2; 483*91f16700Schasinglulu } 484*91f16700Schasinglulu 485*91f16700Schasinglulu SMC_RET18(handle, ret.func, ret.arg1, ret.arg2, ret.arg3, ret.arg4, 486*91f16700Schasinglulu ret.arg5, ret.arg6, ret.arg7, ret.arg8, ret.arg9, ret.arg10, 487*91f16700Schasinglulu ret.arg11, ret.arg12, ret.arg13, ret.arg14, ret.arg15, 488*91f16700Schasinglulu ret.arg16, ret.arg17); 489*91f16700Schasinglulu #else 490*91f16700Schasinglulu return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); 491*91f16700Schasinglulu #endif 492*91f16700Schasinglulu } 493*91f16700Schasinglulu 494*91f16700Schasinglulu /* This function can be used by an SPMD logical partition to invoke the 495*91f16700Schasinglulu * FFA_PARTITION_INFO_GET_REGS ABI to the SPMC, to discover the secure 496*91f16700Schasinglulu * partitions in the system. The function takes a UUID, start index and 497*91f16700Schasinglulu * tag and the partition information are returned in an ffa_value structure 498*91f16700Schasinglulu * and can be consumed by using appropriate helper functions. 499*91f16700Schasinglulu */ 500*91f16700Schasinglulu bool spmd_el3_invoke_partition_info_get( 501*91f16700Schasinglulu const uint32_t target_uuid[4], 502*91f16700Schasinglulu const uint16_t start_index, 503*91f16700Schasinglulu const uint16_t tag, 504*91f16700Schasinglulu struct ffa_value *retval) 505*91f16700Schasinglulu { 506*91f16700Schasinglulu #if ENABLE_SPMD_LP 507*91f16700Schasinglulu uint64_t rc = UINT64_MAX; 508*91f16700Schasinglulu spmd_spm_core_context_t *ctx = spmd_get_context(); 509*91f16700Schasinglulu 510*91f16700Schasinglulu if (retval == NULL) { 511*91f16700Schasinglulu return false; 512*91f16700Schasinglulu } 513*91f16700Schasinglulu 514*91f16700Schasinglulu memset(retval, 0, sizeof(*retval)); 515*91f16700Schasinglulu 516*91f16700Schasinglulu if (!is_spmc_inited) { 517*91f16700Schasinglulu VERBOSE("Cannot discover partition before," 518*91f16700Schasinglulu " SPMC is initialized.\n"); 519*91f16700Schasinglulu spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 520*91f16700Schasinglulu return true; 521*91f16700Schasinglulu } 522*91f16700Schasinglulu 523*91f16700Schasinglulu if (tag != 0) { 524*91f16700Schasinglulu VERBOSE("Tag must be zero. other tags unsupported\n"); 525*91f16700Schasinglulu spmd_encode_ffa_error(retval, 526*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 527*91f16700Schasinglulu return true; 528*91f16700Schasinglulu } 529*91f16700Schasinglulu 530*91f16700Schasinglulu /* Save the non-secure context before entering SPMC */ 531*91f16700Schasinglulu cm_el1_sysregs_context_save(NON_SECURE); 532*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2 533*91f16700Schasinglulu cm_el2_sysregs_context_save(NON_SECURE); 534*91f16700Schasinglulu #endif 535*91f16700Schasinglulu 536*91f16700Schasinglulu spmd_build_ffa_info_get_regs(ctx, target_uuid, start_index, tag); 537*91f16700Schasinglulu spmd_logical_sp_set_info_regs_ongoing(ctx); 538*91f16700Schasinglulu 539*91f16700Schasinglulu rc = spmd_spm_core_sync_entry(ctx); 540*91f16700Schasinglulu if (rc != 0ULL) { 541*91f16700Schasinglulu ERROR("%s failed (%lx) on CPU%u\n", __func__, rc, 542*91f16700Schasinglulu plat_my_core_pos()); 543*91f16700Schasinglulu panic(); 544*91f16700Schasinglulu } 545*91f16700Schasinglulu 546*91f16700Schasinglulu spmd_logical_sp_reset_info_regs_ongoing(ctx); 547*91f16700Schasinglulu spmd_encode_ctx_to_ffa_value(ctx, retval); 548*91f16700Schasinglulu 549*91f16700Schasinglulu assert(is_ffa_error(retval) || is_ffa_success(retval)); 550*91f16700Schasinglulu 551*91f16700Schasinglulu cm_el1_sysregs_context_restore(NON_SECURE); 552*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2 553*91f16700Schasinglulu cm_el2_sysregs_context_restore(NON_SECURE); 554*91f16700Schasinglulu #endif 555*91f16700Schasinglulu cm_set_next_eret_context(NON_SECURE); 556*91f16700Schasinglulu return true; 557*91f16700Schasinglulu #else 558*91f16700Schasinglulu return false; 559*91f16700Schasinglulu #endif 560*91f16700Schasinglulu } 561*91f16700Schasinglulu 562*91f16700Schasinglulu /******************************************************************************* 563*91f16700Schasinglulu * This function sends an FF-A Direct Request from a partition in EL3 to a 564*91f16700Schasinglulu * partition that may reside under an SPMC (only lower ELs supported). The main 565*91f16700Schasinglulu * use of this API is for SPMD logical partitions. 566*91f16700Schasinglulu * The API is expected to be used when there are platform specific SMCs that 567*91f16700Schasinglulu * need to be routed to a secure partition that is FF-A compliant or when 568*91f16700Schasinglulu * there are group 0 interrupts that need to be handled first in EL3 and then 569*91f16700Schasinglulu * forwarded to an FF-A compliant secure partition. Therefore, it is expected 570*91f16700Schasinglulu * that the handle to the context provided belongs to the non-secure context. 571*91f16700Schasinglulu * This also means that interrupts/SMCs that trap to EL3 during secure execution 572*91f16700Schasinglulu * cannot use this API. 573*91f16700Schasinglulu * x1, x2, x3 and x4 are encoded as specified in the FF-A specification. 574*91f16700Schasinglulu * retval is used to pass the direct response values to the caller. 575*91f16700Schasinglulu * The function returns true if retval has valid values, and false otherwise. 576*91f16700Schasinglulu ******************************************************************************/ 577*91f16700Schasinglulu bool spmd_el3_ffa_msg_direct_req(uint64_t x1, 578*91f16700Schasinglulu uint64_t x2, 579*91f16700Schasinglulu uint64_t x3, 580*91f16700Schasinglulu uint64_t x4, 581*91f16700Schasinglulu void *handle, 582*91f16700Schasinglulu struct ffa_value *retval) 583*91f16700Schasinglulu { 584*91f16700Schasinglulu #if ENABLE_SPMD_LP 585*91f16700Schasinglulu 586*91f16700Schasinglulu uint64_t rc = UINT64_MAX; 587*91f16700Schasinglulu spmd_spm_core_context_t *ctx = spmd_get_context(); 588*91f16700Schasinglulu 589*91f16700Schasinglulu if (retval == NULL) { 590*91f16700Schasinglulu return false; 591*91f16700Schasinglulu } 592*91f16700Schasinglulu 593*91f16700Schasinglulu memset(retval, 0, sizeof(*retval)); 594*91f16700Schasinglulu 595*91f16700Schasinglulu if (!is_spmd_lp_inited || !is_spmc_inited) { 596*91f16700Schasinglulu VERBOSE("Cannot send SPMD logical partition direct message," 597*91f16700Schasinglulu " Partitions not initialized or SPMC not initialized.\n"); 598*91f16700Schasinglulu spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 599*91f16700Schasinglulu return true; 600*91f16700Schasinglulu } 601*91f16700Schasinglulu 602*91f16700Schasinglulu /* 603*91f16700Schasinglulu * x2 must be zero, since there is no support for framework message via 604*91f16700Schasinglulu * an SPMD logical partition. This is sort of a useless check and it is 605*91f16700Schasinglulu * possible to not take parameter. However, as the framework extends it 606*91f16700Schasinglulu * may be useful to have x2 and extend this function later with 607*91f16700Schasinglulu * functionality based on x2. 608*91f16700Schasinglulu */ 609*91f16700Schasinglulu if (x2 != 0) { 610*91f16700Schasinglulu VERBOSE("x2 must be zero. Cannot send framework message.\n"); 611*91f16700Schasinglulu spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 612*91f16700Schasinglulu return true; 613*91f16700Schasinglulu } 614*91f16700Schasinglulu 615*91f16700Schasinglulu /* 616*91f16700Schasinglulu * Current context must be non-secure. API is expected to be used 617*91f16700Schasinglulu * when entry into EL3 and the SPMD logical partition is via an 618*91f16700Schasinglulu * interrupt that occurs when execution is in normal world and 619*91f16700Schasinglulu * SMCs from normal world. FF-A compliant SPMCs are expected to 620*91f16700Schasinglulu * trap interrupts during secure execution in lower ELs since they 621*91f16700Schasinglulu * are usually not re-entrant and SMCs from secure world can be 622*91f16700Schasinglulu * handled synchronously. There is no known use case for an SPMD 623*91f16700Schasinglulu * logical partition to send a direct message to another partition 624*91f16700Schasinglulu * in response to a secure interrupt or SMCs from secure world. 625*91f16700Schasinglulu */ 626*91f16700Schasinglulu if (handle != cm_get_context(NON_SECURE)) { 627*91f16700Schasinglulu VERBOSE("Handle must be for the non-secure context.\n"); 628*91f16700Schasinglulu spmd_encode_ffa_error(retval, FFA_ERROR_DENIED); 629*91f16700Schasinglulu return true; 630*91f16700Schasinglulu } 631*91f16700Schasinglulu 632*91f16700Schasinglulu if (!is_spmd_lp_id(ffa_endpoint_source(x1))) { 633*91f16700Schasinglulu VERBOSE("Source ID must be valid SPMD logical partition" 634*91f16700Schasinglulu " ID.\n"); 635*91f16700Schasinglulu spmd_encode_ffa_error(retval, 636*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 637*91f16700Schasinglulu return true; 638*91f16700Schasinglulu } 639*91f16700Schasinglulu 640*91f16700Schasinglulu if (is_spmd_lp_id(ffa_endpoint_destination(x1))) { 641*91f16700Schasinglulu VERBOSE("Destination ID must not be SPMD logical partition" 642*91f16700Schasinglulu " ID.\n"); 643*91f16700Schasinglulu spmd_encode_ffa_error(retval, 644*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 645*91f16700Schasinglulu return true; 646*91f16700Schasinglulu } 647*91f16700Schasinglulu 648*91f16700Schasinglulu if (!ffa_is_secure_world_id(ffa_endpoint_destination(x1))) { 649*91f16700Schasinglulu VERBOSE("Destination ID must be secure world ID.\n"); 650*91f16700Schasinglulu spmd_encode_ffa_error(retval, 651*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 652*91f16700Schasinglulu return true; 653*91f16700Schasinglulu } 654*91f16700Schasinglulu 655*91f16700Schasinglulu if (ffa_endpoint_destination(x1) == SPMD_DIRECT_MSG_ENDPOINT_ID) { 656*91f16700Schasinglulu VERBOSE("Destination ID must not be SPMD ID.\n"); 657*91f16700Schasinglulu spmd_encode_ffa_error(retval, 658*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 659*91f16700Schasinglulu return true; 660*91f16700Schasinglulu } 661*91f16700Schasinglulu 662*91f16700Schasinglulu if (ffa_endpoint_destination(x1) == spmd_spmc_id_get()) { 663*91f16700Schasinglulu VERBOSE("Destination ID must not be SPMC ID.\n"); 664*91f16700Schasinglulu spmd_encode_ffa_error(retval, 665*91f16700Schasinglulu FFA_ERROR_INVALID_PARAMETER); 666*91f16700Schasinglulu return true; 667*91f16700Schasinglulu } 668*91f16700Schasinglulu 669*91f16700Schasinglulu /* Save the non-secure context before entering SPMC */ 670*91f16700Schasinglulu cm_el1_sysregs_context_save(NON_SECURE); 671*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2 672*91f16700Schasinglulu cm_el2_sysregs_context_save(NON_SECURE); 673*91f16700Schasinglulu #endif 674*91f16700Schasinglulu 675*91f16700Schasinglulu /* 676*91f16700Schasinglulu * Perform synchronous entry into the SPMC. Synchronous entry is 677*91f16700Schasinglulu * required because the spec requires that a direct message request 678*91f16700Schasinglulu * from an SPMD LP look like a function call from it's perspective. 679*91f16700Schasinglulu */ 680*91f16700Schasinglulu spmd_build_direct_message_req(ctx, x1, x2, x3, x4); 681*91f16700Schasinglulu spmd_logical_sp_set_dir_req_ongoing(ctx); 682*91f16700Schasinglulu 683*91f16700Schasinglulu rc = spmd_spm_core_sync_entry(ctx); 684*91f16700Schasinglulu 685*91f16700Schasinglulu spmd_logical_sp_reset_dir_req_ongoing(ctx); 686*91f16700Schasinglulu 687*91f16700Schasinglulu if (rc != 0ULL) { 688*91f16700Schasinglulu ERROR("%s failed (%lx) on CPU%u\n", __func__, rc, 689*91f16700Schasinglulu plat_my_core_pos()); 690*91f16700Schasinglulu panic(); 691*91f16700Schasinglulu } else { 692*91f16700Schasinglulu spmd_encode_ctx_to_ffa_value(ctx, retval); 693*91f16700Schasinglulu 694*91f16700Schasinglulu /* 695*91f16700Schasinglulu * Only expect error or direct response, 696*91f16700Schasinglulu * spmd_spm_core_sync_exit should not be called on other paths. 697*91f16700Schasinglulu * Checks are asserts since the LSP can fail gracefully if the 698*91f16700Schasinglulu * source or destination ids are not the same. Panic'ing would 699*91f16700Schasinglulu * not provide any benefit. 700*91f16700Schasinglulu */ 701*91f16700Schasinglulu assert(is_ffa_error(retval) || is_ffa_direct_msg_resp(retval)); 702*91f16700Schasinglulu assert(is_ffa_error(retval) || 703*91f16700Schasinglulu (ffa_endpoint_destination(retval->arg1) == 704*91f16700Schasinglulu ffa_endpoint_source(x1))); 705*91f16700Schasinglulu assert(is_ffa_error(retval) || 706*91f16700Schasinglulu (ffa_endpoint_source(retval->arg1) == 707*91f16700Schasinglulu ffa_endpoint_destination(x1))); 708*91f16700Schasinglulu } 709*91f16700Schasinglulu 710*91f16700Schasinglulu cm_el1_sysregs_context_restore(NON_SECURE); 711*91f16700Schasinglulu #if SPMD_SPM_AT_SEL2 712*91f16700Schasinglulu cm_el2_sysregs_context_restore(NON_SECURE); 713*91f16700Schasinglulu #endif 714*91f16700Schasinglulu cm_set_next_eret_context(NON_SECURE); 715*91f16700Schasinglulu 716*91f16700Schasinglulu return true; 717*91f16700Schasinglulu #else 718*91f16700Schasinglulu return false; 719*91f16700Schasinglulu #endif 720*91f16700Schasinglulu } 721*91f16700Schasinglulu 722*91f16700Schasinglulu bool is_spmd_logical_sp_info_regs_req_in_progress( 723*91f16700Schasinglulu spmd_spm_core_context_t *ctx) 724*91f16700Schasinglulu { 725*91f16700Schasinglulu #if ENABLE_SPMD_LP 726*91f16700Schasinglulu return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_INFO_GET_REG_ONGOING) 727*91f16700Schasinglulu == SPMD_LP_FFA_INFO_GET_REG_ONGOING); 728*91f16700Schasinglulu #else 729*91f16700Schasinglulu return false; 730*91f16700Schasinglulu #endif 731*91f16700Schasinglulu } 732*91f16700Schasinglulu 733*91f16700Schasinglulu bool is_spmd_logical_sp_dir_req_in_progress( 734*91f16700Schasinglulu spmd_spm_core_context_t *ctx) 735*91f16700Schasinglulu { 736*91f16700Schasinglulu #if ENABLE_SPMD_LP 737*91f16700Schasinglulu return ((ctx->spmd_lp_sync_req_ongoing & SPMD_LP_FFA_DIR_REQ_ONGOING) 738*91f16700Schasinglulu == SPMD_LP_FFA_DIR_REQ_ONGOING); 739*91f16700Schasinglulu #else 740*91f16700Schasinglulu return false; 741*91f16700Schasinglulu #endif 742*91f16700Schasinglulu } 743