OSDN Git Service

arm64: errata: Hide CTR_EL0.DIC on systems affected by Neoverse-N1 #1542419
authorJames Morse <james.morse@arm.com>
Fri, 24 Apr 2020 16:38:42 +0000 (17:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 29 Apr 2020 14:31:08 +0000 (16:31 +0200)
[ Upstream commit 05460849c3b51180d5ada3373d0449aea19075e4 ]

Cores affected by Neoverse-N1 #1542419 could execute a stale instruction
when a branch is updated to point to freshly generated instructions.

To workaround this issue we need user-space to issue unnecessary
icache maintenance that we can trap. Start by hiding CTR_EL0.DIC.

Reviewed-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
[ Removed cpu_enable_trap_ctr_access() hunk due to no 4afe8e79da92]
Signed-off-by: James Morse <james.morse@arm.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Documentation/arm64/silicon-errata.txt
arch/arm64/Kconfig
arch/arm64/include/asm/cpucaps.h
arch/arm64/kernel/cpu_errata.c
arch/arm64/kernel/traps.c

index eeb3fc9..667ea90 100644 (file)
@@ -59,6 +59,7 @@ stable kernels.
 | ARM            | Cortex-A73      | #858921         | ARM64_ERRATUM_858921        |
 | ARM            | Cortex-A55      | #1024718        | ARM64_ERRATUM_1024718       |
 | ARM            | Cortex-A76      | #1463225        | ARM64_ERRATUM_1463225       |
+| ARM            | Neoverse-N1     | #1542419        | ARM64_ERRATUM_1542419       |
 | ARM            | MMU-500         | #841119,#826419 | N/A                         |
 |                |                 |                 |                             |
 | Cavium         | ThunderX ITS    | #22375, #24313  | CAVIUM_ERRATUM_22375        |
index 51fe21f..1fe3e5c 100644 (file)
@@ -499,6 +499,22 @@ config ARM64_ERRATUM_1463225
 
          If unsure, say Y.
 
+config ARM64_ERRATUM_1542419
+       bool "Neoverse-N1: workaround mis-ordering of instruction fetches"
+       default y
+       help
+         This option adds a workaround for ARM Neoverse-N1 erratum
+         1542419.
+
+         Affected Neoverse-N1 cores could execute a stale instruction when
+         modified by another CPU. The workaround depends on a firmware
+         counterpart.
+
+         Workaround the issue by hiding the DIC feature from EL0. This
+         forces user-space to perform cache maintenance.
+
+         If unsure, say Y.
+
 config CAVIUM_ERRATUM_22375
        bool "Cavium erratum 22375, 24313"
        default y
index c3de0bb..df8fe8e 100644 (file)
@@ -53,7 +53,8 @@
 #define ARM64_HAS_STAGE2_FWB                   32
 #define ARM64_WORKAROUND_1463225               33
 #define ARM64_SSBS                             34
+#define ARM64_WORKAROUND_1542419               35
 
-#define ARM64_NCAPS                            35
+#define ARM64_NCAPS                            36
 
 #endif /* __ASM_CPUCAPS_H */
index 7188880..76490b0 100644 (file)
@@ -643,6 +643,18 @@ needs_tx2_tvm_workaround(const struct arm64_cpu_capabilities *entry,
        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[] = {
@@ -835,6 +847,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
                .matches = needs_tx2_tvm_workaround,
        },
 #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
        {
        }
 };
index c8dc3a3..253b7f8 100644 (file)
@@ -481,6 +481,9 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs)
        int rt = (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
        unsigned long val = arm64_ftr_reg_user_value(&arm64_ftr_reg_ctrel0);
 
+       if (cpus_have_const_cap(ARM64_WORKAROUND_1542419))
+               val &= ~BIT(CTR_DIC_SHIFT);
+
        pt_regs_write_reg(regs, rt, val);
 
        arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);