Commit 0baba94a authored by Catalin Marinas's avatar Catalin Marinas
Browse files

arm64: errata: Work around early CME DVMSync acknowledgement

C1-Pro acknowledges DVMSync messages before completing the SME/CME
memory accesses. Work around this by issuing an IPI to the affected CPUs
if they are running in EL0 with SME enabled.

Note that we avoid the local DSB in the IPI handler as the kernel runs
with SCTLR_EL1.IESB=1. This is sufficient to complete SME memory
accesses at EL0 on taking an exception to EL1. On the return to user
path, no barrier is necessary either. See the comment in
sme_set_active() and the more detailed explanation in the link below.

To avoid a potential IPI flood from malicious applications (e.g.
madvise(MADV_PAGEOUT) in a tight loop), track where a process is active
via mm_cpumask() and only interrupt those CPUs.

Link: https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3


Cc: Will Deacon <will@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: James Morse <james.morse@arm.com>
Cc: Mark Brown <broonie@kernel.org>
Reviewed-by: default avatarWill Deacon <will@kernel.org>
Signed-off-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
parent 2c995610
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -202,6 +202,8 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | Neoverse-V3AE   | #3312417        | ARM64_ERRATUM_3194386       |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | C1-Pro          | #4193714        | ARM64_ERRATUM_4193714       |
+----------------+-----------------+-----------------+-----------------------------+
| ARM            | MMU-500         | #841119,826419  | ARM_SMMU_MMU_500_CPRE_ERRATA|
|                |                 | #562869,1047329 |                             |
+----------------+-----------------+-----------------+-----------------------------+
+12 −0
Original line number Diff line number Diff line
@@ -1175,6 +1175,18 @@ config ARM64_ERRATUM_4311569

	  If unsure, say Y.

config ARM64_ERRATUM_4193714
	bool "C1-Pro: 4193714: SME DVMSync early acknowledgement"
	depends on ARM64_SME
	default y
	help
	  Enable workaround for C1-Pro acknowledging the DVMSync before
	  the SME memory accesses are complete. This will cause TLB
	  maintenance for processes using SME to also issue an IPI to
	  the affected CPUs.

	  If unsure, say Y.

config CAVIUM_ERRATUM_22375
	bool "Cavium erratum 22375, 24313"
	default y
+2 −0
Original line number Diff line number Diff line
@@ -64,6 +64,8 @@ cpucap_is_possible(const unsigned int cap)
		return IS_ENABLED(CONFIG_ARM64_WORKAROUND_REPEAT_TLBI);
	case ARM64_WORKAROUND_SPECULATIVE_SSBS:
		return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
	case ARM64_WORKAROUND_4193714:
		return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714);
	case ARM64_MPAM:
		/*
		 * KVM MPAM support doesn't rely on the host kernel supporting MPAM.
+21 −0
Original line number Diff line number Diff line
@@ -428,6 +428,24 @@ static inline size_t sme_state_size(struct task_struct const *task)
	return __sme_state_size(task_get_sme_vl(task));
}

void sme_enable_dvmsync(void);
void sme_set_active(void);
void sme_clear_active(void);

static inline void sme_enter_from_user_mode(void)
{
	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
	    test_thread_flag(TIF_SME))
		sme_clear_active();
}

static inline void sme_exit_to_user_mode(void)
{
	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714) &&
	    test_thread_flag(TIF_SME))
		sme_set_active();
}

#else

static inline void sme_user_disable(void) { BUILD_BUG(); }
@@ -456,6 +474,9 @@ static inline size_t sme_state_size(struct task_struct const *task)
	return 0;
}

static inline void sme_enter_from_user_mode(void) { }
static inline void sme_exit_to_user_mode(void) { }

#endif /* ! CONFIG_ARM64_SME */

/* For use by EFI runtime services calls only */
+8 −2
Original line number Diff line number Diff line
@@ -2,11 +2,17 @@
#ifndef _ARCH_ARM64_TLBBATCH_H
#define _ARCH_ARM64_TLBBATCH_H

#include <linux/cpumask.h>

struct arch_tlbflush_unmap_batch {
#ifdef CONFIG_ARM64_ERRATUM_4193714
	/*
	 * For arm64, HW can do tlb shootdown, so we don't
	 * need to record cpumask for sending IPI
	 * Track CPUs that need SME DVMSync on completion of this batch.
	 * Otherwise, the arm64 HW can do tlb shootdown, so we don't need to
	 * record cpumask for sending IPI
	 */
	cpumask_var_t cpumask;
#endif
};

#endif /* _ARCH_ARM64_TLBBATCH_H */
Loading