xref: /rk3399_ARM-atf/common/feat_detect.c (revision b45dd74e3a1b125eb231a873c663e92da797b7fa)
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_AMUv1 (Activity Monitors Extensions v1)
126  ********************************************************/
127 static void read_feat_amuv1(void)
128 {
129 #if (ENABLE_FEAT_AMUv1 == FEAT_STATE_ALWAYS)
130 	feat_detect_panic(is_armv8_4_feat_amuv1_present(), "AMUv1");
131 #endif
132 }
133 
134 /****************************************************************************
135  * Feature : FEAT_MPAM (Memory Partitioning and Monitoring (MPAM) Extension)
136  ***************************************************************************/
137 static void read_feat_mpam(void)
138 {
139 #if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_ALWAYS)
140 	feat_detect_panic(get_mpam_version() != 0U, "MPAM");
141 #endif
142 }
143 
144 /**************************************************************
145  * Feature : FEAT_NV2 (Enhanced Nested Virtualization Support)
146  *************************************************************/
147 static void read_feat_nv2(void)
148 {
149 #if (CTX_INCLUDE_NEVE_REGS == FEAT_STATE_ALWAYS)
150 	unsigned int nv = get_armv8_4_feat_nv_support();
151 
152 	feat_detect_panic((nv == ID_AA64MMFR2_EL1_NV2_SUPPORTED), "NV2");
153 #endif
154 }
155 
156 /***********************************
157  * Feature : FEAT_SEL2 (Secure EL2)
158  **********************************/
159 static void read_feat_sel2(void)
160 {
161 #if (ENABLE_FEAT_SEL2 == FEAT_STATE_ALWAYS)
162 	feat_detect_panic(is_armv8_4_sel2_present(), "SEL2");
163 #endif
164 }
165 
166 /****************************************************
167  * Feature : FEAT_TRF (Self-hosted Trace Extensions)
168  ***************************************************/
169 static void read_feat_trf(void)
170 {
171 #if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS)
172 	feat_detect_panic(is_arm8_4_feat_trf_present(), "TRF");
173 #endif
174 }
175 
176 /************************************************
177  * Feature : FEAT_MTE (Memory Tagging Extension)
178  ***********************************************/
179 static void read_feat_mte(void)
180 {
181 #if (CTX_INCLUDE_MTE_REGS == FEAT_STATE_ALWAYS)
182 	unsigned int mte = get_armv8_5_mte_support();
183 
184 	feat_detect_panic((mte != MTE_UNIMPLEMENTED), "MTE");
185 #endif
186 }
187 
188 /***********************************************
189  * Feature : FEAT_RNG (Random Number Generator)
190  **********************************************/
191 static void read_feat_rng(void)
192 {
193 #if (ENABLE_FEAT_RNG == FEAT_STATE_ALWAYS)
194 	feat_detect_panic(is_armv8_5_rng_present(), "RNG");
195 #endif
196 }
197 
198 /****************************************************
199  * Feature : FEAT_BTI (Branch Target Identification)
200  ***************************************************/
201 static void read_feat_bti(void)
202 {
203 #if (ENABLE_BTI == FEAT_STATE_ALWAYS)
204 	feat_detect_panic(is_armv8_5_bti_present(), "BTI");
205 #endif
206 }
207 
208 /***********************************************
209  * Feature : FEAT_AMUv1p1 (AMU Extensions v1.1)
210  **********************************************/
211 static void read_feat_amuv1p1(void)
212 {
213 #if (ENABLE_FEAT_AMUv1p1 == FEAT_STATE_ALWAYS)
214 	feat_detect_panic(is_armv8_6_feat_amuv1p1_present(), "AMUv1p1");
215 #endif
216 }
217 
218 /*******************************************************
219  * Feature : FEAT_ECV (Enhanced Counter Virtualization)
220  ******************************************************/
221 static void read_feat_ecv(void)
222 {
223 #if (ENABLE_FEAT_ECV == FEAT_STATE_ALWAYS)
224 	unsigned int ecv = get_armv8_6_ecv_support();
225 
226 	feat_detect_panic(((ecv == ID_AA64MMFR0_EL1_ECV_SUPPORTED) ||
227 			(ecv == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH)), "ECV");
228 #endif
229 }
230 
231 /***********************************************************
232  * Feature : FEAT_TWED (Delayed Trapping of WFE Instruction)
233  **********************************************************/
234 static void read_feat_twed(void)
235 {
236 #if (ENABLE_FEAT_TWED == FEAT_STATE_ALWAYS)
237 	feat_detect_panic(is_armv8_6_twed_present(), "TWED");
238 #endif
239 }
240 
241 /******************************************************************
242  * Feature : FEAT_HCX (Extended Hypervisor Configuration Register)
243  *****************************************************************/
244 static void read_feat_hcx(void)
245 {
246 #if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS)
247 	feat_detect_panic(is_feat_hcx_present(), "HCX");
248 #endif
249 }
250 
251 /**************************************************
252  * Feature : FEAT_RME (Realm Management Extension)
253  *************************************************/
254 static void read_feat_rme(void)
255 {
256 #if (ENABLE_RME == FEAT_STATE_ALWAYS)
257 	feat_detect_panic((get_armv9_2_feat_rme_support() !=
258 			ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED), "RME");
259 #endif
260 }
261 
262 /******************************************************
263  * Feature : FEAT_BRBE (Branch Record Buffer Extension)
264  *****************************************************/
265 static void read_feat_brbe(void)
266 {
267 #if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
268 	feat_detect_panic(is_feat_brbe_present(), "BRBE");
269 #endif
270 }
271 
272 /******************************************************
273  * Feature : FEAT_TRBE (Trace Buffer Extension)
274  *****************************************************/
275 static void read_feat_trbe(void)
276 {
277 #if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS)
278 	feat_detect_panic(is_feat_trbe_present(), "TRBE");
279 #endif
280 }
281 
282 /******************************************************************
283  * Feature : FEAT_RNG_TRAP (Trapping support for RNDR/RNDRRS)
284  *****************************************************************/
285 static void read_feat_rng_trap(void)
286 {
287 #if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_ALWAYS)
288 	feat_detect_panic(is_feat_rng_trap_present(), "RNG_TRAP");
289 #endif
290 }
291 
292 /***********************************************************************************
293  * TF-A supports many Arm architectural features starting from arch version
294  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
295  * mechanism helps in validating these build flags in the early boot phase
296  * either in BL1 or BL31 depending on the platform and assists in identifying
297  * and notifying the features which are enabled but not supported by the PE.
298  *
299  * It reads all the enabled features ID-registers and ensures the features
300  * are supported by the PE.
301  * In case if they aren't it stops booting at an early phase and logs the error
302  * messages, notifying the platforms about the features that are not supported.
303  *
304  * Further the procedure is implemented with a tri-state approach for each feature:
305  * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time
306  * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware.
307  *                       There will be panic if feature is not present at cold boot.
308  * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime
309  *                       depending on hardware capability.
310  *
311  * For better readability, state values are defined with macros, namely:
312  * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values
313  * { 0, 1, 2 }, respectively, as their naming.
314  **********************************************************************************/
315 void detect_arch_features(void)
316 {
317 	tainted = false;
318 
319 	/* v8.0 features */
320 	read_feat_sb();
321 	read_feat_csv2_2();
322 
323 	/* v8.1 features */
324 	read_feat_pan();
325 	read_feat_vhe();
326 
327 	/* v8.2 features */
328 	read_feat_ras();
329 
330 	/* v8.3 features */
331 	read_feat_pauth();
332 
333 	/* v8.4 features */
334 	read_feat_dit();
335 	read_feat_amuv1();
336 	read_feat_mpam();
337 	read_feat_nv2();
338 	read_feat_sel2();
339 	read_feat_trf();
340 
341 	/* v8.5 features */
342 	read_feat_mte();
343 	read_feat_rng();
344 	read_feat_bti();
345 	read_feat_rng_trap();
346 
347 	/* v8.6 features */
348 	read_feat_amuv1p1();
349 	check_feature(ENABLE_FEAT_FGT, is_armv8_6_fgt_present(), "FGT");
350 	read_feat_ecv();
351 	read_feat_twed();
352 
353 	/* v8.7 features */
354 	read_feat_hcx();
355 
356 	/* v9.0 features */
357 	read_feat_brbe();
358 	read_feat_trbe();
359 
360 	/* v9.2 features */
361 	read_feat_rme();
362 
363 	if (tainted) {
364 		panic();
365 	}
366 }
367