xref: /arm-trusted-firmware/services/std_svc/spm/el3_spmc/spmc.h (revision 91f16700b400a8c0651d24a598fc48ee2997a0d7)
1*91f16700Schasinglulu /*
2*91f16700Schasinglulu  * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
3*91f16700Schasinglulu  *
4*91f16700Schasinglulu  * SPDX-License-Identifier: BSD-3-Clause
5*91f16700Schasinglulu  */
6*91f16700Schasinglulu 
7*91f16700Schasinglulu #ifndef SPMC_H
8*91f16700Schasinglulu #define SPMC_H
9*91f16700Schasinglulu 
10*91f16700Schasinglulu #include <stdint.h>
11*91f16700Schasinglulu 
12*91f16700Schasinglulu #include <common/bl_common.h>
13*91f16700Schasinglulu #include <lib/psci/psci.h>
14*91f16700Schasinglulu #include <lib/spinlock.h>
15*91f16700Schasinglulu #include <services/el3_spmc_logical_sp.h>
16*91f16700Schasinglulu #include "spm_common.h"
17*91f16700Schasinglulu 
18*91f16700Schasinglulu /*
19*91f16700Schasinglulu  * Ranges of FF-A IDs for Normal world and Secure world components. The
20*91f16700Schasinglulu  * convention matches that used by other SPMCs i.e. Hafnium and OP-TEE.
21*91f16700Schasinglulu  */
22*91f16700Schasinglulu #define FFA_NWD_ID_BASE		0x0
23*91f16700Schasinglulu #define FFA_NWD_ID_LIMIT	0x7FFF
24*91f16700Schasinglulu #define FFA_SWD_ID_BASE		0x8000
25*91f16700Schasinglulu #define FFA_SWD_ID_LIMIT	SPMD_DIRECT_MSG_ENDPOINT_ID - 1
26*91f16700Schasinglulu #define FFA_SWD_ID_MASK		0x8000
27*91f16700Schasinglulu 
28*91f16700Schasinglulu /* ID 0 is reserved for the normal world entity, (Hypervisor or OS Kernel). */
29*91f16700Schasinglulu #define FFA_NWD_ID		U(0)
30*91f16700Schasinglulu /* First ID is reserved for the SPMC */
31*91f16700Schasinglulu #define FFA_SPMC_ID		U(FFA_SWD_ID_BASE)
32*91f16700Schasinglulu /* SP IDs are allocated after the SPMC ID */
33*91f16700Schasinglulu #define FFA_SP_ID_BASE		(FFA_SPMC_ID + 1)
34*91f16700Schasinglulu /* Align with Hafnium implementation */
35*91f16700Schasinglulu #define INV_SP_ID		0x7FFF
36*91f16700Schasinglulu 
37*91f16700Schasinglulu /* FF-A Related helper macros. */
38*91f16700Schasinglulu #define FFA_ID_MASK			U(0xFFFF)
39*91f16700Schasinglulu #define FFA_PARTITION_ID_SHIFT		U(16)
40*91f16700Schasinglulu #define FFA_FEATURES_BIT31_MASK		U(0x1u << 31)
41*91f16700Schasinglulu #define FFA_FEATURES_RET_REQ_NS_BIT	U(0x1 << 1)
42*91f16700Schasinglulu 
43*91f16700Schasinglulu #define FFA_RUN_EP_ID(ep_vcpu_ids) \
44*91f16700Schasinglulu 		((ep_vcpu_ids >> FFA_PARTITION_ID_SHIFT) & FFA_ID_MASK)
45*91f16700Schasinglulu #define FFA_RUN_VCPU_ID(ep_vcpu_ids) \
46*91f16700Schasinglulu 		(ep_vcpu_ids & FFA_ID_MASK)
47*91f16700Schasinglulu 
48*91f16700Schasinglulu #define FFA_PAGE_SIZE (4096)
49*91f16700Schasinglulu #define FFA_RXTX_PAGE_COUNT_MASK 0x1F
50*91f16700Schasinglulu 
51*91f16700Schasinglulu /* Ensure that the page size used by TF-A is 4k aligned. */
52*91f16700Schasinglulu CASSERT((PAGE_SIZE % FFA_PAGE_SIZE) == 0, assert_aligned_page_size);
53*91f16700Schasinglulu 
54*91f16700Schasinglulu /*
55*91f16700Schasinglulu  * Defines to allow an SP to subscribe for power management messages
56*91f16700Schasinglulu  */
57*91f16700Schasinglulu #define FFA_PM_MSG_SUB_CPU_OFF			U(1 << 0)
58*91f16700Schasinglulu #define FFA_PM_MSG_SUB_CPU_SUSPEND		U(1 << 1)
59*91f16700Schasinglulu #define FFA_PM_MSG_SUB_CPU_SUSPEND_RESUME	U(1 << 2)
60*91f16700Schasinglulu 
61*91f16700Schasinglulu /*
62*91f16700Schasinglulu  * Runtime states of an execution context as per the FF-A v1.1 specification.
63*91f16700Schasinglulu  */
64*91f16700Schasinglulu enum sp_runtime_states {
65*91f16700Schasinglulu 	RT_STATE_WAITING,
66*91f16700Schasinglulu 	RT_STATE_RUNNING,
67*91f16700Schasinglulu 	RT_STATE_PREEMPTED,
68*91f16700Schasinglulu 	RT_STATE_BLOCKED
69*91f16700Schasinglulu };
70*91f16700Schasinglulu 
71*91f16700Schasinglulu /*
72*91f16700Schasinglulu  * Runtime model of an execution context as per the FF-A v1.1 specification. Its
73*91f16700Schasinglulu  * value is valid only if the execution context is not in the waiting state.
74*91f16700Schasinglulu  */
75*91f16700Schasinglulu enum sp_runtime_model {
76*91f16700Schasinglulu 	RT_MODEL_DIR_REQ,
77*91f16700Schasinglulu 	RT_MODEL_RUN,
78*91f16700Schasinglulu 	RT_MODEL_INIT,
79*91f16700Schasinglulu 	RT_MODEL_INTR
80*91f16700Schasinglulu };
81*91f16700Schasinglulu 
82*91f16700Schasinglulu enum sp_runtime_el {
83*91f16700Schasinglulu 	EL1 = 0,
84*91f16700Schasinglulu 	S_EL0,
85*91f16700Schasinglulu 	S_EL1
86*91f16700Schasinglulu };
87*91f16700Schasinglulu 
88*91f16700Schasinglulu enum sp_execution_state {
89*91f16700Schasinglulu 	SP_STATE_AARCH64 = 0,
90*91f16700Schasinglulu 	SP_STATE_AARCH32
91*91f16700Schasinglulu };
92*91f16700Schasinglulu 
93*91f16700Schasinglulu enum mailbox_state {
94*91f16700Schasinglulu 	/* There is no message in the mailbox. */
95*91f16700Schasinglulu 	MAILBOX_STATE_EMPTY,
96*91f16700Schasinglulu 
97*91f16700Schasinglulu 	/* There is a message that has been populated in the mailbox. */
98*91f16700Schasinglulu 	MAILBOX_STATE_FULL,
99*91f16700Schasinglulu };
100*91f16700Schasinglulu 
101*91f16700Schasinglulu struct mailbox {
102*91f16700Schasinglulu 	enum mailbox_state state;
103*91f16700Schasinglulu 
104*91f16700Schasinglulu 	/* RX/TX Buffers. */
105*91f16700Schasinglulu 	void *rx_buffer;
106*91f16700Schasinglulu 	const void *tx_buffer;
107*91f16700Schasinglulu 
108*91f16700Schasinglulu 	/* Size of RX/TX Buffer. */
109*91f16700Schasinglulu 	uint32_t rxtx_page_count;
110*91f16700Schasinglulu 
111*91f16700Schasinglulu 	/* Lock access to mailbox. */
112*91f16700Schasinglulu 	spinlock_t lock;
113*91f16700Schasinglulu };
114*91f16700Schasinglulu 
115*91f16700Schasinglulu /*
116*91f16700Schasinglulu  * Execution context members for an SP. This is a bit like struct
117*91f16700Schasinglulu  * vcpu in a hypervisor.
118*91f16700Schasinglulu  */
119*91f16700Schasinglulu struct sp_exec_ctx {
120*91f16700Schasinglulu 	/*
121*91f16700Schasinglulu 	 * Store the stack address to restore C runtime context from after
122*91f16700Schasinglulu 	 * returning from a synchronous entry into the SP.
123*91f16700Schasinglulu 	 */
124*91f16700Schasinglulu 	uint64_t c_rt_ctx;
125*91f16700Schasinglulu 
126*91f16700Schasinglulu 	/* Space to maintain the architectural state of an SP. */
127*91f16700Schasinglulu 	cpu_context_t cpu_ctx;
128*91f16700Schasinglulu 
129*91f16700Schasinglulu 	/* Track the current runtime state of the SP. */
130*91f16700Schasinglulu 	enum sp_runtime_states rt_state;
131*91f16700Schasinglulu 
132*91f16700Schasinglulu 	/* Track the current runtime model of the SP. */
133*91f16700Schasinglulu 	enum sp_runtime_model rt_model;
134*91f16700Schasinglulu 
135*91f16700Schasinglulu 	/* Track the source partition ID to validate a direct response. */
136*91f16700Schasinglulu 	uint16_t dir_req_origin_id;
137*91f16700Schasinglulu };
138*91f16700Schasinglulu 
139*91f16700Schasinglulu /*
140*91f16700Schasinglulu  * Structure to describe the cumulative properties of an SP.
141*91f16700Schasinglulu  */
142*91f16700Schasinglulu struct secure_partition_desc {
143*91f16700Schasinglulu 	/*
144*91f16700Schasinglulu 	 * Execution contexts allocated to this endpoint. Ideally,
145*91f16700Schasinglulu 	 * we need as many contexts as there are physical cpus only
146*91f16700Schasinglulu 	 * for a S-EL1 SP which is MP-pinned.
147*91f16700Schasinglulu 	 */
148*91f16700Schasinglulu 	struct sp_exec_ctx ec[PLATFORM_CORE_COUNT];
149*91f16700Schasinglulu 
150*91f16700Schasinglulu 	/* ID of the Secure Partition. */
151*91f16700Schasinglulu 	uint16_t sp_id;
152*91f16700Schasinglulu 
153*91f16700Schasinglulu 	/* Runtime EL. */
154*91f16700Schasinglulu 	enum sp_runtime_el runtime_el;
155*91f16700Schasinglulu 
156*91f16700Schasinglulu 	/* Partition UUID. */
157*91f16700Schasinglulu 	uint32_t uuid[4];
158*91f16700Schasinglulu 
159*91f16700Schasinglulu 	/* Partition Properties. */
160*91f16700Schasinglulu 	uint32_t properties;
161*91f16700Schasinglulu 
162*91f16700Schasinglulu 	/* Supported FF-A Version. */
163*91f16700Schasinglulu 	uint32_t ffa_version;
164*91f16700Schasinglulu 
165*91f16700Schasinglulu 	/* Execution State. */
166*91f16700Schasinglulu 	enum sp_execution_state execution_state;
167*91f16700Schasinglulu 
168*91f16700Schasinglulu 	/* Mailbox tracking. */
169*91f16700Schasinglulu 	struct mailbox mailbox;
170*91f16700Schasinglulu 
171*91f16700Schasinglulu 	/* Secondary entrypoint. Only valid for a S-EL1 SP. */
172*91f16700Schasinglulu 	uintptr_t secondary_ep;
173*91f16700Schasinglulu 
174*91f16700Schasinglulu 	/*
175*91f16700Schasinglulu 	 * Store whether the SP has subscribed to any power management messages.
176*91f16700Schasinglulu 	 */
177*91f16700Schasinglulu 	uint16_t pwr_mgmt_msgs;
178*91f16700Schasinglulu 
179*91f16700Schasinglulu 	/*
180*91f16700Schasinglulu 	 * Store whether the SP has requested the use of the NS bit for memory
181*91f16700Schasinglulu 	 * management transactions if it is using FF-A v1.0.
182*91f16700Schasinglulu 	 */
183*91f16700Schasinglulu 	bool ns_bit_requested;
184*91f16700Schasinglulu };
185*91f16700Schasinglulu 
186*91f16700Schasinglulu /*
187*91f16700Schasinglulu  * This define identifies the only SP that will be initialised and participate
188*91f16700Schasinglulu  * in FF-A communication. The implementation leaves the door open for more SPs
189*91f16700Schasinglulu  * to be managed in future but for now it is reasonable to assume that either a
190*91f16700Schasinglulu  * single S-EL0 or a single S-EL1 SP will be supported. This define will be used
191*91f16700Schasinglulu  * to identify which SP descriptor to initialise and manage during SP runtime.
192*91f16700Schasinglulu  */
193*91f16700Schasinglulu #define ACTIVE_SP_DESC_INDEX	0
194*91f16700Schasinglulu 
195*91f16700Schasinglulu /*
196*91f16700Schasinglulu  * Structure to describe the cumulative properties of the Hypervisor and
197*91f16700Schasinglulu  * NS-Endpoints.
198*91f16700Schasinglulu  */
199*91f16700Schasinglulu struct ns_endpoint_desc {
200*91f16700Schasinglulu 	/*
201*91f16700Schasinglulu 	 * ID of the NS-Endpoint or Hypervisor.
202*91f16700Schasinglulu 	 */
203*91f16700Schasinglulu 	uint16_t ns_ep_id;
204*91f16700Schasinglulu 
205*91f16700Schasinglulu 	/*
206*91f16700Schasinglulu 	 * Mailbox tracking.
207*91f16700Schasinglulu 	 */
208*91f16700Schasinglulu 	struct mailbox mailbox;
209*91f16700Schasinglulu 
210*91f16700Schasinglulu 	/*
211*91f16700Schasinglulu 	 * Supported FF-A Version
212*91f16700Schasinglulu 	 */
213*91f16700Schasinglulu 	uint32_t ffa_version;
214*91f16700Schasinglulu };
215*91f16700Schasinglulu 
216*91f16700Schasinglulu /* Reference to power management hooks */
217*91f16700Schasinglulu extern const spd_pm_ops_t spmc_pm;
218*91f16700Schasinglulu 
219*91f16700Schasinglulu /* Setup Function for different SP types. */
220*91f16700Schasinglulu void spmc_sp_common_setup(struct secure_partition_desc *sp,
221*91f16700Schasinglulu 			  entry_point_info_t *ep_info,
222*91f16700Schasinglulu 			  int32_t boot_info_reg);
223*91f16700Schasinglulu void spmc_el1_sp_setup(struct secure_partition_desc *sp,
224*91f16700Schasinglulu 		       entry_point_info_t *ep_info);
225*91f16700Schasinglulu void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
226*91f16700Schasinglulu 			      entry_point_info_t *ep_info);
227*91f16700Schasinglulu 
228*91f16700Schasinglulu /*
229*91f16700Schasinglulu  * Helper function to perform a synchronous entry into a SP.
230*91f16700Schasinglulu  */
231*91f16700Schasinglulu uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec);
232*91f16700Schasinglulu 
233*91f16700Schasinglulu /*
234*91f16700Schasinglulu  * Helper function to obtain the descriptor of the current SP on a physical cpu.
235*91f16700Schasinglulu  */
236*91f16700Schasinglulu struct secure_partition_desc *spmc_get_current_sp_ctx(void);
237*91f16700Schasinglulu 
238*91f16700Schasinglulu /*
239*91f16700Schasinglulu  * Helper function to obtain the execution context of an SP on a
240*91f16700Schasinglulu  * physical cpu.
241*91f16700Schasinglulu  */
242*91f16700Schasinglulu struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp);
243*91f16700Schasinglulu 
244*91f16700Schasinglulu /*
245*91f16700Schasinglulu  * Helper function to obtain the index of the execution context of an SP on a
246*91f16700Schasinglulu  * physical cpu.
247*91f16700Schasinglulu  */
248*91f16700Schasinglulu unsigned int get_ec_index(struct secure_partition_desc *sp);
249*91f16700Schasinglulu 
250*91f16700Schasinglulu uint64_t spmc_ffa_error_return(void *handle, int error_code);
251*91f16700Schasinglulu 
252*91f16700Schasinglulu /*
253*91f16700Schasinglulu  * Ensure a partition ID does not clash and follows the secure world convention.
254*91f16700Schasinglulu  */
255*91f16700Schasinglulu bool is_ffa_secure_id_valid(uint16_t partition_id);
256*91f16700Schasinglulu 
257*91f16700Schasinglulu /*
258*91f16700Schasinglulu  * Helper function to obtain the array storing the EL3
259*91f16700Schasinglulu  * Logical Partition descriptors.
260*91f16700Schasinglulu  */
261*91f16700Schasinglulu struct el3_lp_desc *get_el3_lp_array(void);
262*91f16700Schasinglulu 
263*91f16700Schasinglulu /*
264*91f16700Schasinglulu  * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor
265*91f16700Schasinglulu  * or OS kernel in the normal world or the last SP that was run.
266*91f16700Schasinglulu  */
267*91f16700Schasinglulu struct mailbox *spmc_get_mbox_desc(bool secure_origin);
268*91f16700Schasinglulu 
269*91f16700Schasinglulu /*
270*91f16700Schasinglulu  * Helper function to obtain the context of an SP with a given partition ID.
271*91f16700Schasinglulu  */
272*91f16700Schasinglulu struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id);
273*91f16700Schasinglulu 
274*91f16700Schasinglulu /*
275*91f16700Schasinglulu  * Add helper function to obtain the FF-A version of the calling
276*91f16700Schasinglulu  * partition.
277*91f16700Schasinglulu  */
278*91f16700Schasinglulu uint32_t get_partition_ffa_version(bool secure_origin);
279*91f16700Schasinglulu 
280*91f16700Schasinglulu 
281*91f16700Schasinglulu #endif /* SPMC_H */
282