Merge branch 'next-loadpin' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris...
[platform/kernel/linux-rpi.git] / arch / arm64 / kernel / cpu_errata.c
index dec1089..a509e35 100644 (file)
@@ -68,21 +68,43 @@ static bool
 has_mismatched_cache_type(const struct arm64_cpu_capabilities *entry,
                          int scope)
 {
-       u64 mask = CTR_CACHE_MINLINE_MASK;
-
-       /* Skip matching the min line sizes for cache type check */
-       if (entry->capability == ARM64_MISMATCHED_CACHE_TYPE)
-               mask ^= arm64_ftr_reg_ctrel0.strict_mask;
+       u64 mask = arm64_ftr_reg_ctrel0.strict_mask;
+       u64 sys = arm64_ftr_reg_ctrel0.sys_val & mask;
+       u64 ctr_raw, ctr_real;
 
        WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
-       return (read_cpuid_cachetype() & mask) !=
-              (arm64_ftr_reg_ctrel0.sys_val & mask);
+
+       /*
+        * We want to make sure that all the CPUs in the system expose
+        * a consistent CTR_EL0 to make sure that applications behaves
+        * correctly with migration.
+        *
+        * If a CPU has CTR_EL0.IDC but does not advertise it via CTR_EL0 :
+        *
+        * 1) It is safe if the system doesn't support IDC, as CPU anyway
+        *    reports IDC = 0, consistent with the rest.
+        *
+        * 2) If the system has IDC, it is still safe as we trap CTR_EL0
+        *    access on this CPU via the ARM64_HAS_CACHE_IDC capability.
+        *
+        * So, we need to make sure either the raw CTR_EL0 or the effective
+        * CTR_EL0 matches the system's copy to allow a secondary CPU to boot.
+        */
+       ctr_raw = read_cpuid_cachetype() & mask;
+       ctr_real = read_cpuid_effective_cachetype() & mask;
+
+       return (ctr_real != sys) && (ctr_raw != sys);
 }
 
 static void
 cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
 {
-       sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
+       u64 mask = arm64_ftr_reg_ctrel0.strict_mask;
+
+       /* Trap CTR_EL0 access on this CPU, only if it has a mismatch */
+       if ((read_cpuid_cachetype() & mask) !=
+           (arm64_ftr_reg_ctrel0.sys_val & mask))
+               sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
 }
 
 atomic_t arm64_el2_vector_last_slot = ATOMIC_INIT(-1);
@@ -116,6 +138,15 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn,
        static DEFINE_SPINLOCK(bp_lock);
        int cpu, slot = -1;
 
+       /*
+        * enable_smccc_arch_workaround_1() passes NULL for the hyp_vecs
+        * start/end if we're a guest. Skip the hyp-vectors work.
+        */
+       if (!hyp_vecs_start) {
+               __this_cpu_write(bp_hardening_data.fn, fn);
+               return;
+       }
+
        spin_lock(&bp_lock);
        for_each_possible_cpu(cpu) {
                if (per_cpu(bp_hardening_data.fn, cpu) == fn) {
@@ -312,6 +343,14 @@ void __init arm64_enable_wa2_handling(struct alt_instr *alt,
 
 void arm64_set_ssbd_mitigation(bool state)
 {
+       if (this_cpu_has_cap(ARM64_SSBS)) {
+               if (state)
+                       asm volatile(SET_PSTATE_SSBS(0));
+               else
+                       asm volatile(SET_PSTATE_SSBS(1));
+               return;
+       }
+
        switch (psci_ops.conduit) {
        case PSCI_CONDUIT_HVC:
                arm_smccc_1_1_hvc(ARM_SMCCC_ARCH_WORKAROUND_2, state, NULL);
@@ -336,6 +375,11 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
 
        WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
 
+       if (this_cpu_has_cap(ARM64_SSBS)) {
+               required = false;
+               goto out_printmsg;
+       }
+
        if (psci_ops.smccc_version == SMCCC_VERSION_1_0) {
                ssbd_state = ARM64_SSBD_UNKNOWN;
                return false;
@@ -384,7 +428,6 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
 
        switch (ssbd_state) {
        case ARM64_SSBD_FORCE_DISABLE:
-               pr_info_once("%s disabled from command-line\n", entry->desc);
                arm64_set_ssbd_mitigation(false);
                required = false;
                break;
@@ -397,7 +440,6 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
                break;
 
        case ARM64_SSBD_FORCE_ENABLE:
-               pr_info_once("%s forced from command-line\n", entry->desc);
                arm64_set_ssbd_mitigation(true);
                required = true;
                break;
@@ -407,10 +449,27 @@ static bool has_ssbd_mitigation(const struct arm64_cpu_capabilities *entry,
                break;
        }
 
+out_printmsg:
+       switch (ssbd_state) {
+       case ARM64_SSBD_FORCE_DISABLE:
+               pr_info_once("%s disabled from command-line\n", entry->desc);
+               break;
+
+       case ARM64_SSBD_FORCE_ENABLE:
+               pr_info_once("%s forced from command-line\n", entry->desc);
+               break;
+       }
+
        return required;
 }
 #endif /* CONFIG_ARM64_SSBD */
 
+static void __maybe_unused
+cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
+{
+       sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCI, 0);
+}
+
 #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)      \
        .matches = is_affected_midr_range,                      \
        .midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
@@ -616,14 +675,7 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
        },
 #endif
        {
-               .desc = "Mismatched cache line size",
-               .capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
-               .matches = has_mismatched_cache_type,
-               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
-               .cpu_enable = cpu_enable_trap_ctr_access,
-       },
-       {
-               .desc = "Mismatched cache type",
+               .desc = "Mismatched cache type (CTR_EL0)",
                .capability = ARM64_MISMATCHED_CACHE_TYPE,
                .matches = has_mismatched_cache_type,
                .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
@@ -680,6 +732,14 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .matches = has_ssbd_mitigation,
        },
 #endif
+#ifdef CONFIG_ARM64_ERRATUM_1188873
+       {
+               /* Cortex-A76 r0p0 to r2p0 */
+               .desc = "ARM erratum 1188873",
+               .capability = ARM64_WORKAROUND_1188873,
+               ERRATA_MIDR_RANGE(MIDR_CORTEX_A76, 0, 0, 2, 0),
+       },
+#endif
        {
        }
 };