mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Lyude Paul <lyude@redhat.com>
To: rust-for-linux@vger.kernel.org,
	Thomas Gleixner <tglx@linutronix.de>,
	Boqun Feng <boqun.feng@gmail.com>,
	linux-kernel@vger.kernel.org,
	Daniel Almeida <daniel.almeida@collabora.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
	"Alex Gaynor" <alex.gaynor@gmail.com>,
	"Gary Guo" <gary@garyguo.net>,
	"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
	"Benno Lossin" <lossin@kernel.org>,
	"Andreas Hindborg" <a.hindborg@kernel.org>,
	"Alice Ryhl" <aliceryhl@google.com>,
	"Trevor Gross" <tmgross@umich.edu>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Wedson Almeida Filho" <wedsonaf@gmail.com>,
	"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
	"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Xiangfei Ding" <dingxiangfei2009@gmail.com>
Subject: [RFC RESEND v10 04/14] rust: Introduce interrupt module
Date: Tue, 27 May 2025 18:21:45 -0400	[thread overview]
Message-ID: <20250527222254.565881-5-lyude@redhat.com> (raw)
In-Reply-To: <20250527222254.565881-1-lyude@redhat.com>

This introduces a module for dealing with interrupt-disabled contexts,
including the ability to enable and disable interrupts along with the
ability to annotate functions as expecting that IRQs are already
disabled on the local CPU.

[Boqun: This is based on Lyude's work on interrupt disable abstraction,
I port to the new local_interrupt_disable() mechanism to make it work
as a guard type. I cannot even take the credit of this design, since
Lyude also brought up the same idea in zulip. Anyway, this is only for
POC purpose, and of course all bugs are mine]

Signed-off-by: Lyude Paul <lyude@redhat.com>
Co-Developed-by: Boqun Feng <boqun.feng@gmail.com>
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>

---

V10:
* Fix documentation typos

Signed-off-by: Lyude Paul <lyude@redhat.com>
---
 rust/helpers/helpers.c   |  1 +
 rust/helpers/interrupt.c | 18 +++++++++
 rust/kernel/interrupt.rs | 83 ++++++++++++++++++++++++++++++++++++++++
 rust/kernel/lib.rs       |  1 +
 4 files changed, 103 insertions(+)
 create mode 100644 rust/helpers/interrupt.c
 create mode 100644 rust/kernel/interrupt.rs

diff --git a/rust/helpers/helpers.c b/rust/helpers/helpers.c
index 80785b1e7a63e..ddf812af3aff8 100644
--- a/rust/helpers/helpers.c
+++ b/rust/helpers/helpers.c
@@ -17,6 +17,7 @@
 #include "dma.c"
 #include "err.c"
 #include "fs.c"
+#include "interrupt.c"
 #include "io.c"
 #include "jump_label.c"
 #include "kunit.c"
diff --git a/rust/helpers/interrupt.c b/rust/helpers/interrupt.c
new file mode 100644
index 0000000000000..f2380dd461ca5
--- /dev/null
+++ b/rust/helpers/interrupt.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/spinlock.h>
+
+void rust_helper_local_interrupt_disable(void)
+{
+	local_interrupt_disable();
+}
+
+void rust_helper_local_interrupt_enable(void)
+{
+	local_interrupt_enable();
+}
+
+bool rust_helper_irqs_disabled(void)
+{
+	return irqs_disabled();
+}
diff --git a/rust/kernel/interrupt.rs b/rust/kernel/interrupt.rs
new file mode 100644
index 0000000000000..e66aa85f79940
--- /dev/null
+++ b/rust/kernel/interrupt.rs
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Interrupt controls
+//!
+//! This module allows Rust code to annotate areas of code where local processor interrupts should
+//! be disabled, along with actually disabling local processor interrupts.
+//!
+//! # ⚠️ Warning! ⚠️
+//!
+//! The usage of this module can be more complicated than meets the eye, especially surrounding
+//! [preemptible kernels]. It's recommended to take care when using the functions and types defined
+//! here and familiarize yourself with the various documentation we have before using them, along
+//! with the various documents we link to here.
+//!
+//! # Reading material
+//!
+//! - [Software interrupts and realtime (LWN)](https://lwn.net/Articles/520076)
+//!
+//! [preemptible kernels]: https://www.kernel.org/doc/html/latest/locking/preempt-locking.html
+
+use bindings;
+use kernel::types::NotThreadSafe;
+
+/// A guard that represents local processor interrupt disablement on preemptible kernels.
+///
+/// [`LocalInterruptDisabled`] is a guard type that represents that local processor interrupts have
+/// been disabled on a preemptible kernel.
+///
+/// Certain functions take an immutable reference of [`LocalInterruptDisabled`] in order to require
+/// that they may only be run in local-interrupt-disabled contexts on preemptible kernels.
+///
+/// This is a marker type; it has no size, and is simply used as a compile-time guarantee that local
+/// processor interrupts interrupts are disabled on preemptible kernels. Note that no guarantees
+/// about the state of interrupts are made by this type on non-preemptible kernels.
+///
+/// # Invariants
+///
+/// Local processor interrupts are disabled on preemptible kernels for as long as an object of this
+/// type exists.
+pub struct LocalInterruptDisabled(NotThreadSafe);
+
+/// Disable local processor interrupts on a preemptible kernel.
+///
+/// This function disables local processor interrupts on a preemptible kernel, and returns a
+/// [`LocalInterruptDisabled`] token as proof of this. On non-preemptible kernels, this function is
+/// a no-op.
+///
+/// **Usage of this function is discouraged** unless you are absolutely sure you know what you are
+/// doing, as kernel interfaces for rust that deal with interrupt state will typically handle local
+/// processor interrupt state management on their own and managing this by hand is quite error
+/// prone.
+pub fn local_interrupt_disable() -> LocalInterruptDisabled {
+    // SAFETY: It's always safe to call `local_interrupt_disable()`.
+    unsafe { bindings::local_interrupt_disable() };
+
+    LocalInterruptDisabled(NotThreadSafe)
+}
+
+impl Drop for LocalInterruptDisabled {
+    fn drop(&mut self) {
+        // SAFETY: Per type invariants, a `local_interrupt_disable()` must be called to create this
+        // object, hence call the corresponding `local_interrupt_enable()` is safe.
+        unsafe { bindings::local_interrupt_enable() };
+    }
+}
+
+impl LocalInterruptDisabled {
+    const ASSUME_DISABLED: &'static LocalInterruptDisabled = &LocalInterruptDisabled(NotThreadSafe);
+
+    /// Assume that local processor interrupts are disabled on preemptible kernels.
+    ///
+    /// This can be used for annotating code that is known to be run in contexts where local
+    /// processor interrupts are disabled on preemptible kernels. It makes no changes to the local
+    /// interrupt state on its own.
+    ///
+    /// # Safety
+    ///
+    /// For the whole life `'a`, local interrupts must be disabled on preemptible kernels. This
+    /// could be a context like for example, an interrupt handler.
+    pub unsafe fn assume_disabled<'a>() -> &'a LocalInterruptDisabled {
+        Self::ASSUME_DISABLED
+    }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 6e9287136cac7..cd5edccafdad7 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -68,6 +68,7 @@
 pub mod firmware;
 pub mod fs;
 pub mod init;
+pub mod interrupt;
 pub mod io;
 pub mod ioctl;
 pub mod jump_label;
-- 
2.49.0


  parent reply	other threads:[~2025-05-27 22:23 UTC|newest]

Thread overview: 35+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-05-27 22:21 [RFC RESEND v10 00/14] Refcounted interrupts, SpinLockIrq for rust Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 01/14] preempt: Introduce HARDIRQ_DISABLE_BITS Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 02/14] preempt: Introduce __preempt_count_{sub, add}_return() Lyude Paul
2025-05-28  6:37   ` Heiko Carstens
2025-05-27 22:21 ` [RFC RESEND v10 03/14] irq & spin_lock: Add counted interrupt disabling/enabling Lyude Paul
2025-05-28  9:10   ` Peter Zijlstra
2025-05-28 14:03     ` Steven Rostedt
2025-05-28 14:47     ` Boqun Feng
2025-06-16 17:54       ` Joel Fernandes
2025-06-16 18:02         ` Boqun Feng
2025-06-16 18:37           ` Joel Fernandes
2025-06-17 14:14             ` Steven Rostedt
2025-05-28 18:47     ` Lyude Paul
2025-06-16 18:10   ` Joel Fernandes
2025-06-16 18:16     ` Boqun Feng
2025-06-17 14:11   ` Steven Rostedt
2025-06-17 14:34     ` Boqun Feng
2025-06-17 15:11       ` Steven Rostedt
2025-06-17 14:25   ` Boqun Feng
2025-05-27 22:21 ` Lyude Paul [this message]
2025-05-29  9:21   ` [RFC RESEND v10 04/14] rust: Introduce interrupt module Benno Lossin
2025-05-27 22:21 ` [RFC RESEND v10 05/14] rust: helper: Add spin_{un,}lock_irq_{enable,disable}() helpers Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 06/14] rust: sync: Add SpinLockIrq Lyude Paul
2025-06-16 19:51   ` Joel Fernandes
2025-07-16 20:29     ` Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 07/14] rust: sync: Introduce lock::Backend::Context Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 08/14] rust: sync: lock: Add `Backend::BackendInContext` Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 09/14] rust: sync: Add a lifetime parameter to lock::global::GlobalGuard Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 10/14] rust: sync: lock/global: Rename B to G in trait bounds Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 11/14] rust: sync: Expose lock::Backend Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 12/14] rust: sync: lock/global: Add Backend parameter to GlobalGuard Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 13/14] rust: sync: lock/global: Add BackendInContext support to GlobalLock Lyude Paul
2025-05-27 22:21 ` [RFC RESEND v10 14/14] locking: Switch to _irq_{disable,enable}() variants in cleanup guards Lyude Paul
2025-05-28  6:11   ` Sebastian Andrzej Siewior
2025-07-02 10:16 ` [RFC RESEND v10 00/14] Refcounted interrupts, SpinLockIrq for rust Benno Lossin

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=20250527222254.565881-5-lyude@redhat.com \
    --to=lyude@redhat.com \
    --cc=a.hindborg@kernel.org \
    --cc=alex.gaynor@gmail.com \
    --cc=aliceryhl@google.com \
    --cc=bjorn3_gh@protonmail.com \
    --cc=boqun.feng@gmail.com \
    --cc=dakr@kernel.org \
    --cc=daniel.almeida@collabora.com \
    --cc=dingxiangfei2009@gmail.com \
    --cc=fujita.tomonori@gmail.com \
    --cc=gary@garyguo.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=lossin@kernel.org \
    --cc=ojeda@kernel.org \
    --cc=rust-for-linux@vger.kernel.org \
    --cc=tglx@linutronix.de \
    --cc=tmgross@umich.edu \
    --cc=wedsonaf@gmail.com \
    /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®