12559b2c8SAntonio Nino Diaz /*
283ec7e45SBoyan Karatotev * Copyright (c) 2019-2025, Arm Limited. All rights reserved.
32559b2c8SAntonio Nino Diaz *
42559b2c8SAntonio Nino Diaz * SPDX-License-Identifier: BSD-3-Clause
52559b2c8SAntonio Nino Diaz */
62559b2c8SAntonio Nino Diaz
72559b2c8SAntonio Nino Diaz #ifndef ARCH_FEATURES_H
82559b2c8SAntonio Nino Diaz #define ARCH_FEATURES_H
92559b2c8SAntonio Nino Diaz
102559b2c8SAntonio Nino Diaz #include <stdbool.h>
112559b2c8SAntonio Nino Diaz
122559b2c8SAntonio Nino Diaz #include <arch_helpers.h>
13fc8d2d39SAndre Przywara #include <common/feat_detect.h>
142559b2c8SAntonio Nino Diaz
15aaaf2cc3SSona Mathew #define ISOLATE_FIELD(reg, feat, mask) \
16aaaf2cc3SSona Mathew ((unsigned int)(((reg) >> (feat)) & mask))
17fd1dd4cbSAndre Przywara
18aaaf2cc3SSona Mathew #define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
190dfa07b6SOlivier Deprez __attribute__((always_inline)) \
20aaaf2cc3SSona Mathew static inline bool is_ ## name ## _supported(void) \
21aaaf2cc3SSona Mathew { \
22aaaf2cc3SSona Mathew if ((guard) == FEAT_STATE_DISABLED) { \
23aaaf2cc3SSona Mathew return false; \
24aaaf2cc3SSona Mathew } \
25aaaf2cc3SSona Mathew if ((guard) == FEAT_STATE_ALWAYS) { \
26aaaf2cc3SSona Mathew return true; \
27aaaf2cc3SSona Mathew } \
28aaaf2cc3SSona Mathew return read_func(); \
29aaaf2cc3SSona Mathew }
30aaaf2cc3SSona Mathew
31aaaf2cc3SSona Mathew #define CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
320dfa07b6SOlivier Deprez __attribute__((always_inline)) \
33aaaf2cc3SSona Mathew static inline bool is_ ## name ## _present(void) \
34aaaf2cc3SSona Mathew { \
35aaaf2cc3SSona Mathew return (ISOLATE_FIELD(read_ ## idreg(), idfield, mask) >= idval) \
36aaaf2cc3SSona Mathew ? true : false; \
37aaaf2cc3SSona Mathew }
38aaaf2cc3SSona Mathew
39aaaf2cc3SSona Mathew #define CREATE_FEATURE_FUNCS(name, idreg, idfield, mask, idval, guard) \
40aaaf2cc3SSona Mathew CREATE_FEATURE_PRESENT(name, idreg, idfield, mask, idval) \
41aaaf2cc3SSona Mathew CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard)
42aaaf2cc3SSona Mathew
43aaaf2cc3SSona Mathew
44aaaf2cc3SSona Mathew /*
45aaaf2cc3SSona Mathew * +----------------------------+
46aaaf2cc3SSona Mathew * | Features supported |
47aaaf2cc3SSona Mathew * +----------------------------+
48aaaf2cc3SSona Mathew * | GENTIMER |
49aaaf2cc3SSona Mathew * +----------------------------+
50aaaf2cc3SSona Mathew * | FEAT_TTCNP |
51aaaf2cc3SSona Mathew * +----------------------------+
52aaaf2cc3SSona Mathew * | FEAT_AMU |
53aaaf2cc3SSona Mathew * +----------------------------+
54aaaf2cc3SSona Mathew * | FEAT_AMUV1P1 |
55aaaf2cc3SSona Mathew * +----------------------------+
56aaaf2cc3SSona Mathew * | FEAT_TRF |
57aaaf2cc3SSona Mathew * +----------------------------+
58aaaf2cc3SSona Mathew * | FEAT_SYS_REG_TRACE |
59aaaf2cc3SSona Mathew * +----------------------------+
60aaaf2cc3SSona Mathew * | FEAT_DIT |
61aaaf2cc3SSona Mathew * +----------------------------+
62aaaf2cc3SSona Mathew * | FEAT_PAN |
63aaaf2cc3SSona Mathew * +----------------------------+
64aaaf2cc3SSona Mathew * | FEAT_SSBS |
65aaaf2cc3SSona Mathew * +----------------------------+
66aaaf2cc3SSona Mathew * | FEAT_PMUV3 |
67aaaf2cc3SSona Mathew * +----------------------------+
68aaaf2cc3SSona Mathew * | FEAT_MTPMU |
69aaaf2cc3SSona Mathew * +----------------------------+
70aaaf2cc3SSona Mathew */
71aaaf2cc3SSona Mathew
72aaaf2cc3SSona Mathew /* GENTIMER */
730dfa07b6SOlivier Deprez __attribute__((always_inline))
is_armv7_gentimer_present(void)7429a24134SAntonio Nino Diaz static inline bool is_armv7_gentimer_present(void)
7529a24134SAntonio Nino Diaz {
76aaaf2cc3SSona Mathew return ISOLATE_FIELD(read_id_pfr1(), ID_PFR1_GENTIMER_SHIFT,
77aaaf2cc3SSona Mathew ID_PFR1_GENTIMER_MASK) != 0U;
7829a24134SAntonio Nino Diaz }
7929a24134SAntonio Nino Diaz
80aaaf2cc3SSona Mathew /* FEAT_TTCNP: Translation table common not private */
81aaaf2cc3SSona Mathew CREATE_FEATURE_PRESENT(feat_ttcnp, id_mmfr4, ID_MMFR4_CNP_SHIFT,
82aaaf2cc3SSona Mathew ID_MMFR4_CNP_MASK, 1U)
83aaaf2cc3SSona Mathew
84aaaf2cc3SSona Mathew /* 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)85aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_amu, id_pfr0, ID_PFR0_AMU_SHIFT,
86aaaf2cc3SSona Mathew ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1, ENABLE_FEAT_AMU)
87aaaf2cc3SSona Mathew
8883ec7e45SBoyan Karatotev /* Auxiliary counters for FEAT_AMU */
8983ec7e45SBoyan Karatotev CREATE_FEATURE_FUNCS(feat_amu_aux, amcfgr, AMCFGR_NCG_SHIFT,
9083ec7e45SBoyan Karatotev AMCFGR_NCG_MASK, 1U, ENABLE_AMU_AUXILIARY_COUNTERS)
9183ec7e45SBoyan Karatotev
92aaaf2cc3SSona Mathew /* FEAT_AMUV1P1: AMU Extension v1.1 */
93aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_amuv1p1, id_pfr0, ID_PFR0_AMU_SHIFT,
94aaaf2cc3SSona Mathew ID_PFR0_AMU_MASK, ID_PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1)
95aaaf2cc3SSona Mathew
96aaaf2cc3SSona Mathew /* FEAT_TRF: Tracefilter */
97aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_trf, id_dfr0, ID_DFR0_TRACEFILT_SHIFT,
98aaaf2cc3SSona Mathew ID_DFR0_TRACEFILT_MASK, 1U, ENABLE_TRF_FOR_NS)
99aaaf2cc3SSona Mathew
100aaaf2cc3SSona Mathew /* FEAT_SYS_REG_TRACE */
101aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_sys_reg_trace, id_dfr0, ID_DFR0_COPTRC_SHIFT,
102aaaf2cc3SSona Mathew ID_DFR0_COPTRC_MASK, 1U, ENABLE_SYS_REG_TRACE_FOR_NS)
103aaaf2cc3SSona Mathew
104aaaf2cc3SSona Mathew /* FEAT_DIT: Data independent timing */
105aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_dit, id_pfr0, ID_PFR0_DIT_SHIFT,
106aaaf2cc3SSona Mathew ID_PFR0_DIT_MASK, 1U, ENABLE_FEAT_DIT)
107aaaf2cc3SSona Mathew
108aaaf2cc3SSona Mathew /* FEAT_PAN: Privileged access never */
109aaaf2cc3SSona Mathew CREATE_FEATURE_FUNCS(feat_pan, id_mmfr3, ID_MMFR3_PAN_SHIFT,
110aaaf2cc3SSona Mathew ID_MMFR3_PAN_MASK, 1U, ENABLE_FEAT_PAN)
111aaaf2cc3SSona Mathew
112aaaf2cc3SSona Mathew /* FEAT_SSBS: Speculative store bypass safe */
113aaaf2cc3SSona Mathew CREATE_FEATURE_PRESENT(feat_ssbs, id_pfr2, ID_PFR2_SSBS_SHIFT,
114aaaf2cc3SSona Mathew ID_PFR2_SSBS_MASK, 1U)
115aaaf2cc3SSona Mathew
116aaaf2cc3SSona Mathew /* FEAT_PMUV3 */
117aaaf2cc3SSona Mathew CREATE_FEATURE_PRESENT(feat_pmuv3, id_dfr0, ID_DFR0_PERFMON_SHIFT,
118aaaf2cc3SSona Mathew ID_DFR0_PERFMON_MASK, 3U)
119aaaf2cc3SSona Mathew
120aaaf2cc3SSona Mathew /* FEAT_MTPMU */
1210dfa07b6SOlivier Deprez __attribute__((always_inline))
122aaaf2cc3SSona Mathew static inline bool is_feat_mtpmu_present(void)
1232559b2c8SAntonio Nino Diaz {
124aaaf2cc3SSona Mathew unsigned int mtpmu = ISOLATE_FIELD(read_id_dfr1(), ID_DFR1_MTPMU_SHIFT,
125aaaf2cc3SSona Mathew ID_DFR1_MTPMU_MASK);
126aaaf2cc3SSona Mathew return (mtpmu != 0U) && (mtpmu != MTPMU_NOT_IMPLEMENTED);
1272559b2c8SAntonio Nino Diaz }
CREATE_FEATURE_SUPPORTED(feat_mtpmu,is_feat_mtpmu_present,DISABLE_MTPMU)128aaaf2cc3SSona Mathew CREATE_FEATURE_SUPPORTED(feat_mtpmu, is_feat_mtpmu_present, DISABLE_MTPMU)
12930f05b4fSManish Pandey
130733d112fSAndre Przywara /*
131733d112fSAndre Przywara * TWED, ECV, CSV2, RAS are only used by the AArch64 EL2 context switch
132733d112fSAndre Przywara * code. In fact, EL2 context switching is only needed for AArch64 (since
133733d112fSAndre Przywara * there is no secure AArch32 EL2), so just disable these features here.
134733d112fSAndre Przywara */
1350dfa07b6SOlivier Deprez __attribute__((always_inline))
136733d112fSAndre Przywara static inline bool is_feat_twed_supported(void) { return false; }
1370dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_ecv_supported(void)138733d112fSAndre Przywara static inline bool is_feat_ecv_supported(void) { return false; }
1390dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_ecv_v2_supported(void)140733d112fSAndre Przywara static inline bool is_feat_ecv_v2_supported(void) { return false; }
1410dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_csv2_2_supported(void)142733d112fSAndre Przywara static inline bool is_feat_csv2_2_supported(void) { return false; }
1430dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_csv2_3_supported(void)14430019d86SSona Mathew static inline bool is_feat_csv2_3_supported(void) { return false; }
1450dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_ras_supported(void)146733d112fSAndre Przywara static inline bool is_feat_ras_supported(void) { return false; }
147733d112fSAndre Przywara
148733d112fSAndre Przywara /* The following features are supported in AArch64 only. */
1490dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_vhe_supported(void)150733d112fSAndre Przywara static inline bool is_feat_vhe_supported(void) { return false; }
1510dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sel2_supported(void)152733d112fSAndre Przywara static inline bool is_feat_sel2_supported(void) { return false; }
1530dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_fgt_supported(void)154733d112fSAndre Przywara static inline bool is_feat_fgt_supported(void) { return false; }
1550dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_tcr2_supported(void)156733d112fSAndre Przywara static inline bool is_feat_tcr2_supported(void) { return false; }
1570dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_spe_supported(void)158733d112fSAndre Przywara static inline bool is_feat_spe_supported(void) { return false; }
1590dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_rng_supported(void)160733d112fSAndre Przywara static inline bool is_feat_rng_supported(void) { return false; }
1610dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_gcs_supported(void)162733d112fSAndre Przywara static inline bool is_feat_gcs_supported(void) { return false; }
1630dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_mte2_supported(void)1648e397889SGovindraj Raja static inline bool is_feat_mte2_supported(void) { return false; }
1650dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_mpam_supported(void)166733d112fSAndre Przywara static inline bool is_feat_mpam_supported(void) { return false; }
1670dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_hcx_supported(void)168733d112fSAndre Przywara static inline bool is_feat_hcx_supported(void) { return false; }
1690dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sve_supported(void)170733d112fSAndre Przywara static inline bool is_feat_sve_supported(void) { return false; }
1710dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_brbe_supported(void)172733d112fSAndre Przywara static inline bool is_feat_brbe_supported(void) { return false; }
1730dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_trbe_supported(void)174733d112fSAndre Przywara static inline bool is_feat_trbe_supported(void) { return false; }
1750dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_nv2_supported(void)176733d112fSAndre Przywara static inline bool is_feat_nv2_supported(void) { return false; }
1770dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sme_supported(void)178733d112fSAndre Przywara static inline bool is_feat_sme_supported(void) { return false; }
1790dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sme2_supported(void)180733d112fSAndre Przywara static inline bool is_feat_sme2_supported(void) { return false; }
1810dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_s2poe_supported(void)182733d112fSAndre Przywara static inline bool is_feat_s2poe_supported(void) { return false; }
1830dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_s1poe_supported(void)184733d112fSAndre Przywara static inline bool is_feat_s1poe_supported(void) { return false; }
1850dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sxpoe_supported(void)186733d112fSAndre Przywara static inline bool is_feat_sxpoe_supported(void) { return false; }
1870dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_s2pie_supported(void)188733d112fSAndre Przywara static inline bool is_feat_s2pie_supported(void) { return false; }
1890dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_s1pie_supported(void)190733d112fSAndre Przywara static inline bool is_feat_s1pie_supported(void) { return false; }
1910dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sxpie_supported(void)192733d112fSAndre Przywara static inline bool is_feat_sxpie_supported(void) { return false; }
1930dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_uao_present(void)19430f05b4fSManish Pandey static inline bool is_feat_uao_present(void) { return false; }
1950dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_nmi_present(void)19630f05b4fSManish Pandey static inline bool is_feat_nmi_present(void) { return false; }
1970dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_ebep_present(void)19830f05b4fSManish Pandey static inline bool is_feat_ebep_present(void) { return false; }
1990dfa07b6SOlivier Deprez __attribute__((always_inline))
is_feat_sebep_present(void)20030f05b4fSManish Pandey static inline bool is_feat_sebep_present(void) { return false; }
20130655136SGovindraj Raja __attribute__((always_inline))
is_feat_d128_present(void)20230655136SGovindraj Raja static inline bool is_feat_d128_present(void) { return false; }
20319d52a83SAndre Przywara __attribute__((always_inline))
is_feat_ls64_accdata_present(void)20419d52a83SAndre Przywara static inline bool is_feat_ls64_accdata_present(void) { return false; }
2058656bdabSArvind Ram Prakash __attribute__((always_inline))
is_feat_mops_supported(void)2068656bdabSArvind Ram Prakash static inline bool is_feat_mops_supported(void) { return false; }
20710ecd580SBoyan Karatotev __attribute__((always_inline))
is_feat_bti_supported(void)20810ecd580SBoyan Karatotev static inline bool is_feat_bti_supported(void) { return false; }
209*b0b7609eSBoyan Karatotev __attribute__((always_inline))
is_feat_pauth_supported(void)210*b0b7609eSBoyan Karatotev static inline bool is_feat_pauth_supported(void) { return false; }
211733d112fSAndre Przywara
2122559b2c8SAntonio Nino Diaz #endif /* ARCH_FEATURES_H */
213