1 /* 2 * Copyright (c) 2023-2026, Arm Limited and Contributors. All rights reserved. 3 * SPDX-License-Identifier: BSD-3-Clause 4 */ 5 #ifndef EL3_SPMD_LOGICAL_SP_H 6 #define EL3_SPMD_LOGICAL_SP_H 7 8 #include <common/bl_common.h> 9 #include <lib/cassert.h> 10 #include <services/ffa_svc.h> 11 #include <services/lfa_svc.h> 12 13 /******************************************************************************* 14 * Structure definition, typedefs & constants for the SPMD Logical Partitions. 15 ******************************************************************************/ 16 /* Prototype for SPMD logical partition initializing function. */ 17 typedef int32_t (*ffa_spmd_lp_init_t)(void); 18 19 /* SPMD Logical Partition Descriptor. */ 20 struct spmd_lp_desc { 21 ffa_spmd_lp_init_t init; 22 uint16_t sp_id; 23 uint32_t properties; 24 uint32_t uuid[4]; /* Little Endian. */ 25 const char *debug_name; 26 }; 27 28 struct ffa_value { 29 uint64_t func; 30 uint64_t arg1; 31 uint64_t arg2; 32 uint64_t arg3; 33 uint64_t arg4; 34 uint64_t arg5; 35 uint64_t arg6; 36 uint64_t arg7; 37 uint64_t arg8; 38 uint64_t arg9; 39 uint64_t arg10; 40 uint64_t arg11; 41 uint64_t arg12; 42 uint64_t arg13; 43 uint64_t arg14; 44 uint64_t arg15; 45 uint64_t arg16; 46 uint64_t arg17; 47 }; 48 49 /* Convenience macro to declare a SPMD logical partition descriptor. */ 50 #define DECLARE_SPMD_LOGICAL_PARTITION(_name, _init, _sp_id, _uuid, _properties) \ 51 static const struct spmd_lp_desc __partition_desc_ ## _name \ 52 __section(".spmd_lp_descs") __used = { \ 53 .debug_name = #_name, \ 54 .init = (_init), \ 55 .sp_id = (_sp_id), \ 56 .uuid = _uuid, \ 57 .properties = (_properties), \ 58 } 59 60 IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_START__, SPMD_LP_DESCS_START); 61 IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_END__, SPMD_LP_DESCS_END); 62 63 #define SPMD_LP_DESCS_COUNT ((SPMD_LP_DESCS_END - SPMD_LP_DESCS_START) \ 64 / sizeof(struct spmd_lp_desc)) 65 CASSERT(sizeof(struct spmd_lp_desc) == 40, assert_spmd_lp_desc_size_mismatch); 66 67 /* 68 * Reserve 63 IDs for SPMD Logical Partitions. Currently, 0xFFC0 to 0xFFFE 69 * is reserved. 70 */ 71 #define SPMD_LP_ID_END (SPMD_DIRECT_MSG_ENDPOINT_ID - 1) 72 #define SPMD_LP_ID_START (SPMD_LP_ID_END - 62) 73 74 /* 75 * TODO: Arbitrary number. Can make this platform specific in the future, 76 * no known use cases for more LPs at this point. 77 */ 78 #define EL3_SPMD_MAX_NUM_LP U(5) 79 80 /* 81 * Maximum number of struct ffa_partition_info_v1_3 descriptors that fit in one 82 * FFA_PARTITION_INFO_GET_REGS_64 response. The ABI lets the callee populate 83 * args3-args17 (15 x 64-bit registers = 120 bytes) in struct ffa_value; each 84 * descriptor consumes sizeof(struct ffa_partition_info_v1_3) = 48 bytes. 85 * Therefore, rounding it means 2 entries per call for FF-A v1.3. 86 */ 87 #define MAX_INFO_REGS_ENTRIES_PER_CALL 2U 88 89 CASSERT(sizeof(struct ffa_partition_info_v1_3) == 48, 90 ffa_partition_info_desc_size_mismatch); 91 92 static inline bool is_spmd_lp_id(unsigned int id) 93 { 94 #if ENABLE_SPMD_LP 95 return (id >= SPMD_LP_ID_START && id <= SPMD_LP_ID_END); 96 #else 97 return false; 98 #endif 99 } 100 101 static inline bool is_ffa_error(struct ffa_value *retval) 102 { 103 return retval->func == FFA_ERROR; 104 } 105 106 static inline bool is_ffa_success(struct ffa_value *retval) 107 { 108 return (retval->func == FFA_SUCCESS_SMC32) || 109 (retval->func == FFA_SUCCESS_SMC64); 110 } 111 112 static inline bool is_ffa_direct_msg_resp(struct ffa_value *retval) 113 { 114 return (retval->func == FFA_MSG_SEND_DIRECT_RESP_SMC32) || 115 (retval->func == FFA_MSG_SEND_DIRECT_RESP2_SMC64) || 116 (retval->func == FFA_MSG_SEND_DIRECT_RESP_SMC64); 117 } 118 119 static inline uint16_t ffa_partition_info_regs_get_last_idx( 120 struct ffa_value *args) 121 { 122 return (uint16_t)(args->arg2 & 0xFFFFU); 123 } 124 125 static inline uint16_t ffa_partition_info_regs_get_curr_idx( 126 struct ffa_value *args) 127 { 128 return (uint16_t)((args->arg2 >> 16) & 0xFFFFU); 129 } 130 131 static inline uint16_t ffa_partition_info_regs_get_tag(struct ffa_value *args) 132 { 133 return (uint16_t)((args->arg2 >> 32) & 0xFFFFU); 134 } 135 136 static inline uint16_t ffa_partition_info_regs_get_desc_size( 137 struct ffa_value *args) 138 { 139 return (uint16_t)(args->arg2 >> 48); 140 } 141 142 uint64_t spmd_el3_populate_logical_partition_info(void *handle, uint64_t x1, 143 uint64_t x2, uint64_t x3); 144 145 bool ffa_partition_info_regs_get_part_info( 146 struct ffa_value *args, uint8_t idx, 147 struct ffa_partition_info_v1_3 *partition_info); 148 149 bool spmd_el3_invoke_partition_info_get( 150 const uint32_t target_uuid[4], 151 const uint16_t start_index, 152 const uint16_t tag, 153 struct ffa_value *retval); 154 void spmd_logical_sp_set_spmc_initialized(void); 155 void spmc_logical_sp_set_spmc_failure(void); 156 157 int32_t spmd_logical_sp_init(void); 158 bool spmd_el3_ffa_msg_direct_req(uint64_t x1, 159 uint64_t x2, 160 uint64_t x3, 161 uint64_t x4, 162 uint64_t x5, 163 uint64_t x6, 164 uint64_t x7, 165 void *handle, 166 struct ffa_value *retval); 167 168 bool spmd_el3_ffa_msg_direct_req2(uint64_t x1, 169 uint64_t x2, 170 uint64_t x3, 171 uint64_t x4, 172 void *handle, 173 struct ffa_value *retval); 174 175 uintptr_t plat_spmd_logical_sp_smc_handler(unsigned int smc_fid, 176 u_register_t x1, 177 u_register_t x2, 178 u_register_t x3, 179 u_register_t x4, 180 void *cookie, 181 void *handle, 182 u_register_t flags); 183 184 struct lfa_component_ops *get_secure_partition_activator(void); 185 186 enum lfa_retc convert_ffa_error_code_to_lfa(int32_t ffa_error_code); 187 188 enum lfa_retc spmd_lsp_start_request_sp_live_activation(uint16_t lsp_id, 189 uint16_t sp_id, 190 uintptr_t image_base, 191 uint32_t image_page_count, 192 uintptr_t manifest_base, 193 uint32_t manifest_page_count); 194 195 enum lfa_retc spmd_lsp_finish_request_sp_live_activation(uint16_t lsp_id, 196 uint16_t sp_id); 197 198 #endif /* EL3_SPMD_LOGICAL_SP_H */ 199