Commit da8d02d1 authored by Suzuki K. Poulose's avatar Suzuki K. Poulose Committed by Catalin Marinas

arm64/capabilities: Make use of system wide safe value

Now that we can reliably read the system wide safe value for a
feature register, use that to compute the system capability.
This patch also replaces the 'feature-register-specific'
methods with a generic routine to check the capability.
Signed-off-by: default avatarSuzuki K. Poulose <suzuki.poulose@arm.com>
Tested-by: default avatarDave Martin <Dave.Martin@arm.com>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent dbb4e152
...@@ -78,6 +78,7 @@ struct arm64_cpu_capabilities { ...@@ -78,6 +78,7 @@ struct arm64_cpu_capabilities {
}; };
struct { /* Feature register checking */ struct { /* Feature register checking */
u32 sys_reg;
int field_pos; int field_pos;
int min_field_value; int min_field_value;
}; };
......
...@@ -586,34 +586,31 @@ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry) ...@@ -586,34 +586,31 @@ feature_matches(u64 reg, const struct arm64_cpu_capabilities *entry)
return val >= entry->min_field_value; return val >= entry->min_field_value;
} }
#define __ID_FEAT_CHK(reg) \ static bool
static bool __maybe_unused \ has_cpuid_feature(const struct arm64_cpu_capabilities *entry)
has_##reg##_feature(const struct arm64_cpu_capabilities *entry) \ {
{ \ u64 val;
u64 val; \
\
val = read_cpuid(reg##_el1); \
return feature_matches(val, entry); \
}
__ID_FEAT_CHK(id_aa64pfr0); val = read_system_reg(entry->sys_reg);
__ID_FEAT_CHK(id_aa64mmfr1); return feature_matches(val, entry);
__ID_FEAT_CHK(id_aa64isar0); }
static const struct arm64_cpu_capabilities arm64_features[] = { static const struct arm64_cpu_capabilities arm64_features[] = {
{ {
.desc = "GIC system register CPU interface", .desc = "GIC system register CPU interface",
.capability = ARM64_HAS_SYSREG_GIC_CPUIF, .capability = ARM64_HAS_SYSREG_GIC_CPUIF,
.matches = has_id_aa64pfr0_feature, .matches = has_cpuid_feature,
.field_pos = 24, .sys_reg = SYS_ID_AA64PFR0_EL1,
.field_pos = ID_AA64PFR0_GIC_SHIFT,
.min_field_value = 1, .min_field_value = 1,
}, },
#ifdef CONFIG_ARM64_PAN #ifdef CONFIG_ARM64_PAN
{ {
.desc = "Privileged Access Never", .desc = "Privileged Access Never",
.capability = ARM64_HAS_PAN, .capability = ARM64_HAS_PAN,
.matches = has_id_aa64mmfr1_feature, .matches = has_cpuid_feature,
.field_pos = 20, .sys_reg = SYS_ID_AA64MMFR1_EL1,
.field_pos = ID_AA64MMFR1_PAN_SHIFT,
.min_field_value = 1, .min_field_value = 1,
.enable = cpu_enable_pan, .enable = cpu_enable_pan,
}, },
...@@ -622,8 +619,9 @@ static const struct arm64_cpu_capabilities arm64_features[] = { ...@@ -622,8 +619,9 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
{ {
.desc = "LSE atomic instructions", .desc = "LSE atomic instructions",
.capability = ARM64_HAS_LSE_ATOMICS, .capability = ARM64_HAS_LSE_ATOMICS,
.matches = has_id_aa64isar0_feature, .matches = has_cpuid_feature,
.field_pos = 20, .sys_reg = SYS_ID_AA64ISAR0_EL1,
.field_pos = ID_AA64ISAR0_ATOMICS_SHIFT,
.min_field_value = 2, .min_field_value = 2,
}, },
#endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */ #endif /* CONFIG_AS_LSE && CONFIG_ARM64_LSE_ATOMICS */
...@@ -675,6 +673,47 @@ static inline void set_sys_caps_initialised(void) ...@@ -675,6 +673,47 @@ static inline void set_sys_caps_initialised(void)
sys_caps_initialised = true; sys_caps_initialised = true;
} }
/*
* __raw_read_system_reg() - Used by a STARTING cpu before cpuinfo is populated.
*/
static u64 __raw_read_system_reg(u32 sys_id)
{
switch (sys_id) {
case SYS_ID_PFR0_EL1: return (u64)read_cpuid(ID_PFR0_EL1);
case SYS_ID_PFR1_EL1: return (u64)read_cpuid(ID_PFR1_EL1);
case SYS_ID_DFR0_EL1: return (u64)read_cpuid(ID_DFR0_EL1);
case SYS_ID_MMFR0_EL1: return (u64)read_cpuid(ID_MMFR0_EL1);
case SYS_ID_MMFR1_EL1: return (u64)read_cpuid(ID_MMFR1_EL1);
case SYS_ID_MMFR2_EL1: return (u64)read_cpuid(ID_MMFR2_EL1);
case SYS_ID_MMFR3_EL1: return (u64)read_cpuid(ID_MMFR3_EL1);
case SYS_ID_ISAR0_EL1: return (u64)read_cpuid(ID_ISAR0_EL1);
case SYS_ID_ISAR1_EL1: return (u64)read_cpuid(ID_ISAR1_EL1);
case SYS_ID_ISAR2_EL1: return (u64)read_cpuid(ID_ISAR2_EL1);
case SYS_ID_ISAR3_EL1: return (u64)read_cpuid(ID_ISAR3_EL1);
case SYS_ID_ISAR4_EL1: return (u64)read_cpuid(ID_ISAR4_EL1);
case SYS_ID_ISAR5_EL1: return (u64)read_cpuid(ID_ISAR4_EL1);
case SYS_MVFR0_EL1: return (u64)read_cpuid(MVFR0_EL1);
case SYS_MVFR1_EL1: return (u64)read_cpuid(MVFR1_EL1);
case SYS_MVFR2_EL1: return (u64)read_cpuid(MVFR2_EL1);
case SYS_ID_AA64PFR0_EL1: return (u64)read_cpuid(ID_AA64PFR0_EL1);
case SYS_ID_AA64PFR1_EL1: return (u64)read_cpuid(ID_AA64PFR0_EL1);
case SYS_ID_AA64DFR0_EL1: return (u64)read_cpuid(ID_AA64DFR0_EL1);
case SYS_ID_AA64DFR1_EL1: return (u64)read_cpuid(ID_AA64DFR0_EL1);
case SYS_ID_AA64MMFR0_EL1: return (u64)read_cpuid(ID_AA64MMFR0_EL1);
case SYS_ID_AA64MMFR1_EL1: return (u64)read_cpuid(ID_AA64MMFR1_EL1);
case SYS_ID_AA64ISAR0_EL1: return (u64)read_cpuid(ID_AA64ISAR0_EL1);
case SYS_ID_AA64ISAR1_EL1: return (u64)read_cpuid(ID_AA64ISAR1_EL1);
case SYS_CNTFRQ_EL0: return (u64)read_cpuid(CNTFRQ_EL0);
case SYS_CTR_EL0: return (u64)read_cpuid(CTR_EL0);
case SYS_DCZID_EL0: return (u64)read_cpuid(DCZID_EL0);
default:
BUG();
return 0;
}
}
/* /*
* Park the CPU which doesn't have the capability as advertised * Park the CPU which doesn't have the capability as advertised
* by the system. * by the system.
...@@ -719,13 +758,13 @@ void verify_local_cpu_capabilities(void) ...@@ -719,13 +758,13 @@ void verify_local_cpu_capabilities(void)
caps = arm64_features; caps = arm64_features;
for (i = 0; caps[i].desc; i++) { for (i = 0; caps[i].desc; i++) {
if (!cpus_have_cap(caps[i].capability)) if (!cpus_have_cap(caps[i].capability) || !caps[i].sys_reg)
continue; continue;
/* /*
* If the new CPU misses an advertised feature, we cannot proceed * If the new CPU misses an advertised feature, we cannot proceed
* further, park the cpu. * further, park the cpu.
*/ */
if (!caps[i].matches(&caps[i])) if (!feature_matches(__raw_read_system_reg(caps[i].sys_reg), &caps[i]))
fail_incapable_cpu("arm64_features", &caps[i]); fail_incapable_cpu("arm64_features", &caps[i]);
if (caps[i].enable) if (caps[i].enable)
caps[i].enable(NULL); caps[i].enable(NULL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment