]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - arch/arm64/kernel/cpufeature.c
Merge branch 'for-next/fixes' into for-next/core
[thirdparty/linux.git] / arch / arm64 / kernel / cpufeature.c
index 91d2d671496911806c21e1cbb7895fd7cb612810..01a4c1d7fc09a8e2c1c484a5cadcb2c6ca8433bf 100644 (file)
@@ -1081,25 +1081,6 @@ void __init init_cpu_features(struct cpuinfo_arm64 *info)
 
        if (id_aa64pfr1_mte(info->reg_id_aa64pfr1))
                init_cpu_ftr_reg(SYS_GMID_EL1, info->reg_gmid);
-
-       /*
-        * Initialize the indirect array of CPU capabilities pointers before we
-        * handle the boot CPU below.
-        */
-       init_cpucap_indirect_list();
-
-       /*
-        * Detect broken pseudo-NMI. Must be called _before_ the call to
-        * setup_boot_cpu_capabilities() since it interacts with
-        * can_use_gic_priorities().
-        */
-       detect_system_supports_pseudo_nmi();
-
-       /*
-        * Detect and enable early CPU capabilities based on the boot CPU,
-        * after we have initialised the CPU feature infrastructure.
-        */
-       setup_boot_cpu_capabilities();
 }
 
 static void update_cpu_ftr_reg(struct arm64_ftr_reg *reg, u64 new)
@@ -1584,16 +1565,6 @@ static bool has_useable_gicv3_cpuif(const struct arm64_cpu_capabilities *entry,
        return has_sre;
 }
 
-static bool has_no_hw_prefetch(const struct arm64_cpu_capabilities *entry, int __unused)
-{
-       u32 midr = read_cpuid_id();
-
-       /* Cavium ThunderX pass 1.x and 2.x */
-       return midr_is_cpu_model_range(midr, MIDR_THUNDERX,
-               MIDR_CPU_VAR_REV(0, 0),
-               MIDR_CPU_VAR_REV(1, MIDR_REVISION_MASK));
-}
-
 static bool has_cache_idc(const struct arm64_cpu_capabilities *entry,
                          int scope)
 {
@@ -1768,6 +1739,39 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
        return !meltdown_safe;
 }
 
+#if defined(ID_AA64MMFR0_EL1_TGRAN_LPA2) && defined(ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2)
+static bool has_lpa2_at_stage1(u64 mmfr0)
+{
+       unsigned int tgran;
+
+       tgran = cpuid_feature_extract_unsigned_field(mmfr0,
+                                       ID_AA64MMFR0_EL1_TGRAN_SHIFT);
+       return tgran == ID_AA64MMFR0_EL1_TGRAN_LPA2;
+}
+
+static bool has_lpa2_at_stage2(u64 mmfr0)
+{
+       unsigned int tgran;
+
+       tgran = cpuid_feature_extract_unsigned_field(mmfr0,
+                                       ID_AA64MMFR0_EL1_TGRAN_2_SHIFT);
+       return tgran == ID_AA64MMFR0_EL1_TGRAN_2_SUPPORTED_LPA2;
+}
+
+static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
+{
+       u64 mmfr0;
+
+       mmfr0 = read_sanitised_ftr_reg(SYS_ID_AA64MMFR0_EL1);
+       return has_lpa2_at_stage1(mmfr0) && has_lpa2_at_stage2(mmfr0);
+}
+#else
+static bool has_lpa2(const struct arm64_cpu_capabilities *entry, int scope)
+{
+       return false;
+}
+#endif
+
 #ifdef CONFIG_UNMAP_KERNEL_AT_EL0
 #define KPTI_NG_TEMP_VA                (-(1UL << PMD_SHIFT))
 
@@ -1840,7 +1844,7 @@ static int __init __kpti_install_ng_mappings(void *__unused)
 static void __init kpti_install_ng_mappings(void)
 {
        /* Check whether KPTI is going to be used */
-       if (!cpus_have_cap(ARM64_UNMAP_KERNEL_AT_EL0))
+       if (!arm64_kernel_unmapped_at_el0())
                return;
 
        /*
@@ -2325,12 +2329,6 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                ARM64_CPUID_FIELDS(ID_AA64ISAR0_EL1, ATOMIC, IMP)
        },
 #endif /* CONFIG_ARM64_LSE_ATOMICS */
-       {
-               .desc = "Software prefetching using PRFM",
-               .capability = ARM64_HAS_NO_HW_PREFETCH,
-               .type = ARM64_CPUCAP_WEAK_LOCAL_CPU_FEATURE,
-               .matches = has_no_hw_prefetch,
-       },
        {
                .desc = "Virtualization Host Extensions",
                .capability = ARM64_HAS_VIRT_HOST_EXTN,
@@ -2735,6 +2733,12 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
                .matches = has_cpuid_feature,
                ARM64_CPUID_FIELDS(ID_AA64MMFR2_EL1, EVT, IMP)
        },
+       {
+               .desc = "52-bit Virtual Addressing for KVM (LPA2)",
+               .capability = ARM64_HAS_LPA2,
+               .type = ARM64_CPUCAP_SYSTEM_FEATURE,
+               .matches = has_lpa2,
+       },
        {},
 };
 
@@ -3275,14 +3279,6 @@ void check_local_cpu_capabilities(void)
                verify_local_cpu_capabilities();
 }
 
-static void __init setup_boot_cpu_capabilities(void)
-{
-       /* Detect capabilities with either SCOPE_BOOT_CPU or SCOPE_LOCAL_CPU */
-       update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU);
-       /* Enable the SCOPE_BOOT_CPU capabilities alone right away */
-       enable_cpu_capabilities(SCOPE_BOOT_CPU);
-}
-
 bool this_cpu_has_cap(unsigned int n)
 {
        if (!WARN_ON(preemptible()) && n < ARM64_NCAPS) {
@@ -3338,37 +3334,52 @@ unsigned long cpu_get_elf_hwcap2(void)
        return elf_hwcap[1];
 }
 
-void __init setup_system_features(void)
+static void __init setup_boot_cpu_capabilities(void)
 {
-       int i;
        /*
-        * The system-wide safe feature feature register values have been
-        * finalized. Finalize and log the available system capabilities.
+        * The boot CPU's feature register values have been recorded. Detect
+        * boot cpucaps and local cpucaps for the boot CPU, then enable and
+        * patch alternatives for the available boot cpucaps.
         */
-       update_cpu_capabilities(SCOPE_SYSTEM);
-       if (IS_ENABLED(CONFIG_ARM64_SW_TTBR0_PAN) &&
-           !cpus_have_cap(ARM64_HAS_PAN))
-               pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
+       update_cpu_capabilities(SCOPE_BOOT_CPU | SCOPE_LOCAL_CPU);
+       enable_cpu_capabilities(SCOPE_BOOT_CPU);
+       apply_boot_alternatives();
+}
 
+void __init setup_boot_cpu_features(void)
+{
        /*
-        * Enable all the available capabilities which have not been enabled
-        * already.
+        * Initialize the indirect array of CPU capabilities pointers before we
+        * handle the boot CPU.
         */
-       enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
+       init_cpucap_indirect_list();
 
-       kpti_install_ng_mappings();
+       /*
+        * Detect broken pseudo-NMI. Must be called _before_ the call to
+        * setup_boot_cpu_capabilities() since it interacts with
+        * can_use_gic_priorities().
+        */
+       detect_system_supports_pseudo_nmi();
 
-       sve_setup();
-       sme_setup();
+       setup_boot_cpu_capabilities();
+}
 
+static void __init setup_system_capabilities(void)
+{
        /*
-        * Check for sane CTR_EL0.CWG value.
+        * The system-wide safe feature register values have been finalized.
+        * Detect, enable, and patch alternatives for the available system
+        * cpucaps.
         */
-       if (!cache_type_cwg())
-               pr_warn("No Cache Writeback Granule information, assuming %d\n",
-                       ARCH_DMA_MINALIGN);
+       update_cpu_capabilities(SCOPE_SYSTEM);
+       enable_cpu_capabilities(SCOPE_ALL & ~SCOPE_BOOT_CPU);
+       apply_alternatives_all();
 
-       for (i = 0; i < ARM64_NCAPS; i++) {
+       /*
+        * Log any cpucaps with a cpumask as these aren't logged by
+        * update_cpu_capabilities().
+        */
+       for (int i = 0; i < ARM64_NCAPS; i++) {
                const struct arm64_cpu_capabilities *caps = cpucap_ptrs[i];
 
                if (caps && caps->cpus && caps->desc &&
@@ -3376,6 +3387,29 @@ void __init setup_system_features(void)
                        pr_info("detected: %s on CPU%*pbl\n",
                                caps->desc, cpumask_pr_args(caps->cpus));
        }
+
+       /*
+        * TTBR0 PAN doesn't have its own cpucap, so log it manually.
+        */
+       if (system_uses_ttbr0_pan())
+               pr_info("emulated: Privileged Access Never (PAN) using TTBR0_EL1 switching\n");
+}
+
+void __init setup_system_features(void)
+{
+       setup_system_capabilities();
+
+       kpti_install_ng_mappings();
+
+       sve_setup();
+       sme_setup();
+
+       /*
+        * Check for sane CTR_EL0.CWG value.
+        */
+       if (!cache_type_cwg())
+               pr_warn("No Cache Writeback Granule information, assuming %d\n",
+                       ARCH_DMA_MINALIGN);
 }
 
 void __init setup_user_features(void)