@@ -1755,13 +1755,12 @@ has_useable_cnp(const struct arm64_cpu_capabilities *entry, int scope)
return has_cpuid_feature(entry, scope);
}
-static bool __meltdown_safe = true;
-static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
-
-static bool needs_kpti(const struct arm64_cpu_capabilities *entry, int scope)
+static bool cpu_is_meltdown_safe(void)
{
- /* List of CPUs that are not vulnerable and don't need KPTI */
- static const struct midr_range kpti_safe_list[] = {
+ u64 pfr0;
+
+ /* List of CPUs that are not vulnerable to meltdown */
+ static const struct midr_range meltdown_safe_list[] = {
MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
MIDR_ALL_VERSIONS(MIDR_BRAHMA_B53),
@@ -1779,15 +1778,32 @@ static bool needs_kpti(const struct arm64_cpu_capabilities *entry, int scope)
MIDR_ALL_VERSIONS(MIDR_QCOM_KRYO_4XX_SILVER),
{ /* sentinel */ }
};
+
+ if (is_midr_in_range_list(read_cpuid_id(), meltdown_safe_list))
+ return true;
+
+ /*
+ * ID_AA64PFR0_EL1.CSV3 > 0 indicates that this CPU is not vulnerable
+ * to meltdown.
+ */
+ pfr0 = __read_sysreg_by_encoding(SYS_ID_AA64PFR0_EL1);
+ if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_EL1_CSV3_SHIFT))
+ return true;
+
+ return false;
+}
+
+static bool __meltdown_safe = true;
+static int __kpti_forced; /* 0: not forced, >0: forced on, <0: forced off */
+
+static bool needs_kpti(const struct arm64_cpu_capabilities *entry, int scope)
+{
char const *str = "kpti command line option";
bool meltdown_safe;
- meltdown_safe = is_midr_in_range_list(read_cpuid_id(), kpti_safe_list);
-
- /* Defer to CPU feature registers */
- if (has_cpuid_feature(entry, scope))
- meltdown_safe = true;
+ WARN_ON(scope != SCOPE_LOCAL_CPU);
+ meltdown_safe = cpu_is_meltdown_safe();
if (!meltdown_safe)
__meltdown_safe = false;
@@ -2545,11 +2561,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
.type = ARM64_CPUCAP_BOOT_RESTRICTED_CPU_LOCAL_FEATURE,
.cpu_enable = cpu_enable_kpti,
.matches = needs_kpti,
- /*
- * The ID feature fields below are used to indicate that the
- * CPU doesn't need KPTI. See needs_kpti for more details.
- */
- ARM64_CPUID_FIELDS(ID_AA64PFR0_EL1, CSV3, IMP)
},
{
.capability = ARM64_HAS_FPSIMD,
Currently needs_kpti() checks whether a CPU is immune to meltdown. The ID_AA64PFR0_EL1.CSV3 ID register field allows a CPU to self report that it is immune, and kpti_safe_list contains CPUs which are known to be immune but predate the existence of ID_AA64PFR0_EL1.CSV3. In future there may be additional reasons to enable KPTI for a CPU regardless of whether that CPU is immune to meltdown. Factor out the existing meltdown checks into a new cpu_is_meltdown_safe() helper function. The ID_AA64PFR0_EL1.CSV3 field description is removed from the capability structure and made explicit within cpu_is_meltdown_safe(). As needs_kpti() is only called with SCOPE_LOCAL, this should not result in any functional change. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Cc: Catalin Marins <catalin.marinas@arm.com> Cc: Will Deacon <will@kernel.org> --- arch/arm64/kernel/cpufeature.c | 43 +++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 16 deletions(-)