1 /* 2 * Copyright (c) 2019-2025, 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, mask) \ 16 ((unsigned int)(((reg) >> (feat)) & mask)) 17 18 #define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \ 19 __attribute__((always_inline)) \ 20 static inline bool is_ ## name ## _supported(void) \ 21 { \ 22 if ((guard) == FEAT_STATE_DISABLED) { \ 23 return false; \ 24 } \ 25 if ((guard) == FEAT_STATE_ALWAYS) { \ 26 return true; \ 27 } \ 28 return read_func(); \ 29 } 30 31 #define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \ 32 __attribute__((always_inline)) \ 33 static inline bool is_ ## name ## _present(void) \ 34 { \ 35 return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \ 36 ? true : false; \ 37 } 38 39 #define CREATE_FEATURE_FUNCS(name, idreg, idfield, mask, idval, guard) \ 40 CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \ 41 CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard) 42 43 44 /* 45 * +----------------------------+ 46 * | Features supported | 47 * +----------------------------+ 48 * | GENTIMER | 49 * +----------------------------+ 50 * | FEAT_TTCNP | 51 * +----------------------------+ 52 * | FEAT_AMU | 53 * +----------------------------+ 54 * | FEAT_AMUV1P1 | 55 * +----------------------------+ 56 * | FEAT_TRF | 57 * +----------------------------+ 58 * | FEAT_SYS_REG_TRACE | 59 * +----------------------------+ 60 * | FEAT_DIT | 61 * +----------------------------+ 62 * | FEAT_PAN | 63 * +----------------------------+ 64 * | FEAT_SSBS | 65 * +----------------------------+ 66 * | FEAT_PMUV3 | 67 * +----------------------------+ 68 * | FEAT_MTPMU | 69 * +----------------------------+ 70 */ 71 72 /* GENTIMER */ 73 __attribute__((always_inline)) 74 static inline bool is_armv7_gentimer_present(void) 75 { 76 return ISOLATE_FIELD(read_id_pfr1(), ID_PFR1_GENTIMER_SHIFT, 77 ID_PFR1_GENTIMER_MASK) != 0U; 78 } 79 80 /* FEAT_TTCNP: Translation table common not private */ 81 CREATE_FEATURE_PRESENT(feat_ttcnp, id_mmfr4, ID_MMFR4_CNP_SHIFT, 82 ID_MMFR4_CNP_MASK, 1U) 83 84 /* FEAT_AMU: Activity Monitors Extension */ 85 CREATE_FEATURE_FUNCS(feat_amu, id_pfr0, ID_PFR0_AMU_SHIFT, 86 ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1, ENABLE_FEAT_AMU) 87 88 /* Auxiliary counters for FEAT_AMU */ 89 CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr, AMCFGR_NCG_SHIFT, 90 AMCFGR_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS) 91 92 /* FEAT_AMUV1P1: AMU Extension v1.1 */ 93 CREATE_FEATURE_FUNCS(feat_amuv1p1, id_pfr0, ID_PFR0_AMU_SHIFT, 94 ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1) 95 96 /* FEAT_TRF: Tracefilter */ 97 CREATE_FEATURE_FUNCS(feat_trf, id_dfr0, ID_DFR0_TRACEFILT_SHIFT, 98 ID_DFR0_TRACEFILT_MASK, 1U, ENABLE_TRF_FOR_NS) 99 100 /* FEAT_SYS_REG_TRACE */ 101 CREATE_FEATURE_FUNCS(feat_sys_reg_trace, id_dfr0, ID_DFR0_COPTRC_SHIFT, 102 ID_DFR0_COPTRC_MASK, 1U, ENABLE_SYS_REG_TRACE_FOR_NS) 103 104 /* FEAT_DIT: Data independent timing */ 105 CREATE_FEATURE_FUNCS(feat_dit, id_pfr0, ID_PFR0_DIT_SHIFT, 106 ID_PFR0_DIT_MASK, 1U, ENABLE_FEAT_DIT) 107 108 /* FEAT_PAN: Privileged access never */ 109 CREATE_FEATURE_FUNCS(feat_pan, id_mmfr3, ID_MMFR3_PAN_SHIFT, 110 ID_MMFR3_PAN_MASK, 1U, ENABLE_FEAT_PAN) 111 112 /* FEAT_SSBS: Speculative store bypass safe */ 113 CREATE_FEATURE_PRESENT(feat_ssbs, id_pfr2, ID_PFR2_SSBS_SHIFT, 114 ID_PFR2_SSBS_MASK, 1U) 115 116 /* FEAT_PMUV3 */ 117 CREATE_FEATURE_PRESENT(feat_pmuv3, id_dfr0, ID_DFR0_PERFMON_SHIFT, 118 ID_DFR0_PERFMON_MASK, 3U) 119 120 /* FEAT_MTPMU */ 121 __attribute__((always_inline)) 122 static inline bool is_feat_mtpmu_present(void) 123 { 124 unsigned int mtpmu = ISOLATE_FIELD(read_id_dfr1(), ID_DFR1_MTPMU_SHIFT, 125 ID_DFR1_MTPMU_MASK); 126 return (mtpmu != 0U) && (mtpmu != MTPMU_NOT_IMPLEMENTED); 127 } 128 CREATE_FEATURE_SUPPORTED(feat_mtpmu, is_feat_mtpmu_present, DISABLE_MTPMU) 129 130 /* 131 * TWED, ECV, CSV2, RAS are only used by the AArch64 EL2 context switch 132 * code. In fact, EL2 context switching is only needed for AArch64 (since 133 * there is no secure AArch32 EL2), so just disable these features here. 134 */ 135 __attribute__((always_inline)) 136 static inline bool is_feat_twed_supported(void) { return false; } 137 __attribute__((always_inline)) 138 static inline bool is_feat_ecv_supported(void) { return false; } 139 __attribute__((always_inline)) 140 static inline bool is_feat_ecv_v2_supported(void) { return false; } 141 __attribute__((always_inline)) 142 static inline bool is_feat_csv2_2_supported(void) { return false; } 143 __attribute__((always_inline)) 144 static inline bool is_feat_csv2_3_supported(void) { return false; } 145 __attribute__((always_inline)) 146 static inline bool is_feat_ras_supported(void) { return false; } 147 148 /* The following features are supported in AArch64 only. */ 149 __attribute__((always_inline)) 150 static inline bool is_feat_vhe_supported(void) { return false; } 151 __attribute__((always_inline)) 152 static inline bool is_feat_sel2_supported(void) { return false; } 153 __attribute__((always_inline)) 154 static inline bool is_feat_fgt_supported(void) { return false; } 155 __attribute__((always_inline)) 156 static inline bool is_feat_tcr2_supported(void) { return false; } 157 __attribute__((always_inline)) 158 static inline bool is_feat_spe_supported(void) { return false; } 159 __attribute__((always_inline)) 160 static inline bool is_feat_rng_supported(void) { return false; } 161 __attribute__((always_inline)) 162 static inline bool is_feat_gcs_supported(void) { return false; } 163 __attribute__((always_inline)) 164 static inline bool is_feat_mte2_supported(void) { return false; } 165 __attribute__((always_inline)) 166 static inline bool is_feat_mpam_supported(void) { return false; } 167 __attribute__((always_inline)) 168 static inline bool is_feat_hcx_supported(void) { return false; } 169 __attribute__((always_inline)) 170 static inline bool is_feat_sve_supported(void) { return false; } 171 __attribute__((always_inline)) 172 static inline bool is_feat_brbe_supported(void) { return false; } 173 __attribute__((always_inline)) 174 static inline bool is_feat_trbe_supported(void) { return false; } 175 __attribute__((always_inline)) 176 static inline bool is_feat_nv2_supported(void) { return false; } 177 __attribute__((always_inline)) 178 static inline bool is_feat_sme_supported(void) { return false; } 179 __attribute__((always_inline)) 180 static inline bool is_feat_sme2_supported(void) { return false; } 181 __attribute__((always_inline)) 182 static inline bool is_feat_s2poe_supported(void) { return false; } 183 __attribute__((always_inline)) 184 static inline bool is_feat_s1poe_supported(void) { return false; } 185 __attribute__((always_inline)) 186 static inline bool is_feat_sxpoe_supported(void) { return false; } 187 __attribute__((always_inline)) 188 static inline bool is_feat_s2pie_supported(void) { return false; } 189 __attribute__((always_inline)) 190 static inline bool is_feat_s1pie_supported(void) { return false; } 191 __attribute__((always_inline)) 192 static inline bool is_feat_sxpie_supported(void) { return false; } 193 __attribute__((always_inline)) 194 static inline bool is_feat_uao_present(void) { return false; } 195 __attribute__((always_inline)) 196 static inline bool is_feat_nmi_present(void) { return false; } 197 __attribute__((always_inline)) 198 static inline bool is_feat_ebep_present(void) { return false; } 199 __attribute__((always_inline)) 200 static inline bool is_feat_sebep_present(void) { return false; } 201 __attribute__((always_inline)) 202 static inline bool is_feat_d128_present(void) { return false; } 203 __attribute__((always_inline)) 204 static inline bool is_feat_ls64_accdata_present(void) { return false; } 205 206 #endif /* ARCH_FEATURES_H */ 207