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 bool is_armv8_2_feat_spe_present(void) 253 { 254 return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT) & 255 ID_AA64DFR0_PMS_MASK) != ID_AA64DFR0_SPE_NOT_SUPPORTED); 256 } 257 258 /******************************************************************************* 259 * Function to identify the presence of FEAT_SVE (Scalable Vector Extension) 260 ******************************************************************************/ 261 static inline bool is_armv8_2_feat_sve_present(void) 262 { 263 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT) & 264 ID_AA64PFR0_SVE_MASK) == ID_AA64PFR0_SVE_SUPPORTED); 265 } 266 267 /******************************************************************************* 268 * Function to identify the presence of FEAT_RAS (Reliability,Availability, 269 * and Serviceability Extension) 270 ******************************************************************************/ 271 static inline bool is_armv8_2_feat_ras_present(void) 272 { 273 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_RAS_SHIFT) & 274 ID_AA64PFR0_RAS_MASK) != ID_AA64PFR0_RAS_NOT_SUPPORTED); 275 } 276 277 /************************************************************************** 278 * Function to identify the presence of FEAT_DIT (Data Independent Timing) 279 *************************************************************************/ 280 static inline bool is_armv8_4_feat_dit_present(void) 281 { 282 return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & 283 ID_AA64PFR0_DIT_MASK) == ID_AA64PFR0_DIT_SUPPORTED); 284 } 285 286 /************************************************************************* 287 * Function to identify the presence of FEAT_TRF (TraceLift) 288 ************************************************************************/ 289 static inline unsigned int read_feat_trf_id_field(void) 290 { 291 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEFILT); 292 } 293 294 static inline bool is_feat_trf_supported(void) 295 { 296 if (ENABLE_TRF_FOR_NS == FEAT_STATE_DISABLED) { 297 return false; 298 } 299 300 if (ENABLE_TRF_FOR_NS == FEAT_STATE_ALWAYS) { 301 return true; 302 } 303 304 return read_feat_trf_id_field() != 0U; 305 } 306 307 /******************************************************************************** 308 * Function to identify the presence of FEAT_NV2 (Enhanced Nested Virtualization 309 * Support) 310 *******************************************************************************/ 311 static inline unsigned int get_armv8_4_feat_nv_support(void) 312 { 313 return (((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_NV_SHIFT) & 314 ID_AA64MMFR2_EL1_NV_MASK)); 315 } 316 317 /******************************************************************************* 318 * Function to identify the presence of FEAT_BRBE (Branch Record Buffer 319 * Extension) 320 ******************************************************************************/ 321 static inline unsigned int read_feat_brbe_id_field(void) 322 { 323 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_BRBE); 324 } 325 326 static inline bool is_feat_brbe_supported(void) 327 { 328 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_DISABLED) { 329 return false; 330 } 331 332 if (ENABLE_BRBE_FOR_NS == FEAT_STATE_ALWAYS) { 333 return true; 334 } 335 336 return read_feat_brbe_id_field() != 0U; 337 } 338 339 /******************************************************************************* 340 * Function to identify the presence of FEAT_TRBE (Trace Buffer Extension) 341 ******************************************************************************/ 342 static inline unsigned int read_feat_trbe_id_field(void) 343 { 344 return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_TRACEBUFFER); 345 } 346 347 static inline bool is_feat_trbe_supported(void) 348 { 349 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_DISABLED) { 350 return false; 351 } 352 353 if (ENABLE_TRBE_FOR_NS == FEAT_STATE_ALWAYS) { 354 return true; 355 } 356 357 return read_feat_trbe_id_field() != 0U; 358 359 } 360 #endif /* ARCH_FEATURES_H */ 361