* [PATCH 6.18.y 2/6] arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
From: Mark Rutland <mark.rutland@arm.com>
commit a8f78680ee6bf795086384e8aea159a52814f827 upstream.
The ARM64_WORKAROUND_REPEAT_TLBI workaround is used to mitigate several
errata where broadcast TLBI;DSB sequences don't provide all the
architecturally required synchronization. The workaround performs more
work than necessary, and can have significant overhead. This patch
optimizes the workaround, as explained below.
The workaround was originally added for Qualcomm Falkor erratum 1009 in
commit:
d9ff80f83ecb ("arm64: Work around Falkor erratum 1009")
As noted in the message for that commit, the workaround is applied even
in cases where it is not strictly necessary.
The workaround was later reused without changes for:
* Arm Cortex-A76 erratum #1286807
SDEN v33: https://developer.arm.com/documentation/SDEN-885749/33-0/
* Arm Cortex-A55 erratum #2441007
SDEN v16: https://developer.arm.com/documentation/SDEN-859338/1600/
* Arm Cortex-A510 erratum #2441009
SDEN v19: https://developer.arm.com/documentation/SDEN-1873351/1900/
The important details to note are as follows:
1. All relevant errata only affect the ordering and/or completion of
memory accesses which have been translated by an invalidated TLB
entry. The actual invalidation of TLB entries is unaffected.
2. The existing workaround is applied to both broadcast and local TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for broadcast invalidation.
3. The existing workaround replaces every TLBI with a TLBI;DSB;TLBI
sequence, whereas for all relevant errata it is only necessary to
execute a single additional TLBI;DSB sequence after any number of
TLBIs are completed by a DSB.
For example, for a sequence of batched TLBIs:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
... the existing workaround will expand this to:
TLBI <op1>[, <arg1>]
DSB ISH // additional
TLBI <op1>[, <arg1>] // additional
TLBI <op2>[, <arg2>]
DSB ISH // additional
TLBI <op2>[, <arg2>] // additional
TLBI <op3>[, <arg3>]
DSB ISH // additional
TLBI <op3>[, <arg3>] // additional
DSB ISH
... whereas it is sufficient to have:
TLBI <op1>[, <arg1>]
TLBI <op2>[, <arg2>]
TLBI <op3>[, <arg3>]
DSB ISH
TLBI <opX>[, <argX>] // additional
DSB ISH // additional
Using a single additional TBLI and DSB at the end of the sequence can
have significantly lower overhead as each DSB which completes a TLBI
must synchronize with other PEs in the system, with potential
performance effects both locally and system-wide.
4. The existing workaround repeats each specific TLBI operation, whereas
for all relevant errata it is sufficient for the additional TLBI to
use *any* operation which will be broadcast, regardless of which
translation regime or stage of translation the operation applies to.
For example, for a single TLBI:
TLBI ALLE2IS
DSB ISH
... the existing workaround will expand this to:
TLBI ALLE2IS
DSB ISH
TLBI ALLE2IS // additional
DSB ISH // additional
... whereas it is sufficient to have:
TLBI ALLE2IS
DSB ISH
TLBI VALE1IS, XZR // additional
DSB ISH // additional
As the additional TLBI doesn't have to match a specific earlier TLBI,
the additional TLBI can be implemented in separate code, with no
memory of the earlier TLBIs. The additional TLBI can also use a
cheaper TLBI operation.
5. The existing workaround is applied to both Stage-1 and Stage-2 TLB
invalidation, whereas for all relevant errata it is only necessary to
apply a workaround for Stage-1 invalidation.
Architecturally, TLBI operations which invalidate only Stage-2
information (e.g. IPAS2E1IS) are not required to invalidate TLB
entries which combine information from Stage-1 and Stage-2
translation table entries, and consequently may not complete memory
accesses translated by those combined entries. In these cases,
completion of memory accesses is only guaranteed after subsequent
invalidation of Stage-1 information (e.g. VMALLE1IS).
Taking the above points into account, this patch reworks the workaround
logic to reduce overhead:
* New __tlbi_sync_s1ish() and __tlbi_sync_s1ish_hyp() functions are
added and used in place of any dsb(ish) which is used to complete
broadcast Stage-1 TLB maintenance. When the
ARM64_WORKAROUND_REPEAT_TLBI workaround is enabled, these helpers will
execute an additional TLBI;DSB sequence.
For consistency, it might make sense to add __tlbi_sync_*() helpers
for local and stage 2 maintenance. For now I've left those with
open-coded dsb() to keep the diff small.
* The duplication of TLBIs in __TLBI_0() and __TLBI_1() is removed. This
is no longer needed as the necessary synchronization will happen in
__tlbi_sync_s1ish() or __tlbi_sync_s1ish_hyp().
* The additional TLBI operation is chosen to have minimal impact:
- __tlbi_sync_s1ish() uses "TLBI VALE1IS, XZR". This is only used at
EL1 or at EL2 with {E2H,TGE}=={1,1}, where it will target an unused
entry for the reserved ASID in the kernel's own translation regime,
and have no adverse affect.
- __tlbi_sync_s1ish_hyp() uses "TLBI VALE2IS, XZR". This is only used
in hyp code, where it will target an unused entry in the hyp code's
TTBR0 mapping, and should have no adverse effect.
* As __TLBI_0() and __TLBI_1() no longer replace each TLBI with a
TLBI;DSB;TLBI sequence, batching TLBIs is worthwhile, and there's no
need for arch_tlbbatch_should_defer() to consider
ARM64_WORKAROUND_REPEAT_TLBI.
When building defconfig with GCC 15.1.0, compared to v6.19-rc1, this
patch saves ~1KiB of text, makes the vmlinux ~42KiB smaller, and makes
the resulting Image 64KiB smaller:
| [mark@lakrids:~/src/linux]% size vmlinux-*
| text data bss dec hex filename
| 21179831 19660919 708216 41548966 279fca6 vmlinux-after
| 21181075 19660903 708216 41550194 27a0172 vmlinux-before
| [mark@lakrids:~/src/linux]% ls -l vmlinux-*
| -rwxr-xr-x 1 mark mark 157771472 Feb 4 12:05 vmlinux-after
| -rwxr-xr-x 1 mark mark 157815432 Feb 4 12:05 vmlinux-before
| [mark@lakrids:~/src/linux]% ls -l Image-*
| -rw-r--r-- 1 mark mark 41007616 Feb 4 12:05 Image-after
| -rw-r--r-- 1 mark mark 41073152 Feb 4 12:05 Image-before
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 59 ++++++++++++++++++-------------
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/kvm/hyp/nvhe/mm.c | 2 +-
arch/arm64/kvm/hyp/nvhe/tlb.c | 8 ++---
arch/arm64/kvm/hyp/pgtable.c | 2 +-
arch/arm64/kvm/hyp/vhe/tlb.c | 10 +++---
6 files changed, 47 insertions(+), 36 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 0ddb344f83b4..c87d13bee37d 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -31,18 +31,10 @@
*/
#define __TLBI_0(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op "\n" \
- ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op, \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : )
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
"tlbi " #op ", %x0\n" \
- ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op ", %x0", \
- ARM64_WORKAROUND_REPEAT_TLBI, \
- CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
: : "rZ" (arg))
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
@@ -181,6 +173,34 @@ static inline unsigned long get_trans_granule(void)
(__pages >> (5 * (scale) + 1)) - 1; \
})
+#define __repeat_tlbi_sync(op, arg...) \
+do { \
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI)) \
+ break; \
+ __tlbi(op, ##arg); \
+ dsb(ish); \
+} while (0)
+
+/*
+ * Complete broadcast TLB maintenance issued by the host which invalidates
+ * stage 1 information in the host's own translation regime.
+ */
+static inline void __tlbi_sync_s1ish(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
+/*
+ * Complete broadcast TLB maintenance issued by hyp code which invalidates
+ * stage 1 translation information in any translation regime.
+ */
+static inline void __tlbi_sync_s1ish_hyp(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale2is, 0);
+}
+
/*
* TLB Invalidation
* ================
@@ -266,7 +286,7 @@ static inline void flush_tlb_all(void)
{
dsb(ishst);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
@@ -278,7 +298,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
- dsb(ish);
+ __tlbi_sync_s1ish();
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
}
@@ -305,20 +325,11 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long uaddr)
{
flush_tlb_page_nosync(vma, uaddr);
- dsb(ish);
+ __tlbi_sync_s1ish();
}
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
{
- /*
- * TLB flush deferral is not required on systems which are affected by
- * ARM64_WORKAROUND_REPEAT_TLBI, as __tlbi()/__tlbi_user() implementation
- * will have two consecutive TLBI instructions with a dsb(ish) in between
- * defeating the purpose (i.e save overall 'dsb ish' cost).
- */
- if (alternative_has_cap_unlikely(ARM64_WORKAROUND_REPEAT_TLBI))
- return false;
-
return true;
}
@@ -334,7 +345,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- dsb(ish);
+ __tlbi_sync_s1ish();
}
/*
@@ -469,7 +480,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
last_level, tlb_level);
- dsb(ish);
+ __tlbi_sync_s1ish();
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
@@ -501,7 +512,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
dsb(ishst);
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
@@ -515,7 +526,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
- dsb(ish);
+ __tlbi_sync_s1ish();
isb();
}
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index 4a609e9b65de..b9d4998c97ef 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
* We pick the reserved-ASID to minimise the impact.
*/
__tlbi(aside1is, __TLBI_VADDR(0, 0));
- dsb(ish);
+ __tlbi_sync_s1ish();
}
ret = caches_clean_inval_user_pou(start, start + chunk);
diff --git a/arch/arm64/kvm/hyp/nvhe/mm.c b/arch/arm64/kvm/hyp/nvhe/mm.c
index ae8391baebc3..218976287d3f 100644
--- a/arch/arm64/kvm/hyp/nvhe/mm.c
+++ b/arch/arm64/kvm/hyp/nvhe/mm.c
@@ -271,7 +271,7 @@ static void fixmap_clear_slot(struct hyp_fixmap_slot *slot)
*/
dsb(ishst);
__tlbi_level(vale2is, __TLBI_VADDR(addr, 0), level);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
}
diff --git a/arch/arm64/kvm/hyp/nvhe/tlb.c b/arch/arm64/kvm/hyp/nvhe/tlb.c
index 48da9ca9763f..3dc1ce0d27fe 100644
--- a/arch/arm64/kvm/hyp/nvhe/tlb.c
+++ b/arch/arm64/kvm/hyp/nvhe/tlb.c
@@ -169,7 +169,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -226,7 +226,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -240,7 +240,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt, false);
__tlbi(vmalls12e1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -266,5 +266,5 @@ void __kvm_flush_vm_context(void)
/* Same remark as in enter_vmid_context() */
dsb(ish);
__tlbi(alle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
}
diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c
index c351b4abd5db..cbf8cd2e1673 100644
--- a/arch/arm64/kvm/hyp/pgtable.c
+++ b/arch/arm64/kvm/hyp/pgtable.c
@@ -483,7 +483,7 @@ static int hyp_unmap_walker(const struct kvm_pgtable_visit_ctx *ctx,
*unmapped += granule;
}
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
mm_ops->put_page(ctx->ptep);
diff --git a/arch/arm64/kvm/hyp/vhe/tlb.c b/arch/arm64/kvm/hyp/vhe/tlb.c
index ec2569818629..35855dadfb1b 100644
--- a/arch/arm64/kvm/hyp/vhe/tlb.c
+++ b/arch/arm64/kvm/hyp/vhe/tlb.c
@@ -115,7 +115,7 @@ void __kvm_tlb_flush_vmid_ipa(struct kvm_s2_mmu *mmu,
*/
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -176,7 +176,7 @@ void __kvm_tlb_flush_vmid_range(struct kvm_s2_mmu *mmu,
dsb(ish);
__tlbi(vmalle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -192,7 +192,7 @@ void __kvm_tlb_flush_vmid(struct kvm_s2_mmu *mmu)
enter_vmid_context(mmu, &cxt);
__tlbi(vmalls12e1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
exit_vmid_context(&cxt);
@@ -217,7 +217,7 @@ void __kvm_flush_vm_context(void)
{
dsb(ishst);
__tlbi(alle1is);
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
}
/*
@@ -358,7 +358,7 @@ int __kvm_tlbi_s1e2(struct kvm_s2_mmu *mmu, u64 va, u64 sys_encoding)
default:
ret = -EINVAL;
}
- dsb(ish);
+ __tlbi_sync_s1ish_hyp();
isb();
if (mmu)
^ permalink raw reply related
* [PATCH 6.18.y 3/6] arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB maintenance
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 6bfbf574a39139da11af9fdf6e8d56fe1989cd3e upstream.
Add __tlbi_sync_s1ish_kernel() similar to __tlbi_sync_s1ish() and use it
for kernel TLB maintenance. Also use this function in flush_tlb_all()
which is only used in relation to kernel mappings. Subsequent patches
can differentiate between workarounds that apply to user only or both
user and kernel.
A subsequent patch will add mm_struct to __tlbi_sync_s1ish(). Since
arch_tlbbatch_flush() is not specific to an mm, add a corresponding
__tlbi_sync_s1ish_batch() helper.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index c87d13bee37d..387bd86af702 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -191,6 +191,18 @@ static inline void __tlbi_sync_s1ish(void)
__repeat_tlbi_sync(vale1is, 0);
}
+static inline void __tlbi_sync_s1ish_batch(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
+static inline void __tlbi_sync_s1ish_kernel(void)
+{
+ dsb(ish);
+ __repeat_tlbi_sync(vale1is, 0);
+}
+
/*
* Complete broadcast TLB maintenance issued by hyp code which invalidates
* stage 1 translation information in any translation regime.
@@ -286,7 +298,7 @@ static inline void flush_tlb_all(void)
{
dsb(ishst);
__tlbi(vmalle1is);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
@@ -345,7 +357,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_batch();
}
/*
@@ -512,7 +524,7 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end
dsb(ishst);
__flush_tlb_range_op(vaale1is, start, pages, stride, 0,
TLBI_TTL_UNKNOWN, false, lpa2_is_enabled());
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
@@ -526,7 +538,7 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
dsb(ishst);
__tlbi(vaae1is, addr);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish_kernel();
isb();
}
^ permalink raw reply related
* [PATCH 6.18.y 4/6] arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit d9fb08ba946a6190c371dcd9f9e465d0d52c5021 upstream.
The mm structure will be used for workarounds that need limiting to
specific tasks.
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 8 ++++----
arch/arm64/kernel/sys_compat.c | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 387bd86af702..ba36e91aefb8 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -185,7 +185,7 @@ do { \
* Complete broadcast TLB maintenance issued by the host which invalidates
* stage 1 information in the host's own translation regime.
*/
-static inline void __tlbi_sync_s1ish(void)
+static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
@@ -310,7 +310,7 @@ static inline void flush_tlb_mm(struct mm_struct *mm)
asid = __TLBI_VADDR(0, ASID(mm));
__tlbi(aside1is, asid);
__tlbi_user(aside1is, asid);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(mm);
mmu_notifier_arch_invalidate_secondary_tlbs(mm, 0, -1UL);
}
@@ -337,7 +337,7 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
unsigned long uaddr)
{
flush_tlb_page_nosync(vma, uaddr);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(vma->vm_mm);
}
static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
@@ -492,7 +492,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
{
__flush_tlb_range_nosync(vma->vm_mm, start, end, stride,
last_level, tlb_level);
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(vma->vm_mm);
}
static inline void flush_tlb_range(struct vm_area_struct *vma,
diff --git a/arch/arm64/kernel/sys_compat.c b/arch/arm64/kernel/sys_compat.c
index b9d4998c97ef..03fde2677d5b 100644
--- a/arch/arm64/kernel/sys_compat.c
+++ b/arch/arm64/kernel/sys_compat.c
@@ -37,7 +37,7 @@ __do_compat_cache_op(unsigned long start, unsigned long end)
* We pick the reserved-ASID to minimise the impact.
*/
__tlbi(aside1is, __TLBI_VADDR(0, 0));
- __tlbi_sync_s1ish();
+ __tlbi_sync_s1ish(current->mm);
}
ret = caches_clean_inval_user_pou(start, start + chunk);
^ permalink raw reply related
* [PATCH 6.18.y 6/6] arm64: errata: Work around early CME DVMSync acknowledgement
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 0baba94a9779c13c857f6efc55807e6a45b1d4e4 upstream.
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: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
Documentation/arch/arm64/silicon-errata.rst | 2 +
arch/arm64/Kconfig | 12 ++++
arch/arm64/include/asm/cpucaps.h | 2 +
arch/arm64/include/asm/fpsimd.h | 21 ++++++
arch/arm64/include/asm/tlbbatch.h | 10 ++-
arch/arm64/include/asm/tlbflush.h | 72 ++++++++++++++++++-
arch/arm64/kernel/cpu_errata.c | 30 ++++++++
arch/arm64/kernel/entry-common.c | 3 +
arch/arm64/kernel/fpsimd.c | 79 +++++++++++++++++++++
arch/arm64/kernel/process.c | 36 ++++++++++
arch/arm64/tools/cpucaps | 1 +
11 files changed, 264 insertions(+), 4 deletions(-)
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index a7ec57060f64..93cdf1693715 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -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 | |
+----------------+-----------------+-----------------+-----------------------------+
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 6663ffd23f25..840a945cb4ac 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1154,6 +1154,18 @@ config ARM64_ERRATUM_3194386
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
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 9d769291a306..121210b7ffd0 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_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.
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index b8cf0ea43cc0..0fa8d1d5722e 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -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 */
diff --git a/arch/arm64/include/asm/tlbbatch.h b/arch/arm64/include/asm/tlbbatch.h
index fedb0b87b8db..6297631532e5 100644
--- a/arch/arm64/include/asm/tlbbatch.h
+++ b/arch/arm64/include/asm/tlbbatch.h
@@ -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 */
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index ba36e91aefb8..f53ab3ba0c48 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -80,6 +80,71 @@ static inline unsigned long get_trans_granule(void)
}
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+void sme_do_dvmsync(const struct cpumask *mask);
+
+static inline void sme_dvmsync(struct mm_struct *mm)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ sme_do_dvmsync(mm_cpumask(mm));
+}
+
+static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
+ struct mm_struct *mm)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ /*
+ * Order the mm_cpumask() read after the hardware DVMSync.
+ */
+ dsb(ish);
+ if (cpumask_empty(mm_cpumask(mm)))
+ return;
+
+ /*
+ * Allocate the batch cpumask on first use. Fall back to an immediate
+ * IPI for this mm in case of failure.
+ */
+ if (!cpumask_available(batch->cpumask) &&
+ !zalloc_cpumask_var(&batch->cpumask, GFP_ATOMIC)) {
+ sme_do_dvmsync(mm_cpumask(mm));
+ return;
+ }
+
+ cpumask_or(batch->cpumask, batch->cpumask, mm_cpumask(mm));
+}
+
+static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
+{
+ if (!alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ return;
+
+ if (!cpumask_available(batch->cpumask))
+ return;
+
+ sme_do_dvmsync(batch->cpumask);
+ cpumask_clear(batch->cpumask);
+}
+
+#else
+
+static inline void sme_dvmsync(struct mm_struct *mm)
+{
+}
+static inline void sme_dvmsync_add_pending(struct arch_tlbflush_unmap_batch *batch,
+ struct mm_struct *mm)
+{
+}
+static inline void sme_dvmsync_batch(struct arch_tlbflush_unmap_batch *batch)
+{
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
/*
* Level-based TLBI operations.
*
@@ -189,12 +254,14 @@ static inline void __tlbi_sync_s1ish(struct mm_struct *mm)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
+ sme_dvmsync(mm);
}
-static inline void __tlbi_sync_s1ish_batch(void)
+static inline void __tlbi_sync_s1ish_batch(struct arch_tlbflush_unmap_batch *batch)
{
dsb(ish);
__repeat_tlbi_sync(vale1is, 0);
+ sme_dvmsync_batch(batch);
}
static inline void __tlbi_sync_s1ish_kernel(void)
@@ -357,7 +424,7 @@ static inline bool arch_tlbbatch_should_defer(struct mm_struct *mm)
*/
static inline void arch_tlbbatch_flush(struct arch_tlbflush_unmap_batch *batch)
{
- __tlbi_sync_s1ish_batch();
+ __tlbi_sync_s1ish_batch(batch);
}
/*
@@ -546,6 +613,7 @@ static inline void arch_tlbbatch_add_pending(struct arch_tlbflush_unmap_batch *b
struct mm_struct *mm, unsigned long start, unsigned long end)
{
__flush_tlb_range_nosync(mm, start, end, PAGE_SIZE, true, 3);
+ sme_dvmsync_add_pending(batch, mm);
}
#endif
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 8cb3b575a031..6c8c4301d9c6 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -11,6 +11,7 @@
#include <asm/cpu.h>
#include <asm/cputype.h>
#include <asm/cpufeature.h>
+#include <asm/fpsimd.h>
#include <asm/kvm_asm.h>
#include <asm/smp_plat.h>
@@ -551,6 +552,23 @@ static const struct midr_range erratum_spec_ssbs_list[] = {
};
#endif
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+static bool has_sme_dvmsync_erratum(const struct arm64_cpu_capabilities *entry,
+ int scope)
+{
+ if (!id_aa64pfr1_sme(read_sanitised_ftr_reg(SYS_ID_AA64PFR1_EL1)))
+ return false;
+
+ return is_affected_midr_range(entry, scope);
+}
+
+static void cpu_enable_sme_dvmsync(const struct arm64_cpu_capabilities *__unused)
+{
+ if (this_cpu_has_cap(ARM64_WORKAROUND_4193714))
+ sme_enable_dvmsync();
+}
+#endif
+
#ifdef CONFIG_AMPERE_ERRATUM_AC03_CPU_38
static const struct midr_range erratum_ac03_cpu_38_list[] = {
MIDR_ALL_VERSIONS(MIDR_AMPERE1),
@@ -870,6 +888,18 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
ERRATA_MIDR_RANGE_LIST(erratum_spec_ssbs_list),
},
#endif
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+ {
+ .desc = "C1-Pro SME DVMSync early acknowledgement",
+ .capability = ARM64_WORKAROUND_4193714,
+ .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM,
+ .matches = has_sme_dvmsync_erratum,
+ .cpu_enable = cpu_enable_sme_dvmsync,
+ /* C1-Pro r0p0 - r1p2 (the latter only when REVIDR_EL1[0]==0) */
+ .midr_range = MIDR_RANGE(MIDR_C1_PRO, 0, 0, 1, 2),
+ MIDR_FIXED(MIDR_CPU_VAR_REV(1, 2), BIT(0)),
+ },
+#endif
#ifdef CONFIG_ARM64_WORKAROUND_SPECULATIVE_UNPRIV_LOAD
{
.desc = "ARM errata 2966298, 3117295",
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index a9c81715ce59..5b97dfcf796d 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -21,6 +21,7 @@
#include <asm/daifflags.h>
#include <asm/esr.h>
#include <asm/exception.h>
+#include <asm/fpsimd.h>
#include <asm/irq_regs.h>
#include <asm/kprobes.h>
#include <asm/mmu.h>
@@ -84,6 +85,7 @@ static __always_inline void __enter_from_user_mode(struct pt_regs *regs)
{
enter_from_user_mode(regs);
mte_disable_tco_entry(current);
+ sme_enter_from_user_mode();
}
static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
@@ -102,6 +104,7 @@ static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
local_irq_disable();
exit_to_user_mode_prepare(regs);
local_daif_mask();
+ sme_exit_to_user_mode();
mte_check_tfsr_exit();
exit_to_user_mode();
}
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index e3f8f51748bc..ca18214ce2ab 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -15,6 +15,7 @@
#include <linux/compiler.h>
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
+#include <linux/cpumask.h>
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/linkage.h>
@@ -28,6 +29,7 @@
#include <linux/sched/task_stack.h>
#include <linux/signal.h>
#include <linux/slab.h>
+#include <linux/smp.h>
#include <linux/stddef.h>
#include <linux/sysctl.h>
#include <linux/swab.h>
@@ -1384,6 +1386,83 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
put_cpu_fpsimd_context();
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+/*
+ * SME/CME erratum handling.
+ */
+static cpumask_t sme_dvmsync_cpus;
+
+/*
+ * These helpers are only called from non-preemptible contexts, so
+ * smp_processor_id() is safe here.
+ */
+void sme_set_active(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
+ return;
+
+ cpumask_set_cpu(cpu, mm_cpumask(current->mm));
+
+ /*
+ * A subsequent (post ERET) SME access may use a stale address
+ * translation. On C1-Pro, a TLBI+DSB on a different CPU will wait for
+ * the completion of cpumask_set_cpu() above as it appears in program
+ * order before the SME access. The post-TLBI+DSB read of mm_cpumask()
+ * will lead to the IPI being issued.
+ *
+ * https://lore.kernel.org/r/ablEXwhfKyJW1i7l@J2N7QTR9R3
+ */
+}
+
+void sme_clear_active(void)
+{
+ unsigned int cpu = smp_processor_id();
+
+ if (!cpumask_test_cpu(cpu, &sme_dvmsync_cpus))
+ return;
+
+ /*
+ * With SCTLR_EL1.IESB enabled, the SME memory transactions are
+ * completed on entering EL1.
+ */
+ cpumask_clear_cpu(cpu, mm_cpumask(current->mm));
+}
+
+static void sme_dvmsync_ipi(void *unused)
+{
+ /*
+ * With SCTLR_EL1.IESB on, taking an exception is sufficient to ensure
+ * the completion of the SME memory accesses, so no need for an
+ * explicit DSB.
+ */
+}
+
+void sme_do_dvmsync(const struct cpumask *mask)
+{
+ /*
+ * This is called from the TLB maintenance functions after the DSB ISH
+ * to send the hardware DVMSync message. If this CPU sees the mask as
+ * empty, the remote CPU executing sme_set_active() would have seen
+ * the DVMSync and no IPI required.
+ */
+ if (cpumask_empty(mask))
+ return;
+
+ preempt_disable();
+ smp_call_function_many(mask, sme_dvmsync_ipi, NULL, true);
+ preempt_enable();
+}
+
+void sme_enable_dvmsync(void)
+{
+ cpumask_set_cpu(smp_processor_id(), &sme_dvmsync_cpus);
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
/*
* Trapped SME access
*
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index 489554931231..4c328b7c79ba 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -26,6 +26,7 @@
#include <linux/reboot.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/cpumask.h>
#include <linux/cpu.h>
#include <linux/elfcore.h>
#include <linux/pm.h>
@@ -339,8 +340,41 @@ void flush_thread(void)
flush_gcs();
}
+#ifdef CONFIG_ARM64_ERRATUM_4193714
+
+static void arch_dup_tlbbatch_mask(struct task_struct *dst)
+{
+ /*
+ * Clear the inherited cpumask with memset() to cover both cases where
+ * cpumask_var_t is a pointer or an array. It will be allocated lazily
+ * in sme_dvmsync_add_pending() if CPUMASK_OFFSTACK=y.
+ */
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ memset(&dst->tlb_ubc.arch.cpumask, 0,
+ sizeof(dst->tlb_ubc.arch.cpumask));
+}
+
+static void arch_release_tlbbatch_mask(struct task_struct *tsk)
+{
+ if (alternative_has_cap_unlikely(ARM64_WORKAROUND_4193714))
+ free_cpumask_var(tsk->tlb_ubc.arch.cpumask);
+}
+
+#else
+
+static void arch_dup_tlbbatch_mask(struct task_struct *dst)
+{
+}
+
+static void arch_release_tlbbatch_mask(struct task_struct *tsk)
+{
+}
+
+#endif /* CONFIG_ARM64_ERRATUM_4193714 */
+
void arch_release_task_struct(struct task_struct *tsk)
{
+ arch_release_tlbbatch_mask(tsk);
fpsimd_release_task(tsk);
}
@@ -356,6 +390,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src)
*dst = *src;
+ arch_dup_tlbbatch_mask(dst);
+
/*
* Drop stale reference to src's sve_state and convert dst to
* non-streaming FPSIMD mode.
diff --git a/arch/arm64/tools/cpucaps b/arch/arm64/tools/cpucaps
index 1b32c1232d28..16d123088ddd 100644
--- a/arch/arm64/tools/cpucaps
+++ b/arch/arm64/tools/cpucaps
@@ -101,6 +101,7 @@ WORKAROUND_2077057
WORKAROUND_2457168
WORKAROUND_2645198
WORKAROUND_2658417
+WORKAROUND_4193714
WORKAROUND_AMPERE_AC03_CPU_38
WORKAROUND_AMPERE_AC04_CPU_23
WORKAROUND_TRBE_OVERWRITE_FILL_MODE
^ permalink raw reply related
* [PATCH 6.18.y 5/6] arm64: cputype: Add C1-Pro definitions
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
commit 2c99561016c591f4c3d5ad7d22a61b8726e79735 upstream.
Add cputype definitions for C1-Pro. These will be used for errata
detection in subsequent patches.
These values can be found in "Table A-303: MIDR_EL1 bit descriptions" in
issue 07 of the C1-Pro TRM:
https://documentation-service.arm.com/static/6930126730f8f55a656570af
Acked-by: Mark Rutland <mark.rutland@arm.com>
Cc: Will Deacon <will@kernel.org>
Cc: James Morse <james.morse@arm.com>
Reviewed-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/cputype.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 9b00b75acbf2..18f98fb7ee78 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -98,6 +98,7 @@
#define ARM_CPU_PART_CORTEX_A725 0xD87
#define ARM_CPU_PART_CORTEX_A720AE 0xD89
#define ARM_CPU_PART_NEOVERSE_N3 0xD8E
+#define ARM_CPU_PART_C1_PRO 0xD8B
#define APM_CPU_PART_XGENE 0x000
#define APM_CPU_VAR_POTENZA 0x00
@@ -189,6 +190,7 @@
#define MIDR_CORTEX_A725 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A725)
#define MIDR_CORTEX_A720AE MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A720AE)
#define MIDR_NEOVERSE_N3 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_NEOVERSE_N3)
+#define MIDR_C1_PRO MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_C1_PRO)
#define MIDR_THUNDERX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
#define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
^ permalink raw reply related
* [PATCH 6.18.y 1/6] arm64: tlb: Allow XZR argument to TLBI ops
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
In-Reply-To: <20260421100018.335793-1-catalin.marinas@arm.com>
From: Mark Rutland <mark.rutland@arm.com>
commit bfd9c931d19aa59fb8371d557774fa169b15db9a upstream.
The TLBI instruction accepts XZR as a register argument, and for TLBI
operations with a register argument, there is no functional difference
between using XZR or another GPR which contains zeroes. Operations
without a register argument are encoded as if XZR were used.
Allow the __TLBI_1() macro to use XZR when a register argument is all
zeroes.
Today this only results in a trivial code saving in
__do_compat_cache_op()'s workaround for Neoverse-N1 erratum #1542419. In
subsequent patches this pattern will be used more generally.
There should be no functional change as a result of this patch.
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Will Deacon <will@kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
---
arch/arm64/include/asm/tlbflush.h | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 18a5dc0c9a54..0ddb344f83b4 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -38,12 +38,12 @@
: : )
#define __TLBI_1(op, arg) asm (ARM64_ASM_PREAMBLE \
- "tlbi " #op ", %0\n" \
+ "tlbi " #op ", %x0\n" \
ALTERNATIVE("nop\n nop", \
- "dsb ish\n tlbi " #op ", %0", \
+ "dsb ish\n tlbi " #op ", %x0", \
ARM64_WORKAROUND_REPEAT_TLBI, \
CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
- : : "r" (arg))
+ : : "rZ" (arg))
#define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
^ permalink raw reply related
* [PATCH 6.18.y 0/6] arm64: Stable backport of the C1-Pro erratum 4193714 workaround
From: Catalin Marinas @ 2026-04-21 10:00 UTC (permalink / raw)
To: stable; +Cc: Will Deacon, linux-arm-kernel
Hi Greg, Sasha,
As the workaround for this CPU bug just went in, I'm sending it for
stable 6.18. The first two patches are prerequisites to make the
backporting easier. I do not intend to send them for stable 6.12 since
SME is not supported in that version anyway (Android folk did their own
backports already).
A heads-up, the workaround itself is larger than the recommended max 100
lines suitability for stable backports.
Thanks.
Catalin Marinas (4):
arm64: tlb: Introduce __tlbi_sync_s1ish_{kernel,batch}() for TLB
maintenance
arm64: tlb: Pass the corresponding mm to __tlbi_sync_s1ish()
arm64: cputype: Add C1-Pro definitions
arm64: errata: Work around early CME DVMSync acknowledgement
Mark Rutland (2):
arm64: tlb: Allow XZR argument to TLBI ops
arm64: tlb: Optimize ARM64_WORKAROUND_REPEAT_TLBI
Documentation/arch/arm64/silicon-errata.rst | 2 +
arch/arm64/Kconfig | 12 ++
arch/arm64/include/asm/cpucaps.h | 2 +
arch/arm64/include/asm/cputype.h | 2 +
arch/arm64/include/asm/fpsimd.h | 21 +++
arch/arm64/include/asm/tlbbatch.h | 10 +-
arch/arm64/include/asm/tlbflush.h | 143 ++++++++++++++++----
arch/arm64/kernel/cpu_errata.c | 30 ++++
arch/arm64/kernel/entry-common.c | 3 +
arch/arm64/kernel/fpsimd.c | 79 +++++++++++
arch/arm64/kernel/process.c | 36 +++++
arch/arm64/kernel/sys_compat.c | 2 +-
arch/arm64/kvm/hyp/nvhe/mm.c | 2 +-
arch/arm64/kvm/hyp/nvhe/tlb.c | 8 +-
arch/arm64/kvm/hyp/pgtable.c | 2 +-
arch/arm64/kvm/hyp/vhe/tlb.c | 10 +-
arch/arm64/tools/cpucaps | 1 +
17 files changed, 325 insertions(+), 40 deletions(-)
^ permalink raw reply
* Re: [PATCH v5 04/12] coresight: etm4x: exclude ss_status from drvdata->config
From: Mike Leach @ 2026-04-21 9:58 UTC (permalink / raw)
To: Suzuki K Poulose, Leo Yan, Yeoreum Yun
Cc: coresight, linux-arm-kernel, linux-kernel, james.clark,
alexander.shishkin, jie.gan
In-Reply-To: <57dbea1b-670b-4b8f-a590-1d4239bc2c76@arm.com>
Hi,
This register [bit 31] indicates if a single shot comparator has
matched. So read-back provides information to the user post run to
determine which if any of the comparators set in this way has actually
matched.
Moreover, the specification states "Software must reset this bit to 0 to
re-enable single-shot control" and "Reset state is unknown. STATUS must
be written to set an initial state...."
Therefore this register must be written as part of any configuration so
should be available in the drvdata->config for both read and write,
Regards
Mike
On 4/21/26 09:57, Suzuki K Poulose wrote:
> On 16/04/2026 16:51, Leo Yan wrote:
>> On Wed, Apr 15, 2026 at 05:55:20PM +0100, Yeoreum Yun wrote:
>>
>> [...]
>>
>>> @@ -573,11 +573,9 @@ static int etm4_enable_hw(struct etmv4_drvdata
>>> *drvdata)
>>> etm4x_relaxed_write32(csa, config->res_ctrl[i],
>>> TRCRSCTLRn(i));
>>> for (i = 0; i < caps->nr_ss_cmp; i++) {
>>> - /* always clear status bit on restart if using single-shot */
>>> - if (config->ss_ctrl[i] || config->ss_pe_cmp[i])
>>> - config->ss_status[i] &= ~TRCSSCSRn_STATUS;
>>> etm4x_relaxed_write32(csa, config->ss_ctrl[i], TRCSSCCRn(i));
>>> - etm4x_relaxed_write32(csa, config->ss_status[i], TRCSSCSRn(i));
>>> + /* always clear status and pending bits on restart if using
>>> single-shot */
>>> + etm4x_relaxed_write32(csa, 0x0, TRCSSCSRn(i));
>>
>> In Arm ARM, D24.4.60 TRCSSCSR<n>, bits[0..3] are RO. I think it is
>> fine for directly clear the regiser with zero (means it will only
>> clear status / pending bits).
>>
>> [...]
>>
>>> @@ -1841,10 +1839,11 @@ static ssize_t sshot_status_show(struct
>>> device *dev,
>>> {
>>> unsigned long val;
>>> struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
>>> + const struct etmv4_caps *caps = &drvdata->caps;
>>> struct etmv4_config *config = &drvdata->config;
>>> raw_spin_lock(&drvdata->spinlock);
>>> - val = config->ss_status[config->ss_idx];
>>> + val = caps->ss_cmp[config->ss_idx];
>>> raw_spin_unlock(&drvdata->spinlock);
>>> return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
>>> }
>>
>> This sysfs knob never can print out a realtime status for sshot, I am
>
> Won't it give the status, when the ETM was disabled (and saved back to
> config), for as sysfs mode operation, where the user collects
> information about the status via sysfs ? ( The question of if someone
> actually makes use of this is a different question )
>
>
> Cheers
> Suzuki
>
>
>> fine for only printing caps->ss_cmp, this can avoid any misleading.
>>
>> @Suzuki, @Mike, do you agree with the change above?
>>
>> If maintainers agree with this, as Jie suggested, it is good to add a
>> comment in the code and update the document:
>>
>> Documentation/trace/coresight/coresight-etm4x-reference.rst
>>
>> Thanks,
>> Leo
>
^ permalink raw reply
* RE: [PATCH v5 2/4] thermal: qoriq: add i.MX93 tmu support
From: Jacky Bai @ 2026-04-21 9:59 UTC (permalink / raw)
To: Daniel Baluta (OSS), Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Shawn Guo, Sascha Hauer, Fabio Estevam, Pengutronix Kernel Team,
Frank Li
Cc: linux-pm@vger.kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
Alice Guo
In-Reply-To: <2d1bbd53-1f03-4432-8681-939e0c638d37@oss.nxp.com>
> Subject: Re: [PATCH v5 2/4] thermal: qoriq: add i.MX93 tmu support
>
[...]
> > static struct qoriq_tmu_data *qoriq_sensor_to_data(struct
> > qoriq_sensor *s) @@ -225,6 +232,8 @@ static int
> > qoriq_tmu_calibration(struct device *dev,
> >
> > static void qoriq_tmu_init_device(struct qoriq_tmu_data *data) {
> > + u32 teumr0_val;
>
> No need for this here you can just use directly: data->drvdata->teumr0
>
Thx, will resolve it in next version.
BR
> > +
> > /* Disable interrupt, using polling instead */
> > regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
> >
> > @@ -234,7 +243,8 @@ static void qoriq_tmu_init_device(struct
> qoriq_tmu_data *data)
> > regmap_write(data->regmap, REGS_TMTMIR, TMTMIR_DEFAULT);
> > } else {
> > regmap_write(data->regmap, REGS_V2_TMTMIR,
> TMTMIR_DEFAULT);
> > - regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
> > + teumr0_val = data->drvdata->teumr0;
> > + regmap_write(data->regmap, REGS_V2_TEUMR(0), teumr0_val);
> > }
>
^ permalink raw reply
* Re: [PATCH] ACPI: arm64: cpuidle: Tolerate platforms with no deep PSCI idle states
From: Sudeep Holla @ 2026-04-21 9:58 UTC (permalink / raw)
To: Breno Leitao
Cc: Lorenzo Pieralisi, Hanjun Guo, Sudeep Holla, Catalin Marinas,
Will Deacon, Rafael J. Wysocki, Len Brown, Huisong Li,
Rafael J. Wysocki, linux-acpi, linux-arm-kernel, linux-kernel,
pjaroszynski, rmikey, kernel-team, stable
In-Reply-To: <aedGoi-Fk5HPK0OO@gmail.com>
On Tue, Apr 21, 2026 at 02:51:42AM -0700, Breno Leitao wrote:
> On Mon, Apr 20, 2026 at 04:12:38PM +0100, Sudeep Holla wrote:
> > On Mon, Apr 20, 2026 at 02:27:13AM -0700, Breno Leitao wrote:
> > > - count = pr->power.count - 1;
> > > - if (count <= 0)
> > > - return -ENODEV;
> > > -
> >
> > Does it make sense to retain this check like
> > if (pr->power.count < 1)
> > return -EINVAL;
> >
> > Though I see the assignment to pr->power.count in drivers/acpi/processor_idle.c
> > is through unsigned int. So I am fine even without the above check.
>
> I don't think the check is necessary. When count is 0 or 1, the loop
> for (i = 1; i < pr->power.count; i++) body won't execute, and the
> function will return 0.
>
Yes but the point is to handle invalid pr->power.count(0 or less) which
is not possible here though it is signed it because it is assigned from
an unsigned int during initialisation.
> This seems like the correct behavior — if there are no FFH PSCI states
> to validate, there's nothing that should fail.
>
Agreed, but I was thinking of error in parsing _LPI being propogated here
but again that's not happening here.
> Additionally, returning -ENODEV would trigger the "Invalid FFH LPI data"
> error message, which would be misleading since the LPI data isn't
> invalid, it's just not present.
>
The point was to throw that error if _LPI parsing fails.
> That said, please take this with a grain of salt since I'm not deeply
> familiar with _LPI states and their expected behavior.
>
No worries, I agree the check I asked for is not needed.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH v5 02/12] coresight: etm4x: fix underflow for nrseqstate
From: Yeoreum Yun @ 2026-04-21 9:56 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Leo Yan, coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, jie.gan
In-Reply-To: <6dcb14c1-0759-4f2a-8bbc-b85adf3d12f4@arm.com>
On Tue, Apr 21, 2026 at 09:50:56AM +0100, Suzuki K Poulose wrote:
> On 21/04/2026 09:50, Suzuki K Poulose wrote:
> > On 16/04/2026 16:11, Leo Yan wrote:
> > > On Wed, Apr 15, 2026 at 05:55:18PM +0100, Yeoreum Yun wrote:
> > > > TCRSEQEVR<n> is implemented only when TCRIDR5.NUMSEQSTATE is 0b100,
> > > > in which case n ranges from 0 to 2; otherwise,
> > > > TCRIDR5.NUMSEQSTATE is 0b000.
> > >
> > > My suggestion in previous version is not quite right, thanks for
> > > making this correct.
> > >
> > > [...]
> > >
> > > > @@ -1395,6 +1395,8 @@ static ssize_t seq_idx_store(struct device *dev,
> > > > struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > > struct etmv4_config *config = &drvdata->config;
> > > > + if (!drvdata->nrseqstate)
> > > > + return -EINVAL;
> > >
> > > For "nrseqstate = 0" case, would it return -EOPNOTSUPP instead?
> >
> > Or should we make this only visible if the nrseqstore is meaningful ?
> >
> > Suzuki
> >
> > >
> > > Otherwise, LGTM:
> > >
> > > Reviewed-by: Leo Yan <leo.yan@arm.com>
> >
>
> Also, please add Fixes: tag for these bug fixes
Okay. I'll add the tag. Thanks!
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* RE: [PATCH v5 3/4] thermal: qoriq: workaround unexpected temperature readings from tmu
From: Jacky Bai @ 2026-04-21 9:56 UTC (permalink / raw)
To: Frank Li
Cc: Rafael J. Wysocki, Daniel Lezcano, Zhang Rui, Lukasz Luba,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, Shawn Guo,
Sascha Hauer, Fabio Estevam, Pengutronix Kernel Team,
linux-pm@vger.kernel.org, devicetree@vger.kernel.org,
imx@lists.linux.dev, linux-arm-kernel@lists.infradead.org
In-Reply-To: <aec_TlguJkc4A1qN@lizhi-Precision-Tower-5810>
> Subject: Re: [PATCH v5 3/4] thermal: qoriq: workaround unexpected
> temperature readings from tmu
>
[...]
> >
> > + /* ERR052243: If a raising or falling edge happens, try later */
> > + if (qoriq_tmu_has_errata(qdata->drvdata, TMU_ERR052243)) {
> > + regmap_read(qdata->regmap, REGS_TIDR, &tidr);
> > + if (tidr & TEMP_RATE_IRQ_MASK) {
> > + regmap_write(qdata->regmap, REGS_TIDR,
> TEMP_RATE_IRQ_MASK);
> > + return -EAGAIN;
> > + }
> > + }
> > +
> > if (regmap_read_poll_timeout(qdata->regmap,
> > REGS_TRITSR(qsensor->id),
> > val,
> > @@ -130,6 +159,15 @@ static int tmu_get_temp(struct
> thermal_zone_device *tz, int *temp)
> > 10 * USEC_PER_MSEC))
> > return -ENODATA;
> >
> > + /*ERR052243: If a raising or falling edge happens, try later */
> > + if (qoriq_tmu_has_errata(qdata->drvdata, TMU_ERR052243)) {
> > + regmap_read(qdata->regmap, REGS_TIDR, &tidr);
> > + if (tidr & TEMP_RATE_IRQ_MASK) {
> > + regmap_write(qdata->regmap, REGS_TIDR,
> TEMP_RATE_IRQ_MASK);
> > + return -EAGAIN;
> > + }
> > + }
> > +
>
> The above two code blocks are the same. Use helper function to avoid
> duplicat code. And why need check twice?
>
> ret = qoriq_tmu_err052243()
> if (ret)
> return ret;
>
The first check is to make sure no error already happened. if any error, no need
to polling read the sensor value from tmu, return early to save time. The secondary
check is to make sure the sensor value just read out is still a valid one as the error may
happen after the first check.
It should be ok to remove the first check. As the error only happens in some rare
corner case, the sensor read polling delay is acceptable.
If only keep the secondary check, I think no need to wrap this code block into a helper function?
BR
> Frank
>
> > if (qdata->ver == TMU_VER1) {
> > *temp = (val & GENMASK(7, 0)) * MILLIDEGREE_PER_DEGREE;
> > } else {
> > @@ -247,6 +285,14 @@ static void qoriq_tmu_init_device(struct
> qoriq_tmu_data *data)
> > regmap_write(data->regmap, REGS_V2_TEUMR(0), teumr0_val);
> > }
> >
> > + /* ERR052243: Set the raising & falling edge monitor */
> > + if (qoriq_tmu_has_errata(data->drvdata, TMU_ERR052243)) {
> > + regmap_write(data->regmap, TMRTRCTR, TMRTRCTR_EN |
> > + FIELD_PREP(TMRTRCTR_TEMP_MASK,
> TEMP_RATE_THR_LVL));
> > + regmap_write(data->regmap, TMFTRCTR, TMFTRCTR_EN |
> > + FIELD_PREP(TMFTRCTR_TEMP_MASK,
> TEMP_RATE_THR_LVL));
> > +
> > + }
> > /* Disable monitoring */
> > regmap_write(data->regmap, REGS_TMR, TMR_DISABLE); } @@
> -400,6
> > +446,7 @@ static const struct tmu_drvdata imx8mq_tmu_data = {
> >
> > static const struct tmu_drvdata imx93_data = {
> > .teumr0 = TEUMR0_V21,
> > + .tmu_errata = TMU_ERR052243,
> > };
> >
> > static const struct of_device_id qoriq_tmu_match[] = {
> >
> > --
> > 2.34.1
> >
^ permalink raw reply
* Re: [PATCH] ACPI: arm64: cpuidle: Tolerate platforms with no deep PSCI idle states
From: Breno Leitao @ 2026-04-21 9:51 UTC (permalink / raw)
To: Sudeep Holla
Cc: Lorenzo Pieralisi, Hanjun Guo, Catalin Marinas, Will Deacon,
Rafael J. Wysocki, Len Brown, Huisong Li, Rafael J. Wysocki,
linux-acpi, linux-arm-kernel, linux-kernel, pjaroszynski, rmikey,
kernel-team, stable
In-Reply-To: <20260420-sturdy-unique-shark-c4ca8c@sudeepholla>
On Mon, Apr 20, 2026 at 04:12:38PM +0100, Sudeep Holla wrote:
> On Mon, Apr 20, 2026 at 02:27:13AM -0700, Breno Leitao wrote:
> > - count = pr->power.count - 1;
> > - if (count <= 0)
> > - return -ENODEV;
> > -
>
> Does it make sense to retain this check like
> if (pr->power.count < 1)
> return -EINVAL;
>
> Though I see the assignment to pr->power.count in drivers/acpi/processor_idle.c
> is through unsigned int. So I am fine even without the above check.
I don't think the check is necessary. When count is 0 or 1, the loop
for (i = 1; i < pr->power.count; i++) body won't execute, and the
function will return 0.
This seems like the correct behavior — if there are no FFH PSCI states
to validate, there's nothing that should fail.
Additionally, returning -ENODEV would trigger the "Invalid FFH LPI data"
error message, which would be misleading since the LPI data isn't
invalid, it's just not present.
That said, please take this with a grain of salt since I'm not deeply
familiar with _LPI states and their expected behavior.
Thanks for the review,
--breno
^ permalink raw reply
* Re: [PATCH v3 5/6] soc: qcom: pmic-glink-altmode: pass down HPD_IRQ events
From: Konrad Dybcio @ 2026-04-21 9:51 UTC (permalink / raw)
To: Dmitry Baryshkov, Maarten Lankhorst, Maxime Ripard,
Thomas Zimmermann, David Airlie, Simona Vetter, Heikki Krogerus,
Greg Kroah-Hartman, Andrzej Hajda, Neil Armstrong, Robert Foss,
Laurent Pinchart, Jonas Karlman, Jernej Skrabec, Adrien Grassein,
Jani Nikula, Rodrigo Vivi, Joonas Lahtinen, Tvrtko Ursulin,
Kevin Hilman, Jerome Brunet, Martin Blumenstingl, Rob Clark,
Dmitry Baryshkov, Abhinav Kumar, Jessica Zhang, Sean Paul,
Marijn Suijten, Tomi Valkeinen, Bjorn Andersson, Konrad Dybcio,
Pengyu Luo, Nikita Travkin, Yongxing Mou
Cc: dri-devel, linux-kernel, linux-usb, intel-gfx, intel-xe,
linux-amlogic, linux-arm-kernel, linux-arm-msm, freedreno
In-Reply-To: <20260421-hpd-irq-events-v3-5-44d2bf40dfc2@oss.qualcomm.com>
On 4/21/26 1:33 AM, Dmitry Baryshkov wrote:
> Pass IRQ_HPD events to the HPD bridge, letting those to be delivered to
> the DisplayPort driver.
>
> Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
> ---
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
Konrad
^ permalink raw reply
* Re: [PATCH v5 01/12] coresight: etm4x: fix wrong check of etm4x_sspcicrn_present()
From: Yeoreum Yun @ 2026-04-21 9:48 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, leo.yan, jie.gan
In-Reply-To: <d733a0b3-60a6-4bd8-909a-a2ee0c121dde@arm.com>
On Tue, Apr 21, 2026 at 09:47:54AM +0100, Suzuki K Poulose wrote:
> On 15/04/2026 17:55, Yeoreum Yun wrote:
> > According to Embedded Trace Macrocell Architecture Specification
> > ETMv4.0 to ETM4.6 [0], TRCSSPCICR<n> is present only if all of
> > the following are true:
> >
> > - TRCIDR4.NUMSSCC > n.
> > - TRCIDR4.NUMPC > 0b0000.
> > - TRCSSCSR<n>.PC == 0b1.
> >
> > Comment for etm4x_sspcicrn_present() is align with the specification.
> > However, the check should use drvdata->nr_pe_cmp to check TRCIDR4.NUMPC
> > not nr_pe.
> >
> > Link: https://developer.arm.com/documentation/ihi0064/latest/ [0]
>
> Fixes: f6a18f354c58 ("coresight: etm4x: Handle access to TRCSSPCICRn")
>
> With that looks good to me
Thanks!
>
> Suzuki
>
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
> > ---
> > drivers/hwtracing/coresight/coresight-etm4x-core.c | 2 +-
> > 1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > index d565a73f0042..74b7063d130e 100644
> > --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
> > @@ -89,7 +89,7 @@ static int etm4_probe_cpu(unsigned int cpu);
> > static bool etm4x_sspcicrn_present(struct etmv4_drvdata *drvdata, int n)
> > {
> > return (n < drvdata->nr_ss_cmp) &&
> > - drvdata->nr_pe &&
> > + drvdata->nr_pe_cmp &&
> > (drvdata->config.ss_status[n] & TRCSSCSRn_PC);
> > }
>
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* [PATCH v2 1/2] arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Cobra
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz
In-Reply-To: <20260421-px30-eth-phy-v2-0-68c375b120fd@cherry.de>
From: Quentin Schulz <quentin.schulz@cherry.de>
When not passing the PHY ID with an ethernet-phy-idX.Y compatible
property, the MDIO bus will attempt to auto-detect the PHY by reading
its registers and then probing the appropriate driver. For this to work,
the PHY needs to be in a working state.
Unfortunately, the net subsystem doesn't control the PHY reset GPIO when
attempting to auto-detect the PHY. This means the PHY needs to be in a
working state when entering the Linux kernel. This historically has been
the case for this device, but only because the bootloader was taking
care of initializing the Ethernet controller even when not using it.
We're attempting to support the removal of the network stack in the
bootloader, which means the Linux kernel will be entered with the PHY
still in reset and now Ethernet doesn't work anymore.
The devices in the field only ever had a TI DP83825, so let's simply
bypass the auto-detection mechanism entirely by passing the appropriate
PHY IDs via the compatible.
Fixes: bb510ddc9d3e ("arm64: dts: rockchip: add px30-cobra base dtsi and board variants")
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
arch/arm64/boot/dts/rockchip/px30-cobra.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi b/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
index b7e669d8ba4d1..add917af5de78 100644
--- a/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-cobra.dtsi
@@ -397,7 +397,7 @@ &io_domains {
&mdio {
dp83825: ethernet-phy@0 {
- compatible = "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id2000.a140";
reg = <0x0>;
pinctrl-names = "default";
pinctrl-0 = <&phy_rst>;
--
2.53.0
^ permalink raw reply related
* [PATCH v2 2/2] arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Ringneck
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz, stable
In-Reply-To: <20260421-px30-eth-phy-v2-0-68c375b120fd@cherry.de>
From: Quentin Schulz <quentin.schulz@cherry.de>
When not passing the PHY ID with an ethernet-phy-idX.Y compatible
property, the MDIO bus will attempt to auto-detect the PHY by reading
its registers and then probing the appropriate driver. For this to work,
the PHY needs to be in a working state.
Unfortunately, the net subsystem doesn't control the PHY reset GPIO when
attempting to auto-detect the PHY. This means the PHY needs to be in a
working state when entering the Linux kernel. This historically has been
the case for this device, but only because the bootloader was taking
care of initializing the Ethernet controller even when not using it.
We're attempting to support the removal of the network stack in the
bootloader, which means the Linux kernel will be entered with the PHY
still in reset and now Ethernet doesn't work anymore.
The devices in the field only ever had a TI DP83825, so let's simply
bypass the auto-detection mechanism entirely by passing the appropriate
PHY IDs via the compatible.
Note that this is only an issue since commit e463625af7f9 ("arm64: dts:
rockchip: move reset to dedicated eth-phy node on ringneck") as before
that commit the reset was done by the MAC controller before starting the
MDIO auto-detection mechanism, via the snps,reset-* properties.
Cc: stable@vger.kernel.org
Fixes: e463625af7f9 ("arm64: dts: rockchip: move reset to dedicated eth-phy node on ringneck")
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
index 4203b335a2633..973b4c5880e24 100644
--- a/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
+++ b/arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi
@@ -344,7 +344,7 @@ &io_domains {
&mdio {
dp83825: ethernet-phy@0 {
- compatible = "ethernet-phy-ieee802.3-c22";
+ compatible = "ethernet-phy-id2000.a140";
reg = <0x0>;
pinctrl-names = "default";
pinctrl-0 = <&phy_rst>;
--
2.53.0
^ permalink raw reply related
* [PATCH v2 0/2] arm64: dts: rockchip: fix Ethernet PHY on Theobroma PX30 devices
From: Quentin Schulz @ 2026-04-21 9:45 UTC (permalink / raw)
To: Rob Herring, Krzysztof Kozlowski, Conor Dooley, Heiko Stuebner
Cc: Andrew Lunn, Heiko Stuebner, devicetree, linux-arm-kernel,
linux-rockchip, linux-kernel, Quentin Schulz, stable
This removes the reliance on the bootloader setting up the Ethernet PHY
for the Linux kernel to be able to use Ethernet.
This is due to the HW default of the PHY reset line being active and the
MDIO auto-detection mechanism not controlling a PHY's reset line such
that we need to hardcode the PHY ID in the compatible property for it to
be usable by the kernel, regardless of what the bootloader is doing.
We only ever had one PHY (DP83825) for both devices, so it's fine to
hardcode this way.
As discussed in v1[1][2], even though they suffer from the same
limitation, only the patch for Ringneck is targeted for stable releases.
Ethernet is currently broken if the bootloader is built without Ethernet
support for those two boards. Cobra is a product for which the software
stack can only be replaced or updated by Cherry. Ringneck is a SoM
supported since kernel 6.1, the user is likely going to write their own
bootloader support based on the motherboard they attach the SoM to. They
may disable Ethernet support in the bootloader if they don't need to
(e.g. to reduce the attack surface or have an easier time certifying a
device when arguing with an audit company).
Ethernet-less bootloader was supported until commit e463625af7f9
("arm64: dts: rockchip: move reset to dedicated eth-phy node on
ringneck") for Ringneck. Because I do not control what our users have
made with Ringneck, and that it used to work before commit e463625af7f9,
the patch fixing the issue on Ringneck is a candidate for backporting to
stable.
Cobra never supported it due to its support in the kernel being added
with this (unknown at the time) limitation. Moreover, Cherry controls
the whole software stack so this is already patched downstream whenever
required. Therefore, the patch fixing the issue on Cobra is not marked
as a candidate for backporting to stable (but if it ends up being
backported, it's fine as well).
[1] https://lore.kernel.org/linux-rockchip/38452338-6e65-47ad-a696-b90c02ac42f0@lunn.ch/
[2] https://lore.kernel.org/linux-rockchip/b2f12140-ee3d-45bc-864e-d51317c83b8d@cherry.de/
Signed-off-by: Quentin Schulz <quentin.schulz@cherry.de>
---
Changes in v2:
- removed Cc stable on Cobra's patch,
- Link to v1: https://patch.msgid.link/20260202-px30-eth-phy-v1-0-ef365be64922@cherry.de
---
Quentin Schulz (2):
arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Cobra
arm64: dts: rockchip: fix Ethernet PHY not found on PX30 Ringneck
arch/arm64/boot/dts/rockchip/px30-cobra.dtsi | 2 +-
arch/arm64/boot/dts/rockchip/px30-ringneck.dtsi | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
---
base-commit: c1f49dea2b8f335813d3b348fd39117fb8efb428
change-id: 20260130-px30-eth-phy-676fa181e116
Best regards,
--
Quentin Schulz <quentin.schulz@cherry.de>
^ permalink raw reply
* Re: [PATCH v3 1/8] dt-bindings: mfd: khadas: Add new compatible for Khadas VIM4 MCU
From: Ronald Claveau @ 2026-04-21 9:45 UTC (permalink / raw)
To: Conor Dooley
Cc: Neil Armstrong, Lee Jones, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Andi Shyti, Kevin Hilman, Jerome Brunet,
Martin Blumenstingl, Beniamino Galvani, Rafael J. Wysocki,
Daniel Lezcano, Zhang Rui, Lukasz Luba, Liam Girdwood, Mark Brown,
linux-amlogic, devicetree, linux-kernel, linux-i2c,
linux-arm-kernel, linux-pm
In-Reply-To: <20260420-viable-plot-862e0c545837@spud>
On 4/20/26 6:22 PM, Conor Dooley wrote:
> On Fri, Apr 17, 2026 at 06:27:17PM +0200, Ronald Claveau wrote:
>> The Khadas VIM4 MCU register is slightly different
>> from previous boards' MCU.
>> This board also features a switchable power source for its fan.
>>
>> Signed-off-by: Ronald Claveau <linux-kernel-dev@aliel.fr>
>> ---
>> Documentation/devicetree/bindings/mfd/khadas,mcu.yaml | 5 +++++
>> 1 file changed, 5 insertions(+)
>>
>> diff --git a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> index 084960fd5a1fd..a80718f7595ce 100644
>> --- a/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> +++ b/Documentation/devicetree/bindings/mfd/khadas,mcu.yaml
>> @@ -18,6 +18,7 @@ properties:
>> compatible:
>> enum:
>> - khadas,mcu # MCU revision is discoverable
>> + - khadas,vim4-mcu # Different MCU variant, not discoverable
>>
>> "#cooling-cells": # Only needed for boards having FAN control feature
>> const: 2
>> @@ -25,6 +26,10 @@ properties:
>> reg:
>> maxItems: 1
>>
>> + fan-supply:
>> + description: Phandle to the regulator that powers the fan.
>> + $ref: /schemas/types.yaml#/definitions/phandle
>
> Can you limit this by compatible please?
> pw-bot: changes-requested
>
Thanks for your feedback, I will add that.
>> +
>> required:
>> - compatible
>> - reg
>>
>> --
>> 2.49.0
>>
--
Best regards,
Ronald
^ permalink raw reply
* [PATCH] crypto: ixp4xx: Fix null-pointer dereference in chainup_buffers()
From: Ruoyu Wang @ 2026-04-21 9:39 UTC (permalink / raw)
To: clabbe, linusw, kaloz, herbert, davem
Cc: linux-crypto, linux-arm-kernel, linux-kernel, Ruoyu Wang
chainup_buffers() builds a linked list of buffer descriptors for a
scatterlist. If dma_pool_alloc() fails while constructing the list, the
current code sets buf to NULL and later dereferences it unconditionally
at the end of the function:
buf->next = NULL;
buf->phys_next = 0;
This can lead to a null-pointer dereference on allocation failure.
If the failure happens after part of the descriptor chain has already
been allocated and DMA-mapped, the partially constructed chain also
needs to be released.
Fix this by unwinding the partially constructed chain, resetting the
caller-provided hook descriptor, and returning NULL on allocation
failure.
Signed-off-by: Ruoyu Wang <ruoyuw560@gmail.com>
---
drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c | 24 +++++++++++++++++----
1 file changed, 20 insertions(+), 4 deletions(-)
diff --git a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
index fcc0cf4df637..63ef28cd5766 100644
--- a/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
+++ b/drivers/crypto/intel/ixp4xx/ixp4xx_crypto.c
@@ -874,6 +874,11 @@ static struct buffer_desc *chainup_buffers(struct device *dev,
struct buffer_desc *buf, gfp_t flags,
enum dma_data_direction dir)
{
+ struct buffer_desc *first = buf;
+
+ first->next = NULL;
+ first->phys_next = 0;
+
for (; nbytes > 0; sg = sg_next(sg)) {
unsigned int len = min(nbytes, sg->length);
struct buffer_desc *next_buf;
@@ -883,10 +888,15 @@ static struct buffer_desc *chainup_buffers(struct device *dev,
nbytes -= len;
ptr = sg_virt(sg);
next_buf = dma_pool_alloc(buffer_pool, flags, &next_buf_phys);
- if (!next_buf) {
- buf = NULL;
- break;
- }
+ if (!next_buf)
+ goto err_unwind;
+
+ /*
+ * Keep the chain well-formed even on partial construction,
+ * so free_buf_chain() can safely unwind it on failure.
+ */
+ next_buf->next = NULL;
+ next_buf->phys_next = 0;
sg_dma_address(sg) = dma_map_single(dev, ptr, len, dir);
buf->next = next_buf;
buf->phys_next = next_buf_phys;
@@ -899,6 +909,12 @@ static struct buffer_desc *chainup_buffers(struct device *dev,
buf->next = NULL;
buf->phys_next = 0;
return buf;
+
+err_unwind:
+ free_buf_chain(dev, first->next, first->phys_next);
+ first->next = NULL;
+ first->phys_next = 0;
+ return NULL;
}
static int ablk_setkey(struct crypto_skcipher *tfm, const u8 *key,
--
2.43.0
^ permalink raw reply related
* Re: [PATCH V3] dmaengine: imx-sdma: Fix SPBA bus detection on multi-SPBA platforms
From: Marco Felsch @ 2026-04-21 9:44 UTC (permalink / raw)
To: Shengjiu Wang
Cc: Shengjiu Wang, vkoul, Frank.Li, s.hauer, kernel, festevam,
dmaengine, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <CAA+D8ANwT0GKusZtvo6h8mzVf=xXSEkHXsb6nwHGZ2YQzPm5ZQ@mail.gmail.com>
On 26-04-21, Shengjiu Wang wrote:
> On Tue, Apr 21, 2026 at 4:57 PM Marco Felsch <m.felsch@pengutronix.de> wrote:
> >
> > On 26-04-20, Shengjiu Wang wrote:
> > > i.MX8M platforms have multiple SPBA buses under different AIPS buses.
> > > The current code searches the entire device tree and returns the first
> > > SPBA bus found, which may not be under the same AIPS bus as the SDMA
> > > controller.
> > >
> > > This breaks SDMA P2P transfers because the SDMA script needs to know
> > > if peripherals are on SPBA or AIPS to configure watermark levels
> > > correctly. Using the wrong SPBA bus causes DMA timeouts and transfer
> > > failures.
> > >
> > > Fix by searching for the SPBA bus under the SDMA's parent node (AIPS)
> > > first, then falling back to a global search for backward compatibility.
> > >
> > > Example device tree showing the issue:
> > > aips1 {
> > > spba1 { sai@...; }; /* Correct SPBA for sdma1 */
> > > sdma1@...;
> > > };
> > > aips2 {
> > > spba2 { uart@...; }; /* Wrong SPBA - found first by old code */
> > > };
> > >
> > > Fixes: 8391ecf465ec ("dmaengine: imx-sdma: Add device to device support")
> > > Cc: stable@vger.kernel.org
> > > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > > ---
> > > changs in v3:
> > > - add fallback to a global search for backward compatibility, which is
> > > to address comments from sashiko.dev
> > > - update commit subject and commit message
> > > - add comments in code.
> > > - add Cc stable tag
> > > - Don't add Frank's RB on v2 as there are several other changes.
> > >
> > > changes in v2:
> > > - add fixes tag
> > > - use __free(device_node) for auto release.
> > >
> > > drivers/dma/imx-sdma.c | 13 ++++++++++++-
> > > 1 file changed, 12 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> > > index 3d527883776b..592705af2319 100644
> > > --- a/drivers/dma/imx-sdma.c
> > > +++ b/drivers/dma/imx-sdma.c
> > > @@ -2364,7 +2364,18 @@ static int sdma_probe(struct platform_device *pdev)
> > > return dev_err_probe(&pdev->dev, ret,
> > > "failed to register controller\n");
> > >
> > > - spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> > > + /*
> > > + * On i.MX8M platforms with multiple SPBA buses, we need to find
> > > + * the SPBA bus that's under the same AIPS bus as this SDMA controller.
> > > + * First check the SDMA's parent (AIPS bus) for a child SPBA bus.
> > > + * If not found, fall back to searching the entire device tree for
> > > + * backward compatibility with older platforms.
> > > + */
> > > + struct device_node *sdma_parent_np __free(device_node) = of_get_parent(np);
> > > +
> > > + spba_bus = of_get_compatible_child(sdma_parent_np, "fsl,spba-bus");
> > > + if (!spba_bus)
> > > + spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> >
> > And yet the search is still broken for i.MX8MP case since this platform
> > has two sdma engines below the bus@30df0000.
>
> I tested on i.MX8MP. It works. Above line is for backward compatibility
>
> The search has no dependence on the number of sdma engines. It searches the
> spba-bus, not the sdma node. it will find the aips5 first, then find
> the spba-bus for
> sdma2 and sdma3.
And you're abosulte certain that NXP doesn't introduce a 2nd SPBA bus
below the same AIPS in which case the driver is broken again?
Sorry for beeing a bit picky. I do see that NXP decided to drop the SDMA
for i.MX9, at least I don't find any reference in which case I'm fine
with the patch.
Regards,
Marco
>
> aips5: bus@30df0000 {
> spba-bus@30c00000 {
> }
> sdma2: dma-controller@30e10000 {
> }
> sdma3: dma-controller@30e00000 {
> }
> }
>
> Best regards
> Shengjiu Wang
>
> >
> > Regards,
> > Marco
> >
> > > ret = of_address_to_resource(spba_bus, 0, &spba_res);
> > > if (!ret) {
> > > sdma->spba_start_addr = spba_res.start;
> > > --
> > > 2.34.1
> > >
> > >
> > >
> >
> > --
> > #gernperDu
> > #CallMeByMyFirstName
> >
> > Pengutronix e.K. | |
> > Steuerwalder Str. 21 | https://www.pengutronix.de/ |
> > 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> > Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
> >
>
--
#gernperDu
#CallMeByMyFirstName
Pengutronix e.K. | |
Steuerwalder Str. 21 | https://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
^ permalink raw reply
* Re: [RFC PATCH 1/4] security: ima: move ima_init into late_initcall_sync
From: Yeoreum Yun @ 2026-04-21 9:37 UTC (permalink / raw)
To: Jonathan McDowell
Cc: linux-security-module, linux-kernel, linux-integrity,
linux-arm-kernel, kvmarm, paul, jmorris, serge, zohar,
roberto.sassu, dmitry.kasatkin, eric.snowberg, peterhuewe, jarkko,
jgg, sudeep.holla, maz, oupton, joey.gouly, suzuki.poulose,
yuzenghui, catalin.marinas, will
In-Reply-To: <aeYA2Jf7esHsfY4M@earth.li>
On Mon, Apr 20, 2026 at 11:32:56AM +0100, Jonathan McDowell wrote:
> On Fri, Apr 17, 2026 at 06:57:56PM +0100, Yeoreum Yun wrote:
> > To generate the boot_aggregate log in the IMA subsystem with TPM PCR values,
> > the TPM driver must be built as built-in and
> > must be probed before the IMA subsystem is initialized.
> >
> > However, when the TPM device operates over the FF-A protocol using
> > the CRB interface, probing fails and returns -EPROBE_DEFER if
> > the tpm_crb_ffa device — an FF-A device that provides the communication
> > interface to the tpm_crb driver — has not yet been probed.
> >
> > To ensure the TPM device operating over the FF-A protocol with
> > the CRB interface is probed before IMA initialization,
> > the following conditions must be met:
> >
> > 1. The corresponding ffa_device must be registered,
> > which is done via ffa_init().
> >
> > 2. The tpm_crb_driver must successfully probe this device via
> > tpm_crb_ffa_init().
> >
> > 3. The tpm_crb driver using CRB over FF-A can then
> > be probed successfully. (See crb_acpi_add() and
> > tpm_crb_ffa_init() for reference.)
> >
> > Unfortunately, ffa_init(), tpm_crb_ffa_init(), and crb_acpi_driver_init() are
> > all registered with device_initcall, which means crb_acpi_driver_init() may
> > be invoked before ffa_init() and tpm_crb_ffa_init() are completed.
> >
> > When this occurs, probing the TPM device is deferred.
> > However, the deferred probe can happen after the IMA subsystem
> > has already been initialized, since IMA initialization is performed
> > during late_initcall, and deferred_probe_initcall() is performed
> > at the same level.
> >
> > To resolve this, move ima_init() into late_inicall_sync level
> > so that let IMA not miss TPM PCR value when generating boot_aggregate
> > log though TPM device presents in the system.
> >
> > Signed-off-by: Yeoreum Yun <yeoreum.yun@arm.com>
>
> Awesome. This fixes the problems I saw with an SPI TPM on an NVIDIA GB200
> system and reported in
>
> https://lore.kernel.org/linux-integrity/aYXEepLhUouN5f99@earth.li/
>
> Reviewed-by: Jonathan McDowell <noodles@meta.com>
> Tested-by: Jonathan McDowell <noodles@meta.com>
Thanks!
>
> > ---
> > include/linux/lsm_hooks.h | 2 ++
> > security/integrity/ima/ima_main.c | 2 +-
> > security/lsm_init.c | 13 +++++++++++--
> > 3 files changed, 14 insertions(+), 3 deletions(-)
> >
> > diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
> > index d48bf0ad26f4..88fe105b7f00 100644
> > --- a/include/linux/lsm_hooks.h
> > +++ b/include/linux/lsm_hooks.h
> > @@ -166,6 +166,7 @@ enum lsm_order {
> > * @initcall_fs: LSM callback for fs_initcall setup, optional
> > * @initcall_device: LSM callback for device_initcall() setup, optional
> > * @initcall_late: LSM callback for late_initcall() setup, optional
> > + * @initcall_late_sync: LSM callback for late_initcall_sync() setup, optional
> > */
> > struct lsm_info {
> > const struct lsm_id *id;
> > @@ -181,6 +182,7 @@ struct lsm_info {
> > int (*initcall_fs)(void);
> > int (*initcall_device)(void);
> > int (*initcall_late)(void);
> > + int (*initcall_late_sync)(void);
> > };
> >
> > #define DEFINE_LSM(lsm) \
> > diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
> > index 1d6229b156fb..ace280fa3212 100644
> > --- a/security/integrity/ima/ima_main.c
> > +++ b/security/integrity/ima/ima_main.c
> > @@ -1320,5 +1320,5 @@ DEFINE_LSM(ima) = {
> > .order = LSM_ORDER_LAST,
> > .blobs = &ima_blob_sizes,
> > /* Start IMA after the TPM is available */
> > - .initcall_late = init_ima,
> > + .initcall_late_sync = init_ima,
> > };
> > diff --git a/security/lsm_init.c b/security/lsm_init.c
> > index 573e2a7250c4..4e5c59beb82a 100644
> > --- a/security/lsm_init.c
> > +++ b/security/lsm_init.c
> > @@ -547,13 +547,22 @@ device_initcall(security_initcall_device);
> > * security_initcall_late - Run the LSM late initcalls
> > */
> > static int __init security_initcall_late(void)
> > +{
> > + return lsm_initcall(late);
> > +}
> > +late_initcall(security_initcall_late);
> > +
> > +/**
> > + * security_initcall_late_sync - Run the LSM late initcalls sync
> > + */
> > +static int __init security_initcall_late_sync(void)
> > {
> > int rc;
> >
> > - rc = lsm_initcall(late);
> > + rc = lsm_initcall(late_sync);
> > lsm_pr_dbg("all enabled LSMs fully activated\n");
> > call_blocking_lsm_notifier(LSM_STARTED_ALL, NULL);
> >
> > return rc;
> > }
> > -late_initcall(security_initcall_late);
> > +late_initcall_sync(security_initcall_late_sync);
> > --
> > LEVI:{C3F47F37-75D8-414A-A8BA-3980EC8A46D7}
> >
> >
>
> J.
>
> --
> ] https://www.earth.li/~noodles/ [] "Do I scare you?" "No." "Do you [
> ] PGP/GPG Key @ the.earth.li [] want me to?" -- Wayne's World. [
> ] via keyserver, web or email. [] [
> ] RSA: 4096/0x94FA372B2DA8B985 [] [
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH v5 02/12] coresight: etm4x: fix underflow for nrseqstate
From: Yeoreum Yun @ 2026-04-21 9:37 UTC (permalink / raw)
To: Suzuki K Poulose
Cc: Leo Yan, coresight, linux-arm-kernel, linux-kernel, mike.leach,
james.clark, alexander.shishkin, jie.gan
In-Reply-To: <fdfd353d-f198-4806-81d2-61f26b678dea@arm.com>
Hi Suzuki,
> On 16/04/2026 16:11, Leo Yan wrote:
> > On Wed, Apr 15, 2026 at 05:55:18PM +0100, Yeoreum Yun wrote:
> > > TCRSEQEVR<n> is implemented only when TCRIDR5.NUMSEQSTATE is 0b100,
> > > in which case n ranges from 0 to 2; otherwise, TCRIDR5.NUMSEQSTATE is 0b000.
> >
> > My suggestion in previous version is not quite right, thanks for
> > making this correct.
> >
> > [...]
> >
> > > @@ -1395,6 +1395,8 @@ static ssize_t seq_idx_store(struct device *dev,
> > > struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
> > > struct etmv4_config *config = &drvdata->config;
> > > + if (!drvdata->nrseqstate)
> > > + return -EINVAL;
> >
> > For "nrseqstate = 0" case, would it return -EOPNOTSUPP instead?
>
> Or should we make this only visible if the nrseqstore is meaningful ?
We could by chanige the attributes permission and nullify the store
operation for that device attributes.
Not only this, we can apply similar approach to other sysfs entries too:
- vinst_pe_cmp_start_stop_store (when nr_pe_cmp == 0)
- seq_event_reset_store (when nrseqstate == 0)
- ctxid_pid_store (when !caps->ctxid_size || !caps->numcidc)
- ctxid_masks_store (when !caps->ctxid_size || !caps->numcidc)
and others..
Would you like to include those changes in this patchset?
I think it would be better to send seperate patchset..
Thanks!
--
Sincerely,
Yeoreum Yun
^ permalink raw reply
* Re: [PATCH v5 2/4] thermal: qoriq: add i.MX93 tmu support
From: Daniel Baluta @ 2026-04-21 9:17 UTC (permalink / raw)
To: Jacky Bai, Rafael J. Wysocki, Daniel Lezcano, Zhang Rui,
Lukasz Luba, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
Shawn Guo, Sascha Hauer, Fabio Estevam, Pengutronix Kernel Team,
Frank Li
Cc: linux-pm, devicetree, imx, linux-arm-kernel, Alice Guo
In-Reply-To: <20260421-imx93_tmu-v5-2-05ea1969bb9f@nxp.com>
On 4/21/26 10:42, Jacky Bai wrote:
> For Thermal monitor unit(TMU) used on i.MX93, the HW revision info read
> from the ID register is the same the one used on some of the QorIQ
> platform, but the config has some slight differance. Add i.MX93 compatible
> string and corresponding code for it.
>
> Signed-off-by: Alice Guo <alice.guo@nxp.com>
> Reviewed-by: Frank Li <Frank.Li@nxp.com>
> Signed-off-by: Jacky Bai <ping.bai@nxp.com>
> ---
> - v5 changes:
> - drop the unnecessary GET_TEUMR0 helper macro
> - add drvdata for each of the platforms
>
> - v4 changes:
> - no
>
> - v3 changes:
> - use the drv data struct for match data and refine the code
> - update the copyright
>
> - v2 changes:
> - use the compatible match data to identify the i.MX93 TMU variant
> ---
> drivers/thermal/qoriq_thermal.c | 33 ++++++++++++++++++++++++++++++---
> 1 file changed, 30 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/thermal/qoriq_thermal.c b/drivers/thermal/qoriq_thermal.c
> index 01b58be0dcc64d14ca5e4bba654eed8f15e827fc..297a855311f3d6a8d527794abe17ac86c47bf152 100644
> --- a/drivers/thermal/qoriq_thermal.c
> +++ b/drivers/thermal/qoriq_thermal.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0
> //
> // Copyright 2016 Freescale Semiconductor, Inc.
> +// Copyright 2025 NXP
>
> #include <linux/clk.h>
> #include <linux/err.h>
> @@ -24,6 +25,7 @@
> #define TMTMIR_DEFAULT 0x0000000f
> #define TIER_DISABLE 0x0
> #define TEUMR0_V2 0x51009c00
> +#define TEUMR0_V21 0x55000c00
> #define TMSARA_V2 0xe
> #define TMU_VER1 0x1
> #define TMU_VER2 0x2
> @@ -73,12 +75,17 @@ struct qoriq_sensor {
> int id;
> };
>
> +struct tmu_drvdata {
> + u32 teumr0;
> +};
> +
> struct qoriq_tmu_data {
> int ver;
> u32 ttrcr[NUM_TTRCR_MAX];
> struct regmap *regmap;
> struct clk *clk;
> struct qoriq_sensor sensor[SITES_MAX];
> + const struct tmu_drvdata *drvdata;
> };
>
> static struct qoriq_tmu_data *qoriq_sensor_to_data(struct qoriq_sensor *s)
> @@ -225,6 +232,8 @@ static int qoriq_tmu_calibration(struct device *dev,
>
> static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
> {
> + u32 teumr0_val;
No need for this here you can just use directly: data->drvdata->teumr0
> +
> /* Disable interrupt, using polling instead */
> regmap_write(data->regmap, REGS_TIER, TIER_DISABLE);
>
> @@ -234,7 +243,8 @@ static void qoriq_tmu_init_device(struct qoriq_tmu_data *data)
> regmap_write(data->regmap, REGS_TMTMIR, TMTMIR_DEFAULT);
> } else {
> regmap_write(data->regmap, REGS_V2_TMTMIR, TMTMIR_DEFAULT);
> - regmap_write(data->regmap, REGS_V2_TEUMR(0), TEUMR0_V2);
> + teumr0_val = data->drvdata->teumr0;
> + regmap_write(data->regmap, REGS_V2_TEUMR(0), teumr0_val);
> }
^ permalink raw reply
* Re: [PATCH V3] dmaengine: imx-sdma: Fix SPBA bus detection on multi-SPBA platforms
From: Shengjiu Wang @ 2026-04-21 9:13 UTC (permalink / raw)
To: Marco Felsch
Cc: Shengjiu Wang, vkoul, Frank.Li, s.hauer, kernel, festevam,
dmaengine, imx, linux-arm-kernel, linux-kernel
In-Reply-To: <lkwfzz4lia37wv56g6ymzpossm42epz2oylhl7vgdpp7odt23h@vszl4uu2wg65>
On Tue, Apr 21, 2026 at 4:57 PM Marco Felsch <m.felsch@pengutronix.de> wrote:
>
> On 26-04-20, Shengjiu Wang wrote:
> > i.MX8M platforms have multiple SPBA buses under different AIPS buses.
> > The current code searches the entire device tree and returns the first
> > SPBA bus found, which may not be under the same AIPS bus as the SDMA
> > controller.
> >
> > This breaks SDMA P2P transfers because the SDMA script needs to know
> > if peripherals are on SPBA or AIPS to configure watermark levels
> > correctly. Using the wrong SPBA bus causes DMA timeouts and transfer
> > failures.
> >
> > Fix by searching for the SPBA bus under the SDMA's parent node (AIPS)
> > first, then falling back to a global search for backward compatibility.
> >
> > Example device tree showing the issue:
> > aips1 {
> > spba1 { sai@...; }; /* Correct SPBA for sdma1 */
> > sdma1@...;
> > };
> > aips2 {
> > spba2 { uart@...; }; /* Wrong SPBA - found first by old code */
> > };
> >
> > Fixes: 8391ecf465ec ("dmaengine: imx-sdma: Add device to device support")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > ---
> > changs in v3:
> > - add fallback to a global search for backward compatibility, which is
> > to address comments from sashiko.dev
> > - update commit subject and commit message
> > - add comments in code.
> > - add Cc stable tag
> > - Don't add Frank's RB on v2 as there are several other changes.
> >
> > changes in v2:
> > - add fixes tag
> > - use __free(device_node) for auto release.
> >
> > drivers/dma/imx-sdma.c | 13 ++++++++++++-
> > 1 file changed, 12 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
> > index 3d527883776b..592705af2319 100644
> > --- a/drivers/dma/imx-sdma.c
> > +++ b/drivers/dma/imx-sdma.c
> > @@ -2364,7 +2364,18 @@ static int sdma_probe(struct platform_device *pdev)
> > return dev_err_probe(&pdev->dev, ret,
> > "failed to register controller\n");
> >
> > - spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
> > + /*
> > + * On i.MX8M platforms with multiple SPBA buses, we need to find
> > + * the SPBA bus that's under the same AIPS bus as this SDMA controller.
> > + * First check the SDMA's parent (AIPS bus) for a child SPBA bus.
> > + * If not found, fall back to searching the entire device tree for
> > + * backward compatibility with older platforms.
> > + */
> > + struct device_node *sdma_parent_np __free(device_node) = of_get_parent(np);
> > +
> > + spba_bus = of_get_compatible_child(sdma_parent_np, "fsl,spba-bus");
> > + if (!spba_bus)
> > + spba_bus = of_find_compatible_node(NULL, NULL, "fsl,spba-bus");
>
> And yet the search is still broken for i.MX8MP case since this platform
> has two sdma engines below the bus@30df0000.
I tested on i.MX8MP. It works. Above line is for backward compatibility
The search has no dependence on the number of sdma engines. It searches the
spba-bus, not the sdma node. it will find the aips5 first, then find
the spba-bus for
sdma2 and sdma3.
aips5: bus@30df0000 {
spba-bus@30c00000 {
}
sdma2: dma-controller@30e10000 {
}
sdma3: dma-controller@30e00000 {
}
}
Best regards
Shengjiu Wang
>
> Regards,
> Marco
>
> > ret = of_address_to_resource(spba_bus, 0, &spba_res);
> > if (!ret) {
> > sdma->spba_start_addr = spba_res.start;
> > --
> > 2.34.1
> >
> >
> >
>
> --
> #gernperDu
> #CallMeByMyFirstName
>
> Pengutronix e.K. | |
> Steuerwalder Str. 21 | https://www.pengutronix.de/ |
> 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
> Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 |
>
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox