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: Suzuki K. Poulose <suzuki.poulose@arm.com> Tested-by: Dave Martin <Dave.Martin@arm.com> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
parent
dbb4e152b8
commit
da8d02d19f
@ -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)
|
|||||||
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[] = {
|
|||||||
{
|
{
|
||||||
.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)
|
|||||||
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)
|
|||||||
|
|
||||||
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);
|
||||||
|
Loading…
Reference in New Issue
Block a user