/* * Copyright (c) 2023-2026, Arm Limited and Contributors. All rights reserved. * SPDX-License-Identifier: BSD-3-Clause */ #ifndef EL3_SPMD_LOGICAL_SP_H #define EL3_SPMD_LOGICAL_SP_H #include #include #include #include /******************************************************************************* * Structure definition, typedefs & constants for the SPMD Logical Partitions. ******************************************************************************/ /* Prototype for SPMD logical partition initializing function. */ typedef int32_t (*ffa_spmd_lp_init_t)(void); /* SPMD Logical Partition Descriptor. */ struct spmd_lp_desc { ffa_spmd_lp_init_t init; uint16_t sp_id; uint32_t properties; uint32_t uuid[4]; /* Little Endian. */ const char *debug_name; }; struct ffa_value { uint64_t func; uint64_t arg1; uint64_t arg2; uint64_t arg3; uint64_t arg4; uint64_t arg5; uint64_t arg6; uint64_t arg7; uint64_t arg8; uint64_t arg9; uint64_t arg10; uint64_t arg11; uint64_t arg12; uint64_t arg13; uint64_t arg14; uint64_t arg15; uint64_t arg16; uint64_t arg17; }; /* Convenience macro to declare a SPMD logical partition descriptor. */ #define DECLARE_SPMD_LOGICAL_PARTITION(_name, _init, _sp_id, _uuid, _properties) \ static const struct spmd_lp_desc __partition_desc_ ## _name \ __section(".spmd_lp_descs") __used = { \ .debug_name = #_name, \ .init = (_init), \ .sp_id = (_sp_id), \ .uuid = _uuid, \ .properties = (_properties), \ } IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_START__, SPMD_LP_DESCS_START); IMPORT_SYM(uintptr_t, __SPMD_LP_DESCS_END__, SPMD_LP_DESCS_END); #define SPMD_LP_DESCS_COUNT ((SPMD_LP_DESCS_END - SPMD_LP_DESCS_START) \ / sizeof(struct spmd_lp_desc)) CASSERT(sizeof(struct spmd_lp_desc) == 40, assert_spmd_lp_desc_size_mismatch); /* * Reserve 63 IDs for SPMD Logical Partitions. Currently, 0xFFC0 to 0xFFFE * is reserved. */ #define SPMD_LP_ID_END (SPMD_DIRECT_MSG_ENDPOINT_ID - 1) #define SPMD_LP_ID_START (SPMD_LP_ID_END - 62) /* * TODO: Arbitrary number. Can make this platform specific in the future, * no known use cases for more LPs at this point. */ #define EL3_SPMD_MAX_NUM_LP U(5) /* * Maximum number of struct ffa_partition_info_v1_3 descriptors that fit in one * FFA_PARTITION_INFO_GET_REGS_64 response. The ABI lets the callee populate * args3-args17 (15 x 64-bit registers = 120 bytes) in struct ffa_value; each * descriptor consumes sizeof(struct ffa_partition_info_v1_3) = 48 bytes. * Therefore, rounding it means 2 entries per call for FF-A v1.3. */ #define MAX_INFO_REGS_ENTRIES_PER_CALL 2U CASSERT(sizeof(struct ffa_partition_info_v1_3) == 48, ffa_partition_info_desc_size_mismatch); static inline bool is_spmd_lp_id(unsigned int id) { #if ENABLE_SPMD_LP return (id >= SPMD_LP_ID_START && id <= SPMD_LP_ID_END); #else return false; #endif } static inline bool is_ffa_error(struct ffa_value *retval) { return retval->func == FFA_ERROR; } static inline bool is_ffa_success(struct ffa_value *retval) { return (retval->func == FFA_SUCCESS_SMC32) || (retval->func == FFA_SUCCESS_SMC64); } static inline bool is_ffa_direct_msg_resp(struct ffa_value *retval) { return (retval->func == FFA_MSG_SEND_DIRECT_RESP_SMC32) || (retval->func == FFA_MSG_SEND_DIRECT_RESP2_SMC64) || (retval->func == FFA_MSG_SEND_DIRECT_RESP_SMC64); } static inline uint16_t ffa_partition_info_regs_get_last_idx( struct ffa_value *args) { return (uint16_t)(args->arg2 & 0xFFFFU); } static inline uint16_t ffa_partition_info_regs_get_curr_idx( struct ffa_value *args) { return (uint16_t)((args->arg2 >> 16) & 0xFFFFU); } static inline uint16_t ffa_partition_info_regs_get_tag(struct ffa_value *args) { return (uint16_t)((args->arg2 >> 32) & 0xFFFFU); } static inline uint16_t ffa_partition_info_regs_get_desc_size( struct ffa_value *args) { return (uint16_t)(args->arg2 >> 48); } uint64_t spmd_el3_populate_logical_partition_info(void *handle, uint64_t x1, uint64_t x2, uint64_t x3); bool ffa_partition_info_regs_get_part_info( struct ffa_value *args, uint8_t idx, struct ffa_partition_info_v1_3 *partition_info); bool spmd_el3_invoke_partition_info_get( const uint32_t target_uuid[4], const uint16_t start_index, const uint16_t tag, struct ffa_value *retval); void spmd_logical_sp_set_spmc_initialized(void); void spmc_logical_sp_set_spmc_failure(void); int32_t spmd_logical_sp_init(void); bool spmd_el3_ffa_msg_direct_req(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7, void *handle, struct ffa_value *retval); bool spmd_el3_ffa_msg_direct_req2(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4, void *handle, struct ffa_value *retval); uintptr_t plat_spmd_logical_sp_smc_handler(unsigned int smc_fid, u_register_t x1, u_register_t x2, u_register_t x3, u_register_t x4, void *cookie, void *handle, u_register_t flags); struct lfa_component_ops *get_secure_partition_activator(void); enum lfa_retc convert_ffa_error_code_to_lfa(int32_t ffa_error_code); enum lfa_retc spmd_lsp_start_request_sp_live_activation(uint16_t lsp_id, uint16_t sp_id, uintptr_t image_base, uint32_t image_page_count, uintptr_t manifest_base, uint32_t manifest_page_count); enum lfa_retc spmd_lsp_finish_request_sp_live_activation(uint16_t lsp_id, uint16_t sp_id); #endif /* EL3_SPMD_LOGICAL_SP_H */