Linux kernel and device drivers for NXP i.MX platforms
 help / color / mirror / Atom feed
* [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue
@ 2026-07-29  3:28 Peng Fan (OSS)
  2026-07-29  3:42 ` sashiko-bot
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Peng Fan (OSS) @ 2026-07-29  3:28 UTC (permalink / raw)
  To: Catalin Marinas, Will Deacon, Jonathan Corbet, Marc Zyngier,
	Oliver Upton, Fuad Tabba, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu
  Cc: Mark Rutland, Ivan T. Ivanov, Francesco Dolcini, Frank Li,
	linux-arm-kernel, linux-doc, linux-kernel, kvmarm, imx, Peng Fan

From: Peng Fan <peng.fan@nxp.com>

According to NXP errata document IMX8_1N94W[1], the i.MX8QuadMax SoC
suffers from a serious cache coherency issue (ERR050104). The upper
bits, above bit 35, of the ARADDR and ACADDR buses within the Arm A53
subsystem have been incorrectly connected. This causes some TLBI and IC
maintenance operations exchanged between the A53 and A72 core clusters
to be corrupted.

The workaround requires:

  - Downgrading targeted TLBI operations to broadcast-all variants.
    Instead of patching the low-level __TLBI_1 macro (which interferes
    with the REPEAT_TLBI workaround and causes excessive over-
    invalidation), redirect high-level TLB flush functions
    (flush_tlb_mm, __do_flush_tlb_range, flush_tlb_kernel_range,
    __flush_tlb_kernel_pgtable) to use VMALLE1IS via static key checks.

  - Upgrading IC IVAU to IC IALLUIS for both kernel (via ALTERNATIVE in
    invalidate_icache_by_line) and EL0 userspace (via trap-and-upgrade
    in user_cache_maint_handler with SCTLR_EL1.UCI=0).

  - Disabling KVM since correct TLB maintenance cannot be guaranteed
    for guests without the proper devicetree.

  - No need to touch SMMU Broadcast TLB Maintenance (BTM) since i.MX8QM
    does not support broadcast TLB.

SoC detection uses devicetree compatible string "fsl,imx8qm" since the
boot CPU MIDR_EL1 (0x410fd034) and AIDR_EL1 (0) are not unique to this
SoC.

[1] https://www.nxp.com/docs/en/errata/IMX8_1N94W.pdf

[ Reworked per review feedback from Will Deacon and Mark Rutland:
  - Move TLBI workaround from __TLBI_1 macro to high-level flush
    functions to avoid REPEAT_TLBI interaction issues
  - Add kernel IC IVAU upgrade via ALTERNATIVE in assembler.h
  - Add cpucap_is_possible() entry for compile-time elimination]

Co-developed-by: Ivan T. Ivanov <iivanov@suse.de>
Signed-off-by: Ivan T. Ivanov <iivanov@suse.de>
Link: https://lore.kernel.org/all/20230420112952.28340-1-iivanov@suse.de/
Signed-off-by: Peng Fan <peng.fan@nxp.com>
---
This picks up the work originally done by Ivan T. Ivanov in 2023 [1],
reworked to address review feedback from Will Deacon and Mark Rutland,
and rebased onto linux-next (next-20260723).

Changes from v2 [1]:
  - Moved TLBI workaround from __TLBI_1 macro to high-level flush
    functions (flush_tlb_mm, __do_flush_tlb_range, flush_tlb_kernel_range,
    __flush_tlb_kernel_pgtable) to avoid REPEAT_TLBI interaction issues,
    per Will Deacon suggestion to use static keys at the higher level.
  - Added kernel IC IVAU -> IC IALLUIS upgrade via ALTERNATIVE in
    assembler.h, per Mark Rutland review noting that only EL0 traps
    were handled in v2.
  - Added cpucap_is_possible() entry for compile-time elimination when
    CONFIG_NXP_IMX8QM_ERRATUM_ERR050104 is not set.
  - Dropped SMMU BTM changes since iMX8QM does not support broadcast TLB.

[1] https://lore.kernel.org/all/20230420112952.28340-1-iivanov@suse.de/
[2] https://www.nxp.com/docs/en/errata/IMX8_1N94W.pdf
---
 Documentation/arch/arm64/silicon-errata.rst |  2 +
 arch/arm64/Kconfig                          | 16 ++++++++
 arch/arm64/include/asm/assembler.h          |  5 +++
 arch/arm64/include/asm/cpucaps.h            |  2 +
 arch/arm64/include/asm/tlbflush.h           | 61 +++++++++++++++++------------
 arch/arm64/kernel/cpu_errata.c              | 20 ++++++++++
 arch/arm64/kernel/traps.c                   |  6 +++
 arch/arm64/kvm/arm.c                        |  5 +++
 arch/arm64/tools/cpucaps                    |  1 +
 9 files changed, 94 insertions(+), 24 deletions(-)

diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 868bd9eed9a6..a90fd2ec532b 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -321,6 +321,8 @@ stable kernels.
 +----------------+-----------------+-----------------+-----------------------------+
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
 +----------------+-----------------+-----------------+-----------------------------+
+| Freescale/NXP  | i.MX 8QuadMax   | ERR050104       | NXP_IMX8QM_ERRATUM_ERR050104|
++----------------+-----------------+-----------------+-----------------------------+
 +----------------+-----------------+-----------------+-----------------------------+
 | Hisilicon      | Hip0{5,6,7}     | #161010101      | HISILICON_ERRATUM_161010101 |
 +----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index faccdf847a67..eea6774baf0d 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1454,6 +1454,22 @@ config ROCKCHIP_ERRATUM_3588001
 
 	  If unsure, say Y.
 
+config NXP_IMX8QM_ERRATUM_ERR050104
+	bool "NXP iMX8QM ERR050104: broken cache/TLB invalidation broadcast"
+	default y
+	help
+	  On iMX8QM, address bits above bit 35 in the A53 subsystem ARADDR and
+	  ACADDR buses are incorrectly connected. This corrupts targeted TLBI
+	  and IC broadcasts exchanged between the A53 and A72 core clusters.
+
+	  Work around this by redirecting targeted TLBI operations to
+	  broadcast-all variants (VMALLE1IS) in the high-level TLB flush
+	  functions, upgrading IC IVAU to IC IALLUIS for both kernel and
+	  user-space, and disabling KVM since correct TLB maintenance
+	  cannot be guaranteed for guests.
+
+	  If unsure, say Y.
+
 config SOCIONEXT_SYNQUACER_PREITS
 	bool "Socionext Synquacer: Workaround for GICv3 pre-ITS"
 	default y
diff --git a/arch/arm64/include/asm/assembler.h b/arch/arm64/include/asm/assembler.h
index effae53e9739..b35c9308e32b 100644
--- a/arch/arm64/include/asm/assembler.h
+++ b/arch/arm64/include/asm/assembler.h
@@ -455,6 +455,10 @@ alternative_else_nop_endif
  * 	Corrupts:	tmp1, tmp2
  */
 	.macro invalidate_icache_by_line start, end, tmp1, tmp2, fixup
+alternative_if ARM64_WORKAROUND_NXP_ERR050104
+	ic	ialluis
+	b	.Licache_done\@
+alternative_else_nop_endif
 	icache_line_size \tmp1, \tmp2
 	sub	\tmp2, \tmp1, #1
 	bic	\tmp2, \start, \tmp2
@@ -463,6 +467,7 @@ alternative_else_nop_endif
 	add	\tmp2, \tmp2, \tmp1
 	cmp	\tmp2, \end
 	b.lo	.Licache_op\@
+.Licache_done\@:
 	dsb	ish
 	isb
 
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 76350b38f0d7..0c3bfbe99aad 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -66,6 +66,8 @@ cpucap_is_possible(const unsigned int cap)
 		return IS_ENABLED(CONFIG_ARM64_ERRATUM_3194386);
 	case ARM64_WORKAROUND_4193714:
 		return IS_ENABLED(CONFIG_ARM64_ERRATUM_4193714);
+	case ARM64_WORKAROUND_NXP_ERR050104:
+		return IS_ENABLED(CONFIG_NXP_IMX8QM_ERRATUM_ERR050104);
 	case ARM64_MPAM:
 		/*
 		 * KVM MPAM support doesn't rely on the host kernel supporting MPAM.
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 14a78ac0f800..87843e602127 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -378,9 +378,13 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
 	unsigned long asid;
 
 	dsb(ishst);
-	asid = __TLBI_VADDR(0, ASID(mm));
-	__tlbi(aside1is, asid);
-	__tlbi_user(aside1is, asid);
+	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
+		__tlbi(vmalle1is);
+	} else {
+		asid = __TLBI_VADDR(0, ASID(mm));
+		__tlbi(aside1is, asid);
+		__tlbi_user(aside1is, asid);
+	}
 	__tlbi_sync_s1ish(mm);
 	mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
 }
@@ -580,23 +584,27 @@ static __always_inline void __do_flush_tlb_range(struct vm_area_struct *vma,
 
 	asid = ASID(mm);
 
-	switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
-	case TLBF_NONE:
-		__flush_s1_tlb_range_op(vae1is, start, pages, stride,
-					asid, tlb_level);
-		break;
-	case TLBF_NOWALKCACHE:
-		__flush_s1_tlb_range_op(vale1is, start, pages, stride,
-					asid, tlb_level);
-		break;
-	case TLBF_NOBROADCAST:
-		/* Combination unused */
-		BUG();
-		break;
-	case TLBF_NOWALKCACHE | TLBF_NOBROADCAST:
-		__flush_s1_tlb_range_op(vale1, start, pages, stride,
-					asid, tlb_level);
-		break;
+	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
+		__tlbi(vmalle1is);
+	} else {
+		switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
+		case TLBF_NONE:
+			__flush_s1_tlb_range_op(vae1is, start, pages, stride,
+						asid, tlb_level);
+			break;
+		case TLBF_NOWALKCACHE:
+			__flush_s1_tlb_range_op(vale1is, start, pages, stride,
+						asid, tlb_level);
+			break;
+		case TLBF_NOBROADCAST:
+			/* Combination unused */
+			BUG();
+			break;
+		case TLBF_NOWALKCACHE | TLBF_NOBROADCAST:
+			__flush_s1_tlb_range_op(vale1, start, pages, stride,
+						asid, tlb_level);
+			break;
+		}
 	}
 
 	if (!(flags & TLBF_NONOTIFY))
@@ -657,7 +665,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
 	end = round_up(end, stride);
 	pages = (end - start) >> PAGE_SHIFT;
 
-	if (__flush_tlb_range_limit_excess(pages, stride)) {
+	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104) ||
+	    __flush_tlb_range_limit_excess(pages, stride)) {
 		flush_tlb_all();
 		return;
 	}
@@ -675,10 +684,14 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
  */
 static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
 {
-	unsigned long addr = __TLBI_VADDR(kaddr, 0);
-
 	dsb(ishst);
-	__tlbi(vaae1is, addr);
+	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
+		__tlbi(vmalle1is);
+	} else {
+		unsigned long addr = __TLBI_VADDR(kaddr, 0);
+
+		__tlbi(vaae1is, addr);
+	}
 	__tlbi_sync_s1ish_kernel();
 	isb();
 }
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 5db8f0619e4b..1866eeec27ca 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -6,6 +6,7 @@
  */
 
 #include <linux/arm-smccc.h>
+#include <linux/of.h>
 #include <linux/types.h>
 #include <linux/cpu.h>
 #include <asm/cpu.h>
@@ -200,6 +201,16 @@ cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused)
 	sysreg_clear_set(sctlr_el1, SCTLR_EL1_UCI, 0);
 }
 
+#ifdef CONFIG_NXP_IMX8QM_ERRATUM_ERR050104
+static bool
+is_imx8qm_soc(const struct arm64_cpu_capabilities *entry, int scope)
+{
+	WARN_ON(preemptible());
+
+	return of_machine_is_compatible("fsl,imx8qm");
+}
+#endif
+
 #define CAP_MIDR_RANGE(model, v_min, r_min, v_max, r_max)	\
 	.matches = is_affected_midr_range,			\
 	.midr_range = MIDR_RANGE(model, v_min, r_min, v_max, r_max)
@@ -1030,6 +1041,15 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		.type = ARM64_CPUCAP_SYSTEM_FEATURE,
 		.matches = has_broken_gic_v3_seis,
 	},
+#ifdef CONFIG_NXP_IMX8QM_ERRATUM_ERR050104
+	{
+		.desc = "NXP erratum ERR050104",
+		.capability = ARM64_WORKAROUND_NXP_ERR050104,
+		.type = ARM64_CPUCAP_STRICT_BOOT_CPU_FEATURE,
+		.matches = is_imx8qm_soc,
+		.cpu_enable = cpu_enable_cache_maint_trap,
+	},
+#endif
 	{
 	}
 };
diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
index 914282016069..beb658a007d5 100644
--- a/arch/arm64/kernel/traps.c
+++ b/arch/arm64/kernel/traps.c
@@ -585,6 +585,12 @@ static void user_cache_maint_handler(unsigned long esr, struct pt_regs *regs)
 		__user_cache_maint("dc civac", address, ret);
 		break;
 	case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:	/* IC IVAU */
+		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104)) {
+			/* ERR050104: upgrade IC IVAU to IC IALLUIS */
+			asm volatile("ic ialluis");
+			ret = 0;
+			break;
+		}
 		__user_cache_maint("ic ivau", address, ret);
 		break;
 	default:
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index 9a6c72a18672..734ccd7ec056 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -3032,6 +3032,11 @@ static __init int kvm_arm_init(void)
 
 	in_hyp_mode = is_kernel_in_hyp_mode();
 
+	if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104)) {
+		kvm_info("KVM not supported on NXP iMX8QM (ERR050104)\n");
+		return -ENODEV;
+	}
+
 	if (cpus_have_final_cap(ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE) ||
 	    cpus_have_final_cap(ARM64_WORKAROUND_1508412))
 		kvm_info("Guests without required CPU erratum workarounds can deadlock system!\n" \
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index fbf27e887e71..fb3fe9736cc6 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -123,6 +123,7 @@ WORKAROUND_DEVICE_LOAD_ACQUIRE
 WORKAROUND_DISABLE_CNP
 WORKAROUND_GICv3_BROKEN_SEIS
 WORKAROUND_NVIDIA_OLYMPUS_1027
+WORKAROUND_NXP_ERR050104
 WORKAROUND_PMUV3_IMPDEF_TRAPS
 WORKAROUND_QCOM_FALKOR_E1003
 WORKAROUND_QCOM_ORYON_CNTVOFF

---
base-commit: 9eebf259d5352b87080d67758f483583d9e763d7
change-id: 20260729-imx8qm-cache-coherency-3129d5da3de1

Best regards,
--  
Peng Fan <peng.fan@nxp.com>


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue
  2026-07-29  3:28 [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue Peng Fan (OSS)
@ 2026-07-29  3:42 ` sashiko-bot
  2026-07-29  9:50 ` Mark Rutland
  2026-07-29 17:09 ` Frank Li
  2 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-07-29  3:42 UTC (permalink / raw)
  To: Peng Fan (OSS); +Cc: Frank.Li, Oliver Upton, Marc Zyngier, imx, kvmarm

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] Unconditional upgrade of local TLB flushes to global broadcast (`vmalle1is`), resulting in unsynchronized broadcast DVM messages.
- [High] The workaround for user-space IC IVAU silently swallows faults for invalid or kernel addresses.
--

--- Patch [1]: [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue ---
commit 2862fd74023d9e9e12c6a2745e844dc84b6cf1f7
Author: Peng Fan <peng.fan@nxp.com>

arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue

According to NXP errata document IMX8_1N94W, the i.MX8QuadMax SoC suffers
from a cache coherency issue (ERR050104). The workaround includes downgrading
targeted TLBI operations to broadcast-all variants, upgrading IC IVAU to
IC IALLUIS, and disabling KVM.

Link: https://lore.kernel.org/all/20230420112952.28340-1-iivanov@suse.de/

> diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
> index 14a78ac0f8009..87843e602127e 100644
> --- a/arch/arm64/include/asm/tlbflush.h
> +++ b/arch/arm64/include/asm/tlbflush.h
[ ... ]
> @@ -580,23 +584,27 @@ static __always_inline void __do_flush_tlb_range(struct vm_area_struct *vma,
>  
>  	asid = ASID(mm);
>  
> -	switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
> -	case TLBF_NONE:
> -		__flush_s1_tlb_range_op(vae1is, start, pages, stride,
> -					asid, tlb_level);
> -		break;
[ ... ]
> +	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
> +		__tlbi(vmalle1is);

[Severity: High]
Does this code inadvertently break the synchronization for local TLB flushes?
When __do_flush_tlb_range() is called with the TLBF_NOBROADCAST flag (such
as from flush_tlb_fix_spurious_fault()), this block unconditionally upgrades
the local flush to a global broadcast (__tlbi(vmalle1is)).

However, later in the same function, if TLBF_NOBROADCAST is set, the code
synchronizes the operation using dsb(nsh) instead of dsb(ish). Emitting an
inner-shareable broadcast TLB instruction but only waiting for local
completion violates the hardware contract and can overwhelm the system
interconnect with DVM messages that are never waited for.

Should local flushes be upgraded to the local vmalle1 instead, or should
the synchronization be upgraded to dsb(ish)?

> +	} else {
> +		switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
> +		case TLBF_NONE:
[ ... ]
> diff --git a/arch/arm64/kernel/traps.c b/arch/arm64/kernel/traps.c
> index 9142820160698..beb658a007d59 100644
> --- a/arch/arm64/kernel/traps.c
> +++ b/arch/arm64/kernel/traps.c
> @@ -585,6 +585,12 @@ static void user_cache_maint_handler(unsigned long esr, struct pt_regs *regs)
>  		__user_cache_maint("dc civac", address, ret);
>  		break;
>  	case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:	/* IC IVAU */
> +		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104)) {
> +			/* ERR050104: upgrade IC IVAU to IC IALLUIS */
> +			asm volatile("ic ialluis");
> +			ret = 0;
> +			break;
> +		}

[Severity: High]
Will this silently swallow faults if user space passes an invalid or kernel
pointer?

Normally, __user_cache_maint() checks if the address is >= TASK_SIZE_MAX and
sets -EFAULT, which correctly triggers a SIGSEGV for the offending user-space
application. 

Because this workaround executes the ic ialluis instruction and returns success
(ret = 0) unconditionally, it bypasses the address validation entirely. Can we
preserve the TASK_SIZE_MAX check so that buggy or malicious programs aren't
silently ignored?

>  		__user_cache_maint("ic ivau", address, ret);
>  		break;

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260729-imx8qm-cache-coherency-v1-1-c9864e280437@nxp.com?part=1

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue
  2026-07-29  3:28 [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue Peng Fan (OSS)
  2026-07-29  3:42 ` sashiko-bot
@ 2026-07-29  9:50 ` Mark Rutland
  2026-07-29 12:52   ` Peng Fan
  2026-07-29 17:09 ` Frank Li
  2 siblings, 1 reply; 5+ messages in thread
From: Mark Rutland @ 2026-07-29  9:50 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: Catalin Marinas, Will Deacon, Jonathan Corbet, Marc Zyngier,
	Oliver Upton, Fuad Tabba, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Ivan T. Ivanov, Francesco Dolcini, Frank Li,
	linux-arm-kernel, linux-doc, linux-kernel, kvmarm, imx, Peng Fan

On Wed, Jul 29, 2026 at 11:28:52AM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
> 
> According to NXP errata document IMX8_1N94W[1], the i.MX8QuadMax SoC
> suffers from a serious cache coherency issue (ERR050104). The upper
> bits, above bit 35, of the ARADDR and ACADDR buses within the Arm A53
> subsystem have been incorrectly connected. This causes some TLBI and IC
> maintenance operations exchanged between the A53 and A72 core clusters
> to be corrupted.
> 
> The workaround requires:
> 
>   - Downgrading targeted TLBI operations to broadcast-all variants.
>     Instead of patching the low-level __TLBI_1 macro (which interferes
>     with the REPEAT_TLBI workaround and causes excessive over-
>     invalidation), redirect high-level TLB flush functions
>     (flush_tlb_mm, __do_flush_tlb_range, flush_tlb_kernel_range,
>     __flush_tlb_kernel_pgtable) to use VMALLE1IS via static key checks.
> 
>   - Upgrading IC IVAU to IC IALLUIS for both kernel (via ALTERNATIVE in
>     invalidate_icache_by_line) and EL0 userspace (via trap-and-upgrade
>     in user_cache_maint_handler with SCTLR_EL1.UCI=0).
> 
>   - Disabling KVM since correct TLB maintenance cannot be guaranteed
>     for guests without the proper devicetree.
> 
>   - No need to touch SMMU Broadcast TLB Maintenance (BTM) since i.MX8QM
>     does not support broadcast TLB.
> 
> SoC detection uses devicetree compatible string "fsl,imx8qm" since the
> boot CPU MIDR_EL1 (0x410fd034) and AIDR_EL1 (0) are not unique to this
> SoC.
> 
> [1] https://www.nxp.com/docs/en/errata/IMX8_1N94W.pdf

[...]

> +	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
> +		__tlbi(vmalle1is);
> +	} else {
> +		switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
> +		case TLBF_NONE:
> +			__flush_s1_tlb_range_op(vae1is, start, pages, stride,
> +						asid, tlb_level);
> +			break;
> +		case TLBF_NOWALKCACHE:
> +			__flush_s1_tlb_range_op(vale1is, start, pages, stride,
> +						asid, tlb_level);
> +			break;
> +		case TLBF_NOBROADCAST:
> +			/* Combination unused */
> +			BUG();
> +			break;
> +		case TLBF_NOWALKCACHE | TLBF_NOBROADCAST:
> +			__flush_s1_tlb_range_op(vale1, start, pages, stride,
> +						asid, tlb_level);
> +			break;
> +		}
>  	}

Are you sure the workaround needs to be applied for the TLBF_NOBROADCAST
cases? The NXP document lists non-broadcast TLBI instructions, but I
strongly suspect that's in error, as those shouldn't result in
transactions over the core's external interfaces.

[...]

> @@ -585,6 +585,12 @@ static void user_cache_maint_handler(unsigned long esr, struct pt_regs *regs)
>  		__user_cache_maint("dc civac", address, ret);
>  		break;
>  	case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:	/* IC IVAU */
> +		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104)) {
> +			/* ERR050104: upgrade IC IVAU to IC IALLUIS */
> +			asm volatile("ic ialluis");
> +			ret = 0;
> +			break;
> +		}
>  		__user_cache_maint("ic ivau", address, ret);
>  		break;

This doesn't address my feedback on v1:

  https://lore.kernel.org/all/ZIHisLL9FXlbuMLJ@FVFF77S0Q05N/

... which I see Sashiko has also spotted.

Please make this:

	 case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:     /* IC IVAU */
	 	__user_cache_maint("ic ivau", address, ret)
		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104) && !ret)
			asm volatile("ic ialluis");
		break;

If there's a reason that doesn't work, please explain that reason.

Mark.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue
  2026-07-29  9:50 ` Mark Rutland
@ 2026-07-29 12:52   ` Peng Fan
  0 siblings, 0 replies; 5+ messages in thread
From: Peng Fan @ 2026-07-29 12:52 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Catalin Marinas, Will Deacon, Jonathan Corbet, Marc Zyngier,
	Oliver Upton, Fuad Tabba, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Ivan T. Ivanov, Francesco Dolcini, Frank Li,
	linux-arm-kernel, linux-doc, linux-kernel, kvmarm, imx, Peng Fan

Hi Mark,

Thanks for your reviewing.

On Wed, Jul 29, 2026 at 10:50:56AM +0100, Mark Rutland wrote:
>On Wed, Jul 29, 2026 at 11:28:52AM +0800, Peng Fan (OSS) wrote:
>> From: Peng Fan <peng.fan@nxp.com>
>> 
>> According to NXP errata document IMX8_1N94W[1], the i.MX8QuadMax SoC
>> suffers from a serious cache coherency issue (ERR050104). The upper
>> bits, above bit 35, of the ARADDR and ACADDR buses within the Arm A53
>> subsystem have been incorrectly connected. This causes some TLBI and IC
>> maintenance operations exchanged between the A53 and A72 core clusters
>> to be corrupted.
>> 
>> The workaround requires:
>> 
>>   - Downgrading targeted TLBI operations to broadcast-all variants.
>>     Instead of patching the low-level __TLBI_1 macro (which interferes
>>     with the REPEAT_TLBI workaround and causes excessive over-
>>     invalidation), redirect high-level TLB flush functions
>>     (flush_tlb_mm, __do_flush_tlb_range, flush_tlb_kernel_range,
>>     __flush_tlb_kernel_pgtable) to use VMALLE1IS via static key checks.
>> 
>>   - Upgrading IC IVAU to IC IALLUIS for both kernel (via ALTERNATIVE in
>>     invalidate_icache_by_line) and EL0 userspace (via trap-and-upgrade
>>     in user_cache_maint_handler with SCTLR_EL1.UCI=0).
>> 
>>   - Disabling KVM since correct TLB maintenance cannot be guaranteed
>>     for guests without the proper devicetree.
>> 
>>   - No need to touch SMMU Broadcast TLB Maintenance (BTM) since i.MX8QM
>>     does not support broadcast TLB.
>> 
>> SoC detection uses devicetree compatible string "fsl,imx8qm" since the
>> boot CPU MIDR_EL1 (0x410fd034) and AIDR_EL1 (0) are not unique to this
>> SoC.
>> 
>> [1] https://www.nxp.com/docs/en/errata/IMX8_1N94W.pdf
>
>[...]
>
>> +	if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104)) {
>> +		__tlbi(vmalle1is);
>> +	} else {
>> +		switch (flags & (TLBF_NOWALKCACHE | TLBF_NOBROADCAST)) {
>> +		case TLBF_NONE:
>> +			__flush_s1_tlb_range_op(vae1is, start, pages, stride,
>> +						asid, tlb_level);
>> +			break;
>> +		case TLBF_NOWALKCACHE:
>> +			__flush_s1_tlb_range_op(vale1is, start, pages, stride,
>> +						asid, tlb_level);
>> +			break;
>> +		case TLBF_NOBROADCAST:
>> +			/* Combination unused */
>> +			BUG();
>> +			break;
>> +		case TLBF_NOWALKCACHE | TLBF_NOBROADCAST:
>> +			__flush_s1_tlb_range_op(vale1, start, pages, stride,
>> +						asid, tlb_level);
>> +			break;
>> +		}
>>  	}
>
>Are you sure the workaround needs to be applied for the TLBF_NOBROADCAST
>cases? The NXP document lists non-broadcast TLBI instructions, but I
>strongly suspect that's in error, as those shouldn't result in
>transactions over the core's external interfaces.

I think you are right, TLBF_NOBROADCAST should not be applied with the
workaround.

I will use below if this looks good to you.

 if (alternative_has_cap_unlikely(ARM64_WORKAROUND_NXP_ERR050104) &&
     !(flags & TLBF_NOBROADCAST)) {
         __tlbi(vmalle1is);
 } else {
 ...
 }

>
>[...]
>
>> @@ -585,6 +585,12 @@ static void user_cache_maint_handler(unsigned long esr, struct pt_regs *regs)
>>  		__user_cache_maint("dc civac", address, ret);
>>  		break;
>>  	case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:	/* IC IVAU */
>> +		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104)) {
>> +			/* ERR050104: upgrade IC IVAU to IC IALLUIS */
>> +			asm volatile("ic ialluis");
>> +			ret = 0;
>> +			break;
>> +		}
>>  		__user_cache_maint("ic ivau", address, ret);
>>  		break;
>
>This doesn't address my feedback on v1:
>
>  https://lore.kernel.org/all/ZIHisLL9FXlbuMLJ@FVFF77S0Q05N/

Sorry for missing this one.

>
>... which I see Sashiko has also spotted.
>
>Please make this:
>
>	 case ESR_ELx_SYS64_ISS_CRM_IC_IVAU:     /* IC IVAU */
>	 	__user_cache_maint("ic ivau", address, ret)
>		if (cpus_have_final_cap(ARM64_WORKAROUND_NXP_ERR050104) && !ret)
>			asm volatile("ic ialluis");
>		break;
>
>If there's a reason that doesn't work, please explain that reason.

It should be ok.  I will take your suggestion in next version.

Thanks,
Peng

>
>Mark.
>
>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue
  2026-07-29  3:28 [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue Peng Fan (OSS)
  2026-07-29  3:42 ` sashiko-bot
  2026-07-29  9:50 ` Mark Rutland
@ 2026-07-29 17:09 ` Frank Li
  2 siblings, 0 replies; 5+ messages in thread
From: Frank Li @ 2026-07-29 17:09 UTC (permalink / raw)
  To: Peng Fan (OSS)
  Cc: Catalin Marinas, Will Deacon, Jonathan Corbet, Marc Zyngier,
	Oliver Upton, Fuad Tabba, Joey Gouly, Suzuki K Poulose,
	Zenghui Yu, Mark Rutland, Ivan T. Ivanov, Francesco Dolcini,
	Frank Li, linux-arm-kernel, linux-doc, linux-kernel, kvmarm, imx,
	Peng Fan

On Wed, Jul 29, 2026 at 11:28:52AM +0800, Peng Fan (OSS) wrote:
> From: Peng Fan <peng.fan@nxp.com>
>

Thank you for you take over this thread.

Frank

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-07-29 17:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-29  3:28 [PATCH] arm64: errata: Add NXP iMX8QM workaround for A53 cache coherency issue Peng Fan (OSS)
2026-07-29  3:42 ` sashiko-bot
2026-07-29  9:50 ` Mark Rutland
2026-07-29 12:52   ` Peng Fan
2026-07-29 17:09 ` Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox