1 /*
2 * Copyright (c) 2019-2024, 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))
is_armv7_gentimer_present(void)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 */
CREATE_FEATURE_FUNCS(feat_amu,id_pfr0,ID_PFR0_AMU_SHIFT,ID_PFR0_AMU_MASK,ID_PFR0_AMU_V1,ENABLE_FEAT_AMU)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 /* FEAT_AMUV1P1: AMU Extension v1.1 */
89 CREATE_FEATURE_FUNCS(feat_amuv1p1, id_pfr0, ID_PFR0_AMU_SHIFT,
90 ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
91
92 /* FEAT_TRF: Tracefilter */
93 CREATE_FEATURE_FUNCS(feat_trf, id_dfr0, ID_DFR0_TRACEFILT_SHIFT,
94 ID_DFR0_TRACEFILT_MASK, 1U, ENABLE_TRF_FOR_NS)
95
96 /* FEAT_SYS_REG_TRACE */
97 CREATE_FEATURE_FUNCS(feat_sys_reg_trace, id_dfr0, ID_DFR0_COPTRC_SHIFT,
98 ID_DFR0_COPTRC_MASK, 1U, ENABLE_SYS_REG_TRACE_FOR_NS)
99
100 /* FEAT_DIT: Data independent timing */
101 CREATE_FEATURE_FUNCS(feat_dit, id_pfr0, ID_PFR0_DIT_SHIFT,
102 ID_PFR0_DIT_MASK, 1U, ENABLE_FEAT_DIT)
103
104 /* FEAT_PAN: Privileged access never */
105 CREATE_FEATURE_FUNCS(feat_pan, id_mmfr3, ID_MMFR3_PAN_SHIFT,
106 ID_MMFR3_PAN_MASK, 1U, ENABLE_FEAT_PAN)
107
108 /* FEAT_SSBS: Speculative store bypass safe */
109 CREATE_FEATURE_PRESENT(feat_ssbs, id_pfr2, ID_PFR2_SSBS_SHIFT,
110 ID_PFR2_SSBS_MASK, 1U)
111
112 /* FEAT_PMUV3 */
113 CREATE_FEATURE_PRESENT(feat_pmuv3, id_dfr0, ID_DFR0_PERFMON_SHIFT,
114 ID_DFR0_PERFMON_MASK, 3U)
115
116 /* FEAT_MTPMU */
117 __attribute__((always_inline))
118 static inline bool is_feat_mtpmu_present(void)
119 {
120 unsigned int mtpmu = ISOLATE_FIELD(read_id_dfr1(), ID_DFR1_MTPMU_SHIFT,
121 ID_DFR1_MTPMU_MASK);
122 return (mtpmu != 0U) && (mtpmu != MTPMU_NOT_IMPLEMENTED);
123 }
CREATE_FEATURE_SUPPORTED(feat_mtpmu,is_feat_mtpmu_present,DISABLE_MTPMU)124 CREATE_FEATURE_SUPPORTED(feat_mtpmu, is_feat_mtpmu_present, DISABLE_MTPMU)
125
126 /*
127 * TWED, ECV, CSV2, RAS are only used by the AArch64 EL2 context switch
128 * code. In fact, EL2 context switching is only needed for AArch64 (since
129 * there is no secure AArch32 EL2), so just disable these features here.
130 */
131 __attribute__((always_inline))
132 static inline bool is_feat_twed_supported(void) { return false; }
133 __attribute__((always_inline))
is_feat_ecv_supported(void)134 static inline bool is_feat_ecv_supported(void) { return false; }
135 __attribute__((always_inline))
is_feat_ecv_v2_supported(void)136 static inline bool is_feat_ecv_v2_supported(void) { return false; }
137 __attribute__((always_inline))
is_feat_csv2_2_supported(void)138 static inline bool is_feat_csv2_2_supported(void) { return false; }
139 __attribute__((always_inline))
is_feat_csv2_3_supported(void)140 static inline bool is_feat_csv2_3_supported(void) { return false; }
141 __attribute__((always_inline))
is_feat_ras_supported(void)142 static inline bool is_feat_ras_supported(void) { return false; }
143
144 /* The following features are supported in AArch64 only. */
145 __attribute__((always_inline))
is_feat_vhe_supported(void)146 static inline bool is_feat_vhe_supported(void) { return false; }
147 __attribute__((always_inline))
is_feat_sel2_supported(void)148 static inline bool is_feat_sel2_supported(void) { return false; }
149 __attribute__((always_inline))
is_feat_fgt_supported(void)150 static inline bool is_feat_fgt_supported(void) { return false; }
151 __attribute__((always_inline))
is_feat_tcr2_supported(void)152 static inline bool is_feat_tcr2_supported(void) { return false; }
153 __attribute__((always_inline))
is_feat_spe_supported(void)154 static inline bool is_feat_spe_supported(void) { return false; }
155 __attribute__((always_inline))
is_feat_rng_supported(void)156 static inline bool is_feat_rng_supported(void) { return false; }
157 __attribute__((always_inline))
is_feat_gcs_supported(void)158 static inline bool is_feat_gcs_supported(void) { return false; }
159 __attribute__((always_inline))
is_feat_mte2_supported(void)160 static inline bool is_feat_mte2_supported(void) { return false; }
161 __attribute__((always_inline))
is_feat_mpam_supported(void)162 static inline bool is_feat_mpam_supported(void) { return false; }
163 __attribute__((always_inline))
is_feat_hcx_supported(void)164 static inline bool is_feat_hcx_supported(void) { return false; }
165 __attribute__((always_inline))
is_feat_sve_supported(void)166 static inline bool is_feat_sve_supported(void) { return false; }
167 __attribute__((always_inline))
is_feat_brbe_supported(void)168 static inline bool is_feat_brbe_supported(void) { return false; }
169 __attribute__((always_inline))
is_feat_trbe_supported(void)170 static inline bool is_feat_trbe_supported(void) { return false; }
171 __attribute__((always_inline))
is_feat_nv2_supported(void)172 static inline bool is_feat_nv2_supported(void) { return false; }
173 __attribute__((always_inline))
is_feat_sme_supported(void)174 static inline bool is_feat_sme_supported(void) { return false; }
175 __attribute__((always_inline))
is_feat_sme2_supported(void)176 static inline bool is_feat_sme2_supported(void) { return false; }
177 __attribute__((always_inline))
is_feat_s2poe_supported(void)178 static inline bool is_feat_s2poe_supported(void) { return false; }
179 __attribute__((always_inline))
is_feat_s1poe_supported(void)180 static inline bool is_feat_s1poe_supported(void) { return false; }
181 __attribute__((always_inline))
is_feat_sxpoe_supported(void)182 static inline bool is_feat_sxpoe_supported(void) { return false; }
183 __attribute__((always_inline))
is_feat_s2pie_supported(void)184 static inline bool is_feat_s2pie_supported(void) { return false; }
185 __attribute__((always_inline))
is_feat_s1pie_supported(void)186 static inline bool is_feat_s1pie_supported(void) { return false; }
187 __attribute__((always_inline))
is_feat_sxpie_supported(void)188 static inline bool is_feat_sxpie_supported(void) { return false; }
189 __attribute__((always_inline))
is_feat_uao_present(void)190 static inline bool is_feat_uao_present(void) { return false; }
191 __attribute__((always_inline))
is_feat_nmi_present(void)192 static inline bool is_feat_nmi_present(void) { return false; }
193 __attribute__((always_inline))
is_feat_ebep_present(void)194 static inline bool is_feat_ebep_present(void) { return false; }
195 __attribute__((always_inline))
is_feat_sebep_present(void)196 static inline bool is_feat_sebep_present(void) { return false; }
197 __attribute__((always_inline))
is_feat_d128_present(void)198 static inline bool is_feat_d128_present(void) { return false; }
199 __attribute__((always_inline))
is_feat_ls64_accdata_present(void)200 static inline bool is_feat_ls64_accdata_present(void) { return false; }
201
202 #endif /* ARCH_FEATURES_H */
203