xref: /rk3399_ARM-atf/common/feat_detect.c (revision bb7b85a397f4eddef84b2deaa8f3f7a66cb3a09b)
1 /*
2  * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <arch_features.h>
8 #include <common/debug.h>
9 #include <common/feat_detect.h>
10 
11 static bool tainted;
12 
13 /*******************************************************************************
14  * This section lists the wrapper modules for each feature to evaluate the
15  * feature states (FEAT_STATE_ALWAYS and FEAT_STATE_CHECK) and perform
16  * necessary action as below:
17  *
18  * It verifies whether the FEAT_XXX (eg: FEAT_SB) is supported by the PE or not.
19  * Without this check an exception would occur during context save/restore
20  * routines, if the feature is enabled but not supported by PE.
21  ******************************************************************************/
22 
23 #define feat_detect_panic(a, b)		((a) ? (void)0 : feature_panic(b))
24 
25 /*******************************************************************************
26  * Function : feature_panic
27  * Customised panic function with error logging mechanism to list the feature
28  * not supported by the PE.
29  ******************************************************************************/
30 static inline void feature_panic(char *feat_name)
31 {
32 	ERROR("FEAT_%s not supported by the PE\n", feat_name);
33 	panic();
34 }
35 
36 /*******************************************************************************
37  * Function : check_feature
38  * Check for a valid combination of build time flags (ENABLE_FEAT_xxx) and
39  * feature availability on the hardware.
40  * Panics if a feature is forcefully enabled, but not available on the PE.
41  *
42  * We force inlining here to let the compiler optimise away the whole check
43  * if the feature is disabled at build time (FEAT_STATE_DISABLED).
44  ******************************************************************************/
45 static inline void __attribute((__always_inline__))
46 check_feature(int state, unsigned long field, const char *feat_name)
47 {
48 	if (state == FEAT_STATE_ALWAYS && field == 0U) {
49 		ERROR("FEAT_%s not supported by the PE\n", feat_name);
50 		tainted = true;
51 	}
52 }
53 
54 /******************************************
55  * Feature : FEAT_SB (Speculation Barrier)
56  *****************************************/
57 static void read_feat_sb(void)
58 {
59 #if (ENABLE_FEAT_SB == FEAT_STATE_ALWAYS)
60 	feat_detect_panic(is_armv8_0_feat_sb_present(), "SB");
61 #endif
62 }
63 
64 /******************************************************
65  * Feature : FEAT_CSV2_2 (Cache Speculation Variant 2)
66  *****************************************************/
67 static void read_feat_csv2_2(void)
68 {
69 #if (ENABLE_FEAT_CSV2_2 == FEAT_STATE_ALWAYS)
70 	feat_detect_panic(is_armv8_0_feat_csv2_2_present(), "CSV2_2");
71 #endif
72 }
73 
74 /***********************************************
75  * Feature : FEAT_PAN (Privileged Access Never)
76  **********************************************/
77 static void read_feat_pan(void)
78 {
79 #if (ENABLE_FEAT_PAN == FEAT_STATE_ALWAYS)
80 	feat_detect_panic(is_armv8_1_pan_present(), "PAN");
81 #endif
82 }
83 
84 /******************************************************
85  * Feature : FEAT_VHE (Virtualization Host Extensions)
86  *****************************************************/
87 static void read_feat_vhe(void)
88 {
89 #if (ENABLE_FEAT_VHE == FEAT_STATE_ALWAYS)
90 	feat_detect_panic(is_armv8_1_vhe_present(), "VHE");
91 #endif
92 }
93 
94 /*******************************************************************************
95  * Feature : FEAT_RAS (Reliability, Availability, and Serviceability Extension)
96  ******************************************************************************/
97 static void read_feat_ras(void)
98 {
99 #if (RAS_EXTENSION == FEAT_STATE_ALWAYS)
100 	feat_detect_panic(is_armv8_2_feat_ras_present(), "RAS");
101 #endif
102 }
103 
104 /************************************************
105  * Feature : FEAT_PAUTH (Pointer Authentication)
106  ***********************************************/
107 static void read_feat_pauth(void)
108 {
109 #if (ENABLE_PAUTH == FEAT_STATE_ALWAYS) || (CTX_INCLUDE_PAUTH_REGS == FEAT_STATE_ALWAYS)
110 	feat_detect_panic(is_armv8_3_pauth_present(), "PAUTH");
111 #endif
112 }
113 
114 /************************************************************
115  * Feature : FEAT_DIT (Data Independent Timing Instructions)
116  ***********************************************************/
117 static void read_feat_dit(void)
118 {
119 #if (ENABLE_FEAT_DIT == FEAT_STATE_ALWAYS)
120 	feat_detect_panic(is_armv8_4_feat_dit_present(), "DIT");
121 #endif
122 }
123 
124 /****************************************************************************
125  * Feature : FEAT_MPAM (Memory Partitioning and Monitoring (MPAM) Extension)
126  ***************************************************************************/
127 static void read_feat_mpam(void)
128 {
129 #if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_ALWAYS)
130 	feat_detect_panic(get_mpam_version() != 0U, "MPAM");
131 #endif
132 }
133 
134 /**************************************************************
135  * Feature : FEAT_NV2 (Enhanced Nested Virtualization Support)
136  *************************************************************/
137 static void read_feat_nv2(void)
138 {
139 #if (CTX_INCLUDE_NEVE_REGS == FEAT_STATE_ALWAYS)
140 	unsigned int nv = get_armv8_4_feat_nv_support();
141 
142 	feat_detect_panic((nv == ID_AA64MMFR2_EL1_NV2_SUPPORTED), "NV2");
143 #endif
144 }
145 
146 /***********************************
147  * Feature : FEAT_SEL2 (Secure EL2)
148  **********************************/
149 static void read_feat_sel2(void)
150 {
151 #if (ENABLE_FEAT_SEL2 == FEAT_STATE_ALWAYS)
152 	feat_detect_panic(is_armv8_4_sel2_present(), "SEL2");
153 #endif
154 }
155 
156 /****************************************************
157  * Feature : FEAT_TRF (Self-hosted Trace Extensions)
158  ***************************************************/
159 static void read_feat_trf(void)
160 {
161 #if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS)
162 	feat_detect_panic(is_arm8_4_feat_trf_present(), "TRF");
163 #endif
164 }
165 
166 /************************************************
167  * Feature : FEAT_MTE (Memory Tagging Extension)
168  ***********************************************/
169 static void read_feat_mte(void)
170 {
171 #if (CTX_INCLUDE_MTE_REGS == FEAT_STATE_ALWAYS)
172 	unsigned int mte = get_armv8_5_mte_support();
173 
174 	feat_detect_panic((mte != MTE_UNIMPLEMENTED), "MTE");
175 #endif
176 }
177 
178 /***********************************************
179  * Feature : FEAT_RNG (Random Number Generator)
180  **********************************************/
181 static void read_feat_rng(void)
182 {
183 #if (ENABLE_FEAT_RNG == FEAT_STATE_ALWAYS)
184 	feat_detect_panic(is_armv8_5_rng_present(), "RNG");
185 #endif
186 }
187 
188 /****************************************************
189  * Feature : FEAT_BTI (Branch Target Identification)
190  ***************************************************/
191 static void read_feat_bti(void)
192 {
193 #if (ENABLE_BTI == FEAT_STATE_ALWAYS)
194 	feat_detect_panic(is_armv8_5_bti_present(), "BTI");
195 #endif
196 }
197 
198 /***********************************************
199  * Feature : FEAT_AMUv1p1 (AMU Extensions v1.1)
200  **********************************************/
201 static void read_feat_amuv1p1(void)
202 {
203 #if (ENABLE_FEAT_AMUv1p1 == FEAT_STATE_ALWAYS)
204 	feat_detect_panic(is_armv8_6_feat_amuv1p1_present(), "AMUv1p1");
205 #endif
206 }
207 
208 /*******************************************************
209  * Feature : FEAT_ECV (Enhanced Counter Virtualization)
210  ******************************************************/
211 static void read_feat_ecv(void)
212 {
213 #if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS)
214 	unsigned int ecv = get_armv8_6_ecv_support();
215 
216 	feat_detect_panic(((ecv == ID_AA64MMFR0_EL1_ECV_SUPPORTED) ||
217 			(ecv == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH)), "ECV");
218 #endif
219 }
220 
221 /***********************************************************
222  * Feature : FEAT_TWED (Delayed Trapping of WFE Instruction)
223  **********************************************************/
224 static void read_feat_twed(void)
225 {
226 #if (ENABLE_FEAT_TWED == FEAT_STATE_ALWAYS)
227 	feat_detect_panic(is_armv8_6_twed_present(), "TWED");
228 #endif
229 }
230 
231 /******************************************************************
232  * Feature : FEAT_HCX (Extended Hypervisor Configuration Register)
233  *****************************************************************/
234 static void read_feat_hcx(void)
235 {
236 #if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS)
237 	feat_detect_panic(is_feat_hcx_present(), "HCX");
238 #endif
239 }
240 
241 /**************************************************
242  * Feature : FEAT_RME (Realm Management Extension)
243  *************************************************/
244 static void read_feat_rme(void)
245 {
246 #if (ENABLE_RME == FEAT_STATE_ALWAYS)
247 	feat_detect_panic((get_armv9_2_feat_rme_support() !=
248 			ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED), "RME");
249 #endif
250 }
251 
252 /******************************************************
253  * Feature : FEAT_BRBE (Branch Record Buffer Extension)
254  *****************************************************/
255 static void read_feat_brbe(void)
256 {
257 #if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
258 	feat_detect_panic(is_feat_brbe_present(), "BRBE");
259 #endif
260 }
261 
262 /******************************************************
263  * Feature : FEAT_TRBE (Trace Buffer Extension)
264  *****************************************************/
265 static void read_feat_trbe(void)
266 {
267 #if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS)
268 	feat_detect_panic(is_feat_trbe_present(), "TRBE");
269 #endif
270 }
271 
272 /******************************************************************
273  * Feature : FEAT_RNG_TRAP (Trapping support for RNDR/RNDRRS)
274  *****************************************************************/
275 static void read_feat_rng_trap(void)
276 {
277 #if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_ALWAYS)
278 	feat_detect_panic(is_feat_rng_trap_present(), "RNG_TRAP");
279 #endif
280 }
281 
282 /***********************************************************************************
283  * TF-A supports many Arm architectural features starting from arch version
284  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
285  * mechanism helps in validating these build flags in the early boot phase
286  * either in BL1 or BL31 depending on the platform and assists in identifying
287  * and notifying the features which are enabled but not supported by the PE.
288  *
289  * It reads all the enabled features ID-registers and ensures the features
290  * are supported by the PE.
291  * In case if they aren't it stops booting at an early phase and logs the error
292  * messages, notifying the platforms about the features that are not supported.
293  *
294  * Further the procedure is implemented with a tri-state approach for each feature:
295  * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time
296  * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware.
297  *                       There will be panic if feature is not present at cold boot.
298  * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime
299  *                       depending on hardware capability.
300  *
301  * For better readability, state values are defined with macros, namely:
302  * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values
303  * { 0, 1, 2 }, respectively, as their naming.
304  **********************************************************************************/
305 void detect_arch_features(void)
306 {
307 	tainted = false;
308 
309 	/* v8.0 features */
310 	read_feat_sb();
311 	read_feat_csv2_2();
312 
313 	/* v8.1 features */
314 	read_feat_pan();
315 	read_feat_vhe();
316 
317 	/* v8.2 features */
318 	read_feat_ras();
319 
320 	/* v8.3 features */
321 	read_feat_pauth();
322 
323 	/* v8.4 features */
324 	read_feat_dit();
325 	check_feature(ENABLE_FEAT_AMUv1, read_feat_amu_id_field(), "AMUv1");
326 	read_feat_mpam();
327 	read_feat_nv2();
328 	read_feat_sel2();
329 	read_feat_trf();
330 
331 	/* v8.5 features */
332 	read_feat_mte();
333 	read_feat_rng();
334 	read_feat_bti();
335 	read_feat_rng_trap();
336 
337 	/* v8.6 features */
338 	read_feat_amuv1p1();
339 	check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT");
340 	read_feat_ecv();
341 	read_feat_twed();
342 
343 	/* v8.7 features */
344 	read_feat_hcx();
345 
346 	/* v9.0 features */
347 	read_feat_brbe();
348 	read_feat_trbe();
349 
350 	/* v9.2 features */
351 	read_feat_rme();
352 
353 	if (tainted) {
354 		panic();
355 	}
356 }
357