Commit 96d389ca authored by Rob Herring's avatar Rob Herring Committed by Will Deacon
Browse files

arm64: Add workaround for Arm Cortex-A77 erratum 1508412

On Cortex-A77 r0p0 and r1p0, a sequence of a non-cacheable or device load
and a store exclusive or PAR_EL1 read can cause a deadlock.

The workaround requires a DMB SY before and after a PAR_EL1 register
read. In addition, it's possible an interrupt (doing a device read) or
KVM guest exit could be taken between the DMB and PAR read, so we
also need a DMB before returning from interrupt and before returning to
a guest.

A deadlock is still possible with the workaround as KVM guests must also
have the workaround. IOW, a malicious guest can deadlock an affected
systems.

This workaround also depends on a firmware counterpart to enable the h/w
to insert DMB SY after load and store exclusive instructions. See the
errata document SDEN-1152370 v10 [1] for more information.

[1] https://static.docs.arm.com/101992/0010/Arm_Cortex_A77_MP074_Software_Developer_Errata_Notice_v10.pdf



Signed-off-by: default avatarRob Herring <robh@kernel.org>
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarMarc Zyngier <maz@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Suzuki K Poulose <suzuki.poulose@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: Julien Thierry <julien.thierry.kdev@gmail.com>
Cc: kvmarm@lists.cs.columbia.edu
Link: https://lore.kernel.org/r/20201028182839.166037-2-robh@kernel.org


Signed-off-by: default avatarWill Deacon <will@kernel.org>
parent 8a6b88e6
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -90,6 +90,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | Cortex-A76      | #1463225        | ARM64_ERRATUM_1463225       |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | Cortex-A77      | #1508412        | ARM64_ERRATUM_1508412       |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | Neoverse-N1     | #1188873,1418040| ARM64_ERRATUM_1418040       |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | Neoverse-N1     | #1349291        | N/A                         |
+20 −0
Original line number Diff line number Diff line
@@ -636,6 +636,26 @@ config ARM64_ERRATUM_1542419

	  If unsure, say Y.

config ARM64_ERRATUM_1508412
	bool "Cortex-A77: 1508412: workaround deadlock on sequence of NC/Device load and store exclusive or PAR read"
	default y
	help
	  This option adds a workaround for Arm Cortex-A77 erratum 1508412.

	  Affected Cortex-A77 cores (r0p0, r1p0) could deadlock on a sequence
	  of a store-exclusive or read of PAR_EL1 and a load with device or
	  non-cacheable memory attributes. The workaround depends on a firmware
	  counterpart.

	  KVM guests must also have the workaround implemented or they can
	  deadlock the system.

	  Work around the issue by inserting DMB SY barriers around PAR_EL1
	  register reads and warning KVM users. The DMB barrier is sufficient
	  to prevent a speculative PAR_EL1 read.

	  If unsure, say Y.

config CAVIUM_ERRATUM_22375
	bool "Cavium erratum 22375, 24313"
	default y
+2 −1
Original line number Diff line number Diff line
@@ -65,7 +65,8 @@
#define ARM64_HAS_ARMv8_4_TTL			55
#define ARM64_HAS_TLB_RANGE			56
#define ARM64_MTE				57
#define ARM64_WORKAROUND_1508412		58

#define ARM64_NCAPS				58
#define ARM64_NCAPS				59

#endif /* __ASM_CPUCAPS_H */
+9 −0
Original line number Diff line number Diff line
@@ -1007,6 +1007,7 @@

#include <linux/build_bug.h>
#include <linux/types.h>
#include <asm/alternative.h>

#define __DEFINE_MRS_MSR_S_REGNUM				\
"	.irp	num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30\n" \
@@ -1095,6 +1096,14 @@
		write_sysreg_s(__scs_new, sysreg);			\
} while (0)

#define read_sysreg_par() ({						\
	u64 par;							\
	asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));	\
	par = read_sysreg(par_el1);					\
	asm(ALTERNATIVE("nop", "dmb sy", ARM64_WORKAROUND_1508412));	\
	par;								\
})

#endif

#endif	/* __ASM_SYSREG_H */
+10 −0
Original line number Diff line number Diff line
@@ -522,6 +522,16 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
		.matches = has_neoverse_n1_erratum_1542419,
		.cpu_enable = cpu_enable_trap_ctr_access,
	},
#endif
#ifdef CONFIG_ARM64_ERRATUM_1508412
	{
		/* we depend on the firmware portion for correctness */
		.desc = "ARM erratum 1508412 (kernel portion)",
		.capability = ARM64_WORKAROUND_1508412,
		ERRATA_MIDR_RANGE(MIDR_CORTEX_A77,
				  0, 0,
				  1, 0),
	},
#endif
	{
	}
Loading