Merge branch 'for-next/neoverse-n1-stale-instr' into for-next/core
authorCatalin Marinas <catalin.marinas@arm.com>
Mon, 28 Oct 2019 16:12:40 +0000 (16:12 +0000)
committerCatalin Marinas <catalin.marinas@arm.com>
Mon, 28 Oct 2019 16:12:40 +0000 (16:12 +0000)
Neoverse-N1 cores with the 'COHERENT_ICACHE' feature may fetch stale
instructions when software depends on prefetch-speculation-protection
instead of explicit synchronization. [0]

The workaround is to trap I-Cache maintenance and issue an
inner-shareable TLBI. The affected cores have a Coherent I-Cache, so the
I-Cache maintenance isn't necessary. The core tells user-space it can
skip it with CTR_EL0.DIC. We also have to trap this register to hide the
bit forcing DIC-aware user-space to perform the maintenance.

To avoid trapping all cache-maintenance, this workaround depends on
a firmware component that only traps I-cache maintenance from EL0 and
performs the workaround.

For user-space, the kernel's work is to trap CTR_EL0 to hide DIC, and
produce a fake IminLine. EL3 traps the now-necessary I-Cache maintenance
and performs the inner-shareable-TLBI that makes everything better.

[0] https://developer.arm.com/docs/sden885747/latest/arm-neoverse-n1-mp050-software-developer-errata-notice

* for-next/neoverse-n1-stale-instr:
  arm64: Silence clang warning on mismatched value/register sizes
  arm64: compat: Workaround Neoverse-N1 #1542419 for compat user-space
  arm64: Fake the IminLine size on systems affected by Neoverse-N1 #1542419
  arm64: errata: Hide CTR_EL0.DIC on systems affected by Neoverse-N1 #1542419

1  2 
Documentation/arm64/silicon-errata.rst
arch/arm64/Kconfig
arch/arm64/include/asm/cpucaps.h
arch/arm64/kernel/cpu_errata.c

Simple merge
  #define ARM64_HAS_IRQ_PRIO_MASKING            42
  #define ARM64_HAS_DCPODP                      43
  #define ARM64_WORKAROUND_1463225              44
 -#define ARM64_WORKAROUND_1542419              45
 +#define ARM64_WORKAROUND_CAVIUM_TX2_219_TVM   45
 +#define ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM  46
++#define ARM64_WORKAROUND_1542419              47
  
- #define ARM64_NCAPS                           47
 -#define ARM64_NCAPS                           46
++#define ARM64_NCAPS                           48
  
  #endif /* __ASM_CPUCAPS_H */
@@@ -624,30 -631,18 +632,42 @@@ check_branch_predictor(const struct arm
        return (need_wa > 0);
  }
  
 +static const __maybe_unused struct midr_range tx2_family_cpus[] = {
 +      MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN),
 +      MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2),
 +      {},
 +};
 +
 +static bool __maybe_unused
 +needs_tx2_tvm_workaround(const struct arm64_cpu_capabilities *entry,
 +                       int scope)
 +{
 +      int i;
 +
 +      if (!is_affected_midr_range_list(entry, scope) ||
 +          !is_hyp_mode_available())
 +              return false;
 +
 +      for_each_possible_cpu(i) {
 +              if (MPIDR_AFFINITY_LEVEL(cpu_logical_map(i), 0) != 0)
 +                      return true;
 +      }
 +
 +      return false;
 +}
 +
+ static bool __maybe_unused
+ has_neoverse_n1_erratum_1542419(const struct arm64_cpu_capabilities *entry,
+                               int scope)
+ {
+       u32 midr = read_cpuid_id();
+       bool has_dic = read_cpuid_cachetype() & BIT(CTR_DIC_SHIFT);
+       const struct midr_range range = MIDR_ALL_VERSIONS(MIDR_NEOVERSE_N1);
+       WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible());
+       return is_midr_in_range(midr, &range) && has_dic;
+ }
  #ifdef CONFIG_HARDEN_EL2_VECTORS
  
  static const struct midr_range arm64_harden_el2_vectors[] = {
@@@ -877,19 -872,16 +897,29 @@@ const struct arm64_cpu_capabilities arm
                .matches = has_cortex_a76_erratum_1463225,
        },
  #endif
 +#ifdef CONFIG_CAVIUM_TX2_ERRATUM_219
 +      {
 +              .desc = "Cavium ThunderX2 erratum 219 (KVM guest sysreg trapping)",
 +              .capability = ARM64_WORKAROUND_CAVIUM_TX2_219_TVM,
 +              ERRATA_MIDR_RANGE_LIST(tx2_family_cpus),
 +              .matches = needs_tx2_tvm_workaround,
 +      },
 +      {
 +              .desc = "Cavium ThunderX2 erratum 219 (PRFM removal)",
 +              .capability = ARM64_WORKAROUND_CAVIUM_TX2_219_PRFM,
 +              ERRATA_MIDR_RANGE_LIST(tx2_family_cpus),
 +      },
 +#endif
+ #ifdef CONFIG_ARM64_ERRATUM_1542419
+       {
+               /* we depend on the firmware portion for correctness */
+               .desc = "ARM erratum 1542419 (kernel portion)",
+               .capability = ARM64_WORKAROUND_1542419,
+               .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+               .matches = has_neoverse_n1_erratum_1542419,
+               .cpu_enable = cpu_enable_trap_ctr_access,
+       },
+ #endif
        {
        }
  };