[RFC 3/6] powerpc/mm/book3s64: Rework native_flush_hash_range() to remove conditional locking
From: Ritesh Harjani (IBM)
Date: Mon Sep 28 2026 - 06:45:50 EST
Clang's context analysis reports:
hash_native.c:851:2: error: raw_spinlock 'native_tlbie_lock' is not held on every path through here [-Werror,-Wthread-safety-analysis]
hash_native.c:868:3: error: releasing raw_spinlock 'native_tlbie_lock' that was not held [-Werror,-Wthread-safety-analysis]
This patch reworks the native_flush_hash_range() function to remove the
conditional locking. It fixes the clang context analysis reported
errors. However, this also simplifies the code in native_flush_hash_range()
due to various if conditions.
No functional change intended.
Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@xxxxxxxxx>
---
arch/powerpc/mm/book3s64/hash_native.c | 88 ++++++++++++++++----------
1 file changed, 54 insertions(+), 34 deletions(-)
diff --git a/arch/powerpc/mm/book3s64/hash_native.c b/arch/powerpc/mm/book3s64/hash_native.c
index 6bad0545b57a..9b4eea35b540 100644
--- a/arch/powerpc/mm/book3s64/hash_native.c
+++ b/arch/powerpc/mm/book3s64/hash_native.c
@@ -792,6 +792,54 @@ static notrace void native_hpte_clear(void)
asm volatile("eieio; tlbsync; ptesync":::"memory");
}
+static void native_flush_hash_range_tlbiel(struct ppc64_tlb_batch *batch,
+ unsigned long number)
+{
+ unsigned long vpn = 0, index, shift;
+ real_pte_t pte;
+ unsigned long psize = batch->psize;
+ int ssize = batch->ssize;
+ unsigned long i;
+
+ asm volatile("ptesync":::"memory");
+ for (i = 0; i < number; i++) {
+ vpn = batch->vpn[i];
+ pte = batch->pte[i];
+
+ pte_iterate_hashed_subpages(pte, psize,
+ vpn, index, shift) {
+ __tlbiel(vpn, psize, psize, ssize);
+ } pte_iterate_hashed_end();
+ }
+ ppc_after_tlbiel_barrier();
+}
+
+static void native_flush_hash_range_tlbie(struct ppc64_tlb_batch *batch,
+ unsigned long number)
+{
+ unsigned long vpn = 0, index, shift;
+ real_pte_t pte;
+ unsigned long psize = batch->psize;
+ int ssize = batch->ssize;
+ unsigned long i;
+
+ asm volatile("ptesync":::"memory");
+ for (i = 0; i < number; i++) {
+ vpn = batch->vpn[i];
+ pte = batch->pte[i];
+
+ pte_iterate_hashed_subpages(pte, psize,
+ vpn, index, shift) {
+ __tlbie(vpn, psize, psize, ssize);
+ } pte_iterate_hashed_end();
+ }
+ /*
+ * Just do one more with the last used values.
+ */
+ fixup_tlbie_vpn(vpn, psize, psize, ssize);
+ asm volatile("eieio; tlbsync; ptesync":::"memory");
+}
+
/*
* Batched hash table flush, we batch the tlbie's to avoid taking/releasing
* the lock all the time
@@ -845,41 +893,13 @@ static void native_flush_hash_range(unsigned long number, int local)
if (mmu_has_feature(MMU_FTR_TLBIEL) &&
mmu_psize_defs[psize].tlbiel && local) {
- asm volatile("ptesync":::"memory");
- for (i = 0; i < number; i++) {
- vpn = batch->vpn[i];
- pte = batch->pte[i];
-
- pte_iterate_hashed_subpages(pte, psize,
- vpn, index, shift) {
- __tlbiel(vpn, psize, psize, ssize);
- } pte_iterate_hashed_end();
- }
- ppc_after_tlbiel_barrier();
+ native_flush_hash_range_tlbiel(batch, number);
+ } else if (!mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE)) {
+ raw_spin_lock(&native_tlbie_lock);
+ native_flush_hash_range_tlbie(batch, number);
+ raw_spin_unlock(&native_tlbie_lock);
} else {
- int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
-
- if (lock_tlbie)
- raw_spin_lock(&native_tlbie_lock);
-
- asm volatile("ptesync":::"memory");
- for (i = 0; i < number; i++) {
- vpn = batch->vpn[i];
- pte = batch->pte[i];
-
- pte_iterate_hashed_subpages(pte, psize,
- vpn, index, shift) {
- __tlbie(vpn, psize, psize, ssize);
- } pte_iterate_hashed_end();
- }
- /*
- * Just do one more with the last used values.
- */
- fixup_tlbie_vpn(vpn, psize, psize, ssize);
- asm volatile("eieio; tlbsync; ptesync":::"memory");
-
- if (lock_tlbie)
- raw_spin_unlock(&native_tlbie_lock);
+ native_flush_hash_range_tlbie(batch, number);
}
local_irq_restore(flags);
--
2.39.5