From: Lyude Paul <lyude@redhat.com>
To: rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Cc: "Danilo Krummrich" <dakr@redhat.com>,
airlied@redhat.com, "Ingo Molnar" <mingo@redhat.com>,
"Will Deacon" <will@kernel.org>,
"Waiman Long" <longman@redhat.com>,
"Peter Zijlstra" <peterz@infradead.org>,
"Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Wedson Almeida Filho" <wedsonaf@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@samsung.com>,
"Alice Ryhl" <aliceryhl@google.com>,
"FUJITA Tomonori" <fujita.tomonori@gmail.com>,
"Aakash Sen Sharma" <aakashsensharma@gmail.com>,
"Valentin Obst" <kernel@valentinobst.de>
Subject: [PATCH v3 1/3] rust: Introduce irq module
Date: Thu, 1 Aug 2024 20:10:00 -0400 [thread overview]
Message-ID: <20240802001452.464985-2-lyude@redhat.com> (raw)
In-Reply-To: <20240802001452.464985-1-lyude@redhat.com>
This introduces a module for dealing with interrupt-disabled contexts,
including the ability to enable and disable interrupts
(with_irqs_disabled()) - along with the ability to annotate functions as
expecting that IRQs are already disabled on the local CPU.
Signed-off-by: Lyude Paul <lyude@redhat.com>
---
V2:
* Actually make it so that we check whether or not we have interrupts
disabled with debug assertions
* Fix issues in the documentation (added suggestions, missing periods, made
sure that all rustdoc examples compile properly)
* Pass IrqDisabled by value, not reference
* Ensure that IrqDisabled is !Send and !Sync using
PhantomData<(&'a (), *mut ())>
* Add all of the suggested derives from Benno Lossin
V3:
* Use `impl` for FnOnce bounds in with_irqs_disabled()
* Use higher-ranked trait bounds for the lifetime of with_irqs_disabled()
* Wording changes in the documentation for the module itself
---
rust/helpers.c | 22 ++++++++++++
rust/kernel/irq.rs | 84 ++++++++++++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
3 files changed, 107 insertions(+)
create mode 100644 rust/kernel/irq.rs
diff --git a/rust/helpers.c b/rust/helpers.c
index 92d3c03ae1bd5..42de410f92d63 100644
--- a/rust/helpers.c
+++ b/rust/helpers.c
@@ -85,6 +85,28 @@ void rust_helper_spin_unlock(spinlock_t *lock)
}
EXPORT_SYMBOL_GPL(rust_helper_spin_unlock);
+unsigned long rust_helper_local_irq_save(void)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+
+ return flags;
+}
+EXPORT_SYMBOL_GPL(rust_helper_local_irq_save);
+
+void rust_helper_local_irq_restore(unsigned long flags)
+{
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(rust_helper_local_irq_restore);
+
+bool rust_helper_irqs_disabled(void)
+{
+ return irqs_disabled();
+}
+EXPORT_SYMBOL_GPL(rust_helper_irqs_disabled);
+
void rust_helper_init_wait(struct wait_queue_entry *wq_entry)
{
init_wait(wq_entry);
diff --git a/rust/kernel/irq.rs b/rust/kernel/irq.rs
new file mode 100644
index 0000000000000..b52f8073e5cd0
--- /dev/null
+++ b/rust/kernel/irq.rs
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Interrupt controls
+//!
+//! This module allows Rust code to control processor interrupts. [`with_irqs_disabled()`] may be
+//! used for nested disables of interrupts, whereas [`IrqDisabled`] can be used for annotating code
+//! that requires interrupts to be disabled.
+
+use bindings;
+use core::marker::*;
+
+/// A token that is only available in contexts where IRQs are disabled.
+///
+/// [`IrqDisabled`] is marker made available when interrupts are not active. Certain functions take
+/// an [`IrqDisabled`] in order to indicate that they may only be run in IRQ-free contexts.
+///
+/// This is a marker type; it has no size, and is simply used as a compile-time guarantee that
+/// interrupts are disabled where required.
+///
+/// This token can be created by [`with_irqs_disabled`]. See [`with_irqs_disabled`] for examples and
+/// further information.
+#[derive(Copy, Clone, Debug, Ord, Eq, PartialOrd, PartialEq, Hash)]
+pub struct IrqDisabled<'a>(PhantomData<(&'a (), *mut ())>);
+
+impl IrqDisabled<'_> {
+ /// Create a new [`IrqDisabled`] without disabling interrupts.
+ ///
+ /// This creates an [`IrqDisabled`] token, which can be passed to functions that must be run
+ /// without interrupts. If debug assertions are enabled, this function will assert that
+ /// interrupts are disabled upon creation. Otherwise, it has no size or cost at runtime.
+ ///
+ /// # Panics
+ ///
+ /// If debug assertions are enabled, this function will panic if interrupts are not disabled
+ /// upon creation.
+ ///
+ /// # Safety
+ ///
+ /// This function must only be called in contexts where it is already known that interrupts have
+ /// been disabled for the current CPU, as the user is making a promise that they will remain
+ /// disabled at least until this [`IrqDisabled`] is dropped.
+ pub unsafe fn new() -> Self {
+ // SAFETY: FFI call with no special requirements
+ debug_assert!(unsafe { bindings::irqs_disabled() });
+
+ Self(PhantomData)
+ }
+}
+
+/// Run the closure `cb` with interrupts disabled on the local CPU.
+///
+/// This creates an [`IrqDisabled`] token, which can be passed to functions that must be run
+/// without interrupts.
+///
+/// # Examples
+///
+/// Using [`with_irqs_disabled`] to call a function that can only be called with interrupts
+/// disabled:
+///
+/// ```
+/// use kernel::irq::{IrqDisabled, with_irqs_disabled};
+///
+/// // Requiring interrupts be disabled to call a function
+/// fn dont_interrupt_me(_irq: IrqDisabled<'_>) {
+/// /* When this token is available, IRQs are known to be disabled. Actions that rely on this
+/// * can be safely performed
+/// */
+/// }
+///
+/// // Disabling interrupts. They'll be re-enabled once this closure completes.
+/// with_irqs_disabled(|irq| dont_interrupt_me(irq));
+/// ```
+#[inline]
+pub fn with_irqs_disabled<T>(cb: impl for<'a> FnOnce(IrqDisabled<'a>) -> T) -> T {
+ // SAFETY: FFI call with no special requirements
+ let flags = unsafe { bindings::local_irq_save() };
+
+ let ret = cb(IrqDisabled(PhantomData));
+
+ // SAFETY: `flags` comes from our previous call to local_irq_save
+ unsafe { bindings::local_irq_restore(flags) };
+
+ ret
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 274bdc1b0a824..ead3a7ca5ba11 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -36,6 +36,7 @@
pub mod firmware;
pub mod init;
pub mod ioctl;
+pub mod irq;
#[cfg(CONFIG_KUNIT)]
pub mod kunit;
#[cfg(CONFIG_NET)]
--
2.45.2
next prev parent reply other threads:[~2024-08-02 0:15 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-02 0:09 [PATCH v3 0/3] rust: Add irq abstraction, SpinLockIrq Lyude Paul
2024-08-02 0:10 ` Lyude Paul [this message]
2024-08-14 17:10 ` [PATCH v3 1/3] rust: Introduce irq module Boqun Feng
2024-08-14 17:35 ` Boqun Feng
2024-08-14 19:38 ` Lyude Paul
2024-08-14 20:17 ` Boqun Feng
2024-08-14 20:44 ` Benno Lossin
2024-08-14 20:57 ` Boqun Feng
2024-08-15 4:53 ` Boqun Feng
2024-08-15 6:40 ` Benno Lossin
2024-08-15 16:02 ` Boqun Feng
2024-08-15 21:05 ` Lyude Paul
2024-08-15 21:31 ` Lyude Paul
2024-08-15 21:46 ` Benno Lossin
2024-08-15 22:13 ` Lyude Paul
2024-08-16 15:28 ` Boqun Feng
2024-08-15 21:41 ` Benno Lossin
2024-08-15 21:43 ` Lyude Paul
2024-08-15 20:31 ` Lyude Paul
2024-08-15 21:48 ` Benno Lossin
2024-08-26 11:21 ` Dirk Behme
2024-08-26 14:21 ` Boqun Feng
2024-08-26 14:59 ` Dirk Behme
2024-08-26 15:34 ` Boqun Feng
2024-08-02 0:10 ` [PATCH v3 2/3] rust: sync: Introduce lock::Backend::Context Lyude Paul
2024-08-20 10:26 ` Dirk Behme
2024-08-02 0:10 ` [PATCH v3 3/3] rust: sync: Add SpinLockIrq Lyude Paul
2024-08-13 20:26 ` [PATCH v3 0/3] rust: Add irq abstraction, SpinLockIrq Lyude Paul
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=20240802001452.464985-2-lyude@redhat.com \
--to=lyude@redhat.com \
--cc=a.hindborg@samsung.com \
--cc=aakashsensharma@gmail.com \
--cc=airlied@redhat.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@redhat.com \
--cc=fujita.tomonori@gmail.com \
--cc=gary@garyguo.net \
--cc=kernel@valentinobst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=longman@redhat.com \
--cc=mingo@redhat.com \
--cc=ojeda@kernel.org \
--cc=peterz@infradead.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=wedsonaf@gmail.com \
--cc=will@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.