From nobody Tue Oct 13 19:50:42 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4j44h81mf2z6w5Vr for ; Tue, 13 Oct 2026 19:50:48 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange x25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4j44h74rscz4Gsp for ; Tue, 13 Oct 2026 19:50:47 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791921047; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4nt0oYEsuBuMOK0c7xf/DG4OteIiqVCE0xmP1Ox8NoI=; b=Vi3UC+LhEUAAzLy3YS5BX0Dg8E8SeBJ1JSOrf2rWMZZKeFw0HDUl3QVmqr35W0ITHhLBvw sX4u/sbik6GULGWvNN7m6u+r8WEgh5PeHe1HaDHpj1iE/JDd7Z1vdP0tgDFFL/0MWaXRQh ckO58YI0mAmnLXt3gkdCImBHUa6L2Vhe2UGX3Vfcif1JJtUDn2HrDFAcwcHaw1Zwny/Tmu 3MVAbxqJ4uAOekVnoeM8zGlCP6j8lsyxgZp5fTjo6YzZVRH+561EZ/ov5iaYg5n7Qn5NWK EfwM8hm5yNz+VG/wCDkdUmXU8IsdmNRUb9MJfC2tnbWcXEIORnpn8Orvd85y8g== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1791921047; b=dzbc6MUexyzv6ABU3tUybxbYn3ec31Pfpu10VWlOHK9q6MzxnROS/tNTAV6uO6KE7Sc+Jd Dh73u6z/9b6jf7lrFvmCpdzFMgYYyU8U82cOvmy+aX5DZ9JkikflXOrA81kYGNFEfrKVAI rgdcaGFrOqYoyf4wS4UWLf94belkfAOuMVhXdb0tdONTW6cn1yS7E9pZeL1ieRHjaa+/Dv 2LR7fboXUsTmFEmast4tHuG88RDMPX3GLSHsTAs2/f8cWWaihvc5JTL0k8bS1WCIhgOS+Z tIg/z1YiNThW62Tr5W8OUm++ZrPwWZYFnDQ1GaFTIHFJtcOKcE2qO5BVwpVGpA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1791921047; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=4nt0oYEsuBuMOK0c7xf/DG4OteIiqVCE0xmP1Ox8NoI=; b=xq2JGGs94SoHiXkKL44EDGg/VuFCjdFGQo7ExRlvLfRJQj8fow9kK/RU+xdU9HrL4Ds3Wn WST35k/JOfMk8lQet98tYOSe5HqdnBDRD/V8D6A/ckMrJtnXNZrvcOmuOU1t1qo00NbGSS NjrlJy31SFqU2AW+hr1ixskxpF550+zI8ZjLGsF5Y5UoXZNnKkU6JIvQPhN5yv9W5U4FsW 5OOFjRUKLPTcC7OTixItAnG7Pu0gTq3eHTjgM0N/csJctmwXOx60qFERT06zayRCAmJlqu gk6YtWwypmmbGaH6iuNHVPfLQ3E9hti8/dQCGzXzsnvObUEgm7Z8pLs9Br9BSw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4j44h72pbczT0J for ; Tue, 13 Oct 2026 19:50:47 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 44d20 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Tue, 13 Oct 2026 19:50:42 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Minsoo Choo Subject: git: 0571d8a0cc60 - main - powerpc: Avoid deadlock when CPUs exchange threads List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: Commit messages for all branches of the src repository List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: mchoo X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0571d8a0cc606be9a216439b3cfea685b709d6ea Auto-Submitted: auto-generated Date: Tue, 13 Oct 2026 19:50:42 +0000 Message-Id: <6ace8b92.44d20.7699f3ce@gitrepo.freebsd.org> The branch main has been updated by mchoo: URL: https://cgit.FreeBSD.org/src/commit/?id=0571d8a0cc606be9a216439b3cfea685b709d6ea commit 0571d8a0cc606be9a216439b3cfea685b709d6ea Author: Minsoo Choo AuthorDate: 2026-09-16 19:37:01 +0000 Commit: Minsoo Choo CommitDate: 2026-10-13 19:48:22 +0000 powerpc: Avoid deadlock when CPUs exchange threads The PowerPC context switch waited for the incoming thread to leave blocked_lock before releasing the outgoing thread. If two CPUs selected each other's running threads concurrently, both CPUs waited for the other to perform the release and neither could progress. This appeared as intermittent boot hangs under QEMU MTTCG when taskqueue threads were bound to opposite CPUs. 8df2e5421468 ("powerpc: put the isync inside the TD_LOCK()...") attempted to fix the same hang by moving isync into the polling loop. That did not address the circular wait: isync cannot cause either CPU to execute the release store after the loop. It only added context synchronization to failed iterations and changed timing. Move isync back to the successful exit, which preserves acquire ordering for subsequent context loads. Match the ordering used by other architectures: publish the outgoing thread's new lock before waiting for the incoming thread. Apply the correction to both 32-bit and 64-bit switch paths. The 2015 change moved the release after the stack switch because the old implementation continued through pmap_activate() and optional state restoration on the outgoing thread's stack after making that thread runnable. The switch path has since changed: after the release it only polls wired td_lock state using registers, then immediately loads the incoming PCB_SP before updating per-CPU state or making any calls. cpu_switch() also runs with external and decrementer interrupts disabled by spinlock_enter(). Thus this does not restore the post-release call window that the 2015 change corrected. Reviewed by: jhb, jhibbits Approved by: jhb (mentor) Fixes: 53607fe3cc8d ("Fix an extremely subtle concurrency bug...") Fixes: 7a49d964d3f9 ("Merge r278429 from ppc64:") Fixes: 8df2e5421468 ("powerpc: put the isync inside the TD_LOCK()...") MFC after: 2 weeks Sponsored by: FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D59742 --- sys/powerpc/powerpc/swtch32.S | 18 +++++++++++------- sys/powerpc/powerpc/swtch64.S | 18 +++++++++++------- 2 files changed, 22 insertions(+), 14 deletions(-) diff --git a/sys/powerpc/powerpc/swtch32.S b/sys/powerpc/powerpc/swtch32.S index 262e7035bb29..40b89f98ea56 100644 --- a/sys/powerpc/powerpc/swtch32.S +++ b/sys/powerpc/powerpc/swtch32.S @@ -124,6 +124,15 @@ ENTRY(cpu_switch) sync /* Make sure all of that finished */ cpu_switchin: + /* + * Release the old thread before waiting for the new one. Two CPUs + * may exchange threads, so waiting first would leave each CPU waiting + * for the other to perform this store. + */ + cmpwi %r14,0 + beq- 1f + stw %r16,TD_LOCK(%r14) /* ULE: update old thread's lock */ +1: #if defined(SMP) /* Wait for the new thread to become unblocked */ bl 1f @@ -136,19 +145,14 @@ cpu_switchin: blocked_loop: lwz %r7,TD_LOCK(%r2) cmpw %r6,%r7 - isync beq- blocked_loop + isync /* Acquire thread state. */ #endif lwz %r17,TD_PCB(%r2) /* Get new current PCB */ lwz %r1,PCB_SP(%r17) /* Load new stack pointer */ - /* Release old thread now that we have a stack pointer set up */ - cmpwi %r14,0 - beq- 1f - stw %r16,TD_LOCK(%r14) /* ULE: update old thread's lock */ - -1: mfsprg %r7,0 /* Get the pcpu pointer */ + mfsprg %r7,0 /* Get the pcpu pointer */ stw %r2,PC_CURTHREAD(%r7) /* Store new current thread */ lwz %r17,TD_PCB(%r2) /* Store new current PCB */ stw %r17,PC_CURPCB(%r7) diff --git a/sys/powerpc/powerpc/swtch64.S b/sys/powerpc/powerpc/swtch64.S index 61af10aabaee..bd3e0a0dd687 100644 --- a/sys/powerpc/powerpc/swtch64.S +++ b/sys/powerpc/powerpc/swtch64.S @@ -186,6 +186,15 @@ save_tar: sync /* Make sure all of that finished */ cpu_switchin: + /* + * Release the old thread before waiting for the new one. Two CPUs + * may exchange threads, so waiting first would leave each CPU waiting + * for the other to perform this store. + */ + cmpdi %r14,0 + beq- 1f + std %r16,TD_LOCK(%r14) /* ULE: update old thread's lock */ +1: #if defined(SMP) /* Wait for the new thread to become unblocked */ addis %r6,%r2,TOC_REF(blocked_lock)@ha @@ -193,20 +202,15 @@ cpu_switchin: blocked_loop: ld %r7,TD_LOCK(%r13) cmpd %r6,%r7 - isync beq- blocked_loop + isync /* Acquire thread state. */ #endif ld %r17,TD_PCB(%r13) /* Get new PCB */ ld %r1,PCB_SP(%r17) /* Load the stack pointer */ addi %r1,%r1,-48 /* Remember about cpu_switch stack frame */ - /* Release old thread now that we have a stack pointer set up */ - cmpdi %r14,0 - beq- 1f - std %r16,TD_LOCK(%r14) /* ULE: update old thread's lock */ - -1: mfsprg %r7,0 /* Get the pcpu pointer */ + mfsprg %r7,0 /* Get the pcpu pointer */ std %r13,PC_CURTHREAD(%r7) /* Store new current thread */ ld %r17,TD_PCB(%r13) /* Store new current PCB */ std %r17,PC_CURPCB(%r7)