xref: /rk3399_ARM-atf/common/feat_detect.c (revision f90fe02f061b8a203391e566682221396b656c6f)
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_RME (Realm Management Extension)
233  *************************************************/
234 static void read_feat_rme(void)
235 {
236 #if (ENABLE_RME == FEAT_STATE_ALWAYS)
237 	feat_detect_panic((get_armv9_2_feat_rme_support() !=
238 			ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED), "RME");
239 #endif
240 }
241 
242 /******************************************************
243  * Feature : FEAT_BRBE (Branch Record Buffer Extension)
244  *****************************************************/
245 static void read_feat_brbe(void)
246 {
247 #if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS)
248 	feat_detect_panic(is_feat_brbe_present(), "BRBE");
249 #endif
250 }
251 
252 /******************************************************
253  * Feature : FEAT_TRBE (Trace Buffer Extension)
254  *****************************************************/
255 static void read_feat_trbe(void)
256 {
257 #if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS)
258 	feat_detect_panic(is_feat_trbe_present(), "TRBE");
259 #endif
260 }
261 
262 /******************************************************************
263  * Feature : FEAT_RNG_TRAP (Trapping support for RNDR/RNDRRS)
264  *****************************************************************/
265 static void read_feat_rng_trap(void)
266 {
267 #if (ENABLE_FEAT_RNG_TRAP == FEAT_STATE_ALWAYS)
268 	feat_detect_panic(is_feat_rng_trap_present(), "RNG_TRAP");
269 #endif
270 }
271 
272 /***********************************************************************************
273  * TF-A supports many Arm architectural features starting from arch version
274  * (8.0 till 8.7+). These features are mostly enabled through build flags. This
275  * mechanism helps in validating these build flags in the early boot phase
276  * either in BL1 or BL31 depending on the platform and assists in identifying
277  * and notifying the features which are enabled but not supported by the PE.
278  *
279  * It reads all the enabled features ID-registers and ensures the features
280  * are supported by the PE.
281  * In case if they aren't it stops booting at an early phase and logs the error
282  * messages, notifying the platforms about the features that are not supported.
283  *
284  * Further the procedure is implemented with a tri-state approach for each feature:
285  * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time
286  * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware.
287  *                       There will be panic if feature is not present at cold boot.
288  * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime
289  *                       depending on hardware capability.
290  *
291  * For better readability, state values are defined with macros, namely:
292  * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values
293  * { 0, 1, 2 }, respectively, as their naming.
294  **********************************************************************************/
295 void detect_arch_features(void)
296 {
297 	tainted = false;
298 
299 	/* v8.0 features */
300 	read_feat_sb();
301 	read_feat_csv2_2();
302 
303 	/* v8.1 features */
304 	read_feat_pan();
305 	read_feat_vhe();
306 
307 	/* v8.2 features */
308 	read_feat_ras();
309 
310 	/* v8.3 features */
311 	read_feat_pauth();
312 
313 	/* v8.4 features */
314 	read_feat_dit();
315 	check_feature(ENABLE_FEAT_AMUv1, read_feat_amu_id_field(), "AMUv1");
316 	read_feat_mpam();
317 	read_feat_nv2();
318 	read_feat_sel2();
319 	read_feat_trf();
320 
321 	/* v8.5 features */
322 	read_feat_mte();
323 	read_feat_rng();
324 	read_feat_bti();
325 	read_feat_rng_trap();
326 
327 	/* v8.6 features */
328 	read_feat_amuv1p1();
329 	check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), "FGT");
330 	read_feat_ecv();
331 	read_feat_twed();
332 
333 	/* v8.7 features */
334 	check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), "HCX");
335 
336 	/* v9.0 features */
337 	read_feat_brbe();
338 	read_feat_trbe();
339 
340 	/* v9.2 features */
341 	read_feat_rme();
342 
343 	if (tainted) {
344 		panic();
345 	}
346 }
347