1 /* 2 * Copyright (c) 2019-2023, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 */ 6 7 #ifndef ARCH_FEATURES_H 8 #define ARCH_FEATURES_H 9 10 #include <stdbool.h> 11 12 #include <arch_helpers.h> 13 #include <common/feat_detect.h> 14 15 #define ISOLATE_FIELD(reg, feat) \ 16 ((unsigned int)(((reg) >> (feat ## _SHIFT)) & (feat ## _MASK))) 17 18 static inline bool is_armv7_gentimer_present(void) 19 { 20 /* The Generic Timer is always present in an ARMv8-A implementation */ 21 return true; 22 } 23 24 static inline bool is_armv8_1_pan_present(void) 25 { 26 return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) & 27 ID_AA64MMFR1_EL1_PAN_MASK) != 0U; 28 } 29 30 static inline bool is_armv8_1_vhe_present(void) 31 { 32 return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) & 33 ID_AA64MMFR1_EL1_VHE_MASK) != 0U; 34 } 35 36 static inline bool is_armv8_2_ttcnp_present(void) 37 { 38 return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) & 39 ID_AA64MMFR2_EL1_CNP_MASK) != 0U; 40 } 41 42 static inline bool is_feat_pacqarma3_present(void) 43 { 44 uint64_t mask_id_aa64isar2 = 45 (ID_AA64ISAR2_GPA3_MASK << ID_AA64ISAR2_GPA3_SHIFT) | 46 (ID_AA64ISAR2_APA3_MASK << ID_AA64ISAR2_APA3_SHIFT); 47 48 /* If any of the fields is not zero, QARMA3 algorithm is present */ 49 return (read_id_aa64isar2_el1() & mask_id_aa64isar2) != 0U; 50 } 51 52 static inline bool is_armv8_3_pauth_present(void) 53 { 54 uint64_t mask_id_aa64isar1 = 55 (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | 56 (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) | 57 (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | 58 (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); 59 60 /* 61 * If any of the fields is not zero or QARMA3 is present, 62 * PAuth is present 63 */ 64 return ((read_id_aa64isar1_el1() & mask_id_aa64isar1) != 0U || 65 is_feat_pacqarma3_present()); 66 } 67 68 static inline bool is_armv8_4_dit_present(void) 69 { 70 return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & 71 ID_AA64PFR0_DIT_MASK) == 1U; 72 } 73 74 static inline bool is_armv8_4_ttst_present(void) 75 { 76 return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & 77 ID_AA64MMFR2_EL1_ST_MASK) == 1U; 78 } 79 80 static inline bool is_armv8_5_bti_present(void) 81 { 82 return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) & 83 ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED; 84 } 85 86 static inline unsigned int get_armv8_5_mte_support(void) 87 { 88 return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & 89 ID_AA64PFR1_EL1_MTE_MASK); 90 } 91 92 static inline bool is_armv8_4_sel2_present(void) 93 { 94 return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SEL2_SHIFT) & 95 ID_AA64PFR0_SEL2_MASK) == 1ULL; 96 } 97 98 static inline bool is_armv8_6_twed_present(void) 99 { 100 return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_TWED_SHIFT) & 101 ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED); 102 } 103 104 static unsigned int read_feat_fgt_id_field(void) 105 { 106 return ISOLATE_FIELD(read_id_aa64mmfr0_el1(), ID_AA64MMFR0_EL1_FGT); 107 } 108 109 static inline bool is_feat_fgt_supported(void) 110 { 111 if (ENABLE_FEAT_FGT == FEAT_STATE_DISABLED) { 112 return false; 113 } 114 115 if (ENABLE_FEAT_FGT == FEAT_STATE_ALWAYS) { 116 return true; 117 } 118 119 return read_feat_fgt_id_field() != 0U; 120 } 121 122 static inline unsigned long int get_armv8_6_ecv_support(void) 123 { 124 return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) & 125 ID_AA64MMFR0_EL1_ECV_MASK); 126 } 127 128 static inline bool is_armv8_5_rng_present(void) 129 { 130 return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) & 131 ID_AA64ISAR0_RNDR_MASK); 132 } 133 134 static unsigned int read_feat_tcrx_id_field(void) 135 { 136 return ISOLATE_FIELD(read_id_aa64mmfr3_el1(), ID_AA64MMFR3_EL1_TCRX); 137 } 138 139 static inline bool is_feat_tcr2_supported(void) 140 { 141 if (ENABLE_FEAT_TCR2 == FEAT_STATE_DISABLED) { 142 return false; 143 } 144 145 if (ENABLE_FEAT_TCR2 == FEAT_STATE_ALWAYS) { 146 return true; 147 } 148 149 return read_feat_tcrx_id_field() != 0U; 150 } 151 152 /******************************************************************************* 153 * Functions to identify the presence of the Activity Monitors Extension 154 ******************************************************************************/ 155 static unsigned int read_feat_amu_id_field(void) 156 { 157 return ISOLATE_FIELD(read_id_aa64pfr0_el1(), ID_AA64PFR0_AMU); 158 } 159 160 static inline bool is_feat_amu_supported(void) 161 { 162 if (ENABLE_FEAT_AMUv1 == FEAT_STATE_DISABLED) { 163 return false; 164 } 165 166 if (ENABLE_FEAT_AMUv1 == FEAT_STATE_ALWAYS) { 167 return true; 168 } 169 170 return read_feat_amu_id_field() >= ID_AA64PFR0_AMU_V1; 171 } 172 173 static inline bool is_armv8_6_feat_amuv1p1_present(void) 174 { 175 return read_feat_amu_id_field() >= ID_AA64PFR0_AMU_V1P1; 176 } 177 178 /* 179 * Return MPAM version: 180 * 181 * 0x00: None Armv8.0 or later 182 * 0x01: v0.1 Armv8.4 or later 183 * 0x10: v1.0 Armv8.2 or later 184 * 0x11: v1.1 Armv8.4 or later 185 * 186 */ 187 static inline unsigned int read_feat_mpam_version(void) 188 { 189 return (unsigned int)((((read_id_aa64pfr0_el1() >> 190 ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) | 191 ((read_id_aa64pfr1_el1() >> 192 ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK)); 193 } 194 195 static inline bool is_feat_mpam_supported(void) 196 { 197 if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_DISABLED) { 198 return false; 199 } 200 201 if (ENABLE_MPAM_FOR_LOWER_ELS == FEAT_STATE_ALWAYS) { 202 return true; 203 } 204 205 return read_feat_mpam_version() != 0U; 206 } 207 208 static inline unsigned int read_feat_hcx_id_field(void) 209 { 210 return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_HCX); 211 } 212 213 static inline bool is_feat_hcx_supported(void) 214 { 215 if (ENABLE_FEAT_HCX == FEAT_STATE_DISABLED) { 216 return false; 217 } 218 219 if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS) { 220 return true; 221 } 222 223 return read_feat_hcx_id_field() != 0U; 224 } 225 226 static inline bool is_feat_rng_trap_present(void) 227 { 228 return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT) & 229 ID_AA64PFR1_EL1_RNDR_TRAP_MASK) 230 == ID_AA64PFR1_EL1_RNG_TRAP_SUPPORTED); 231 } 232 233 static inline unsigned int get_armv9_2_feat_rme_support(void) 234 { 235 /* 236 * Return the RME version, zero if not supported. This function can be 237 * used as both an integer value for the RME version or compared to zero 238 * to detect RME presence. 239 */ 240 return (unsigned int)(read_id_aa64pfr0_el1() >> 241 ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK; 242 } 243 244 /********************************************************************************* 245 * Function to identify the presence of FEAT_SB (Speculation Barrier Instruction) 246 ********************************************************************************/ 247 static inline bool is_armv8_0_feat_sb_present(void) 248 { 249 return (((read_id_aa64isar1_el1() >> ID_AA64ISAR1_SB_SHIFT) & 250 ID_AA64ISAR1_SB_MASK) == ID_AA64ISAR1_SB_SUPPORTED); 251 } 252 253 /********************************************************************************* 254 * Function to identify the presence of FEAT_CSV2_2 (Cache Speculation Variant 2) 255 ********************************************************************************/ 256 static inline bool is_armv8_0_feat_csv2_2_present(void) 257 { 258 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_CSV2_SHIFT) & 259 ID_AA64PFR0_CSV2_MASK) == ID_AA64PFR0_CSV2_2_SUPPORTED); 260 } 261 262 /********************************************************************************** 263 * Function to identify the presence of FEAT_SPE (Statistical Profiling Extension) 264 *********************************************************************************/ 265 static inline unsigned int read_feat_spe_id_field(void) 266 { 267 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_PMS); 268 } 269 270 static inline bool is_feat_spe_supported(void) 271 { 272 if (ENABLE_SPE_FOR_NS == FEAT_STATE_DISABLED) { 273 return false; 274 } 275 276 if (ENABLE_SPE_FOR_NS == FEAT_STATE_ALWAYS) { 277 return true; 278 } 279 280 return read_feat_spe_id_field() != 0U; 281 } 282 283 /******************************************************************************* 284 * Function to identify the presence of FEAT_SVE (Scalable Vector Extension) 285 ******************************************************************************/ 286 static inline bool is_armv8_2_feat_sve_present(void) 287 { 288 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) & 289 ID_AA64PFR0_SVE_MASK) == ID_AA64PFR0_SVE_SUPPORTED); 290 } 291 292 /******************************************************************************* 293 * Function to identify the presence of FEAT_RAS (Reliability,Availability, 294 * and Serviceability Extension) 295 ******************************************************************************/ 296 static inline bool is_armv8_2_feat_ras_present(void) 297 { 298 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_RAS_SHIFT) & 299 ID_AA64PFR0_RAS_MASK) != ID_AA64PFR0_RAS_NOT_SUPPORTED); 300 } 301 302 /************************************************************************** 303 * Function to identify the presence of FEAT_DIT (Data Independent Timing) 304 *************************************************************************/ 305 static inline bool is_armv8_4_feat_dit_present(void) 306 { 307 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & 308 ID_AA64PFR0_DIT_MASK) == ID_AA64PFR0_DIT_SUPPORTED); 309 } 310 311 /************************************************************************* 312 * Function to identify the presence of FEAT_TRF (TraceLift) 313 ************************************************************************/ 314 static inline unsigned int read_feat_trf_id_field(void) 315 { 316 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEFILT); 317 } 318 319 static inline bool is_feat_trf_supported(void) 320 { 321 if (ENABLE_TRF_FOR_NS == FEAT_STATE_DISABLED) { 322 return false; 323 } 324 325 if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS) { 326 return true; 327 } 328 329 return read_feat_trf_id_field() != 0U; 330 } 331 332 /******************************************************************************** 333 * Function to identify the presence of FEAT_NV2 (Enhanced Nested Virtualization 334 * Support) 335 *******************************************************************************/ 336 static inline unsigned int get_armv8_4_feat_nv_support(void) 337 { 338 return (((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_NV_SHIFT) & 339 ID_AA64MMFR2_EL1_NV_MASK)); 340 } 341 342 /******************************************************************************* 343 * Function to identify the presence of FEAT_BRBE (Branch Record Buffer 344 * Extension) 345 ******************************************************************************/ 346 static inline unsigned int read_feat_brbe_id_field(void) 347 { 348 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_BRBE); 349 } 350 351 static inline bool is_feat_brbe_supported(void) 352 { 353 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_DISABLED) { 354 return false; 355 } 356 357 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS) { 358 return true; 359 } 360 361 return read_feat_brbe_id_field() != 0U; 362 } 363 364 /******************************************************************************* 365 * Function to identify the presence of FEAT_TRBE (Trace Buffer Extension) 366 ******************************************************************************/ 367 static inline unsigned int read_feat_trbe_id_field(void) 368 { 369 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEBUFFER); 370 } 371 372 static inline bool is_feat_trbe_supported(void) 373 { 374 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_DISABLED) { 375 return false; 376 } 377 378 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS) { 379 return true; 380 } 381 382 return read_feat_trbe_id_field() != 0U; 383 384 } 385 #endif /* ARCH_FEATURES_H */ 386