From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from hall.aurel32.net (hall.aurel32.net [195.154.119.183]) (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 953D7299929 for ; Wed, 11 Mar 2026 06:47:19 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=195.154.119.183 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773211641; cv=none; b=Hlf2LruWsxpt/D+c0DCe9QavPPYffcO7GJpCnPqEx1d8eXg/SQfCDuCjMd+G77kI9Jz0GCbA9SKaNSoBXDh718x7gewZoFF50+dFPdtMRmkqMXgrYm2srEpK46DLIBMHZHcQQAfRolgYkCjGD3t07BlYt2Sl5WxYKZNftt4zXRA= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1773211641; c=relaxed/simple; bh=IIJOCIZ/M/HW+gfs2Takd72x0YAl7hRSBhB/dpOB9GM=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=NGuTmyClYo+MXfHtX1ZnY4q/vWIgXq2WBoQM+N4Wl/R5/QB+N+THdS3ldRtTVDTn9zEYASNJYGwxWRoPGIrhFGzIe+FLEucrBzPPCzqTt/DPI6RwCTt1vNq7JY1djUmaTBhlRdouawhrN6l3AVCs5td3uGVkDLeJewUmmgcN4c4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=aurel32.net; spf=pass smtp.mailfrom=aurel32.net; dkim=pass (2048-bit key) header.d=aurel32.net header.i=@aurel32.net header.b=R82/ksyq; arc=none smtp.client-ip=195.154.119.183 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=aurel32.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=aurel32.net Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=aurel32.net header.i=@aurel32.net header.b="R82/ksyq" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=aurel32.net ; s=202004.hall; h=In-Reply-To:Content-Transfer-Encoding:Content-Type: MIME-Version:References:Message-ID:Subject:Cc:To:From:Date:From:Reply-To: Subject:Content-ID:Content-Description:X-Debbugs-Cc; bh=mztUlcYsUX1SUhrIWnhDg4vSM7m0nS0R9ybKsM7yhNY=; b=R82/ksyqGntVvfC04lFZNYXKM4 0S9DHgqPTFRk9b/WsdLTqXtZMIqDNHD5pMCJBHyk+jf5tj5e4EfKTqgsrA344Ml3domQz7myBi2n5 EnxP2k0UeWIqdqf3D7mjQKvNP0ctmKdSiqlIbiIGZxe06l8ex2necvO23A9ihOCbH7k1jAD9bHQZw jz8MryCs8CzX+yrAz9hSooLRTdt18tsu7IqFC0uZLAcc/CQ0CS7BdVqt5mh1uPhJd4wRtFREYnpOa qDBTztbIovXGDNLkbUEJiOWD4SMaZ/634sCtM2Fa6Uzbqrj9Mj3GkaxYQ0hAvSsOdu6MT5da7NpS9 1hRQn87Q==; Received: from authenticated user by hall.aurel32.net with esmtpsa (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.98.2) (envelope-from ) id 1w0DLf-000000070BW-49YH; Wed, 11 Mar 2026 07:47:16 +0100 Date: Wed, 11 Mar 2026 07:47:15 +0100 From: Aurelien Jarno To: Troy Mitchell Cc: Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org Subject: Re: [PATCH RFC] riscv: disable local interrupts and stop other CPUs before restart Message-ID: Mail-Followup-To: Troy Mitchell , Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org References: <20260311-v7-0-rc1-rv-dis-int-before-restart-v1-1-bc46b4351cac@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-Transfer-Encoding: quoted-printable In-Reply-To: <20260311-v7-0-rc1-rv-dis-int-before-restart-v1-1-bc46b4351cac@linux.dev> User-Agent: Mutt/2.2.13 (2024-03-09) 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 system > 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() evaluates > 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 spl= at: > "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 =66rom a workqueue instead of directly from the notifier call back, but=20 that's just papering over the issue. 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 Regards Aurelien --=20 Aurelien Jarno GPG: 4096R/1DDD8C9B aurelien@aurel32.net http://aurel32.net