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 get_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 unsigned int read_feat_hcx_id_field(void) 196 { 197 return ISOLATE_FIELD(read_id_aa64mmfr1_el1(), ID_AA64MMFR1_EL1_HCX); 198 } 199 200 static inline bool is_feat_hcx_supported(void) 201 { 202 if (ENABLE_FEAT_HCX == FEAT_STATE_DISABLED) { 203 return false; 204 } 205 206 if (ENABLE_FEAT_HCX == FEAT_STATE_ALWAYS) { 207 return true; 208 } 209 210 return read_feat_hcx_id_field() != 0U; 211 } 212 213 static inline bool is_feat_rng_trap_present(void) 214 { 215 return (((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT) & 216 ID_AA64PFR1_EL1_RNDR_TRAP_MASK) 217 == ID_AA64PFR1_EL1_RNG_TRAP_SUPPORTED); 218 } 219 220 static inline unsigned int get_armv9_2_feat_rme_support(void) 221 { 222 /* 223 * Return the RME version, zero if not supported. This function can be 224 * used as both an integer value for the RME version or compared to zero 225 * to detect RME presence. 226 */ 227 return (unsigned int)(read_id_aa64pfr0_el1() >> 228 ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK; 229 } 230 231 /********************************************************************************* 232 * Function to identify the presence of FEAT_SB (Speculation Barrier Instruction) 233 ********************************************************************************/ 234 static inline bool is_armv8_0_feat_sb_present(void) 235 { 236 return (((read_id_aa64isar1_el1() >> ID_AA64ISAR1_SB_SHIFT) & 237 ID_AA64ISAR1_SB_MASK) == ID_AA64ISAR1_SB_SUPPORTED); 238 } 239 240 /********************************************************************************* 241 * Function to identify the presence of FEAT_CSV2_2 (Cache Speculation Variant 2) 242 ********************************************************************************/ 243 static inline bool is_armv8_0_feat_csv2_2_present(void) 244 { 245 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_CSV2_SHIFT) & 246 ID_AA64PFR0_CSV2_MASK) == ID_AA64PFR0_CSV2_2_SUPPORTED); 247 } 248 249 /********************************************************************************** 250 * Function to identify the presence of FEAT_SPE (Statistical Profiling Extension) 251 *********************************************************************************/ 252 static inline unsigned int read_feat_spe_id_field(void) 253 { 254 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_PMS); 255 } 256 257 static inline bool is_feat_spe_supported(void) 258 { 259 if (ENABLE_SPE_FOR_NS == FEAT_STATE_DISABLED) { 260 return false; 261 } 262 263 if (ENABLE_SPE_FOR_NS == FEAT_STATE_ALWAYS) { 264 return true; 265 } 266 267 return read_feat_spe_id_field() != 0U; 268 } 269 270 /******************************************************************************* 271 * Function to identify the presence of FEAT_SVE (Scalable Vector Extension) 272 ******************************************************************************/ 273 static inline bool is_armv8_2_feat_sve_present(void) 274 { 275 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) & 276 ID_AA64PFR0_SVE_MASK) == ID_AA64PFR0_SVE_SUPPORTED); 277 } 278 279 /******************************************************************************* 280 * Function to identify the presence of FEAT_RAS (Reliability,Availability, 281 * and Serviceability Extension) 282 ******************************************************************************/ 283 static inline bool is_armv8_2_feat_ras_present(void) 284 { 285 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_RAS_SHIFT) & 286 ID_AA64PFR0_RAS_MASK) != ID_AA64PFR0_RAS_NOT_SUPPORTED); 287 } 288 289 /************************************************************************** 290 * Function to identify the presence of FEAT_DIT (Data Independent Timing) 291 *************************************************************************/ 292 static inline bool is_armv8_4_feat_dit_present(void) 293 { 294 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & 295 ID_AA64PFR0_DIT_MASK) == ID_AA64PFR0_DIT_SUPPORTED); 296 } 297 298 /************************************************************************* 299 * Function to identify the presence of FEAT_TRF (TraceLift) 300 ************************************************************************/ 301 static inline unsigned int read_feat_trf_id_field(void) 302 { 303 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEFILT); 304 } 305 306 static inline bool is_feat_trf_supported(void) 307 { 308 if (ENABLE_TRF_FOR_NS == FEAT_STATE_DISABLED) { 309 return false; 310 } 311 312 if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS) { 313 return true; 314 } 315 316 return read_feat_trf_id_field() != 0U; 317 } 318 319 /******************************************************************************** 320 * Function to identify the presence of FEAT_NV2 (Enhanced Nested Virtualization 321 * Support) 322 *******************************************************************************/ 323 static inline unsigned int get_armv8_4_feat_nv_support(void) 324 { 325 return (((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_NV_SHIFT) & 326 ID_AA64MMFR2_EL1_NV_MASK)); 327 } 328 329 /******************************************************************************* 330 * Function to identify the presence of FEAT_BRBE (Branch Record Buffer 331 * Extension) 332 ******************************************************************************/ 333 static inline unsigned int read_feat_brbe_id_field(void) 334 { 335 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_BRBE); 336 } 337 338 static inline bool is_feat_brbe_supported(void) 339 { 340 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_DISABLED) { 341 return false; 342 } 343 344 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS) { 345 return true; 346 } 347 348 return read_feat_brbe_id_field() != 0U; 349 } 350 351 /******************************************************************************* 352 * Function to identify the presence of FEAT_TRBE (Trace Buffer Extension) 353 ******************************************************************************/ 354 static inline unsigned int read_feat_trbe_id_field(void) 355 { 356 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEBUFFER); 357 } 358 359 static inline bool is_feat_trbe_supported(void) 360 { 361 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_DISABLED) { 362 return false; 363 } 364 365 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS) { 366 return true; 367 } 368 369 return read_feat_trbe_id_field() != 0U; 370 371 } 372 #endif /* ARCH_FEATURES_H */ 373