summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorBoyan Karatotev <boyan.karatotev@arm.com>2026-05-12 11:30:57 +0100
committerBoyan Karatotev <boyan.karatotev@arm.com>2026-06-19 15:12:03 +0100
commit53e114b38424df419d3f1d814313fee0283ff436 (patch)
tree16c039e0ee76e221ca8176d877cc6bb5fd022fc1 /include
parent64d14b6a35a6ac81c4125b65b0bc933d83d1ee1f (diff)
downloadarm-trusted-firmware-53e114b38424df419d3f1d814313fee0283ff436.tar.gz
arm-trusted-firmware-53e114b38424df419d3f1d814313fee0283ff436.zip
feat(cpufeat): create a central feature database
The original purpose of the arch_features.h header was abstract away the detection details for Architectural features into a central place. Over time this has grown to a fully featured framework - ENABLE_FEAT. However, as its scope has grown its promise of being a central repository has faltered - there are independent lists of FEATURE_DETECTION and FEAT_IDTE3. As a result, reasoning about all the checkboxes a feature must tick is very convoluted and prone to errors. Further, untangling what type a feature is rather difficult and requires an understanding of the various CREATE_* helpers, of which there are many permutations. This patch resolves all of this by collating a truly central repository for all ID related information about all Architectural features TF-A needs to know about. Every feature receives a single X macro that contains the 7 bits of information needed to reason about the features' ID state: the ID register, field, and min/max known values, the enable flag, and which worlds it'll be enabled for. This effectively combines the present information in arch_features.h and feat_detect.c. Each entry has been manually checked that it's been carried forward. Then, features are organised into a handful of lists for easy usage. These lists are used to generate the is_feat_abc_supported() functions, check them with FEATURE_DETECTION, and mask them with FEAT_IDTE3. Each function can pick and choose what it needs with an expansion macro. Like errata, most features fit the central pattern exactly, but a minority do not. Similarly to the errata framework, the architecture features list can be unravelled progressively to allow as much reuse as possible. This patch surfaces a bug: FEAT_LS64_ACCDATA's feature detection min value is 1 whereas it should be 3. This patch corrects this. Another implicit modification is that the check_if_trbe_disable_affected_core() call is omitted from the IDTE3 entry for FEAT_TRBE. This is because cores that observe this erratum do not have FEAT_IDTE3 so the added complexity is not needed. Along the central premise of the patch, some housekeeping must happen atomically: * FEAT_CRYPTO is downgraded from an architectural feature to a helper - there is no ID register to check but the feature is always present when either FEAT_AES or FEAT_SHA1 (and its superset FEAT_SHA2) are present. Those are added as full features * FEAT_IESB becomes a full feature, although it's only used for feature detection * the format of FEATURE_DETECTION changes ever so slightly to avoid having to carry another entry in the database * FEAT_IDTE3 receives a cosmetic rename to make things clearer * FEAT_SSBS is now checked with FEATURE_DETECTION and awareness is checked up to FEAT_SSBS2 * comments are moved towards their central locations and taken away from the leaves Change-Id: I0c02c3f18df6a80dc34ee81e304902ced3e3cdbb Signed-off-by: Boyan Karatotev <boyan.karatotev@arm.com>
Diffstat (limited to 'include')
-rw-r--r--include/arch/aarch32/arch_features.h15
-rw-r--r--include/arch/aarch64/arch.h65
-rw-r--r--include/arch/aarch64/arch_features.h1035
-rw-r--r--include/common/feat_detect.h33
4 files changed, 560 insertions, 588 deletions
diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h
index b1e444a29..0c5cb071e 100644
--- a/include/arch/aarch32/arch_features.h
+++ b/include/arch/aarch32/arch_features.h
@@ -12,12 +12,15 @@
#include <arch_helpers.h>
#include <common/feat_detect.h>
-#define CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
-_CREATE_FEATURE_PRESENT(name, idreg, idfield, idval)
-
-#define CREATE_FEATURE_FUNCS(name, idreg, idfield, idval, guard) \
-CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
-CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard)
+#define CREATE_FEATURE_PRESENT(name, idreg, field, min) \
+ _CREATE_FEATURE_ID_FIELD(name, idreg, guard, field, min, NA, NA) \
+ _CREATE_FEATURE_PRESENT(name, NA, NA, field, min, NA, NA)
+#define CREATE_FEATURE_SUPPORTED(name, idreg, field, min, guard) \
+ _CREATE_FEATURE_SUPPORTED(name, idreg, guard, field, min, NA, NA)
+
+#define CREATE_FEATURE_FUNCS(name, idreg, field, min, guard) \
+ CREATE_FEATURE_PRESENT(name, idreg, field, min) \
+ CREATE_FEATURE_SUPPORTED(name, idreg, field, min, guard)
__attribute__((always_inline))
static inline bool is_armv7_gentimer_present(void)
diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h
index e23bb26e7..b9c4bd69e 100644
--- a/include/arch/aarch64/arch.h
+++ b/include/arch/aarch64/arch.h
@@ -220,8 +220,6 @@
#define ID_AA64PFR0_AMU_SHIFT U(44)
#define ID_AA64PFR0_AMU_WIDTH U(4)
-#define ID_AA64PFR0_AMU_V1 ULL(0x1)
-#define ID_AA64PFR0_AMU_V1P1 U(0x2)
#define ID_AA64PFR0_ELX_MASK ULL(0xf)
#define ID_AA64PFR0_EL0_MASK ID_AA64PFR0_ELX_MASK
@@ -235,7 +233,6 @@
#define ID_AA64PFR0_SVE_SHIFT U(32)
#define ID_AA64PFR0_SVE_WIDTH U(4)
#define ID_AA64PFR0_SVE_LENGTH U(4)
-#define SVE_IMPLEMENTED ULL(0x1)
#define ID_AA64PFR0_SEL2_SHIFT U(36)
#define ID_AA64PFR0_SEL2_WIDTH U(4)
@@ -246,19 +243,14 @@
#define ID_AA64PFR0_DIT_SHIFT U(48)
#define ID_AA64PFR0_DIT_WIDTH U(4)
#define ID_AA64PFR0_DIT_LENGTH U(4)
-#define DIT_IMPLEMENTED ULL(1)
#define ID_AA64PFR0_CSV2_SHIFT U(56)
#define ID_AA64PFR0_CSV2_WIDTH U(4)
#define ID_AA64PFR0_CSV2_LENGTH U(4)
-#define CSV2_2_IMPLEMENTED ULL(0x2)
-#define CSV2_3_IMPLEMENTED ULL(0x3)
#define ID_AA64PFR0_FEAT_RME_SHIFT U(52)
#define ID_AA64PFR0_FEAT_RME_WIDTH U(4)
#define ID_AA64PFR0_FEAT_RME_LENGTH U(4)
-#define RME_NOT_IMPLEMENTED ULL(0)
-#define RME_GPC2_IMPLEMENTED ULL(0x2)
#define ID_AA64PFR0_RAS_SHIFT U(28)
#define ID_AA64PFR0_RAS_WIDTH U(4)
@@ -272,7 +264,6 @@
/* ID_AA64DFR0_EL1.DebugVer definitions */
#define ID_AA64DFR0_DEBUGVER_SHIFT U(0)
#define ID_AA64DFR0_DEBUGVER_WIDTH U(4)
-#define DEBUGVER_V8P9_IMPLEMENTED ULL(0xb)
/* ID_AA64DFR0_EL1.TraceVer definitions */
#define ID_AA64DFR0_TRACEVER_SHIFT U(4)
@@ -282,45 +273,35 @@
#define ID_AA64DFR0_TRACEFILT_SHIFT U(40)
#define ID_AA64DFR0_TRACEFILT_WIDTH U(4)
#define ID_AA64DFR0_TRACEFILT_LENGTH U(4)
-#define TRACEFILT_IMPLEMENTED ULL(1)
#define ID_AA64DFR0_PMUVER_LENGTH U(4)
#define ID_AA64DFR0_PMUVER_SHIFT U(8)
#define ID_AA64DFR0_PMUVER_WIDTH U(4)
#define ID_AA64DFR0_PMUVER_PMUV3 U(1)
-#define ID_AA64DFR0_PMUVER_PMUV3P9 U(9)
-#define ID_AA64DFR0_PMUVER_IMP_DEF U(0xf)
/* ID_AA64DFR0_EL1.SEBEP definitions */
#define ID_AA64DFR0_SEBEP_SHIFT U(24)
#define ID_AA64DFR0_SEBEP_WIDTH U(4)
-#define SEBEP_IMPLEMENTED ULL(1)
/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */
#define ID_AA64DFR0_PMS_SHIFT U(32)
#define ID_AA64DFR0_PMS_WIDTH U(4)
-#define SPE_IMPLEMENTED ULL(0x1)
-#define SPE_NOT_IMPLEMENTED ULL(0x0)
/* ID_AA64DFR0_EL1.TraceBuffer definitions */
#define ID_AA64DFR0_TRACEBUFFER_SHIFT U(44)
#define ID_AA64DFR0_TRACEBUFFER_WIDTH U(4)
-#define TRACEBUFFER_IMPLEMENTED ULL(1)
/* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */
#define ID_AA64DFR0_MTPMU_SHIFT U(48)
#define ID_AA64DFR0_MTPMU_WIDTH U(4)
-#define MTPMU_IMPLEMENTED ULL(1)
/* ID_AA64DFR0_EL1.BRBE definitions */
#define ID_AA64DFR0_BRBE_SHIFT U(52)
#define ID_AA64DFR0_BRBE_WIDTH U(4)
-#define BRBE_IMPLEMENTED ULL(1)
/* ID_AA64DFR1_EL1 definitions */
#define ID_AA64DFR1_EBEP_SHIFT U(48)
#define ID_AA64DFR1_EBEP_WIDTH U(4)
-#define EBEP_IMPLEMENTED ULL(1)
#define ID_AA64DFR1_BRP_SHIFT U(8)
#define ID_AA64DFR1_BRP_WIDTH U(8)
@@ -356,15 +337,9 @@
#define ID_AA64ISAR1_LS64_SHIFT U(60)
#define ID_AA64ISAR1_LS64_WIDTH U(4)
-#define LS64_ACCDATA_IMPLEMENTED ULL(0x3)
-#define LS64_V_IMPLEMENTED ULL(0x2)
-#define LS64_IMPLEMENTED ULL(0x1)
-#define LS64_NOT_IMPLEMENTED ULL(0x0)
#define ID_AA64ISAR1_SB_SHIFT U(36)
#define ID_AA64ISAR1_SB_WIDTH U(4)
-#define SB_IMPLEMENTED ULL(0x1)
-#define SB_NOT_IMPLEMENTED ULL(0x0)
#define ID_AA64ISAR1_GPI_SHIFT U(28)
#define ID_AA64ISAR1_GPI_WIDTH UL(4)
@@ -381,8 +356,6 @@
#define ID_AA64ISAR2_EL1_MOPS_SHIFT U(16)
#define ID_AA64ISAR2_EL1_MOPS_WIDTH U(4)
-#define MOPS_IMPLEMENTED ULL(0x1)
-
#define ID_AA64ISAR2_GPA3_SHIFT U(8)
#define ID_AA64ISAR2_GPA3_WIDTH U(4)
@@ -400,8 +373,6 @@
#define ID_AA64ISAR3_EL1_CPA_SHIFT U(0)
#define ID_AA64ISAR3_EL1_CPA_WIDTH U(4)
-#define CPA2_IMPLEMENTED ULL(0x2)
-
/* ID_AA64MMFR0_EL1 definitions */
#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0)
#define ID_AA64MMFR0_EL1_PARANGE_WIDTH U(4)
@@ -417,14 +388,9 @@
#define ID_AA64MMFR0_EL1_ECV_SHIFT U(60)
#define ID_AA64MMFR0_EL1_ECV_WIDTH U(4)
-#define ID_AA64MMFR0_EL1_ECV_SELF_SYNCH ULL(0x2)
-#define ECV_IMPLEMENTED ULL(0x1)
#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56)
#define ID_AA64MMFR0_EL1_FGT_WIDTH U(4)
-#define FGT2_IMPLEMENTED ULL(0x2)
-#define FGT_IMPLEMENTED ULL(0x1)
-#define FGT_NOT_IMPLEMENTED ULL(0x0)
#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28)
#define ID_AA64MMFR0_EL1_TGRAN4_WIDTH U(4)
@@ -434,29 +400,22 @@
#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20)
#define ID_AA64MMFR0_EL1_TGRAN16_WIDTH U(4)
-#define TGRAN16_IMPLEMENTED ULL(0x1)
/* ID_AA64MMFR1_EL1 definitions */
#define ID_AA64MMFR1_EL1_TWED_SHIFT U(32)
#define ID_AA64MMFR1_EL1_TWED_WIDTH U(4)
-#define TWED_IMPLEMENTED ULL(0x1)
#define ID_AA64MMFR1_EL1_HAFDBS_SHIFT U(0)
#define ID_AA64MMFR1_EL1_HAFDBS_WIDTH U(4)
-#define HDBSS_IMPLEMENTED ULL(0x4)
#define ID_AA64MMFR1_EL1_PAN_SHIFT U(20)
#define ID_AA64MMFR1_EL1_PAN_WIDTH U(4)
-#define PAN_IMPLEMENTED ULL(0x1)
-#define PAN2_IMPLEMENTED ULL(0x2)
-#define PAN3_IMPLEMENTED ULL(0x3)
#define ID_AA64MMFR1_EL1_VHE_SHIFT U(8)
#define ID_AA64MMFR1_EL1_VHE_WIDTH U(4)
#define ID_AA64MMFR1_EL1_HCX_SHIFT U(40)
#define ID_AA64MMFR1_EL1_HCX_WIDTH U(4)
-#define HCX_IMPLEMENTED ULL(0x1)
/* ID_AA64MMFR2_EL1 definitions */
#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2
@@ -481,14 +440,12 @@
#define ID_AA64MMFR2_EL1_NV_SHIFT U(24)
#define ID_AA64MMFR2_EL1_NV_WIDTH U(4)
-#define NV2_IMPLEMENTED ULL(0x2)
/* ID_AA64MMFR3_EL1 definitions */
#define ID_AA64MMFR3_EL1 S3_0_C0_C7_3
#define ID_AA64MMFR3_EL1_D128_SHIFT U(32)
#define ID_AA64MMFR3_EL1_D128_WIDTH U(4)
-#define D128_IMPLEMENTED ULL(0x1)
#define ID_AA64MMFR3_EL1_MEC_SHIFT U(28)
#define ID_AA64MMFR3_EL1_MEC_WIDTH U(4)
@@ -510,7 +467,6 @@
#define ID_AA64MMFR3_EL1_SCTLR2_SHIFT U(4)
#define ID_AA64MMFR3_EL1_SCTLR2_WIDTH U(4)
-#define SCTLR2_IMPLEMENTED ULL(1)
#define ID_AA64MMFR3_EL1_TCRX_SHIFT U(0)
#define ID_AA64MMFR3_EL1_TCRX_WIDTH U(4)
@@ -520,42 +476,33 @@
#define ID_AA64MMFR4_EL1_HACDBS_SHIFT U(12)
#define ID_AA64MMFR4_EL1_HACDBS_WIDTH U(4)
-#define HACDBS_IMPLEMENTED ULL(0x1)
#define ID_AA64MMFR4_EL1_FGWTE3_SHIFT U(16)
#define ID_AA64MMFR4_EL1_FGWTE3_WIDTH U(4)
-#define FGWTE3_IMPLEMENTED ULL(0x1)
#define ID_AA64MMFR4_EL1_RME_GDI_SHIFT U(28)
#define ID_AA64MMFR4_EL1_RME_GDI_WIDTH U(4)
#define ID_AA64MMFR4_EL1_RME_GDI_LENGTH U(4)
-#define RME_GDI_IMPLEMENTED ULL(0x1)
/* ID_AA64PFR1_EL1 definitions */
#define ID_AA64PFR1_EL1_BT_SHIFT U(0)
#define ID_AA64PFR1_EL1_BT_WIDTH U(4)
-#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */
#define ID_AA64PFR1_EL1_SSBS_SHIFT U(4)
#define ID_AA64PFR1_EL1_SSBS_WIDTH U(4)
-#define SSBS_NOT_IMPLEMENTED ULL(0) /* No architectural SSBS support */
#define ID_AA64PFR1_EL1_RNDR_TRAP_SHIFT U(28)
#define ID_AA64PFR1_EL1_RNDR_TRAP_WIDTH U(4)
-#define RNG_TRAP_IMPLEMENTED ULL(0x1)
#define ID_AA64PFR1_EL1_NMI_SHIFT U(36)
#define ID_AA64PFR1_EL1_NMI_WIDTH U(4)
-#define NMI_IMPLEMENTED ULL(1)
#define ID_AA64PFR1_EL1_GCS_SHIFT U(44)
#define ID_AA64PFR1_EL1_GCS_WIDTH U(4)
-#define GCS_IMPLEMENTED ULL(1)
#define ID_AA64PFR1_EL1_THE_SHIFT U(48)
#define ID_AA64PFR1_EL1_THE_WIDTH U(4)
-#define THE_IMPLEMENTED ULL(1)
#define ID_AA64PFR1_EL1_PFAR_SHIFT U(60)
#define ID_AA64PFR1_EL1_PFAR_WIDTH U(4)
@@ -564,7 +511,6 @@
#define ID_AA64PFR1_EL1_CE_SHIFT U(20)
#define ID_AA64PFR1_EL1_CE_WIDTH U(4)
/* 0b0000 means Morello arch is not present, 0b0001 means it is present */
-#define MORELLO_EXTENSION_IMPLEMENTED ULL(0x1)
#define CSCR_EL3_SETTAG ULL(0x1)
/* ID_AA64PFR1_EL1.MTE field: MTE architecture presence (bits [11:8]) */
@@ -585,13 +531,10 @@
#define ID_AA64PFR2_EL1_UINJ_SHIFT U(16)
#define ID_AA64PFR2_EL1_UINJ_WIDTH U(4)
-#define UINJ_IMPLEMENTED ULL(0x1)
#define ID_AA64PFR2_EL1_FPMR_SHIFT U(32)
#define ID_AA64PFR2_EL1_FPMR_WIDTH U(4)
-#define FPMR_IMPLEMENTED ULL(0x1)
-
#define VDISR_EL2 S3_4_C12_C1_1
#define VSESR_EL2 S3_4_C5_C2_3
@@ -612,9 +555,6 @@
#define ID_AA64PFR1_EL1_SME_SHIFT U(24)
#define ID_AA64PFR1_EL1_SME_WIDTH U(4)
-#define SME_IMPLEMENTED ULL(0x1)
-#define SME2_IMPLEMENTED ULL(0x2)
-#define SME_NOT_IMPLEMENTED ULL(0x0)
/* ID_AA64PFR2_EL1 definitions */
#define ID_AA64PFR2_EL1 S3_0_C0_C4_2
@@ -1453,11 +1393,8 @@
/* ID_AA64SMFR0_EL1 definitions */
#define ID_AA64SMFR0_EL1_SME_FA64_SHIFT U(63)
#define ID_AA64SMFR0_EL1_SME_FA64_WIDTH U(1)
-#define SME_FA64_IMPLEMENTED U(0x1)
#define ID_AA64SMFR0_EL1_SME_VER_SHIFT U(55)
#define ID_AA64SMFR0_EL1_SME_VER_MASK ULL(0xf)
-#define SME_INST_IMPLEMENTED ULL(0x0)
-#define SME2_INST_IMPLEMENTED ULL(0x1)
/* SMCR_ELx definitions */
#define SMCR_ELX_LEN_SHIFT U(0)
@@ -1637,6 +1574,8 @@
#define MPAM2_EL2_TRAPMPAM1EL1 (ULL(1) << 48)
#define MPAMIDR_HAS_BW_CTRL_BIT (ULL(1) << 56)
+#define MPAMIDR_HAS_BW_CTRL_SHIFT U(56)
+#define MPAMIDR_HAS_BW_CTRL_WIDTH U(1)
#define MPAMIDR_HAS_HCR_BIT (ULL(1) << 17)
/* MPAM_PE_BW_CTRL register definitions */
diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h
index b56062663..c90fbb631 100644
--- a/include/arch/aarch64/arch_features.h
+++ b/include/arch/aarch64/arch_features.h
@@ -31,141 +31,493 @@
#define FEAT_ENABLE_SECURE (1 << CPU_CONTEXT_SECURE)
#define FEAT_ENABLE_NS (1 << CPU_CONTEXT_NS)
-#define SHOULD_ID_FIELD_DISABLE(guard, enabled_worlds, world) \
- (((guard) == 0U) || ((((enabled_worlds) >> (world)) & 1U) == 0U))
+#define CREATE_FEATURE_ID_FIELD _CREATE_FEATURE_ID_FIELD
+#define CREATE_FEATURE_PRESENT _CREATE_FEATURE_PRESENT
+#define CREATE_FEATURE_SUPPORTED _CREATE_FEATURE_SUPPORTED
+#define CREATE_FEATURE_FUNCS(name, idreg, guard, field, min, max, worlds) \
+ CREATE_FEATURE_ID_FIELD(name, idreg, guard, field, min, max, worlds) \
+ CREATE_FEATURE_PRESENT(name, idreg, guard, field, min, max, worlds) \
+ CREATE_FEATURE_SUPPORTED(name, idreg, guard, field, min, max, worlds)
-/*
- * CREATE_IDREG_UPDATE and CREATE_PERCPU_IDREG_UPDATE are two macros that
- * generate the update_feat_abc_idreg_field() function based on how its
- * corresponding ID register is cached.
- * The function disables ID register fields related to a feature if the build
- * flag for that feature is 0 or if the feature should be disabled for that
- * world. If the particular field has to be disabled, its field in the cached
- * ID register is set to 0.
- *
- * Note: For most ID register fields, a value of 0 represents
- * the Unimplemented state, and hence we use this macro to show features
- * disabled in EL3 as unimplemented to lower ELs. However, certain feature's
- * ID Register fields (like ID_AA64MMFR4_EL1.E2H0) deviate from this convention,
- * where 0 does not represent Unimplemented.
- * For those features, a custom update_feat_abc_idreg_field()
- * needs to be created. This custom function should set the field to the
- * feature's unimplemented state value if the feature is disabled in EL3.
+/*******************************************************************************
+ * THE ARCHITECTURE FEATURES LIST.
*
- * For example:
+ * TF-A supports many Arm architectural features starting from arch version 8.0
+ * onwards. These features are mostly enabled through build flags, and are
+ * discoverable in hardware through standard ID registers. This is the central
+ * database to encode all necessary information to manipulate any given feature.
+ * If TF-A needs to interact with a feature, it must be registered here with a
+ * templating macro that's to be called with 7 arguments:
+ * * name - the lowercase name of the feature as it appears in the ARM Arm
+ * * idreg - the name of the ID register where this feature is listed
+ * * guard - the tri-state (``ENABLE_FEAT`` compliant) flag for the feature
+ * * field - the base name of the macros for a field of the ID register above
+ * that identifies this feature.
+ * * min - the minimum value the field above can take for the feature to be
+ * considered implemented.
+ * * max - the maximum value for the field that support has been validated for
+ * * worlds - a bitmap of which non-root worlds the feature is enabled for
+
+ * The database is used to automatically generate accessors, validators, and
+ * meta-feature (like FEAT_IDTE3) boilerplate.
*
- * __attribute__((always_inline))
- * static inline void update_feat_abc_idreg_field(size_t security_state)
- * {
- * if (SHOULD_ID_FIELD_DISABLE(guard, enabled_worlds, security_state)) {
- * per_world_context_t *per_world_ctx =
- * &per_world_context[security_state];
- * perworld_idregs_t *perworld_idregs = &(per_world_ctx->idregs);
+ * Some features don't need or don't fit into this pattern. The template can be
+ * unravelled and unnecessary/illogical information should be replaced with "NA"
+ * placeholders. You should familiarize with the usage of CPUFEAT_LIST before
+ * going that path. A good example of this is FEAT_PAuth.
*
- * perworld_idregs->idreg &= ~((u_register_t)MASK(idfield));
- * perworld_idregs->idreg |=
- * ((u_register_t)<unimplemented state value> << idfield##_SHIFT);
- * }
- * }
- */
-
-#if (ENABLE_FEAT_IDTE3 && IMAGE_BL31)
-#define CREATE_IDREG_UPDATE(name, idreg, idfield, guard, enabled_worlds) \
- __attribute__((always_inline)) \
-static inline void update_ ## name ## _idreg_field(size_t security_state) \
-{ \
- if (SHOULD_ID_FIELD_DISABLE(guard, enabled_worlds, security_state)) { \
- per_world_context_t *per_world_ctx = \
- &per_world_context[security_state]; \
- perworld_idregs_t *perworld_idregs = &(per_world_ctx->idregs); \
- perworld_idregs->idreg &= ~((u_register_t)MASK(idfield)); \
- } \
-}
-#define CREATE_PERCPU_IDREG_UPDATE(name, idreg, idfield, guard, \
- enabled_worlds) \
- __attribute__((always_inline)) \
-static inline void update_ ## name ## _idreg_field(size_t security_state) \
-{ \
- if (SHOULD_ID_FIELD_DISABLE(guard, enabled_worlds, security_state)) { \
- percpu_idregs_t *percpu_idregs = \
- &(get_cpu_data(idregs[security_state]));\
- percpu_idregs->idreg &= ~((u_register_t)MASK(idfield)); \
- } \
-}
-#else
-#define CREATE_IDREG_UPDATE(name, idreg, idfield, guard, enabled_worlds)
-#define CREATE_PERCPU_IDREG_UPDATE(name, idreg, idfield, guard, \
- enabled_worlds)
-#endif
-
-#define _CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
-__attribute__((always_inline)) \
-static inline unsigned int read_ ## name ## _id_field(void) \
-{ \
- return (unsigned int)EXTRACT(idfield, read_ ## idreg()); \
-} \
-__attribute__((always_inline)) \
-static inline bool is_ ## name ## _present(void) \
-{ \
- return (read_ ## name ## _id_field() >= idval) ? true : false; \
-}
-
-#define CREATE_FEATURE_PRESENT(name, idreg, idfield, idval, \
- enabled_worlds) \
- _CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
- CREATE_IDREG_UPDATE(name, idreg, idfield, 1U, enabled_worlds)
-
-#define CREATE_PERCPU_FEATURE_PRESENT(name, idreg, idfield, idval, \
- enabled_worlds) \
- _CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
- CREATE_PERCPU_IDREG_UPDATE(name, idreg, idfield, 1U, \
- enabled_worlds)
-
-#define CREATE_FEATURE_FUNCS(name, idreg, idfield, idval, guard, \
- enabled_worlds) \
- CREATE_FEATURE_PRESENT(name, idreg, idfield, idval, \
- enabled_worlds) \
- CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard)
-
-#define CREATE_PERCPU_FEATURE_FUNCS(name, idreg, idfield, idval, guard, \
- enabled_worlds) \
- CREATE_PERCPU_FEATURE_PRESENT(name, idreg, idfield, idval, \
- enabled_worlds) \
- CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard)
-
-__attribute__((always_inline))
-static inline bool is_armv7_gentimer_present(void)
-{
- /* The Generic Timer is always present in an ARMv8-A implementation */
- return true;
-}
+ * Please put features in the version section according to the feature's chapter
+ * in the Arm ARM. For example, if a feature is part of the Armv9.5 extension,
+ * it is optional from Armv9.4 and mandatory from Armv9.6, then it should be in
+ * the Armv9.5 section below.
+ ******************************************************************************/
-CREATE_FEATURE_FUNCS(feat_pan, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_PAN,
- 1U, ENABLE_FEAT_PAN,
- FEAT_ENABLE_ALL_WORLDS)
+/* === v8.0 features === */
+#define FEAT_CSV2_2(gen) \
+ gen(feat_csv2_2, id_aa64pfr0_el1, ENABLE_FEAT_CSV2_2, \
+ ID_AA64PFR0_CSV2, 2U, 3U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-CREATE_FEATURE_FUNCS(feat_vhe, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_VHE,
- 1U, ENABLE_FEAT_VHE,
- FEAT_ENABLE_ALL_WORLDS)
+#define FEAT_CSV2_3(gen) \
+ gen(feat_csv2_3, id_aa64pfr0_el1, ENABLE_FEAT_CSV2_3, \
+ ID_AA64PFR0_CSV2, 3U, 3U, FEAT_ENABLE_ALL_WORLDS)
-CREATE_FEATURE_PRESENT(feat_ttcnp, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_CNP,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_PRESENT(feat_uao, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_UAO,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-__attribute__((always_inline))
-static inline bool is_feat_pacqarma3_present(void)
-{
- u_register_t isar2 = read_id_aa64isar2_el1();
+/*
+ * Even though the PMUv3 is an OPTIONAL feature, it is always implemented and
+ * Arm prescribes so. So assume it will be there and do away with a flag for it.
+ * This is used to check minor PMUv3px revisions so that we catch them as they
+ * come along
+ */
+#define FEAT_PMUV3(gen) \
+ gen(feat_pmuv3, id_aa64dfr0_el1, FEAT_STATE_ALWAYS, \
+ ID_AA64DFR0_PMUVER, 1U, 9U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TGRAN16K(gen) \
+ gen(feat_tgran16K, id_aa64mmfr0_el1, FEAT_STATE_CHECKED, \
+ ID_AA64MMFR0_EL1_TGRAN16, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_AES(gen) \
+ gen(feat_aes, id_aa64isar0_el1, ENABLE_FEAT_CRYPTO, \
+ ID_AA64ISAR0_AES, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SHA1(gen) \
+ gen(feat_sha1, id_aa64isar0_el1, ENABLE_FEAT_CRYPTO, \
+ ID_AA64ISAR0_SHA1, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* Not named in the architecture. Relates to FEAT_TRC_SR */
+#define FEAT_SYS_REG_TRACE(gen) \
+ gen(feat_sys_reg_trace, id_aa64dfr0_el1, ENABLE_SYS_REG_TRACE_FOR_NS, \
+ ID_AA64DFR0_TRACEVER, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.1 features === */
+#define FEAT_PAN(gen) \
+ gen(feat_pan, id_aa64mmfr1_el1, ENABLE_FEAT_PAN, \
+ ID_AA64MMFR1_EL1_PAN, 1U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_LSE(gen) \
+ gen(feat_lse, id_aa64isar0_el1, USE_SPINLOCK_CAS, \
+ ID_AA64ISAR0_ATOMIC, 2U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_VHE(gen) \
+ gen(feat_vhe, id_aa64mmfr1_el1, ENABLE_FEAT_VHE, \
+ ID_AA64MMFR1_EL1_VHE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.2 features === */
+#define FEAT_RAS(gen) \
+ gen(feat_ras, id_aa64pfr0_el1, ENABLE_FEAT_RAS, \
+ ID_AA64PFR0_RAS, 1U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_IESB(gen) \
+ gen(feat_iesb, id_aa64mmfr2_el1, ENABLE_FEAT_RAS, \
+ ID_AA64MMFR2_EL1_IESB, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SVE(gen) \
+ gen(feat_sve, id_aa64pfr0_el1, ENABLE_SVE_FOR_NS, \
+ ID_AA64PFR0_SVE, 1U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TTCNP(gen) \
+ gen(feat_ttcnp, id_aa64mmfr2_el1, FEAT_STATE_CHECKED, \
+ ID_AA64MMFR2_EL1_CNP, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_UAO(gen) \
+ gen(feat_uao, id_aa64mmfr2_el1, FEAT_STATE_CHECKED, \
+ ID_AA64MMFR2_EL1_UAO, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SPE(gen) \
+ gen(feat_spe, id_aa64dfr0_el1, ENABLE_SPE_FOR_NS, \
+ ID_AA64DFR0_PMS, 1U, 6U, FEAT_ENABLE_NS)
+
+/* === v8.3 features === */
+#define FEAT_PAUTH(gen) \
+ gen(feat_pauth, NA, ENABLE_PAUTH, NA, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.4 features === */
+#define FEAT_DIT(gen) \
+ gen(feat_dit, id_aa64pfr0_el1, ENABLE_FEAT_DIT, \
+ ID_AA64PFR0_DIT, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TTST(gen) \
+ gen(feat_ttst, id_aa64mmfr2_el1, FEAT_STATE_CHECKED, \
+ ID_AA64MMFR2_EL1_ST, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* FEAT_AMUv1 in the architecture */
+#define FEAT_AMU(gen) \
+ gen(feat_amu, id_aa64pfr0_el1, ENABLE_FEAT_AMU, \
+ ID_AA64PFR0_AMU, 1U, 2U, FEAT_ENABLE_NS)
+
+#define FEAT_MPAM(gen) \
+ gen(feat_mpam, NA, ENABLE_FEAT_MPAM, \
+ NA, 1U, 17U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
+
+#define FEAT_NV2(gen) \
+ gen(feat_nv2, id_aa64mmfr2_el1, CTX_INCLUDE_NEVE_REGS, \
+ ID_AA64MMFR2_EL1_NV, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SEL2(gen) \
+ gen(feat_sel2, id_aa64pfr0_el1, ENABLE_FEAT_SEL2, \
+ ID_AA64PFR0_SEL2, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TRF(gen) \
+ gen(feat_trf, id_aa64dfr0_el1, ENABLE_TRF_FOR_NS, \
+ ID_AA64DFR0_TRACEFILT, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.5 features === */
+#define FEAT_SB(gen) \
+ gen(feat_sb, id_aa64isar1_el1, ENABLE_FEAT_SB, \
+ ID_AA64ISAR1_SB, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_MTE2(gen) \
+ gen(feat_mte2, id_aa64pfr1_el1, ENABLE_FEAT_MTE2, \
+ ID_AA64PFR1_EL1_MTE, 2U, 3U, FEAT_ENABLE_SECURE | FEAT_ENABLE_NS)
+
+#define FEAT_RNG(gen) \
+ gen(feat_rng, id_aa64isar0_el1, ENABLE_FEAT_RNG, \
+ ID_AA64ISAR0_RNDR, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_BTI(gen) \
+ gen(feat_bti, id_aa64pfr1_el1, ENABLE_BTI, \
+ ID_AA64PFR1_EL1_BT, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_RNG_TRAP(gen) \
+ gen(feat_rng_trap, id_aa64pfr1_el1, ENABLE_FEAT_RNG_TRAP, \
+ ID_AA64PFR1_EL1_RNDR_TRAP, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SSBS(gen) \
+ gen(feat_ssbs, id_aa64pfr1_el1, FEAT_STATE_CHECKED, \
+ ID_AA64PFR1_EL1_SSBS, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.6 features === */
+#define FEAT_AMUV1P1(gen) \
+ gen(feat_amuv1p1, id_aa64pfr0_el1, ENABLE_FEAT_AMUv1p1, \
+ ID_AA64PFR0_AMU, 2U, 2U, FEAT_ENABLE_NS)
+
+#define FEAT_FGT(gen) \
+ gen(feat_fgt, id_aa64mmfr0_el1, ENABLE_FEAT_FGT, \
+ ID_AA64MMFR0_EL1_FGT, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_ECV(gen) \
+ gen(feat_ecv, id_aa64mmfr0_el1, ENABLE_FEAT_ECV, \
+ ID_AA64MMFR0_EL1_ECV, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TWED(gen) \
+ gen(feat_twed, id_aa64mmfr1_el1, ENABLE_FEAT_TWED, \
+ ID_AA64MMFR1_EL1_TWED, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_MTPMU(gen) \
+ gen(feat_mtpmu, id_aa64dfr0_el1, DISABLE_MTPMU, \
+ ID_AA64DFR0_MTPMU, 1U, 15U, FEAT_ENABLE_ALL_WORLDS)
+
+/* FEAT_ECV_POFF in the architecture */
+#define FEAT_ECV_V2(gen) \
+ gen(feat_ecv_v2, id_aa64mmfr0_el1, ENABLE_FEAT_ECV, \
+ ID_AA64MMFR0_EL1_ECV, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.7 features === */
+#define FEAT_HCX(gen) \
+ gen(feat_hcx, id_aa64mmfr1_el1, ENABLE_FEAT_HCX, \
+ ID_AA64MMFR1_EL1_HCX, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_LS64_ACCDATA(gen) \
+ gen(feat_ls64_accdata, id_aa64isar1_el1, ENABLE_FEAT_LS64_ACCDATA, \
+ ID_AA64ISAR1_LS64, 3U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.8 features === */
+#define FEAT_MOPS(gen) \
+ gen(feat_mops, id_aa64isar2_el1, ENABLE_FEAT_MOPS, \
+ ID_AA64ISAR2_EL1_MOPS, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_TCR2(gen) \
+ gen(feat_tcr2, id_aa64mmfr3_el1, ENABLE_FEAT_TCR2, \
+ ID_AA64MMFR3_EL1_TCRX, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_NMI(gen) \
+ gen(feat_nmi, id_aa64pfr1_el1, FEAT_STATE_CHECKED, \
+ ID_AA64PFR1_EL1_NMI, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v8.9 features === */
+#define FEAT_FGT2(gen) \
+ gen(feat_fgt2, id_aa64mmfr0_el1, ENABLE_FEAT_FGT2, \
+ ID_AA64MMFR0_EL1_FGT, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_CLRBHB(gen) \
+ gen(feat_clrbhb, id_aa64isar2_el1, ENABLE_FEAT_CLRBHB, \
+ ID_AA64ISAR2_CLRBHB, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_S2PIE(gen) \
+ gen(feat_s2pie, id_aa64mmfr3_el1, ENABLE_FEAT_S2PIE, \
+ ID_AA64MMFR3_EL1_S2PIE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_S1PIE(gen) \
+ gen(feat_s1pie, id_aa64mmfr3_el1, ENABLE_FEAT_S1PIE, \
+ ID_AA64MMFR3_EL1_S1PIE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_S2POE(gen) \
+ gen(feat_s2poe, id_aa64mmfr3_el1, ENABLE_FEAT_S2POE, \
+ ID_AA64MMFR3_EL1_S2POE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_S1POE(gen) \
+ gen(feat_s1poe, id_aa64mmfr3_el1, ENABLE_FEAT_S1POE, \
+ ID_AA64MMFR3_EL1_S1POE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_DEBUGV8P9(gen) \
+ gen(feat_debugv8p9, id_aa64dfr0_el1, ENABLE_FEAT_DEBUGV8P9, \
+ ID_AA64DFR0_DEBUGVER, 11U, 11U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
+
+#define FEAT_THE(gen) \
+ gen(feat_the, id_aa64pfr1_el1, ENABLE_FEAT_THE, \
+ ID_AA64PFR1_EL1_THE, 1U, 1U, FEAT_ENABLE_NS)
+
+#define FEAT_SCTLR2(gen) \
+ gen(feat_sctlr2, id_aa64mmfr3_el1, ENABLE_FEAT_SCTLR2, \
+ ID_AA64MMFR3_EL1_SCTLR2, 1U, 1U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
+
+#define FEAT_AIE(gen) \
+ gen(feat_aie, id_aa64mmfr3_el1, ENABLE_FEAT_AIE, \
+ ID_AA64MMFR3_EL1_AIE, 1U, 1U, FEAT_ENABLE_NS)
+
+#define FEAT_PFAR(gen) \
+ gen(feat_pfar, id_aa64pfr1_el1, ENABLE_FEAT_PFAR, \
+ ID_AA64PFR1_EL1_PFAR, 1U, 1U, FEAT_ENABLE_NS)
+
+/* === v9.0 features === */
+#define FEAT_TRBE(gen) \
+ gen(feat_trbe, id_aa64dfr0_el1, ENABLE_TRBE_FOR_NS, \
+ ID_AA64DFR0_TRACEBUFFER, 1U, 1U, FEAT_ENABLE_NS)
+
+/* === v9.2 features === */
+#define FEAT_RME(gen) \
+ gen(feat_rme, id_aa64pfr0_el1, ENABLE_FEAT_RME, \
+ ID_AA64PFR0_FEAT_RME, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_BRBE(gen) \
+ gen(feat_brbe, id_aa64dfr0_el1, ENABLE_BRBE_FOR_NS, \
+ ID_AA64DFR0_BRBE, 1U, 2U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
+
+#define FEAT_SME(gen) \
+ gen(feat_sme, id_aa64pfr1_el1, ENABLE_SME_FOR_NS, \
+ ID_AA64PFR1_EL1_SME, 1U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SME_FA64(gen) \
+ gen(feat_sme_fa64, id_aa64smfr0_el1, FEAT_STATE_CHECKED, \
+ ID_AA64SMFR0_EL1_SME_FA64, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v9.3 features === */
+#define FEAT_SME2(gen) \
+ gen(feat_sme2, id_aa64pfr1_el1, ENABLE_SME2_FOR_NS, \
+ ID_AA64PFR1_EL1_SME, 2U, 3U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_GCIE(gen) \
+ gen(feat_gcie, id_aa64pfr2_el1, ENABLE_FEAT_GCIE, \
+ ID_AA64PFR2_EL1_GCIE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_EBEP(gen) \
+ gen(feat_ebep, id_aa64dfr1_el1, ENABLE_FEAT_EBEP, \
+ ID_AA64DFR1_EBEP, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_MEC(gen) \
+ gen(feat_mec, id_aa64mmfr3_el1, ENABLE_FEAT_MEC, \
+ ID_AA64MMFR3_EL1_MEC, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v9.4 features === */
+#define FEAT_D128(gen) \
+ gen(feat_d128, id_aa64mmfr3_el1, ENABLE_FEAT_D128, \
+ ID_AA64MMFR3_EL1_D128, 1U, 1U, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
+
+#define FEAT_GCS(gen) \
+ gen(feat_gcs, id_aa64pfr1_el1, ENABLE_FEAT_GCS, \
+ ID_AA64PFR1_EL1_GCS, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_RME_GDI(gen) \
+ gen(feat_rme_gdi, id_aa64mmfr4_el1, ENABLE_FEAT_RME_GDI, \
+ ID_AA64MMFR4_EL1_RME_GDI, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_IDTE3(gen) \
+ gen(feat_idte3, id_aa64mmfr2_el1, ENABLE_FEAT_IDTE3, \
+ ID_AA64MMFR2_EL1_IDS, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SEBEP(gen) \
+ gen(feat_sebep, id_aa64dfr0_el1, FEAT_STATE_CHECKED, \
+ ID_AA64DFR0_SEBEP, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v9.5 features === */
+#define FEAT_FGWTE3(gen) \
+ gen(feat_fgwte3, id_aa64mmfr4_el1, ENABLE_FEAT_FGWTE3, \
+ ID_AA64MMFR4_EL1_FGWTE3, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_PAUTH_LR(gen) \
+ gen(feat_pauth_lr, NA, ENABLE_FEAT_PAUTH_LR, \
+ NA, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_FPMR(gen) \
+ gen(feat_fpmr, id_aa64pfr2_el1, ENABLE_FEAT_FPMR, \
+ ID_AA64PFR2_EL1_FPMR, 1U, 1U, FEAT_ENABLE_NS)
+
+#define FEAT_CPA2(gen) \
+ gen(feat_cpa2, id_aa64isar3_el1, ENABLE_FEAT_CPA2, \
+ ID_AA64ISAR3_EL1_CPA, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_HDBSS(gen) \
+ gen(feat_hdbss, id_aa64mmfr1_el1, ENABLE_FEAT_HDBSS, \
+ ID_AA64MMFR1_EL1_HAFDBS, 4U, 4U, FEAT_ENABLE_NS)
+
+#define FEAT_HACDBS(gen) \
+ gen(feat_hacdbs, id_aa64mmfr4_el1, ENABLE_FEAT_HACDBS, \
+ ID_AA64MMFR4_EL1_HACDBS, 1U, 1U, FEAT_ENABLE_NS)
+
+#define FEAT_RME_GPC2(gen) \
+ gen(feat_rme_gpc2, id_aa64pfr0_el1, FEAT_STATE_CHECKED, \
+ ID_AA64PFR0_FEAT_RME, 2U, 2U, FEAT_ENABLE_ALL_WORLDS)
+
+/* === v9.6 features === */
+#define FEAT_UINJ(gen) \
+ gen(feat_uinj, id_aa64pfr2_el1, ENABLE_FEAT_UINJ, \
+ ID_AA64PFR2_EL1_UINJ, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_STEP2(gen) \
+ gen(feat_step2, id_aa64dfr2_el1, ENABLE_FEAT_STEP2, \
+ ID_AA64DFR2_STEP, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define FEAT_SPE_EXC(gen) \
+ gen(feat_spe_exc, id_aa64dfr2_el1, ENABLE_FEAT_SPEV1P5, \
+ ID_AA64DFR2_SPE_EXC, 1U, 1U, FEAT_ENABLE_NS)
+
+#define FEAT_SPE_NVM(gen) \
+ gen(feat_spe_nvm, id_aa64dfr2_el1, ENABLE_FEAT_SPEV1P5, \
+ ID_AA64DFR2_SPE_NVM, 1U, 1U, FEAT_ENABLE_NS)
+
+/* Auxiliary features. Don't relate to an architectural feature directly */
+#define FEAT_AMU_AUX(gen) \
+ gen(feat_amu_aux, amcfgr_el0, ENABLE_AMU_AUXILIARY_COUNTERS, \
+ AMCFGR_EL0_NCG, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+/* 9.3 but no standalone ID field */
+#define FEAT_MPAM_PE_BW_CTRL(gen) \
+ gen(feat_mpam_pe_bw_ctrl, mpamidr_el1, ENABLE_FEAT_MPAM_PE_BW_CTRL, \
+ MPAMIDR_HAS_BW_CTRL, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
+
+#define CTX_PAUTH(gen) \
+ gen(ctx_pauth, NA, CTX_INCLUDE_PAUTH_REGS, \
+ NA, NA, NA, NA)
+
+/* Non-Architectural features */
+#define FEAT_MORELLO(gen) \
+ gen(feat_morello, id_aa64pfr1_el1, ENABLE_FEAT_MORELLO, \
+ ID_AA64PFR1_EL1_CE, 1U, 1U, FEAT_ENABLE_ALL_WORLDS)
- return (EXTRACT(ID_AA64ISAR2_GPA3, isar2) |
- EXTRACT(ID_AA64ISAR2_APA3, isar2)) != 0;
-}
+/*
+ * List of "standard" features. They obey the common format of the ID register
+ * scheme (D24.1.3 in the ARM) and can have all boilerplate generated
+ * automatically.
+ */
+#define CPUFEAT_LIST(gen) \
+ FEAT_CSV2_2(gen) \
+ FEAT_CSV2_3(gen) \
+ FEAT_TGRAN16K(gen) \
+ FEAT_AES(gen) \
+ FEAT_SHA1(gen) \
+ FEAT_PAN(gen) \
+ FEAT_LSE(gen) \
+ FEAT_VHE(gen) \
+ FEAT_RAS(gen) \
+ FEAT_IESB(gen) \
+ FEAT_SVE(gen) \
+ FEAT_TTCNP(gen) \
+ FEAT_UAO(gen) \
+ FEAT_DIT(gen) \
+ FEAT_TTST(gen) \
+ FEAT_AMU(gen) \
+ FEAT_NV2(gen) \
+ FEAT_SEL2(gen) \
+ FEAT_SB(gen) \
+ FEAT_MTE2(gen) \
+ FEAT_RNG(gen) \
+ FEAT_BTI(gen) \
+ FEAT_RNG_TRAP(gen) \
+ FEAT_SSBS(gen) \
+ FEAT_AMUV1P1(gen) \
+ FEAT_FGT(gen) \
+ FEAT_ECV(gen) \
+ FEAT_TWED(gen) \
+ FEAT_ECV_V2(gen) \
+ FEAT_HCX(gen) \
+ FEAT_LS64_ACCDATA(gen) \
+ FEAT_MOPS(gen) \
+ FEAT_TCR2(gen) \
+ FEAT_NMI(gen) \
+ FEAT_FGT2(gen) \
+ FEAT_CLRBHB(gen) \
+ FEAT_S2PIE(gen) \
+ FEAT_S1PIE(gen) \
+ FEAT_S2POE(gen) \
+ FEAT_S1POE(gen) \
+ FEAT_THE(gen) \
+ FEAT_SCTLR2(gen) \
+ FEAT_AIE(gen) \
+ FEAT_PFAR(gen) \
+ FEAT_RME(gen) \
+ FEAT_SME(gen) \
+ FEAT_SME_FA64(gen) \
+ FEAT_SME2(gen) \
+ FEAT_GCIE(gen) \
+ FEAT_MEC(gen) \
+ FEAT_D128(gen) \
+ FEAT_GCS(gen) \
+ FEAT_RME_GDI(gen) \
+ FEAT_IDTE3(gen) \
+ FEAT_FGWTE3(gen) \
+ FEAT_FPMR(gen) \
+ FEAT_CPA2(gen) \
+ FEAT_HDBSS(gen) \
+ FEAT_HACDBS(gen) \
+ FEAT_RME_GPC2(gen) \
+ FEAT_UINJ(gen) \
+ FEAT_STEP2(gen) \
+ FEAT_SPE_EXC(gen) \
+ FEAT_SPE_NVM(gen) \
+ FEAT_MORELLO(gen)
+/*
+ * Same as the above list, except presence of the feature is allowed to be
+ * asymmetric across cores.
+ */
+#define CPUFEAT_PERCPU_LIST(gen) \
+ FEAT_PMUV3(gen) \
+ FEAT_SYS_REG_TRACE(gen) \
+ FEAT_SPE(gen) \
+ FEAT_TRF(gen) \
+ FEAT_MTPMU(gen) \
+ FEAT_DEBUGV8P9(gen) \
+ FEAT_TRBE(gen) \
+ FEAT_BRBE(gen) \
+ FEAT_EBEP(gen) \
+ FEAT_SEBEP(gen)
+
+CPUFEAT_LIST(CREATE_FEATURE_FUNCS)
+CPUFEAT_PERCPU_LIST(CREATE_FEATURE_FUNCS)
+
+/*******************************************************************************
+ * Helpers that can't match the standard pattern
+ ******************************************************************************/
__attribute__((always_inline))
static inline bool is_feat_pauth_present(void)
{
@@ -175,66 +527,27 @@ static inline bool is_feat_pauth_present(void)
MASK(ID_AA64ISAR1_API) |
MASK(ID_AA64ISAR1_APA);
+ uint64_t mask_id_aa64isar2 =
+ MASK(ID_AA64ISAR2_GPA3) |
+ MASK(ID_AA64ISAR2_APA3);
+
/*
* If any of the fields is not zero or QARMA3 is present,
* PAuth is present
*/
- return ((read_id_aa64isar1_el1() & mask_id_aa64isar1) != 0U ||
- is_feat_pacqarma3_present());
-}
-CREATE_FEATURE_SUPPORTED(feat_pauth, is_feat_pauth_present, ENABLE_PAUTH)
-CREATE_FEATURE_SUPPORTED(ctx_pauth, is_feat_pauth_present, CTX_INCLUDE_PAUTH_REGS)
+ return (read_id_aa64isar1_el1() & mask_id_aa64isar1) != 0U ||
+ (read_id_aa64isar2_el1() & mask_id_aa64isar2) != 0U;
-__attribute__((always_inline))
-static inline bool is_feat_crypto_present(void)
-{
- uint64_t mask_id_aa64isar0 =
- MASK(ID_AA64ISAR0_AES) |
- MASK(ID_AA64ISAR0_SHA1) |
- MASK(ID_AA64ISAR0_SHA2);
-
- /*
- * Check if AES, SHA1, SHA2 extension presents.
- */
- return ((read_id_aa64isar0_el1() & mask_id_aa64isar0) != 0U);
}
-CREATE_FEATURE_SUPPORTED(feat_crypto, is_feat_crypto_present, ENABLE_FEAT_CRYPTO)
-#if (ENABLE_FEAT_IDTE3 && IMAGE_BL31)
-__attribute__((always_inline))
-static inline void update_feat_pauth_idreg_field(size_t security_state)
+/* Make this simple enough to fit into the pattern */
+static inline unsigned int _read_feat_pauth_id_field(void)
{
- uint64_t mask_id_aa64isar1 =
- MASK(ID_AA64ISAR1_GPI) |
- MASK(ID_AA64ISAR1_GPA) |
- MASK(ID_AA64ISAR1_API) |
- MASK(ID_AA64ISAR1_APA);
-
- /* FEAT_PACQARMA3 */
- uint64_t mask_id_aa64isar2 =
- MASK(ID_AA64ISAR2_APA3) |
- MASK(ID_AA64ISAR2_GPA3);
-
- per_world_context_t *per_world_ctx = &per_world_context[security_state];
- perworld_idregs_t *perworld_idregs =
- &(per_world_ctx->idregs);
-
- if ((SHOULD_ID_FIELD_DISABLE(ENABLE_PAUTH, FEAT_ENABLE_NS,
- security_state)) &&
- (SHOULD_ID_FIELD_DISABLE(CTX_INCLUDE_PAUTH_REGS,
- FEAT_ENABLE_ALL_WORLDS,
- security_state))) {
- perworld_idregs->id_aa64isar1_el1 &= ~(mask_id_aa64isar1);
- perworld_idregs->id_aa64isar2_el1 &= ~(mask_id_aa64isar2);
- }
+ return (is_feat_pauth_present()) ? 1 : 0;
}
-#endif
-/*
- * This feature has a non-standard discovery method so define this function
- * manually then call use the CREATE_FEATURE_SUPPORTED macro with it. This
- * feature is enabled with ENABLE_PAUTH when present.
- */
+static inline bool is_ctx_pauth_present(void) { return is_feat_pauth_present(); }
+
__attribute__((always_inline))
static inline bool is_feat_pauth_lr_present(void)
{
@@ -256,333 +569,71 @@ static inline bool is_feat_pauth_lr_present(void)
}
return false;
}
-CREATE_FEATURE_SUPPORTED(feat_pauth_lr, is_feat_pauth_lr_present, ENABLE_FEAT_PAUTH_LR)
-
-CREATE_FEATURE_PRESENT(feat_ttst, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_ST,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_bti, id_aa64pfr1_el1, ID_AA64PFR1_EL1_BT,
- BTI_IMPLEMENTED, ENABLE_BTI,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_mte2, id_aa64pfr1_el1, ID_AA64PFR1_EL1_MTE,
- MTE_IMPLEMENTED_ELX, ENABLE_FEAT_MTE2,
- FEAT_ENABLE_SECURE | FEAT_ENABLE_NS)
-
-CREATE_FEATURE_PRESENT(feat_ssbs, id_aa64pfr1_el1, ID_AA64PFR1_EL1_SSBS,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_PRESENT(feat_nmi, id_aa64pfr1_el1, ID_AA64PFR1_EL1_NMI,
- NMI_IMPLEMENTED,
- FEAT_ENABLE_ALL_WORLDS)
-CREATE_PERCPU_FEATURE_FUNCS(feat_ebep, id_aa64dfr1_el1, ID_AA64DFR1_EBEP,
- 1U, ENABLE_FEAT_EBEP,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_PERCPU_FEATURE_PRESENT(feat_sebep, id_aa64dfr0_el1, ID_AA64DFR0_SEBEP,
- SEBEP_IMPLEMENTED,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_sel2, id_aa64pfr0_el1, ID_AA64PFR0_SEL2,
- 1U, ENABLE_FEAT_SEL2,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_twed, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_TWED,
- 1U, ENABLE_FEAT_TWED,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_fgt, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT,
- 1U, ENABLE_FEAT_FGT,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_fgt2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_FGT,
- FGT2_IMPLEMENTED, ENABLE_FEAT_FGT2,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_fgwte3, id_aa64mmfr4_el1, ID_AA64MMFR4_EL1_FGWTE3,
- FGWTE3_IMPLEMENTED,
- ENABLE_FEAT_FGWTE3, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_ecv, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV,
- 1U, ENABLE_FEAT_ECV,
- FEAT_ENABLE_ALL_WORLDS)
-CREATE_FEATURE_FUNCS(feat_ecv_v2, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_ECV,
- ID_AA64MMFR0_EL1_ECV_SELF_SYNCH,
- ENABLE_FEAT_ECV, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_rng, id_aa64isar0_el1, ID_AA64ISAR0_RNDR,
- 1U, ENABLE_FEAT_RNG,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_tcr2, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_TCRX,
- 1U, ENABLE_FEAT_TCR2,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_s2poe, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S2POE,
- 1U, ENABLE_FEAT_S2POE,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_s1poe, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1POE,
- 1U, ENABLE_FEAT_S1POE,
- FEAT_ENABLE_ALL_WORLDS)
-
-__attribute__((always_inline))
-static inline bool is_feat_sxpoe_supported(void)
+/* Make this simple enough to fit into the pattern */
+static inline unsigned int _read_feat_pauth_lr_id_field(void)
{
- return is_feat_s1poe_supported() || is_feat_s2poe_supported();
+ return (is_feat_pauth_lr_present()) ? 1 : 0;
}
-CREATE_FEATURE_FUNCS(feat_s2pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S2PIE,
- 1U, ENABLE_FEAT_S2PIE,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_s1pie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_S1PIE,
- 1U, ENABLE_FEAT_S1PIE,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_the, id_aa64pfr1_el1, ID_AA64PFR1_EL1_THE,
- THE_IMPLEMENTED, ENABLE_FEAT_THE,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_sctlr2, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_SCTLR2,
- SCTLR2_IMPLEMENTED,
- ENABLE_FEAT_SCTLR2,
- FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-
-CREATE_FEATURE_FUNCS(feat_d128, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_D128,
- D128_IMPLEMENTED,
- ENABLE_FEAT_D128, FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-
-_CREATE_FEATURE_PRESENT(feat_rme_gpc2, id_aa64pfr0_el1,
- ID_AA64PFR0_FEAT_RME,
- RME_GPC2_IMPLEMENTED)
-
-CREATE_FEATURE_FUNCS(feat_rme_gdi, id_aa64mmfr4_el1,
- ID_AA64MMFR4_EL1_RME_GDI,
- RME_GDI_IMPLEMENTED,
- ENABLE_FEAT_RME_GDI, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_fpmr, id_aa64pfr2_el1, ID_AA64PFR2_EL1_FPMR,
- FPMR_IMPLEMENTED,
- ENABLE_FEAT_FPMR, FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_mops, id_aa64isar2_el1, ID_AA64ISAR2_EL1_MOPS,
- MOPS_IMPLEMENTED,
- ENABLE_FEAT_MOPS, FEAT_ENABLE_ALL_WORLDS)
-
__attribute__((always_inline))
-static inline bool is_feat_sxpie_supported(void)
+static inline unsigned int _read_feat_mpam_id_field(void)
{
- return is_feat_s1pie_supported() || is_feat_s2pie_supported();
+ return EXTRACT(ID_AA64PFR0_MPAM, read_id_aa64pfr0_el1()) << ID_AA64PFR0_MPAM_WIDTH |
+ EXTRACT(ID_AA64PFR1_MPAM_FRAC, read_id_aa64pfr1_el1());
}
-CREATE_FEATURE_FUNCS(feat_gcs, id_aa64pfr1_el1, ID_AA64PFR1_EL1_GCS,
- 1U, ENABLE_FEAT_GCS,
- FEAT_ENABLE_ALL_WORLDS)
+/*******************************************************************************
+ * Features who have at least one helper that doesn't match the standard
+ * pattern. These need special attention when integrating with FEAT_IDTE3 and
+ * FEATURE_DETECTION
+ ******************************************************************************/
+FEAT_PAUTH(CREATE_FEATURE_SUPPORTED)
+FEAT_PAUTH_LR(CREATE_FEATURE_SUPPORTED)
-CREATE_FEATURE_FUNCS(feat_amu, id_aa64pfr0_el1, ID_AA64PFR0_AMU,
- 1U, ENABLE_FEAT_AMU,
- FEAT_ENABLE_NS)
+FEAT_MPAM(CREATE_FEATURE_PRESENT)
+FEAT_MPAM(CREATE_FEATURE_SUPPORTED)
-_CREATE_FEATURE_PRESENT(feat_amu_aux, amcfgr_el0,
- AMCFGR_EL0_NCG, 1U)
+FEAT_AMU_AUX(CREATE_FEATURE_FUNCS)
-CREATE_FEATURE_SUPPORTED(feat_amu_aux, is_feat_amu_aux_present,
- ENABLE_AMU_AUXILIARY_COUNTERS)
+/* Automatic inclusion for FEATURE_DETECTION. IDTE3 is on a case-by-case basis */
+#define CPUFEAT_SPECIAL_FEAT_DETECT_LIST(gen) \
+ FEAT_PAUTH(gen) \
+ FEAT_PAUTH_LR(gen) \
+ FEAT_MPAM(gen)
-CREATE_FEATURE_FUNCS(feat_amuv1p1, id_aa64pfr0_el1, ID_AA64PFR0_AMU,
- ID_AA64PFR0_AMU_V1P1, ENABLE_FEAT_AMUv1p1,
- FEAT_ENABLE_NS)
+/* Exclude these from FEATURE_DETECTION and IDTE3 */
+CTX_PAUTH(CREATE_FEATURE_SUPPORTED)
+FEAT_MPAM_PE_BW_CTRL(CREATE_FEATURE_FUNCS)
-/*
- * 0x00: None Armv8.0 or later
- * 0x01: v0.1 Armv8.4 or later
- * 0x10: v1.0 Armv8.2 or later
- * 0x11: v1.1 Armv8.4 or later
- */
+/*******************************************************************************
+ * Non-standard, not directly architectural helpers
+ ******************************************************************************/
__attribute__((always_inline))
-static inline unsigned int read_feat_mpam_id_field(void)
-{
- return (EXTRACT(ID_AA64PFR0_MPAM, read_id_aa64pfr0_el1()) << 4) |
- EXTRACT(ID_AA64PFR1_MPAM_FRAC, read_id_aa64pfr1_el1());
-}
-
-__attribute__((always_inline))
-static inline bool is_feat_mpam_present(void)
+static inline bool is_armv7_gentimer_present(void)
{
- return read_feat_mpam_id_field();
+ /* The Generic Timer is always present in an ARMv8-A implementation */
+ return true;
}
-CREATE_FEATURE_SUPPORTED(feat_mpam, is_feat_mpam_present, ENABLE_FEAT_MPAM)
-
-
-#if (ENABLE_FEAT_IDTE3 && IMAGE_BL31)
__attribute__((always_inline))
-static inline void update_feat_mpam_idreg_field(size_t security_state)
+static inline bool is_feat_sxpoe_supported(void)
{
- if (SHOULD_ID_FIELD_DISABLE(ENABLE_FEAT_MPAM,
- FEAT_ENABLE_NS | FEAT_ENABLE_REALM, security_state)) {
- per_world_context_t *per_world_ctx =
- &per_world_context[security_state];
- perworld_idregs_t *perworld_idregs =
- &(per_world_ctx->idregs);
-
- perworld_idregs->id_aa64pfr0_el1 &=
- ~((u_register_t)MASK(ID_AA64PFR0_MPAM));
-
- perworld_idregs->id_aa64pfr1_el1 &=
- ~((u_register_t)MASK(ID_AA64PFR1_MPAM_FRAC));
- }
+ return is_feat_s1poe_supported() || is_feat_s2poe_supported();
}
-#endif
__attribute__((always_inline))
-static inline bool is_feat_mpam_pe_bw_ctrl_present(void)
+static inline bool is_feat_sxpie_supported(void)
{
- if (is_feat_mpam_present()) {
- return ((unsigned long long)(read_mpamidr_el1() &
- MPAMIDR_HAS_BW_CTRL_BIT) != 0U);
- }
- return false;
+ return is_feat_s1pie_supported() || is_feat_s2pie_supported();
}
-CREATE_FEATURE_SUPPORTED(feat_mpam_pe_bw_ctrl, is_feat_mpam_pe_bw_ctrl_present,
- ENABLE_FEAT_MPAM_PE_BW_CTRL)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_debugv8p9, id_aa64dfr0_el1,
- ID_AA64DFR0_DEBUGVER, DEBUGVER_V8P9_IMPLEMENTED, ENABLE_FEAT_DEBUGV8P9,
- FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-
-CREATE_FEATURE_FUNCS(feat_hcx, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_HCX,
- 1U, ENABLE_FEAT_HCX,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_rng_trap, id_aa64pfr1_el1, ID_AA64PFR1_EL1_RNDR_TRAP,
- RNG_TRAP_IMPLEMENTED, ENABLE_FEAT_RNG_TRAP,
- FEAT_ENABLE_ALL_WORLDS)
-
-_CREATE_FEATURE_PRESENT(feat_rme, id_aa64pfr0_el1,
- ID_AA64PFR0_FEAT_RME, 1U)
-
-CREATE_FEATURE_SUPPORTED(feat_rme, is_feat_rme_present, ENABLE_FEAT_RME)
-
-CREATE_FEATURE_PRESENT(feat_sb, id_aa64isar1_el1, ID_AA64ISAR1_SB,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_mec, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_MEC,
- 1U, ENABLE_FEAT_MEC,
- FEAT_ENABLE_ALL_WORLDS)
-
-/*
- * 0b0000 - Feature FEAT_CSV2 is not implemented.
- * 0b0001 - Feature FEAT_CSV2 is implemented, but FEAT_CSV2_2 and FEAT_CSV2_3
- * are not implemented.
- * 0b0010 - Feature FEAT_CSV2_2 is implemented but FEAT_CSV2_3 is not
- * implemented.
- * 0b0011 - Feature FEAT_CSV2_3 is implemented.
- */
-CREATE_FEATURE_FUNCS(feat_csv2_2, id_aa64pfr0_el1, ID_AA64PFR0_CSV2,
- CSV2_2_IMPLEMENTED, ENABLE_FEAT_CSV2_2,
- FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-CREATE_FEATURE_FUNCS(feat_csv2_3, id_aa64pfr0_el1, ID_AA64PFR0_CSV2,
- CSV2_3_IMPLEMENTED, ENABLE_FEAT_CSV2_3,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_clrbhb, id_aa64isar2_el1, ID_AA64ISAR2_CLRBHB,
- 1U, ENABLE_FEAT_CLRBHB,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_spe, id_aa64dfr0_el1, ID_AA64DFR0_PMS,
- 1U, ENABLE_SPE_FOR_NS,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_spe_exc, id_aa64dfr2_el1, ID_AA64DFR2_SPE_EXC,
- 1U, ENABLE_FEAT_SPEV1P5,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_spe_nvm, id_aa64dfr2_el1, ID_AA64DFR2_SPE_NVM,
- 1U, ENABLE_FEAT_SPEV1P5,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_sve, id_aa64pfr0_el1, ID_AA64PFR0_SVE,
- 1U, ENABLE_SVE_FOR_NS,
- FEAT_ENABLE_ALL_WORLDS)
-
__attribute__((always_inline))
-static inline unsigned int read_feat_iesb_id_field(void)
+static inline bool is_feat_crypto_supported(void)
{
- return (unsigned int)EXTRACT(ID_AA64MMFR2_EL1_IESB,
- read_id_aa64mmfr2_el1());
+ return is_feat_aes_supported() || is_feat_sha1_supported();
}
-CREATE_FEATURE_FUNCS(feat_ras, id_aa64pfr0_el1, ID_AA64PFR0_RAS,
- 1U, ENABLE_FEAT_RAS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_dit, id_aa64pfr0_el1, ID_AA64PFR0_DIT,
- 1U, ENABLE_FEAT_DIT,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_sys_reg_trace, id_aa64dfr0_el1,
- ID_AA64DFR0_TRACEVER, 1U, ENABLE_SYS_REG_TRACE_FOR_NS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_trf, id_aa64dfr0_el1, ID_AA64DFR0_TRACEFILT,
- 1U, ENABLE_TRF_FOR_NS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_nv2, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_NV,
- NV2_IMPLEMENTED, CTX_INCLUDE_NEVE_REGS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_brbe, id_aa64dfr0_el1, ID_AA64DFR0_BRBE,
- 1U, ENABLE_BRBE_FOR_NS,
- FEAT_ENABLE_NS | FEAT_ENABLE_REALM)
-
-_CREATE_FEATURE_PRESENT(feat_trbe, id_aa64dfr0_el1, ID_AA64DFR0_TRACEBUFFER, 1U)
-
-CREATE_FEATURE_SUPPORTED(feat_trbe, is_feat_trbe_present, ENABLE_TRBE_FOR_NS)
-
-CREATE_PERCPU_IDREG_UPDATE(feat_trbe, id_aa64dfr0_el1, ID_AA64DFR0_TRACEBUFFER,
- ENABLE_TRBE_FOR_NS && !check_if_trbe_disable_affected_core(),
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_PRESENT(feat_sme_fa64, id_aa64smfr0_el1, ID_AA64SMFR0_EL1_SME_FA64,
- 1U,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_sme, id_aa64pfr1_el1, ID_AA64PFR1_EL1_SME,
- 1U, ENABLE_SME_FOR_NS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_sme2, id_aa64pfr1_el1, ID_AA64PFR1_EL1_SME,
- SME2_IMPLEMENTED, ENABLE_SME2_FOR_NS,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_ls64_accdata, id_aa64isar1_el1, ID_AA64ISAR1_LS64,
- LS64_ACCDATA_IMPLEMENTED,
- ENABLE_FEAT_LS64_ACCDATA, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_aie, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_AIE,
- 1U, ENABLE_FEAT_AIE,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_pfar, id_aa64pfr1_el1, ID_AA64PFR1_EL1_PFAR,
- 1U, ENABLE_FEAT_PFAR,
- FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_idte3, id_aa64mmfr2_el1, ID_AA64MMFR2_EL1_IDS,
- 2U, ENABLE_FEAT_IDTE3,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_lse, id_aa64isar0_el1, ID_AA64ISAR0_ATOMIC,
- 1U, USE_SPINLOCK_CAS,
- FEAT_ENABLE_ALL_WORLDS)
-
__attribute__((always_inline))
static inline bool is_feat_tgran4K_present(void)
{
@@ -591,10 +642,6 @@ static inline bool is_feat_tgran4K_present(void)
return (tgranx < 8U);
}
-CREATE_FEATURE_PRESENT(feat_tgran16K, id_aa64mmfr0_el1, ID_AA64MMFR0_EL1_TGRAN16,
- TGRAN16_IMPLEMENTED,
- FEAT_ENABLE_ALL_WORLDS)
-
__attribute__((always_inline))
static inline bool is_feat_tgran64K_present(void)
{
@@ -603,38 +650,4 @@ static inline bool is_feat_tgran64K_present(void)
return (tgranx < 8U);
}
-_CREATE_FEATURE_PRESENT(feat_pmuv3, id_aa64dfr0_el1, ID_AA64DFR0_PMUVER, 1U)
-
-CREATE_PERCPU_FEATURE_FUNCS(feat_mtpmu, id_aa64dfr0_el1, ID_AA64DFR0_MTPMU,
- MTPMU_IMPLEMENTED, DISABLE_MTPMU,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_gcie, id_aa64pfr2_el1, ID_AA64PFR2_EL1_GCIE,
- 1U, ENABLE_FEAT_GCIE,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_cpa2, id_aa64isar3_el1, ID_AA64ISAR3_EL1_CPA,
- CPA2_IMPLEMENTED,
- ENABLE_FEAT_CPA2, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_uinj, id_aa64pfr2_el1, ID_AA64PFR2_EL1_UINJ,
- UINJ_IMPLEMENTED,
- ENABLE_FEAT_UINJ, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_morello, id_aa64pfr1_el1, ID_AA64PFR1_EL1_CE,
- MORELLO_EXTENSION_IMPLEMENTED,
- ENABLE_FEAT_MORELLO, FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_step2, id_aa64dfr2_el1, ID_AA64DFR2_STEP,
- 1U, ENABLE_FEAT_STEP2,
- FEAT_ENABLE_ALL_WORLDS)
-
-CREATE_FEATURE_FUNCS(feat_hdbss, id_aa64mmfr1_el1, ID_AA64MMFR1_EL1_HAFDBS,
- HDBSS_IMPLEMENTED,
- ENABLE_FEAT_HDBSS, FEAT_ENABLE_NS)
-
-CREATE_FEATURE_FUNCS(feat_hacdbs, id_aa64mmfr4_el1, ID_AA64MMFR4_EL1_HACDBS,
- HACDBS_IMPLEMENTED,
- ENABLE_FEAT_HACDBS, FEAT_ENABLE_NS)
-
#endif /* ARCH_FEATURES_H */
diff --git a/include/common/feat_detect.h b/include/common/feat_detect.h
index 10bc68b12..21f7531e5 100644
--- a/include/common/feat_detect.h
+++ b/include/common/feat_detect.h
@@ -10,24 +10,41 @@
/* Function Prototypes */
void detect_arch_features(unsigned int core_pos);
-/* Macro Definitions */
+/*
+ * The `ENABLE_FEAT` mechanism is implemented with a tri-state approach for each
+ * feature:
+ * ENABLE_FEAT_xxx = 0 : The feature is disabled statically at compile time.
+ * ENABLE_FEAT_xxx = 1 : The feature is enabled and must be present in hardware.
+ * `FEATURE_DETECTION` will panic if feature is not present
+ * at cold boot.
+ * ENABLE_FEAT_xxx = 2 : The feature is enabled but dynamically enabled at
+ * runtime depending on hardware capability.
+ *
+ * For better readability, state values are defined with macros:
+ */
#define FEAT_STATE_DISABLED 0
#define FEAT_STATE_ALWAYS 1
#define FEAT_STATE_CHECKED 2
-#define _CREATE_FEATURE_PRESENT(name, idreg, idfield, idval) \
+/*
+ * Force inlining to let the compiler optimise away the whole check on
+ * FEAT_STATE_DISABLED.
+ */
+#define _CREATE_FEATURE_ID_FIELD(name, idreg, guard, field, min, max, worlds) \
__attribute__((always_inline)) \
-static inline unsigned int read_ ## name ## _id_field(void) \
+static inline unsigned int _read_ ## name ## _id_field(void) \
{ \
- return (unsigned int)EXTRACT(idfield, read_ ## idreg()); \
-} \
+ return (unsigned int)EXTRACT(field, read_ ## idreg()); \
+}
+
+#define _CREATE_FEATURE_PRESENT(name, idreg, guard, field, min, max, worlds) \
__attribute__((always_inline)) \
static inline bool is_ ## name ## _present(void) \
{ \
- return (read_ ## name ## _id_field() >= idval) ? true : false; \
+ return (_read_ ## name ## _id_field() >= min) ? true : false; \
}
-#define CREATE_FEATURE_SUPPORTED(name, read_func, guard) \
+#define _CREATE_FEATURE_SUPPORTED(name, idreg, guard, field, min, max, worlds) \
__attribute__((always_inline)) \
static inline bool is_ ## name ## _supported(void) \
{ \
@@ -37,7 +54,7 @@ static inline bool is_ ## name ## _supported(void) \
if ((guard) == FEAT_STATE_ALWAYS) { \
return true; \
} \
- return read_func(); \
+ return is_ ## name ## _present(); \
}
#endif /* FEAT_DETECT_H */