|
|
@@ -31,23 +31,19 @@ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
|
|
|
return val >= entry->min_field_value;
|
|
|
}
|
|
|
|
|
|
-static bool
|
|
|
-has_id_aa64pfr0_feature(const struct arm64_cpu_capabilities *entry)
|
|
|
-{
|
|
|
- u64 val;
|
|
|
-
|
|
|
- val = read_cpuid(id_aa64pfr0_el1);
|
|
|
- return feature_matches(val, entry);
|
|
|
+#define __ID_FEAT_CHK(reg) \
|
|
|
+static bool __maybe_unused \
|
|
|
+has_##reg##_feature(const struct arm64_cpu_capabilities *entry) \
|
|
|
+{ \
|
|
|
+ u64 val; \
|
|
|
+ \
|
|
|
+ val = read_cpuid(reg##_el1); \
|
|
|
+ return feature_matches(val, entry); \
|
|
|
}
|
|
|
|
|
|
-static bool __maybe_unused
|
|
|
-has_id_aa64mmfr1_feature(const struct arm64_cpu_capabilities *entry)
|
|
|
-{
|
|
|
- u64 val;
|
|
|
-
|
|
|
- val = read_cpuid(id_aa64mmfr1_el1);
|
|
|
- return feature_matches(val, entry);
|
|
|
-}
|
|
|
+__ID_FEAT_CHK(id_aa64pfr0);
|
|
|
+__ID_FEAT_CHK(id_aa64mmfr1);
|
|
|
+__ID_FEAT_CHK(id_aa64isar0);
|
|
|
|
|
|
static const struct arm64_cpu_capabilities arm64_features[] = {
|
|
|
{
|
|
|
@@ -67,6 +63,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
|
|
|
.enable = cpu_enable_pan,
|
|
|
},
|
|
|
#endif /* CONFIG_ARM64_PAN */
|
|
|
+#if defined(CONFIG_AS_LSE) && defined(CONFIG_ARM64_LSE_ATOMICS)
|
|
|
+ {
|
|
|
+ .desc = "LSE atomic instructions",
|
|
|
+ .capability = ARM64_HAS_LSE_ATOMICS,
|
|
|
+ .matches = has_id_aa64isar0_feature,
|
|
|
+ .field_pos = 20,
|
|
|
+ .min_field_value = 2,
|
|
|
+ },
|
|
|
+#endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
|
|
|
{},
|
|
|
};
|
|
|
|
|
|
@@ -93,5 +98,5 @@ void check_cpu_capabilities(const struct arm64_cpu_capabilities *caps,
|
|
|
|
|
|
void check_local_cpu_features(void)
|
|
|
{
|
|
|
- check_cpu_capabilities(arm64_features, "detected feature");
|
|
|
+ check_cpu_capabilities(arm64_features, "detected feature:");
|
|
|
}
|