Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 1 | /* |
Boyan Karatotev | b0b7609 | 2025-04-01 13:50:56 +0100 | [diff] [blame] | 2 | * Copyright (c) 2022-2025, Arm Limited and Contributors. All rights reserved. |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 3 | * |
| 4 | * SPDX-License-Identifier: BSD-3-Clause |
| 5 | */ |
| 6 | |
Andre Przywara | 69c17f5 | 2022-11-14 15:38:58 +0000 | [diff] [blame] | 7 | #include <arch_features.h> |
| 8 | #include <common/debug.h> |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 9 | #include <common/feat_detect.h> |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 10 | #include <plat/common/platform.h> |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 11 | |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 12 | static bool detection_done[PLATFORM_CORE_COUNT] = { false }; |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 13 | |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 14 | /******************************************************************************* |
| 15 | * This section lists the wrapper modules for each feature to evaluate the |
Andre Przywara | 69c17f5 | 2022-11-14 15:38:58 +0000 | [diff] [blame] | 16 | * feature states (FEAT_STATE_ALWAYS and FEAT_STATE_CHECK) and perform |
| 17 | * necessary action as below: |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 18 | * |
| 19 | * It verifies whether the FEAT_XXX (eg: FEAT_SB) is supported by the PE or not. |
| 20 | * Without this check an exception would occur during context save/restore |
| 21 | * routines, if the feature is enabled but not supported by PE. |
| 22 | ******************************************************************************/ |
| 23 | |
Andre Przywara | 69c17f5 | 2022-11-14 15:38:58 +0000 | [diff] [blame] | 24 | #define feat_detect_panic(a, b) ((a) ? (void)0 : feature_panic(b)) |
| 25 | |
| 26 | /******************************************************************************* |
| 27 | * Function : feature_panic |
| 28 | * Customised panic function with error logging mechanism to list the feature |
| 29 | * not supported by the PE. |
| 30 | ******************************************************************************/ |
| 31 | static inline void feature_panic(char *feat_name) |
| 32 | { |
| 33 | ERROR("FEAT_%s not supported by the PE\n", feat_name); |
| 34 | panic(); |
| 35 | } |
| 36 | |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 37 | /******************************************************************************* |
| 38 | * Function : check_feature |
| 39 | * Check for a valid combination of build time flags (ENABLE_FEAT_xxx) and |
Andre Przywara | a4cccb4 | 2023-02-01 11:46:31 +0000 | [diff] [blame] | 40 | * feature availability on the hardware. <min> is the smallest feature |
| 41 | * ID field value that is required for that feature. |
| 42 | * Triggers a panic later if a feature is forcefully enabled, but not |
| 43 | * available on the PE. Also will panic if the hardware feature ID field |
| 44 | * is larger than the maximum known and supported number, specified by <max>. |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 45 | * |
| 46 | * We force inlining here to let the compiler optimise away the whole check |
| 47 | * if the feature is disabled at build time (FEAT_STATE_DISABLED). |
| 48 | ******************************************************************************/ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 49 | static inline bool __attribute((__always_inline__)) |
Andre Przywara | a4cccb4 | 2023-02-01 11:46:31 +0000 | [diff] [blame] | 50 | check_feature(int state, unsigned long field, const char *feat_name, |
| 51 | unsigned int min, unsigned int max) |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 52 | { |
Andre Przywara | a4cccb4 | 2023-02-01 11:46:31 +0000 | [diff] [blame] | 53 | if (state == FEAT_STATE_ALWAYS && field < min) { |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 54 | ERROR("FEAT_%s not supported by the PE\n", feat_name); |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 55 | return true; |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 56 | } |
Andre Przywara | a4cccb4 | 2023-02-01 11:46:31 +0000 | [diff] [blame] | 57 | if (state >= FEAT_STATE_ALWAYS && field > max) { |
| 58 | ERROR("FEAT_%s is version %ld, but is only known up to version %d\n", |
| 59 | feat_name, field, max); |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 60 | return true; |
Andre Przywara | a4cccb4 | 2023-02-01 11:46:31 +0000 | [diff] [blame] | 61 | } |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 62 | |
| 63 | return false; |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 64 | } |
| 65 | |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 66 | static unsigned int read_feat_rng_trap_id_field(void) |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 67 | { |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 68 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT, |
| 69 | ID_AA64PFR1_EL1_RNDR_TRAP_MASK); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 70 | } |
| 71 | |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 72 | static unsigned int read_feat_bti_id_field(void) |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 73 | { |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 74 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_BT_SHIFT, |
| 75 | ID_AA64PFR1_EL1_BT_MASK); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 76 | } |
| 77 | |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 78 | static unsigned int read_feat_sb_id_field(void) |
Juan Pablo Conde | ff86e0b | 2022-07-12 16:40:29 -0400 | [diff] [blame] | 79 | { |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 80 | return ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_SB_SHIFT, |
| 81 | ID_AA64ISAR1_SB_MASK); |
| 82 | } |
| 83 | |
| 84 | static unsigned int read_feat_csv2_id_field(void) |
| 85 | { |
| 86 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_CSV2_SHIFT, |
| 87 | ID_AA64PFR0_CSV2_MASK); |
| 88 | } |
| 89 | |
Arvind Ram Prakash | 83271d5 | 2024-05-22 15:24:00 -0500 | [diff] [blame] | 90 | static unsigned int read_feat_debugv8p9_id_field(void) |
| 91 | { |
| 92 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_DEBUGVER_SHIFT, |
| 93 | ID_AA64DFR0_DEBUGVER_MASK); |
| 94 | } |
| 95 | |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 96 | static unsigned int read_feat_pmuv3_id_field(void) |
| 97 | { |
| 98 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_PMUVER_SHIFT, |
| 99 | ID_AA64DFR0_PMUVER_MASK); |
| 100 | } |
| 101 | |
| 102 | static unsigned int read_feat_vhe_id_field(void) |
| 103 | { |
| 104 | return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_VHE_SHIFT, |
| 105 | ID_AA64MMFR1_EL1_VHE_MASK); |
| 106 | } |
| 107 | |
| 108 | static unsigned int read_feat_sve_id_field(void) |
| 109 | { |
| 110 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_SVE_SHIFT, |
| 111 | ID_AA64PFR0_SVE_MASK); |
| 112 | } |
| 113 | |
| 114 | static unsigned int read_feat_ras_id_field(void) |
| 115 | { |
| 116 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_RAS_SHIFT, |
| 117 | ID_AA64PFR0_RAS_MASK); |
| 118 | } |
| 119 | |
| 120 | static unsigned int read_feat_dit_id_field(void) |
| 121 | { |
| 122 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_DIT_SHIFT, |
| 123 | ID_AA64PFR0_DIT_MASK); |
| 124 | } |
| 125 | |
| 126 | static unsigned int read_feat_amu_id_field(void) |
| 127 | { |
| 128 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_AMU_SHIFT, |
| 129 | ID_AA64PFR0_AMU_MASK); |
| 130 | } |
| 131 | |
| 132 | static unsigned int read_feat_mpam_version(void) |
| 133 | { |
| 134 | return (unsigned int)((((read_id_aa64pfr0_el1() >> |
| 135 | ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) | |
| 136 | ((read_id_aa64pfr1_el1() >> |
| 137 | ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK)); |
| 138 | } |
| 139 | |
| 140 | static unsigned int read_feat_nv_id_field(void) |
| 141 | { |
| 142 | return ISOLATE_FIELD(read_id_aa64mmfr2_el1(), ID_AA64MMFR2_EL1_NV_SHIFT, |
| 143 | ID_AA64MMFR2_EL1_NV_MASK); |
| 144 | } |
| 145 | |
| 146 | static unsigned int read_feat_sel2_id_field(void) |
| 147 | { |
| 148 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_SEL2_SHIFT, |
| 149 | ID_AA64PFR0_SEL2_MASK); |
| 150 | } |
| 151 | |
| 152 | static unsigned int read_feat_trf_id_field(void) |
| 153 | { |
| 154 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEFILT_SHIFT, |
| 155 | ID_AA64DFR0_TRACEFILT_MASK); |
| 156 | } |
| 157 | static unsigned int get_armv8_5_mte_support(void) |
| 158 | { |
| 159 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_MTE_SHIFT, |
| 160 | ID_AA64PFR1_EL1_MTE_MASK); |
| 161 | } |
| 162 | static unsigned int read_feat_rng_id_field(void) |
| 163 | { |
| 164 | return ISOLATE_FIELD(read_id_aa64isar0_el1(), ID_AA64ISAR0_RNDR_SHIFT, |
| 165 | ID_AA64ISAR0_RNDR_MASK); |
| 166 | } |
| 167 | static unsigned int read_feat_fgt_id_field(void) |
| 168 | { |
| 169 | return ISOLATE_FIELD(read_id_aa64mmfr0_el1(), ID_AA64MMFR0_EL1_FGT_SHIFT, |
| 170 | ID_AA64MMFR0_EL1_FGT_MASK); |
| 171 | } |
| 172 | static unsigned int read_feat_ecv_id_field(void) |
| 173 | { |
| 174 | return ISOLATE_FIELD(read_id_aa64mmfr0_el1(), ID_AA64MMFR0_EL1_ECV_SHIFT, |
| 175 | ID_AA64MMFR0_EL1_ECV_MASK); |
| 176 | } |
| 177 | static unsigned int read_feat_twed_id_field(void) |
| 178 | { |
| 179 | return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_TWED_SHIFT, |
| 180 | ID_AA64MMFR1_EL1_TWED_MASK); |
| 181 | } |
| 182 | |
| 183 | static unsigned int read_feat_hcx_id_field(void) |
| 184 | { |
| 185 | return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_HCX_SHIFT, |
| 186 | ID_AA64MMFR1_EL1_HCX_MASK); |
| 187 | } |
Andre Przywara | 19d52a8 | 2024-08-09 17:04:22 +0100 | [diff] [blame] | 188 | static unsigned int read_feat_ls64_id_field(void) |
| 189 | { |
| 190 | return ISOLATE_FIELD(read_id_aa64isar1_el1(), ID_AA64ISAR1_LS64_SHIFT, |
| 191 | ID_AA64ISAR1_LS64_MASK); |
| 192 | } |
Sona Mathew | 011829b | 2024-04-19 00:24:18 -0500 | [diff] [blame] | 193 | static unsigned int read_feat_tcr2_id_field(void) |
| 194 | { |
| 195 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_TCRX_SHIFT, |
| 196 | ID_AA64MMFR3_EL1_TCRX_MASK); |
| 197 | } |
| 198 | static unsigned int read_feat_s2pie_id_field(void) |
| 199 | { |
| 200 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2PIE_SHIFT, |
| 201 | ID_AA64MMFR3_EL1_S2PIE_MASK); |
| 202 | } |
| 203 | static unsigned int read_feat_s1pie_id_field(void) |
| 204 | { |
| 205 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1PIE_SHIFT, |
| 206 | ID_AA64MMFR3_EL1_S1PIE_MASK); |
| 207 | } |
| 208 | static unsigned int read_feat_s2poe_id_field(void) |
| 209 | { |
| 210 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S2POE_SHIFT, |
| 211 | ID_AA64MMFR3_EL1_S2POE_MASK); |
| 212 | } |
| 213 | static unsigned int read_feat_s1poe_id_field(void) |
| 214 | { |
| 215 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_S1POE_SHIFT, |
| 216 | ID_AA64MMFR3_EL1_S1POE_MASK); |
| 217 | } |
| 218 | static unsigned int read_feat_brbe_id_field(void) |
| 219 | { |
| 220 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_BRBE_SHIFT, |
| 221 | ID_AA64DFR0_BRBE_MASK); |
| 222 | } |
| 223 | static unsigned int read_feat_trbe_id_field(void) |
| 224 | { |
| 225 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEBUFFER_SHIFT, |
| 226 | ID_AA64DFR0_TRACEBUFFER_MASK); |
| 227 | } |
| 228 | static unsigned int read_feat_sme_id_field(void) |
| 229 | { |
| 230 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_SME_SHIFT, |
| 231 | ID_AA64PFR1_EL1_SME_MASK); |
| 232 | } |
| 233 | static unsigned int read_feat_gcs_id_field(void) |
| 234 | { |
| 235 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_GCS_SHIFT, |
| 236 | ID_AA64PFR1_EL1_GCS_MASK); |
| 237 | } |
| 238 | |
| 239 | static unsigned int read_feat_rme_id_field(void) |
| 240 | { |
| 241 | return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_FEAT_RME_SHIFT, |
| 242 | ID_AA64PFR0_FEAT_RME_MASK); |
| 243 | } |
| 244 | |
| 245 | static unsigned int read_feat_pan_id_field(void) |
| 246 | { |
| 247 | return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_PAN_SHIFT, |
| 248 | ID_AA64MMFR1_EL1_PAN_MASK); |
| 249 | } |
| 250 | |
| 251 | static unsigned int read_feat_mtpmu_id_field(void) |
| 252 | { |
| 253 | return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_MTPMU_SHIFT, |
| 254 | ID_AA64DFR0_MTPMU_MASK); |
| 255 | |
Juan Pablo Conde | ff86e0b | 2022-07-12 16:40:29 -0400 | [diff] [blame] | 256 | } |
| 257 | |
Jayanth Dodderi Chidanand | 6d0433f | 2024-09-05 22:24:04 +0100 | [diff] [blame] | 258 | static unsigned int read_feat_the_id_field(void) |
| 259 | { |
| 260 | return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_THE_SHIFT, |
| 261 | ID_AA64PFR1_EL1_THE_MASK); |
| 262 | } |
| 263 | |
Jayanth Dodderi Chidanand | 4ec4e54 | 2024-09-06 13:49:31 +0100 | [diff] [blame] | 264 | static unsigned int read_feat_sctlr2_id_field(void) |
| 265 | { |
| 266 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_SCTLR2_SHIFT, |
| 267 | ID_AA64MMFR3_EL1_SCTLR2_MASK); |
| 268 | } |
| 269 | |
Govindraj Raja | 3065513 | 2024-09-06 15:43:43 +0100 | [diff] [blame] | 270 | static unsigned int read_feat_d128_id_field(void) |
| 271 | { |
| 272 | return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_D128_SHIFT, |
| 273 | ID_AA64MMFR3_EL1_D128_MASK); |
| 274 | } |
Boyan Karatotev | 8cef63d | 2025-01-07 11:26:56 +0000 | [diff] [blame] | 275 | static unsigned int read_feat_gcie_id_field(void) |
| 276 | { |
| 277 | return ISOLATE_FIELD(read_id_aa64pfr2_el1(), ID_AA64PFR2_EL1_GCIE_SHIFT, |
| 278 | ID_AA64PFR2_EL1_GCIE_MASK); |
| 279 | } |
Govindraj Raja | 3065513 | 2024-09-06 15:43:43 +0100 | [diff] [blame] | 280 | |
Arvind Ram Prakash | a57e18e | 2024-11-11 14:32:37 -0600 | [diff] [blame] | 281 | static unsigned int read_feat_fpmr_id_field(void) |
| 282 | { |
| 283 | return ISOLATE_FIELD(read_id_aa64pfr2_el1(), ID_AA64PFR2_EL1_FPMR_SHIFT, |
| 284 | ID_AA64PFR2_EL1_FPMR_MASK); |
| 285 | } |
| 286 | |
Arvind Ram Prakash | 6b8df7b | 2025-01-09 17:18:30 -0600 | [diff] [blame] | 287 | static unsigned int read_feat_mops_id_field(void) |
| 288 | { |
| 289 | return ISOLATE_FIELD(read_id_aa64isar2_el1(), ID_AA64ISAR2_EL1_MOPS_SHIFT, |
| 290 | ID_AA64ISAR2_EL1_MOPS_MASK); |
| 291 | } |
| 292 | |
Arvind Ram Prakash | 4274b52 | 2025-06-23 15:21:44 -0500 | [diff] [blame] | 293 | static unsigned int read_feat_fgwte3_id_field(void) |
| 294 | { |
| 295 | return ISOLATE_FIELD(read_id_aa64mmfr4_el1(), ID_AA64MMFR4_EL1_FGWTE3_SHIFT, |
| 296 | ID_AA64MMFR4_EL1_FGWTE3_MASK); |
| 297 | } |
| 298 | |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 299 | /*********************************************************************************** |
| 300 | * TF-A supports many Arm architectural features starting from arch version |
| 301 | * (8.0 till 8.7+). These features are mostly enabled through build flags. This |
| 302 | * mechanism helps in validating these build flags in the early boot phase |
| 303 | * either in BL1 or BL31 depending on the platform and assists in identifying |
| 304 | * and notifying the features which are enabled but not supported by the PE. |
| 305 | * |
| 306 | * It reads all the enabled features ID-registers and ensures the features |
| 307 | * are supported by the PE. |
| 308 | * In case if they aren't it stops booting at an early phase and logs the error |
| 309 | * messages, notifying the platforms about the features that are not supported. |
| 310 | * |
| 311 | * Further the procedure is implemented with a tri-state approach for each feature: |
| 312 | * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time |
| 313 | * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware. |
| 314 | * There will be panic if feature is not present at cold boot. |
| 315 | * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at runtime |
| 316 | * depending on hardware capability. |
| 317 | * |
Andre Przywara | 69c17f5 | 2022-11-14 15:38:58 +0000 | [diff] [blame] | 318 | * For better readability, state values are defined with macros, namely: |
| 319 | * { FEAT_STATE_DISABLED, FEAT_STATE_ALWAYS, FEAT_STATE_CHECK }, taking values |
| 320 | * { 0, 1, 2 }, respectively, as their naming. |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 321 | **********************************************************************************/ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 322 | void detect_arch_features(unsigned int core_pos) |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 323 | { |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 324 | /* No need to keep checking after the first time for each core. */ |
| 325 | if (detection_done[core_pos]) { |
| 326 | return; |
| 327 | } |
| 328 | |
| 329 | bool tainted = false; |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 330 | |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 331 | /* v8.0 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 332 | tainted |= check_feature(ENABLE_FEAT_SB, read_feat_sb_id_field(), |
| 333 | "SB", 1, 1); |
| 334 | tainted |= check_feature(ENABLE_FEAT_CSV2_2, read_feat_csv2_id_field(), |
| 335 | "CSV2_2", 2, 3); |
Boyan Karatotev | c73686a | 2023-02-15 13:21:50 +0000 | [diff] [blame] | 336 | /* |
| 337 | * Even though the PMUv3 is an OPTIONAL feature, it is always |
| 338 | * implemented and Arm prescribes so. So assume it will be there and do |
| 339 | * away with a flag for it. This is used to check minor PMUv3px |
| 340 | * revisions so that we catch them as they come along |
| 341 | */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 342 | tainted |= check_feature(FEAT_STATE_ALWAYS, read_feat_pmuv3_id_field(), |
| 343 | "PMUv3", 1, ID_AA64DFR0_PMUVER_PMUV3P9); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 344 | |
| 345 | /* v8.1 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 346 | tainted |= check_feature(ENABLE_FEAT_PAN, read_feat_pan_id_field(), |
| 347 | "PAN", 1, 3); |
| 348 | tainted |= check_feature(ENABLE_FEAT_VHE, read_feat_vhe_id_field(), |
| 349 | "VHE", 1, 1); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 350 | |
| 351 | /* v8.2 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 352 | tainted |= check_feature(ENABLE_SVE_FOR_NS, read_feat_sve_id_field(), |
| 353 | "SVE", 1, 1); |
| 354 | tainted |= check_feature(ENABLE_FEAT_RAS, read_feat_ras_id_field(), |
| 355 | "RAS", 1, 2); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 356 | |
| 357 | /* v8.3 features */ |
Boyan Karatotev | e293fca | 2025-07-03 15:25:55 +0100 | [diff] [blame] | 358 | /* the PAuth fields are very complicated, no min/max is checked */ |
| 359 | tainted |= check_feature(ENABLE_PAUTH, is_feat_pauth_present(), |
| 360 | "PAUTH", 1, 1); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 361 | |
| 362 | /* v8.4 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 363 | tainted |= check_feature(ENABLE_FEAT_DIT, read_feat_dit_id_field(), |
| 364 | "DIT", 1, 1); |
| 365 | tainted |= check_feature(ENABLE_FEAT_AMU, read_feat_amu_id_field(), |
| 366 | "AMUv1", 1, 2); |
| 367 | tainted |= check_feature(ENABLE_FEAT_MOPS, read_feat_mops_id_field(), |
| 368 | "MOPS", 1, 1); |
| 369 | tainted |= check_feature(ENABLE_FEAT_MPAM, read_feat_mpam_version(), |
| 370 | "MPAM", 1, 17); |
| 371 | tainted |= check_feature(CTX_INCLUDE_NEVE_REGS, read_feat_nv_id_field(), |
| 372 | "NV2", 2, 2); |
| 373 | tainted |= check_feature(ENABLE_FEAT_SEL2, read_feat_sel2_id_field(), |
| 374 | "SEL2", 1, 1); |
| 375 | tainted |= check_feature(ENABLE_TRF_FOR_NS, read_feat_trf_id_field(), |
| 376 | "TRF", 1, 1); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 377 | |
| 378 | /* v8.5 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 379 | tainted |= check_feature(ENABLE_FEAT_MTE2, get_armv8_5_mte_support(), |
| 380 | "MTE2", MTE_IMPLEMENTED_ELX, MTE_IMPLEMENTED_ASY); |
| 381 | tainted |= check_feature(ENABLE_FEAT_RNG, read_feat_rng_id_field(), |
| 382 | "RNG", 1, 1); |
| 383 | tainted |= check_feature(ENABLE_BTI, read_feat_bti_id_field(), |
| 384 | "BTI", 1, 1); |
| 385 | tainted |= check_feature(ENABLE_FEAT_RNG_TRAP, read_feat_rng_trap_id_field(), |
| 386 | "RNG_TRAP", 1, 1); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 387 | |
| 388 | /* v8.6 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 389 | tainted |= check_feature(ENABLE_FEAT_AMUv1p1, read_feat_amu_id_field(), |
| 390 | "AMUv1p1", 2, 2); |
| 391 | tainted |= check_feature(ENABLE_FEAT_FGT, read_feat_fgt_id_field(), |
| 392 | "FGT", 1, 2); |
| 393 | tainted |= check_feature(ENABLE_FEAT_FGT2, read_feat_fgt_id_field(), |
| 394 | "FGT2", 2, 2); |
| 395 | tainted |= check_feature(ENABLE_FEAT_ECV, read_feat_ecv_id_field(), |
| 396 | "ECV", 1, 2); |
| 397 | tainted |= check_feature(ENABLE_FEAT_TWED, read_feat_twed_id_field(), |
| 398 | "TWED", 1, 1); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 399 | |
Boyan Karatotev | 83a4dae | 2023-02-16 09:45:29 +0000 | [diff] [blame] | 400 | /* |
| 401 | * even though this is a "DISABLE" it does confusingly perform feature |
| 402 | * enablement duties like all other flags here. Check it against the HW |
| 403 | * feature when we intend to diverge from the default behaviour |
| 404 | */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 405 | tainted |= check_feature(DISABLE_MTPMU, read_feat_mtpmu_id_field(), |
| 406 | "MTPMU", 1, 1); |
Boyan Karatotev | 83a4dae | 2023-02-16 09:45:29 +0000 | [diff] [blame] | 407 | |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 408 | /* v8.7 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 409 | tainted |= check_feature(ENABLE_FEAT_HCX, read_feat_hcx_id_field(), |
| 410 | "HCX", 1, 1); |
| 411 | tainted |= check_feature(ENABLE_FEAT_LS64_ACCDATA, read_feat_ls64_id_field(), |
| 412 | "LS64", 1, 3); |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 413 | |
Mark Brown | d333160 | 2023-03-14 20:13:03 +0000 | [diff] [blame] | 414 | /* v8.9 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 415 | tainted |= check_feature(ENABLE_FEAT_TCR2, read_feat_tcr2_id_field(), |
| 416 | "TCR2", 1, 1); |
| 417 | tainted |= check_feature(ENABLE_FEAT_S2PIE, read_feat_s2pie_id_field(), |
| 418 | "S2PIE", 1, 1); |
| 419 | tainted |= check_feature(ENABLE_FEAT_S1PIE, read_feat_s1pie_id_field(), |
| 420 | "S1PIE", 1, 1); |
| 421 | tainted |= check_feature(ENABLE_FEAT_S2POE, read_feat_s2poe_id_field(), |
| 422 | "S2POE", 1, 1); |
| 423 | tainted |= check_feature(ENABLE_FEAT_S1POE, read_feat_s1poe_id_field(), |
| 424 | "S1POE", 1, 1); |
| 425 | tainted |= check_feature(ENABLE_FEAT_CSV2_3, read_feat_csv2_id_field(), |
| 426 | "CSV2_3", 3, 3); |
| 427 | tainted |= check_feature(ENABLE_FEAT_DEBUGV8P9, read_feat_debugv8p9_id_field(), |
| 428 | "DEBUGV8P9", 11, 11); |
| 429 | tainted |= check_feature(ENABLE_FEAT_THE, read_feat_the_id_field(), |
| 430 | "THE", 1, 1); |
| 431 | tainted |= check_feature(ENABLE_FEAT_SCTLR2, read_feat_sctlr2_id_field(), |
| 432 | "SCTLR2", 1, 1); |
Mark Brown | d333160 | 2023-03-14 20:13:03 +0000 | [diff] [blame] | 433 | |
Jayanth Dodderi Chidanand | 1298f2f | 2022-05-09 12:33:03 +0100 | [diff] [blame] | 434 | /* v9.0 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 435 | tainted |= check_feature(ENABLE_BRBE_FOR_NS, read_feat_brbe_id_field(), |
| 436 | "BRBE", 1, 2); |
| 437 | tainted |= check_feature(ENABLE_TRBE_FOR_NS, read_feat_trbe_id_field(), |
| 438 | "TRBE", 1, 1); |
Jayanth Dodderi Chidanand | 1298f2f | 2022-05-09 12:33:03 +0100 | [diff] [blame] | 439 | |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 440 | /* v9.2 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 441 | tainted |= check_feature(ENABLE_SME_FOR_NS, read_feat_sme_id_field(), |
| 442 | "SME", 1, 2); |
| 443 | tainted |= check_feature(ENABLE_SME2_FOR_NS, read_feat_sme_id_field(), |
| 444 | "SME2", 2, 2); |
| 445 | tainted |= check_feature(ENABLE_FEAT_FPMR, read_feat_fpmr_id_field(), |
| 446 | "FPMR", 1, 1); |
Mark Brown | 688ab57 | 2023-03-14 21:33:04 +0000 | [diff] [blame] | 447 | |
Govindraj Raja | 3065513 | 2024-09-06 15:43:43 +0100 | [diff] [blame] | 448 | /* v9.3 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 449 | tainted |= check_feature(ENABLE_FEAT_D128, read_feat_d128_id_field(), |
| 450 | "D128", 1, 1); |
| 451 | tainted |= check_feature(ENABLE_FEAT_GCIE, read_feat_gcie_id_field(), |
| 452 | "GCIE", 1, 1); |
Govindraj Raja | 3065513 | 2024-09-06 15:43:43 +0100 | [diff] [blame] | 453 | |
Mark Brown | 688ab57 | 2023-03-14 21:33:04 +0000 | [diff] [blame] | 454 | /* v9.4 features */ |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 455 | tainted |= check_feature(ENABLE_FEAT_GCS, read_feat_gcs_id_field(), |
| 456 | "GCS", 1, 1); |
| 457 | tainted |= check_feature(ENABLE_RME, read_feat_rme_id_field(), |
| 458 | "RME", 1, 1); |
| 459 | tainted |= check_feature(ENABLE_FEAT_PAUTH_LR, is_feat_pauth_lr_present(), |
| 460 | "PAUTH_LR", 1, 1); |
| 461 | tainted |= check_feature(ENABLE_FEAT_FGWTE3, read_feat_fgwte3_id_field(), |
| 462 | "FGWTE3", 1, 1); |
Andre Przywara | b45dd74 | 2022-11-14 15:42:44 +0000 | [diff] [blame] | 463 | |
| 464 | if (tainted) { |
| 465 | panic(); |
| 466 | } |
Boyan Karatotev | d335bbb | 2025-07-03 14:59:55 +0100 | [diff] [blame] | 467 | |
| 468 | detection_done[core_pos] = true; |
Jayanth Dodderi Chidanand | 6a0da73 | 2022-01-17 18:57:17 +0000 | [diff] [blame] | 469 | } |