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
is_spmd_lp_id(unsigned int id)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
is_ffa_error(struct ffa_value * retval)101 static inline bool is_ffa_error(struct ffa_value *retval)
102 {
103 return retval->func == FFA_ERROR;
104 }
105
is_ffa_success(struct ffa_value * retval)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
is_ffa_direct_msg_resp(struct ffa_value * retval)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
ffa_partition_info_regs_get_last_idx(struct ffa_value * args)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
ffa_partition_info_regs_get_curr_idx(struct ffa_value * args)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
ffa_partition_info_regs_get_tag(struct ffa_value * args)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
ffa_partition_info_regs_get_desc_size(struct ffa_value * args)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