From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from smtpbguseast3.qq.com (smtpbguseast3.qq.com [54.243.244.52]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0AC5E28980F for ; Wed, 11 Mar 2026 09:51:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=54.243.244.52 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773222665; cv=none; b=rYLE9nNd9EeK7VSTc91sl4aLWNbGBvCAlSoRu+O4r7m996KNhoJWfIJ4VYxvx5DS98CmBtxmmHYtrvSpMTLyJb6VNddqFFxhKADZzNetPvoSpyNAxmzA2s2v1JxTNebhLqKDi7EUHCiyZ7Xwtj5tRYR8ZdGG9jdui64f/iBYyjg= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773222665; c=relaxed/simple; bh=cTxRfP9YZ+CqbW9d2TT4ze9+SnboTqBKpkTx8iYls/Q=; h=Mime-Version:Content-Type:Date:Message-Id:Cc:Subject:From:To: References:In-Reply-To; b=hx/gZ/TltQLUPQzH7S+etaxnMf5cB4QwjwXflx9ng2QCqylaKnRGAyh0FaE+VE085Hg3+eF9upghOqTjIId1w/qFAFrg8rrBUlqKbHktAW+xpDomBeGXYT/WAWpUibmr/GDdmnJSr7Wrxb/vIhuI25nG8chqRiihwHtJ8tp1JyY= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.dev; spf=none smtp.mailfrom=linux.spacemit.com; arc=none smtp.client-ip=54.243.244.52 Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=none smtp.mailfrom=linux.spacemit.com X-QQ-mid: zesmtpsz7t1773222552t96c6394d X-QQ-Originating-IP: tLsdr5O1OVgnv6pRMxCTwQmUYnvtTVooyzNm1cn2Huc= Received: from = ( [120.237.158.181]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 11 Mar 2026 17:49:10 +0800 (CST) X-QQ-SSF: 0000000000000000000000000000000 X-QQ-GoodBg: 0 X-BIZMAIL-ID: 15209476583786432799 X-QQ-CSender: troy.mitchell@linux.spacemit.com Sender: troy.mitchell@linux.spacemit.com Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=UTF-8 Date: Wed, 11 Mar 2026 17:49:10 +0800 Message-Id: Cc: "Paul Walmsley" , "Palmer Dabbelt" , "Albert Ou" , "Alexandre Ghiti" , , Subject: Re: [PATCH RFC] riscv: disable local interrupts and stop other CPUs before restart From: "Troy Mitchell" To: "Aurelien Jarno" , "Troy Mitchell" X-Mailer: aerc 0.21.0-0-g5549850facc2 References: <20260311-v7-0-rc1-rv-dis-int-before-restart-v1-1-bc46b4351cac@linux.dev> In-Reply-To: X-QQ-SENDSIZE: 520 Feedback-ID: zesmtpsz:linux.spacemit.com:qybglogicsvrgz:qybglogicsvrgz3a-0 X-QQ-XMAILINFO: OYpbVsTx4C81bWtly/iq7uKUBmmiZmV+rjCsSHht1V4IG6u/RvI0uEyj SzJ8IuX51AO9sSV8fsB7Yn78iD8zOxYp2xxcy1Y4yDmxw/CbFkjcJEmCtdbBnyPHK5AWu1b XIbFeuLrB9Pmks/8ZzHrI8neaoOCAJ7d/4hoTsqqMoaYO7ZLURWQlgP9vECkStLJ1/3peFS rDMIHAVzIpAZlH02+hzwAH0QtuVnRCIUNlcMMpL1x9gMJ8nyVqk/oKV7Y/dMngmkP0Wcup+ WkoUHZFiyktl/xidz+/R7v/udm+gChjPR0NuK+XfWvtTlnA4GwYzyxsFXwrML1u/E8gM09a 4PQpahpIDZ37oNHclYSXc897FfNJWcniOjT9G3P8M5q5J9e1Zn/XFPHpBSX/opxIGVt6HwG ye6wbx5BtkLY+HhKu71Z+2Up6/ICmjVBDoalf6mAdaBSn7FXbzfCm00mU0aX2DwvZUNEmCJ 5cGj40/4tPtg3XV0feeXLe7cc/3yFD3arEvghDIS7EL9bJDzaGZGiEcD3GVTyspGj+MudHJ lLPJxIrp48BicJNQ93I30TPPJhdDTRTPJ6U/mOS4oiz3psYO7rcwygwwndR0KAjpIdIib40 f1AiBdONcTfiQzkao02hSbRXe3En1Jl54Y7abmkL16LMFIbeYWKftu/xEiZvHDYk5B9nwTW kTDVN2ldlTy9ciwP4arxU4dKQjB2CSPmN/zPdYSfV5I8w2fgCE+0Mvwx9tW3nwTu+RBo0ed UXPWAJBPvdW7htjimAwE//v/hG51VpSCn0NTExLLzZHUVz15Wvyu5zDEEgx8C4saYnDVVcv 8s5QbKhvI5EC0eatJe8GMBU2sWi4HB0dfKTGX/Ep0QgeGS0hd/zq9gb2UCzJ5aLtxZp1SCC wTvHDZ3Ae2P9BMema7BjmJcH7QqEX0HCcPIJ79rnzbkzNxeX/xkEVNTz5JDwosJqGN/9Dum XsutoK3Ufgvm7dmSTL8uCzG/ZcIzOG8Dffb69ueAQPgcEVqApN9QGdlM/ZaVXxBmN3shVj6 49TOP3MqkdkcGcyF4UtC+SEBmMUpvvWKY4rzm9EjzuVpTdpDOm X-QQ-XMRINFO: NS+P29fieYNwqS3WCnRCOn9D1NpZuCnCRA== X-QQ-RECHKSPAM: 0 On Wed Mar 11, 2026 at 2:47 PM CST, Aurelien Jarno wrote: > Hi Troy, > > On 2026-03-11 10:51, Troy Mitchell wrote: >> Currently, the RISC-V implementation of machine_restart() directly calls >> do_kernel_restart() without disabling local interrupts or stopping other >> CPUs. This missing architectural setup causes fatal issues for systems >> that rely on external peripherals (e.g., I2C PMICs) to execute the syste= m >> restart when CONFIG_PREEMPT_RCU is enabled. >>=20 >> When a restart handler relies on the I2C subsystem, the I2C core checks >> i2c_in_atomic_xfer_mode() to decide whether to use the sleepable xfer >> or the polling atomic_xfer. This check evaluates to true if >> (!preemptible() || irqs_disabled()). >>=20 >> During do_kernel_restart(), the restart handlers are invoked via >> atomic_notifier_call_chain(), which holds an RCU read lock. >> The behavior diverges based on the preemption model: >> 1. Under CONFIG_PREEMPT_VOLUNTARY or CONFIG_PREEMPT_NONE, rcu_read_lock(= ) >> implicitly disables preemption. preemptible() evaluates to false, and >> the I2C core correctly routes to the atomic, polling transfer path. >> 2. Under CONFIG_PREEMPT_RCU, rcu_read_lock() does NOT disable preemption= . >> Since machine_restart() left local interrupts enabled, irqs_disabled(= ) >> is false, and preempt_count is 0. Consequently, preemptible() evaluat= es >> to true. >>=20 >> As a result, the I2C core falsely assumes a sleepable context and routes >> the transfer to the standard master_xfer path. This inevitably triggers = a >> schedule() call while holding the RCU read lock, resulting in a fatal sp= lat: >> "Voluntary context switch within RCU read-side critical section!" and >> a system hang. >>=20 >> Align RISC-V with other major architectures (e.g., ARM64) by adding >> local_irq_disable() and smp_send_stop() to machine_restart(). >> - local_irq_disable() guarantees a strict atomic context, forcing sub- >> systems like I2C to always fall back to polling mode. >> - smp_send_stop() ensures exclusive hardware access by quiescing other >> CPUs, preventing them from holding bus locks (e.g., I2C spinlocks) >> during the final restart phase. >>=20 >> Signed-off-by: Troy Mitchell >> --- >> arch/riscv/kernel/reset.c | 5 +++++ >> 1 file changed, 5 insertions(+) > > Thanks. I have been debugging that and it matches my analysis. > >> diff --git a/arch/riscv/kernel/reset.c b/arch/riscv/kernel/reset.c >> index 912288572226..7a5dcfdc3674 100644 >> --- a/arch/riscv/kernel/reset.c >> +++ b/arch/riscv/kernel/reset.c >> @@ -5,6 +5,7 @@ >> =20 >> #include >> #include >> +#include >> =20 >> static void default_power_off(void) >> { >> @@ -17,6 +18,10 @@ EXPORT_SYMBOL(pm_power_off); >> =20 >> void machine_restart(char *cmd) >> { >> + /* Disable interrupts first */ >> + local_irq_disable(); >> + smp_send_stop(); >> + >> do_kernel_restart(cmd); >> while (1); >> } >>=20 > > I have started to change the power reset driver to call the I2C code=20 > from a workqueue instead of directly from the notifier call back, but=20 > that's just papering over the issue. Since the requirements for i2c_in_atomic() weren't being met, I initially considered disabling interrupts before the p1 restart code. However, I didn't feel that was a generic enough solution, so I looked into the architecture-level implementation. That's when I realized how bare-bone= s the current RISC-V machine_restart() actually is.. > > Your approach is much better and=20 > aligns riscv64 with other architectures, which is important as we might= =20 > have shared PMIC drivers. > > Therefore: > > Tested-by: Aurelien Jarno > Reviewed-by: Aurelien Jarno Thanks. :) - Troy > > Regards > Aurelien