summaryrefslogtreecommitdiff
path: root/common/feat_detect.c
blob: 21dd35d4e9af6ddbfcc96522719f516796cb242a (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
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
/*
 * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

#include <arch_features.h>
#include <common/debug.h>
#include <common/feat_detect.h>

static bool tainted;

/*******************************************************************************
 * This section lists the wrapper modules for each feature to evaluate the
 * feature states (FEAT_STATE_ALWAYS and FEAT_STATE_CHECK) and perform
 * necessary action as below:
 *
 * It verifies whether the FEAT_XXX (eg: FEAT_SB) is supported by the PE or not.
 * Without this check an exception would occur during context save/restore
 * routines, if the feature is enabled but not supported by PE.
 ******************************************************************************/

#define feat_detect_panic(a, b)		((a) ? (void)0 : feature_panic(b))

/*******************************************************************************
 * Function : feature_panic
 * Customised panic function with error logging mechanism to list the feature
 * not supported by the PE.
 ******************************************************************************/
static inline void feature_panic(char *feat_name)
{
	ERROR("FEAT_%s not supported by the PE\n", feat_name);
	panic();
}

/*******************************************************************************
 * Function : check_feature
 * Check for a valid combination of build time flags (ENABLE_FEAT_xxx) and
 * feature availability on the hardware.
 * Panics if a feature is forcefully enabled, but not available on the PE.
 *
 * We force inlining here to let the compiler optimise away the whole check
 * if the feature is disabled at build time (FEAT_STATE_DISABLED).
 ******************************************************************************/
static inline void __attribute((__always_inline__))
check_feature(int state, unsigned long field, const char *feat_name)
{
	if (state == FEAT_STATE_ALWAYS && field == 0U) {
		ERROR("FEAT_%s not supported by the PE\n", feat_name);
		tainted = true;
	}
}

/******************************************
 * Feature : FEAT_SB (Speculation Barrier)
 *****************************************/
static void read_feat_sb(void)
{
#if (ENABLE_FEAT_SB == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_0_feat_sb_present(), "SB");
#endif
}

/******************************************************
 * Feature : FEAT_CSV2_2 (Cache Speculation Variant 2)
 *****************************************************/
static void read_feat_csv2_2(void)
{
#if (ENABLE_FEAT_CSV2_2 == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_0_feat_csv2_2_present(), "CSV2_2");
#endif
}

/***********************************************
 * Feature : FEAT_PAN (Privileged Access Never)
 **********************************************/
static void read_feat_pan(void)
{
#if (ENABLE_FEAT_PAN == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_1_pan_present(), "PAN");
#endif
}

/******************************************************
 * Feature : FEAT_VHE (Virtualization Host Extensions)
 *****************************************************/
static void read_feat_vhe(void)
{
#if (ENABLE_FEAT_VHE == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_1_vhe_present(), "VHE");
#endif
}

/*******************************************************************************
 * Feature : FEAT_RAS (Reliability, Availability, and Serviceability Extension)
 ******************************************************************************/
static void read_feat_ras(void)
{
#if (RAS_EXTENSION == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_2_feat_ras_present(), "RAS");
#endif
}

/************************************************
 * Feature : FEAT_PAUTH (Pointer Authentication)
 ***********************************************/
static void read_feat_pauth(void)
{
#if (ENABLE_PAUTH == FEAT_STATE_ALWAYS) || (CTX_INCLUDE_PAUTH_REGS == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_3_pauth_present(), "PAUTH");
#endif
}

/************************************************************
 * Feature : FEAT_DIT (Data Independent Timing Instructions)
 ***********************************************************/
static void read_feat_dit(void)
{
#if (ENABLE_FEAT_DIT == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_4_feat_dit_present(), "DIT");
#endif
}

/*********************************************************
 * Feature : FEAT_AMUv1 (Activity Monitors Extensions v1)
 ********************************************************/
static void read_feat_amuv1(void)
{
#if (ENABLE_FEAT_AMUv1 == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_4_feat_amuv1_present(), "AMUv1");
#endif
}

/****************************************************************************
 * Feature : FEAT_MPAM (Memory Partitioning and Monitoring (MPAM) Extension)
 ***************************************************************************/
static void read_feat_mpam(void)
{
#if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_ALWAYS)
	feat_detect_panic(get_mpam_version() != 0U, "MPAM");
#endif
}

/**************************************************************
 * Feature : FEAT_NV2 (Enhanced Nested Virtualization Support)
 *************************************************************/
static void read_feat_nv2(void)
{
#if (CTX_INCLUDE_NEVE_REGS == FEAT_STATE_ALWAYS)
	unsigned int nv = get_armv8_4_feat_nv_support();

	feat_detect_panic((nv == ID_AA64MMFR2_EL1_NV2_SUPPORTED), "NV2");
#endif
}

/***********************************
 * Feature : FEAT_SEL2 (Secure EL2)
 **********************************/
static void read_feat_sel2(void)
{
#if (ENABLE_FEAT_SEL2 == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_4_sel2_present(), "SEL2");
#endif
}

/****************************************************
 * Feature : FEAT_TRF (Self-hosted Trace Extensions)
 ***************************************************/
static void read_feat_trf(void)
{
#if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_arm8_4_feat_trf_present(), "TRF");
#endif
}

/************************************************
 * Feature : FEAT_MTE (Memory Tagging Extension)
 ***********************************************/
static void read_feat_mte(void)
{
#if (CTX_INCLUDE_MTE_REGS == FEAT_STATE_ALWAYS)
	unsigned int mte = get_armv8_5_mte_support();

	feat_detect_panic((mte != MTE_UNIMPLEMENTED), "MTE");
#endif
}

/***********************************************
 * Feature : FEAT_RNG (Random Number Generator)
 **********************************************/
static void read_feat_rng(void)
{
#if (ENABLE_FEAT_RNG == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_5_rng_present(), "RNG");
#endif
}

/****************************************************
 * Feature : FEAT_BTI (Branch Target Identification)
 ***************************************************/
static void read_feat_bti(void)
{
#if (ENABLE_BTI == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_5_bti_present(), "BTI");
#endif
}

/***********************************************
 * Feature : FEAT_AMUv1p1 (AMU Extensions v1.1)
 **********************************************/
static void read_feat_amuv1p1(void)
{
#if (ENABLE_FEAT_AMUv1p1 == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_6_feat_amuv1p1_present(), "AMUv1p1");
#endif
}

/*******************************************************
 * Feature : FEAT_ECV (Enhanced Counter Virtualization)
 ******************************************************/
static void read_feat_ecv(void)
{
#if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS)
	unsigned int ecv = get_armv8_6_ecv_support();

	feat_detect_panic(((ecv == ID_AA64MMFR0_EL1_ECV_SUPPORTED) ||
			(ecv == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH)), "ECV");
#endif
}

/***********************************************************
 * Feature : FEAT_TWED (Delayed Trapping of WFE Instruction)
 **********************************************************/
static void read_feat_twed(void)
{
#if (ENABLE_FEAT_TWED == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_armv8_6_twed_present(), "TWED");
#endif
}

/******************************************************************
 * Feature : FEAT_HCX (Extended Hypervisor Configuration Register)
 *****************************************************************/
static void read_feat_hcx(void)
{
#if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_feat_hcx_present(), "HCX");
#endif
}

/**************************************************
 * Feature : FEAT_RME (Realm Management Extension)
 *************************************************/
static void read_feat_rme(void)
{
#if (ENABLE_RME == FEAT_STATE_ALWAYS)
	feat_detect_panic((get_armv9_2_feat_rme_support() !=
			ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED), "RME");
#endif
}

/******************************************************
 * Feature : FEAT_BRBE (Branch Record Buffer Extension)
 *****************************************************/
static void read_feat_brbe(void)
{
#if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_feat_brbe_present(), "BRBE");
#endif
}

/******************************************************
 * Feature : FEAT_TRBE (Trace Buffer Extension)
 *****************************************************/
static void read_feat_trbe(void)
{
#if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_feat_trbe_present(), "TRBE");
#endif
}

/******************************************************************
 * Feature : FEAT_RNG_TRAP (Trapping support for RNDR/RNDRRS)
 *****************************************************************/
static void read_feat_rng_trap(void)
{
#if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_ALWAYS)
	feat_detect_panic(is_feat_rng_trap_present(), "RNG_TRAP");
#endif
}

/***********************************************************************************
 * TF-A supports many Arm architectural features starting from arch version
 * (8.0 till 8.7+). These features are mostly enabled through build flags. This
 * mechanism helps in validating these build flags in the early boot phase
 * either in BL1 or BL31 depending on the platform and assists in identifying
 * and notifying the features which are enabled but not supported by the PE.
 *
 * It reads all the enabled features ID-registers and ensures the features
 * are supported by the PE.
 * In case if they aren't it stops booting at an early phase and logs the error
 * messages, notifying the platforms about the features that are not supported.
 *
 * Further the procedure is implemented with a tri-state approach for each feature:
 * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time
 * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware.
 *                       There will be panic if feature is not present at cold boot.
 * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime
 *                       depending on hardware capability.
 *
 * For better readability, state values are defined with macros, namely:
 * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values
 * { 0, 1, 2 }, respectively, as their naming.
 **********************************************************************************/
void detect_arch_features(void)
{
	tainted = false;

	/* v8.0 features */
	read_feat_sb();
	read_feat_csv2_2();

	/* v8.1 features */
	read_feat_pan();
	read_feat_vhe();

	/* v8.2 features */
	read_feat_ras();

	/* v8.3 features */
	read_feat_pauth();

	/* v8.4 features */
	read_feat_dit();
	read_feat_amuv1();
	read_feat_mpam();
	read_feat_nv2();
	read_feat_sel2();
	read_feat_trf();

	/* v8.5 features */
	read_feat_mte();
	read_feat_rng();
	read_feat_bti();
	read_feat_rng_trap();

	/* v8.6 features */
	read_feat_amuv1p1();
	check_feature(ENABLE_FEAT_FGT, is_armv8_6_fgt_present(), "FGT");
	read_feat_ecv();
	read_feat_twed();

	/* v8.7 features */
	read_feat_hcx();

	/* v9.0 features */
	read_feat_brbe();
	read_feat_trbe();

	/* v9.2 features */
	read_feat_rme();

	if (tainted) {
		panic();
	}
}