summaryrefslogtreecommitdiffstats
path: root/include/lib/gpt_rme/gpt_rme.h
blob: 94a88b0d5b2be6323d58db2becad30a14e87638f (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
/*
 * Copyright (c) 2022, Arm Limited. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#ifndef GPT_RME_H
#define GPT_RME_H

#include <stdint.h>

#include <arch.h>

/******************************************************************************/
/* GPT helper macros and definitions                                          */
/******************************************************************************/

/*
 * Structure for specifying a mapping range and it's properties. This should not
 * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as
 * to avoid potential incompatibilities in the future.
 */
typedef struct pas_region {
	uintptr_t	base_pa;	/* Base address for PAS. */
	size_t		size;		/* Size of the PAS. */
	unsigned int	attrs;		/* PAS GPI and entry type. */
} pas_region_t;

/* GPT GPI definitions */
#define GPT_GPI_NO_ACCESS		U(0x0)
#define GPT_GPI_SECURE			U(0x8)
#define GPT_GPI_NS			U(0x9)
#define GPT_GPI_ROOT			U(0xA)
#define GPT_GPI_REALM			U(0xB)
#define GPT_GPI_ANY			U(0xF)
#define GPT_GPI_VAL_MASK		UL(0xF)

#define GPT_NSE_SECURE			U(0b00)
#define GPT_NSE_ROOT			U(0b01)
#define GPT_NSE_NS			U(0b10)
#define GPT_NSE_REALM			U(0b11)

#define GPT_NSE_SHIFT                   U(62)

/* PAS attribute GPI definitions. */
#define GPT_PAS_ATTR_GPI_SHIFT		U(0)
#define GPT_PAS_ATTR_GPI_MASK		U(0xF)
#define GPT_PAS_ATTR_GPI(_attrs)	(((_attrs)			\
					>> GPT_PAS_ATTR_GPI_SHIFT)	\
					& GPT_PAS_ATTR_GPI_MASK)

/* PAS attribute mapping type definitions */
#define GPT_PAS_ATTR_MAP_TYPE_BLOCK	U(0x0)
#define GPT_PAS_ATTR_MAP_TYPE_GRANULE	U(0x1)
#define GPT_PAS_ATTR_MAP_TYPE_SHIFT	U(4)
#define GPT_PAS_ATTR_MAP_TYPE_MASK	U(0x1)
#define GPT_PAS_ATTR_MAP_TYPE(_attrs)	(((_attrs)			\
					>> GPT_PAS_ATTR_MAP_TYPE_SHIFT)	\
					& GPT_PAS_ATTR_MAP_TYPE_MASK)

/*
 * Macro to initialize the attributes field in the pas_region_t structure.
 * [31:5] Reserved
 * [4]    Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions)
 * [3:0]  PAS GPI type (GPT_GPI_x definitions)
 */
#define GPT_PAS_ATTR(_type, _gpi)					\
	((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK)			\
	  << GPT_PAS_ATTR_MAP_TYPE_SHIFT) |				\
	(((_gpi) & GPT_PAS_ATTR_GPI_MASK)				\
	 << GPT_PAS_ATTR_GPI_SHIFT))

/*
 * Macro to create a GPT entry for this PAS range as a block descriptor. If this
 * region does not fit the requirements for a block descriptor then GPT
 * initialization will fail.
 */
#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi)				\
	{								\
		.base_pa = (_pa),					\
		.size = (_sz),						\
		.attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \
	}

/*
 * Macro to create a GPT entry for this PAS range as a table descriptor. If this
 * region does not fit the requirements for a table descriptor then GPT
 * initialization will fail.
 */
#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi)				\
	{								\
		.base_pa = (_pa),					\
		.size = (_sz),						\
		.attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \
	}

/******************************************************************************/
/* GPT register field definitions                                             */
/******************************************************************************/

/*
 * Least significant address bits protected by each entry in level 0 GPT. This
 * field is read-only.
 */
#define GPCCR_L0GPTSZ_SHIFT	U(20)
#define GPCCR_L0GPTSZ_MASK	U(0xF)

typedef enum {
	GPCCR_L0GPTSZ_30BITS	= U(0x0),
	GPCCR_L0GPTSZ_34BITS	= U(0x4),
	GPCCR_L0GPTSZ_36BITS	= U(0x6),
	GPCCR_L0GPTSZ_39BITS	= U(0x9)
} gpccr_l0gptsz_e;

/* Granule protection check priority bit definitions */
#define GPCCR_GPCP_SHIFT	U(17)
#define GPCCR_GPCP_BIT		(ULL(1) << GPCCR_EL3_GPCP_SHIFT)

/* Granule protection check bit definitions */
#define GPCCR_GPC_SHIFT		U(16)
#define GPCCR_GPC_BIT		(ULL(1) << GPCCR_GPC_SHIFT)

/* Physical granule size bit definitions */
#define GPCCR_PGS_SHIFT		U(14)
#define GPCCR_PGS_MASK		U(0x3)
#define SET_GPCCR_PGS(x)	(((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT)

typedef enum {
	GPCCR_PGS_4K		= U(0x0),
	GPCCR_PGS_64K		= U(0x1),
	GPCCR_PGS_16K		= U(0x2)
} gpccr_pgs_e;

/* GPT fetch shareability attribute bit definitions */
#define GPCCR_SH_SHIFT		U(12)
#define GPCCR_SH_MASK		U(0x3)
#define SET_GPCCR_SH(x)		(((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT)

typedef enum {
	GPCCR_SH_NS		= U(0x0),
	GPCCR_SH_OS		= U(0x2),
	GPCCR_SH_IS		= U(0x3)
} gpccr_sh_e;

/* GPT fetch outer cacheability attribute bit definitions */
#define GPCCR_ORGN_SHIFT	U(10)
#define GPCCR_ORGN_MASK		U(0x3)
#define SET_GPCCR_ORGN(x)	(((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT)

typedef enum {
	GPCCR_ORGN_NC		= U(0x0),
	GPCCR_ORGN_WB_RA_WA	= U(0x1),
	GPCCR_ORGN_WT_RA_NWA	= U(0x2),
	GPCCR_ORGN_WB_RA_NWA	= U(0x3)
} gpccr_orgn_e;

/* GPT fetch inner cacheability attribute bit definitions */
#define GPCCR_IRGN_SHIFT	U(8)
#define GPCCR_IRGN_MASK		U(0x3)
#define SET_GPCCR_IRGN(x)	(((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT)

typedef enum {
	GPCCR_IRGN_NC		= U(0x0),
	GPCCR_IRGN_WB_RA_WA	= U(0x1),
	GPCCR_IRGN_WT_RA_NWA	= U(0x2),
	GPCCR_IRGN_WB_RA_NWA	= U(0x3)
} gpccr_irgn_e;

/* Protected physical address size bit definitions */
#define GPCCR_PPS_SHIFT		U(0)
#define GPCCR_PPS_MASK		U(0x7)
#define SET_GPCCR_PPS(x)	(((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT)

typedef enum {
	GPCCR_PPS_4GB		= U(0x0),
	GPCCR_PPS_64GB		= U(0x1),
	GPCCR_PPS_1TB		= U(0x2),
	GPCCR_PPS_4TB		= U(0x3),
	GPCCR_PPS_16TB		= U(0x4),
	GPCCR_PPS_256TB		= U(0x5),
	GPCCR_PPS_4PB		= U(0x6)
} gpccr_pps_e;

/* Base Address for the GPT bit definitions */
#define GPTBR_BADDR_SHIFT	U(0)
#define GPTBR_BADDR_VAL_SHIFT	U(12)
#define GPTBR_BADDR_MASK	ULL(0xffffffffff)

/******************************************************************************/
/* GPT public APIs                                                            */
/******************************************************************************/

/*
 * Public API that initializes the entire protected space to GPT_GPI_ANY using
 * the L0 tables (block descriptors).  Ideally, this function is invoked prior
 * to DDR discovery and initialization.  The MMU must be initialized before
 * calling this function.
 *
 * Parameters
 *   pps		PPS value to use for table generation
 *   l0_mem_base	Base address of L0 tables in memory.
 *   l0_mem_size	Total size of memory available for L0 tables.
 *
 * Return
 *   Negative Linux error code in the event of a failure, 0 for success.
 */
int gpt_init_l0_tables(gpccr_pps_e pps,
		       uintptr_t l0_mem_base,
		       size_t l0_mem_size);

/*
 * Public API that carves out PAS regions from the L0 tables and builds any L1
 * tables that are needed.  This function ideally is run after DDR discovery and
 * initialization.  The L0 tables must have already been initialized to GPI_ANY
 * when this function is called.
 *
 * Parameters
 *   pgs		PGS value to use for table generation.
 *   l1_mem_base	Base address of memory used for L1 tables.
 *   l1_mem_size	Total size of memory available for L1 tables.
 *   *pas_regions	Pointer to PAS regions structure array.
 *   pas_count		Total number of PAS regions.
 *
 * Return
 *   Negative Linux error code in the event of a failure, 0 for success.
 */
int gpt_init_pas_l1_tables(gpccr_pgs_e pgs,
			   uintptr_t l1_mem_base,
			   size_t l1_mem_size,
			   pas_region_t *pas_regions,
			   unsigned int pas_count);

/*
 * Public API to initialize the runtime gpt_config structure based on the values
 * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization
 * typically happens in a bootloader stage prior to setting up the EL3 runtime
 * environment for the granule transition service so this function detects the
 * initialization from a previous stage. Granule protection checks must be
 * enabled already or this function will return an error.
 *
 * Return
 *   Negative Linux error code in the event of a failure, 0 for success.
 */
int gpt_runtime_init(void);

/*
 * Public API to enable granule protection checks once the tables have all been
 * initialized.  This function is called at first initialization and then again
 * later during warm boots of CPU cores.
 *
 * Return
 *   Negative Linux error code in the event of a failure, 0 for success.
 */
int gpt_enable(void);

/*
 * Public API to disable granule protection checks.
 */
void gpt_disable(void);

/*
 * This function is the core of the granule transition service. When a granule
 * transition request occurs it is routed to this function where the request is
 * validated then fulfilled if possible.
 *
 * TODO: implement support for transitioning multiple granules at once.
 *
 * Parameters
 *   base: Base address of the region to transition, must be aligned to granule
 *         size.
 *   size: Size of region to transition, must be aligned to granule size.
 *   src_sec_state: Security state of the originating SMC invoking the API.
 *
 * Return
 *    Negative Linux error code in the event of a failure, 0 for success.
 */
int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state);
int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state);

#endif /* GPT_RME_H */