mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-18 17:54:13 +08:00
arm64: errata: Hide CTR_EL0.DIC on systems affected by Neoverse-N1 #1542419
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>
This commit is contained in:
parent
4f5cafb5cb
commit
05460849c3
@ -88,6 +88,8 @@ stable kernels.
|
|||||||
+----------------+-----------------+-----------------+-----------------------------+
|
+----------------+-----------------+-----------------+-----------------------------+
|
||||||
| ARM | Neoverse-N1 | #1349291 | N/A |
|
| ARM | Neoverse-N1 | #1349291 | N/A |
|
||||||
+----------------+-----------------+-----------------+-----------------------------+
|
+----------------+-----------------+-----------------+-----------------------------+
|
||||||
|
| ARM | Neoverse-N1 | #1542419 | ARM64_ERRATUM_1542419 |
|
||||||
|
+----------------+-----------------+-----------------+-----------------------------+
|
||||||
| ARM | MMU-500 | #841119,826419 | N/A |
|
| ARM | MMU-500 | #841119,826419 | N/A |
|
||||||
+----------------+-----------------+-----------------+-----------------------------+
|
+----------------+-----------------+-----------------+-----------------------------+
|
||||||
+----------------+-----------------+-----------------+-----------------------------+
|
+----------------+-----------------+-----------------+-----------------------------+
|
||||||
|
@ -558,6 +558,22 @@ config ARM64_ERRATUM_1463225
|
|||||||
|
|
||||||
If unsure, say Y.
|
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
|
config CAVIUM_ERRATUM_22375
|
||||||
bool "Cavium erratum 22375, 24313"
|
bool "Cavium erratum 22375, 24313"
|
||||||
default y
|
default y
|
||||||
|
@ -52,7 +52,8 @@
|
|||||||
#define ARM64_HAS_IRQ_PRIO_MASKING 42
|
#define ARM64_HAS_IRQ_PRIO_MASKING 42
|
||||||
#define ARM64_HAS_DCPODP 43
|
#define ARM64_HAS_DCPODP 43
|
||||||
#define ARM64_WORKAROUND_1463225 44
|
#define ARM64_WORKAROUND_1463225 44
|
||||||
|
#define ARM64_WORKAROUND_1542419 45
|
||||||
|
|
||||||
#define ARM64_NCAPS 45
|
#define ARM64_NCAPS 46
|
||||||
|
|
||||||
#endif /* __ASM_CPUCAPS_H */
|
#endif /* __ASM_CPUCAPS_H */
|
||||||
|
@ -87,13 +87,21 @@ has_mismatched_cache_type(const struct arm64_cpu_capabilities *entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *__unused)
|
cpu_enable_trap_ctr_access(const struct arm64_cpu_capabilities *cap)
|
||||||
{
|
{
|
||||||
u64 mask = arm64_ftr_reg_ctrel0.strict_mask;
|
u64 mask = arm64_ftr_reg_ctrel0.strict_mask;
|
||||||
|
bool enable_uct_trap = false;
|
||||||
|
|
||||||
/* Trap CTR_EL0 access on this CPU, only if it has a mismatch */
|
/* Trap CTR_EL0 access on this CPU, only if it has a mismatch */
|
||||||
if ((read_cpuid_cachetype() & mask) !=
|
if ((read_cpuid_cachetype() & mask) !=
|
||||||
(arm64_ftr_reg_ctrel0.sys_val & mask))
|
(arm64_ftr_reg_ctrel0.sys_val & mask))
|
||||||
|
enable_uct_trap = true;
|
||||||
|
|
||||||
|
/* ... or if the system is affected by an erratum */
|
||||||
|
if (cap->capability == ARM64_WORKAROUND_1542419)
|
||||||
|
enable_uct_trap = true;
|
||||||
|
|
||||||
|
if (enable_uct_trap)
|
||||||
sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
|
sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCT, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,6 +631,18 @@ check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope)
|
|||||||
return (need_wa > 0);
|
return (need_wa > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
#ifdef CONFIG_HARDEN_EL2_VECTORS
|
||||||
|
|
||||||
static const struct midr_range arm64_harden_el2_vectors[] = {
|
static const struct midr_range arm64_harden_el2_vectors[] = {
|
||||||
@ -851,6 +871,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
|
|||||||
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
.type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
|
||||||
.matches = has_cortex_a76_erratum_1463225,
|
.matches = has_cortex_a76_erratum_1463225,
|
||||||
},
|
},
|
||||||
|
#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
|
#endif
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -470,6 +470,9 @@ static void ctr_read_handler(unsigned int esr, struct pt_regs *regs)
|
|||||||
int rt = ESR_ELx_SYS64_ISS_RT(esr);
|
int rt = ESR_ELx_SYS64_ISS_RT(esr);
|
||||||
unsigned long val = arm64_ftr_reg_user_value(&arm64_ftr_reg_ctrel0);
|
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);
|
pt_regs_write_reg(regs, rt, val);
|
||||||
|
|
||||||
arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
|
arm64_skip_faulting_instruction(regs, AARCH64_INSN_SIZE);
|
||||||
|
Loading…
Reference in New Issue
Block a user