summaryrefslogtreecommitdiffstats
path: root/services/std_svc/spm/el3_spmc/spmc.h
blob: 523365002ed4b73be115649359cefd8b8d67329f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
/*
 * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef SPMC_H
#define SPMC_H

#include <stdint.h>

#include <common/bl_common.h>
#include <lib/psci/psci.h>
#include <lib/spinlock.h>
#include <services/el3_spmc_logical_sp.h>
#include "spm_common.h"

/*
 * Ranges of FF-A IDs for Normal world and Secure world components. The
 * convention matches that used by other SPMCs i.e. Hafnium and OP-TEE.
 */
#define FFA_NWD_ID_BASE		0x0
#define FFA_NWD_ID_LIMIT	0x7FFF
#define FFA_SWD_ID_BASE		0x8000
#define FFA_SWD_ID_LIMIT	SPMD_DIRECT_MSG_ENDPOINT_ID - 1
#define FFA_SWD_ID_MASK		0x8000

/* ID 0 is reserved for the normal world entity, (Hypervisor or OS Kernel). */
#define FFA_NWD_ID		U(0)
/* First ID is reserved for the SPMC */
#define FFA_SPMC_ID		U(FFA_SWD_ID_BASE)
/* SP IDs are allocated after the SPMC ID */
#define FFA_SP_ID_BASE		(FFA_SPMC_ID + 1)
/* Align with Hafnium implementation */
#define INV_SP_ID		0x7FFF

/* FF-A Related helper macros. */
#define FFA_ID_MASK			U(0xFFFF)
#define FFA_PARTITION_ID_SHIFT		U(16)
#define FFA_FEATURES_BIT31_MASK		U(0x1u << 31)
#define FFA_FEATURES_RET_REQ_NS_BIT	U(0x1 << 1)

#define FFA_RUN_EP_ID(ep_vcpu_ids) \
		((ep_vcpu_ids >> FFA_PARTITION_ID_SHIFT) & FFA_ID_MASK)
#define FFA_RUN_VCPU_ID(ep_vcpu_ids) \
		(ep_vcpu_ids & FFA_ID_MASK)

#define FFA_PAGE_SIZE (4096)
#define FFA_RXTX_PAGE_COUNT_MASK 0x1F

/* Ensure that the page size used by TF-A is 4k aligned. */
CASSERT((PAGE_SIZE % FFA_PAGE_SIZE) == 0, assert_aligned_page_size);

/*
 * Defines to allow an SP to subscribe for power management messages
 */
#define FFA_PM_MSG_SUB_CPU_OFF			U(1 << 0)
#define FFA_PM_MSG_SUB_CPU_SUSPEND		U(1 << 1)
#define FFA_PM_MSG_SUB_CPU_SUSPEND_RESUME	U(1 << 2)

/*
 * Runtime states of an execution context as per the FF-A v1.1 specification.
 */
enum sp_runtime_states {
	RT_STATE_WAITING,
	RT_STATE_RUNNING,
	RT_STATE_PREEMPTED,
	RT_STATE_BLOCKED
};

/*
 * Runtime model of an execution context as per the FF-A v1.1 specification. Its
 * value is valid only if the execution context is not in the waiting state.
 */
enum sp_runtime_model {
	RT_MODEL_DIR_REQ,
	RT_MODEL_RUN,
	RT_MODEL_INIT,
	RT_MODEL_INTR
};

enum sp_runtime_el {
	EL1 = 0,
	S_EL0,
	S_EL1
};

enum sp_execution_state {
	SP_STATE_AARCH64 = 0,
	SP_STATE_AARCH32
};

enum mailbox_state {
	/* There is no message in the mailbox. */
	MAILBOX_STATE_EMPTY,

	/* There is a message that has been populated in the mailbox. */
	MAILBOX_STATE_FULL,
};

struct mailbox {
	enum mailbox_state state;

	/* RX/TX Buffers. */
	void *rx_buffer;
	const void *tx_buffer;

	/* Size of RX/TX Buffer. */
	uint32_t rxtx_page_count;

	/* Lock access to mailbox. */
	spinlock_t lock;
};

/*
 * Execution context members for an SP. This is a bit like struct
 * vcpu in a hypervisor.
 */
struct sp_exec_ctx {
	/*
	 * Store the stack address to restore C runtime context from after
	 * returning from a synchronous entry into the SP.
	 */
	uint64_t c_rt_ctx;

	/* Space to maintain the architectural state of an SP. */
	cpu_context_t cpu_ctx;

	/* Track the current runtime state of the SP. */
	enum sp_runtime_states rt_state;

	/* Track the current runtime model of the SP. */
	enum sp_runtime_model rt_model;
};

/*
 * Structure to describe the cumulative properties of an SP.
 */
struct secure_partition_desc {
	/*
	 * Execution contexts allocated to this endpoint. Ideally,
	 * we need as many contexts as there are physical cpus only
	 * for a S-EL1 SP which is MP-pinned.
	 */
	struct sp_exec_ctx ec[PLATFORM_CORE_COUNT];

	/* ID of the Secure Partition. */
	uint16_t sp_id;

	/* Runtime EL. */
	enum sp_runtime_el runtime_el;

	/* Partition UUID. */
	uint32_t uuid[4];

	/* Partition Properties. */
	uint32_t properties;

	/* Supported FF-A Version. */
	uint32_t ffa_version;

	/* Execution State. */
	enum sp_execution_state execution_state;

	/* Mailbox tracking. */
	struct mailbox mailbox;

	/* Secondary entrypoint. Only valid for a S-EL1 SP. */
	uintptr_t secondary_ep;

	/*
	 * Store whether the SP has subscribed to any power management messages.
	 */
	uint16_t pwr_mgmt_msgs;

	/*
	 * Store whether the SP has requested the use of the NS bit for memory
	 * management transactions if it is using FF-A v1.0.
	 */
	bool ns_bit_requested;
};

/*
 * This define identifies the only SP that will be initialised and participate
 * in FF-A communication. The implementation leaves the door open for more SPs
 * to be managed in future but for now it is reasonable to assume that either a
 * single S-EL0 or a single S-EL1 SP will be supported. This define will be used
 * to identify which SP descriptor to initialise and manage during SP runtime.
 */
#define ACTIVE_SP_DESC_INDEX	0

/*
 * Structure to describe the cumulative properties of the Hypervisor and
 * NS-Endpoints.
 */
struct ns_endpoint_desc {
	/*
	 * ID of the NS-Endpoint or Hypervisor.
	 */
	uint16_t ns_ep_id;

	/*
	 * Mailbox tracking.
	 */
	struct mailbox mailbox;

	/*
	 * Supported FF-A Version
	 */
	uint32_t ffa_version;
};

/**
 * Holds information returned for each partition by the FFA_PARTITION_INFO_GET
 * interface.
 */
struct ffa_partition_info_v1_0 {
	uint16_t ep_id;
	uint16_t execution_ctx_count;
	uint32_t properties;
};

/* Extended structure for v1.1. */
struct ffa_partition_info_v1_1 {
	uint16_t ep_id;
	uint16_t execution_ctx_count;
	uint32_t properties;
	uint32_t uuid[4];
};

/* Reference to power management hooks */
extern const spd_pm_ops_t spmc_pm;

/* Setup Function for different SP types. */
void spmc_sp_common_setup(struct secure_partition_desc *sp,
			  entry_point_info_t *ep_info,
			  int32_t boot_info_reg);
void spmc_el1_sp_setup(struct secure_partition_desc *sp,
		       entry_point_info_t *ep_info);
void spmc_sp_common_ep_commit(struct secure_partition_desc *sp,
			      entry_point_info_t *ep_info);

/*
 * Helper function to perform a synchronous entry into a SP.
 */
uint64_t spmc_sp_synchronous_entry(struct sp_exec_ctx *ec);

/*
 * Helper function to obtain the descriptor of the current SP on a physical cpu.
 */
struct secure_partition_desc *spmc_get_current_sp_ctx(void);

/*
 * Helper function to obtain the execution context of an SP on a
 * physical cpu.
 */
struct sp_exec_ctx *spmc_get_sp_ec(struct secure_partition_desc *sp);

/*
 * Helper function to obtain the index of the execution context of an SP on a
 * physical cpu.
 */
unsigned int get_ec_index(struct secure_partition_desc *sp);

uint64_t spmc_ffa_error_return(void *handle, int error_code);

/*
 * Ensure a partition ID does not clash and follows the secure world convention.
 */
bool is_ffa_secure_id_valid(uint16_t partition_id);

/*
 * Helper function to obtain the array storing the EL3
 * Logical Partition descriptors.
 */
struct el3_lp_desc *get_el3_lp_array(void);

/*
 * Helper function to obtain the RX/TX buffer pair descriptor of the Hypervisor
 * or OS kernel in the normal world or the last SP that was run.
 */
struct mailbox *spmc_get_mbox_desc(bool secure_origin);

/*
 * Helper function to obtain the context of an SP with a given partition ID.
 */
struct secure_partition_desc *spmc_get_sp_ctx(uint16_t id);

/*
 * Add helper function to obtain the FF-A version of the calling
 * partition.
 */
uint32_t get_partition_ffa_version(bool secure_origin);


#endif /* SPMC_H */