From: Magnus Lindholm <linmag7@gmail.com>
To: davem@davemloft.net, andreas@gaisler.com
Cc: sam@ravnborg.org, sparclinux@vger.kernel.org,
linux-kernel@vger.kernel.org, Magnus Lindholm <linmag7@gmail.com>
Subject: [PATCH 1/2] sparc32: serialize SuperSPARC demap operations
Date: Fri, 4 Sep 2026 07:53:05 +0200 [thread overview]
Message-ID: <20260904055359.327050-2-linmag7@gmail.com> (raw)
In-Reply-To: <20260904055359.327050-1-linmag7@gmail.com>
SuperSPARC requires software to guarantee that only one Demap operation
is in progress across the system. On MBus, each processor which may
retain a stale translation must perform its own local Demap.
A lock around each local operation is not safe on sun4m. Cross-call
callbacks run at interrupt level 15, so they can interrupt a CPU even
while spin_lock_irqsave() protects its local Demap. If the callback then
takes the same lock, it deadlocks against the interrupted owner.
Serialize each complete shootdown at the initiating CPU instead. Invoke
remote CPUs one at a time with lock-free callbacks, perform the
initiator's local Demap last, and release the lock only after the entire
operation is complete.
sun4m_cross_call() waits for the target CPU to complete its callback.
Singleton cross-calls therefore serialize the actual Demap operations,
not merely their dispatch.
sun4d already serializes Viking TLB flushes around its broadcast Demap
operations, so this wrapper is needed only for sun4m.
This is independent of MBus cache coherence. MBus Level 2 and the MXCC
coherence protocol describe physical cache-block transactions; they do
not make an MBus peer discard a virtual TLB entry.
This follows SuperSPARC Family User's Manual sections 8.5.3 and 9.8.2;
Sun-4M System Architecture section 7.1.4; MBus Interface Specification,
Level 2 Overview; and MXCC Addendum section B.2, Multiprocessor Cache
Coherence Support.
Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
---
arch/sparc/mm/srmmu.c | 88 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 88 insertions(+)
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c
index 1b24c5e8d73d..3b87e6f53fca 100644
--- a/arch/sparc/mm/srmmu.c
+++ b/arch/sparc/mm/srmmu.c
@@ -1642,6 +1642,33 @@ static void smp_flush_tlb_all(void)
local_ops->tlb_all();
}
+/* Serialize complete sun4m Viking shootdowns; remote callbacks must not lock. */
+static DEFINE_SPINLOCK(viking_tlb_lock);
+
+static void smp_viking_flush_tlb_xcall(void *func, unsigned long arg1,
+ unsigned long arg2,
+ unsigned long arg3)
+{
+ int cpu;
+
+ for_each_online_cpu(cpu) {
+ if (cpu == smp_processor_id())
+ continue;
+ sparc32_ipi_ops->cross_call(func, *cpumask_of(cpu),
+ arg1, arg2, arg3, 0);
+ }
+}
+
+static void smp_viking_flush_tlb_all(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&viking_tlb_lock, flags);
+ smp_viking_flush_tlb_xcall(local_ops->tlb_all, 0, 0, 0);
+ local_ops->tlb_all();
+ spin_unlock_irqrestore(&viking_tlb_lock, flags);
+}
+
static bool any_other_mm_cpus(struct mm_struct *mm)
{
return cpumask_any_but(mm_cpumask(mm), smp_processor_id()) < nr_cpu_ids;
@@ -1669,6 +1696,25 @@ static void smp_flush_tlb_mm(struct mm_struct *mm)
}
}
+static void smp_viking_flush_tlb_mm(struct mm_struct *mm)
+{
+ unsigned long flags;
+
+ if (mm->context != NO_CONTEXT) {
+ spin_lock_irqsave(&viking_tlb_lock, flags);
+ if (any_other_mm_cpus(mm)) {
+ smp_viking_flush_tlb_xcall(local_ops->tlb_mm,
+ (unsigned long)mm, 0, 0);
+ if (atomic_read(&mm->mm_users) == 1 &&
+ current->active_mm == mm)
+ cpumask_copy(mm_cpumask(mm),
+ cpumask_of(smp_processor_id()));
+ }
+ local_ops->tlb_mm(mm);
+ spin_unlock_irqrestore(&viking_tlb_lock, flags);
+ }
+}
+
static void smp_flush_cache_range(struct vm_area_struct *vma,
unsigned long start,
unsigned long end)
@@ -1697,6 +1743,24 @@ static void smp_flush_tlb_range(struct vm_area_struct *vma,
}
}
+static void smp_viking_flush_tlb_range(struct vm_area_struct *vma,
+ unsigned long start,
+ unsigned long end)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long flags;
+
+ if (mm->context != NO_CONTEXT) {
+ spin_lock_irqsave(&viking_tlb_lock, flags);
+ if (any_other_mm_cpus(mm))
+ smp_viking_flush_tlb_xcall(local_ops->tlb_range,
+ (unsigned long)vma,
+ start, end);
+ local_ops->tlb_range(vma, start, end);
+ spin_unlock_irqrestore(&viking_tlb_lock, flags);
+ }
+}
+
static void smp_flush_cache_page(struct vm_area_struct *vma, unsigned long page)
{
struct mm_struct *mm = vma->vm_mm;
@@ -1719,6 +1783,23 @@ static void smp_flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
}
}
+static void smp_viking_flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long page)
+{
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long flags;
+
+ if (mm->context != NO_CONTEXT) {
+ spin_lock_irqsave(&viking_tlb_lock, flags);
+ if (any_other_mm_cpus(mm))
+ smp_viking_flush_tlb_xcall(local_ops->tlb_page,
+ (unsigned long)vma,
+ page, 0);
+ local_ops->tlb_page(vma, page);
+ spin_unlock_irqrestore(&viking_tlb_lock, flags);
+ }
+}
+
static void smp_flush_page_to_ram(unsigned long page)
{
/* Current theory is that those who call this are the one's
@@ -1773,6 +1854,13 @@ void __init load_mmu(void)
}
if (poke_srmmu == poke_viking) {
+ if (sparc_cpu_model == sun4m) {
+ smp_cachetlb_ops.tlb_all = smp_viking_flush_tlb_all;
+ smp_cachetlb_ops.tlb_mm = smp_viking_flush_tlb_mm;
+ smp_cachetlb_ops.tlb_range = smp_viking_flush_tlb_range;
+ smp_cachetlb_ops.tlb_page = smp_viking_flush_tlb_page;
+ }
+
/* Avoid unnecessary cross calls. */
smp_cachetlb_ops.cache_all = local_ops->cache_all;
smp_cachetlb_ops.cache_mm = local_ops->cache_mm;
--
2.43.0
next prev parent reply other threads:[~2026-09-04 5:54 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-04 5:53 [PATCH 0/2] sparc32: fix SuperSPARC SMP synchronization Magnus Lindholm
2026-09-04 5:53 ` Magnus Lindholm [this message]
2026-09-04 5:53 ` [PATCH 2/2] sparc32: synchronize SuperSPARC instruction updates Magnus Lindholm
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260904055359.327050-2-linmag7@gmail.com \
--to=linmag7@gmail.com \
--cc=andreas@gaisler.com \
--cc=davem@davemloft.net \
--cc=linux-kernel@vger.kernel.org \
--cc=sam@ravnborg.org \
--cc=sparclinux@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®