feat_detect.c 11 KB

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