Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
[sfrench/cifs-2.6.git] / arch / arm64 / kernel / cpu_errata.c
index 3c0bb6c4ed02172d9d151a90807b3ad531aff45c..2df792771053f14dd8a1fc63bd256f93c81879d1 100644 (file)
@@ -40,6 +40,14 @@ is_affected_midr_range(const struct arm64_cpu_capabilities *entry, int scope)
        return true;
 }
 
+static bool __maybe_unused
+is_affected_midr_range_list(const struct arm64_cpu_capabilities *entry,
+                           int scope)
+{
+       WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+       return is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list);
+}
+
 static bool __maybe_unused
 is_kryo_midr(const struct arm64_cpu_capabilities *entry, int scope)
 {
@@ -188,7 +196,7 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
        case PSCI_CONDUIT_HVC:
                arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
                                  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
-               if (res.a0)
+               if ((int)res.a0 < 0)
                        return;
                cb = call_hvc_arch_workaround_1;
                smccc_start = __smccc_workaround_1_hvc_start;
@@ -198,7 +206,7 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry)
        case PSCI_CONDUIT_SMC:
                arm_smccc_1_1_smc(ARM_SMCCC_ARCH_FEATURES_FUNC_ID,
                                  ARM_SMCCC_ARCH_WORKAROUND_1, &res);
-               if (res.a0)
+               if ((int)res.a0 < 0)
                        return;
                cb = call_smc_arch_workaround_1;
                smccc_start = __smccc_workaround_1_smc_start;
@@ -250,6 +258,10 @@ qcom_enable_link_stack_sanitization(const struct arm64_cpu_capabilities *entry)
        .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,                         \
        CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)
 
+#define CAP_MIDR_RANGE_LIST(list)                              \
+       .matches = is_affected_midr_range_list,                 \
+       .midr_range_list = list
+
 /* Errata affecting a range of revisions of  given model variant */
 #define ERRATA_MIDR_REV_RANGE(m, var, r_min, r_max)     \
        ERRATA_MIDR_RANGE(m, var, r_min, var, r_max)
@@ -263,6 +275,79 @@ qcom_enable_link_stack_sanitization(const struct arm64_cpu_capabilities *entry)
        .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,                 \
        CAP_MIDR_ALL_VERSIONS(model)
 
+/* Errata affecting a list of midr ranges, with same work around */
+#define ERRATA_MIDR_RANGE_LIST(midr_list)                      \
+       .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,                 \
+       CAP_MIDR_RANGE_LIST(midr_list)
+
+/*
+ * Generic helper for handling capabilties with multiple (match,enable) pairs
+ * of call backs, sharing the same capability bit.
+ * Iterate over each entry to see if at least one matches.
+ */
+static bool __maybe_unused
+multi_entry_cap_matches(const struct arm64_cpu_capabilities *entry, int scope)
+{
+       const struct arm64_cpu_capabilities *caps;
+
+       for (caps = entry->match_list; caps->matches; caps++)
+               if (caps->matches(caps, scope))
+                       return true;
+
+       return false;
+}
+
+/*
+ * Take appropriate action for all matching entries in the shared capability
+ * entry.
+ */
+static void __maybe_unused
+multi_entry_cap_cpu_enable(const struct arm64_cpu_capabilities *entry)
+{
+       const struct arm64_cpu_capabilities *caps;
+
+       for (caps = entry->match_list; caps->matches; caps++)
+               if (caps->matches(caps, SCOPE_LOCAL_CPU) &&
+                   caps->cpu_enable)
+                       caps->cpu_enable(caps);
+}
+
+#ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
+
+/*
+ * List of CPUs where we need to issue a psci call to
+ * harden the branch predictor.
+ */
+static const struct midr_range arm64_bp_harden_smccc_cpus[] = {
+       MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
+       MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
+       MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
+       MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
+       MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
+       MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
+       {},
+};
+
+static const struct midr_range qcom_bp_harden_cpus[] = {
+       MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
+       MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
+       {},
+};
+
+static const struct arm64_cpu_capabilities arm64_bp_harden_list[] = {
+       {
+               CAP_MIDR_RANGE_LIST(arm64_bp_harden_smccc_cpus),
+               .cpu_enable = enable_smccc_arch_workaround_1,
+       },
+       {
+               CAP_MIDR_RANGE_LIST(qcom_bp_harden_cpus),
+               .cpu_enable = qcom_enable_link_stack_sanitization,
+       },
+       {},
+};
+
+#endif
+
 const struct arm64_cpu_capabilities arm64_errata[] = {
 #if    defined(CONFIG_ARM64_ERRATUM_826319) || \
        defined(CONFIG_ARM64_ERRATUM_827319) || \
@@ -406,51 +491,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR
        {
                .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A57),
-               .cpu_enable = enable_smccc_arch_workaround_1,
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A72),
-               .cpu_enable = enable_smccc_arch_workaround_1,
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A73),
-               .cpu_enable = enable_smccc_arch_workaround_1,
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_CORTEX_A75),
-               .cpu_enable = enable_smccc_arch_workaround_1,
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-               .cpu_enable = qcom_enable_link_stack_sanitization,
-       },
-       {
-               .capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1),
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
-               .cpu_enable = qcom_enable_link_stack_sanitization,
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+               .matches = multi_entry_cap_matches,
+               .cpu_enable = multi_entry_cap_cpu_enable,
+               .match_list = arm64_bp_harden_list,
        },
        {
                .capability = ARM64_HARDEN_BP_POST_GUEST_EXIT,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR),
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
-               .cpu_enable = enable_smccc_arch_workaround_1,
-       },
-       {
-               .capability = ARM64_HARDEN_BRANCH_PREDICTOR,
-               ERRATA_MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
-               .cpu_enable = enable_smccc_arch_workaround_1,
+               ERRATA_MIDR_RANGE_LIST(qcom_bp_harden_cpus),
        },
 #endif
        {