[PATCH 7/9] rust: hrtimer: expose interrupt state in hard callbacks

Mike Lothian <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
Hard hrtimer modes guarantee that their callbacks run with local
interrupts disabled. Carry that guarantee through HrTimerCallbackContext
so users of IRQ-aware locks do not need to assert the callback
context themselves.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Mike Lothian <[email protected]>
---
 rust/kernel/time/hrtimer.rs | 21 ++++++++++++++++++++-
 1 file changed, 20 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 2d7f1131a813..a55b3ce53735 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -404,7 +404,7 @@
 //! [`Arc`]: kernel::sync::Arc
 
 use super::{ClockSource, Delta, Instant};
-use crate::{prelude::*, types::Opaque};
+use crate::{interrupt::LocalInterruptDisabled, prelude::*, types::Opaque};
 use core::{marker::PhantomData, ptr::NonNull};
 use pin_init::PinInit;
 
@@ -900,6 +900,11 @@ pub trait HrTimerMode: private::Sealed {
     type Expires: HrTimerExpires;
 }
 
+/// A timer mode whose callback runs with local interrupts disabled.
+///
+/// This trait is sealed by [`HrTimerMode`].
+pub trait HardHrTimerMode: HrTimerMode {}
+
 /// Timer that expires at a fixed point in time.
 pub struct AbsoluteMode<C: ClockSource>(PhantomData<C>);
 
@@ -982,6 +987,7 @@ impl<C: ClockSource> HrTimerMode for AbsoluteHardMode<C> {
     type Clock = C;
     type Expires = Instant<C>;
 }
+impl<C: ClockSource> HardHrTimerMode for AbsoluteHardMode<C> {}
 
 /// Timer with relative expiration, handled in hard irq context.
 pub struct RelativeHardMode<C: ClockSource>(PhantomData<C>);
@@ -991,6 +997,7 @@ impl<C: ClockSource> HrTimerMode for RelativeHardMode<C> {
     type Clock = C;
     type Expires = Delta;
 }
+impl<C: ClockSource> HardHrTimerMode for RelativeHardMode<C> {}
 
 /// Timer with absolute expiration, pinned to CPU and handled in hard irq context.
 pub struct AbsolutePinnedHardMode<C: ClockSource>(PhantomData<C>);
@@ -1000,6 +1007,7 @@ impl<C: ClockSource> HrTimerMode for AbsolutePinnedHardMode<C> {
     type Clock = C;
     type Expires = Instant<C>;
 }
+impl<C: ClockSource> HardHrTimerMode for AbsolutePinnedHardMode<C> {}
 
 /// Timer with relative expiration, pinned to CPU and handled in hard irq context.
 pub struct RelativePinnedHardMode<C: ClockSource>(PhantomData<C>);
@@ -1009,6 +1017,7 @@ impl<C: ClockSource> HrTimerMode for RelativePinnedHardMode<C> {
     type Clock = C;
     type Expires = Delta;
 }
+impl<C: ClockSource> HardHrTimerMode for RelativePinnedHardMode<C> {}
 
 /// Privileged smart-pointer for a [`HrTimer`] callback context.
 ///
@@ -1065,6 +1074,16 @@ pub fn forward(&mut self, now: HrTimerInstant<T>, interval: Delta) -> u64 {
     pub fn forward_now(&mut self, duration: Delta) -> u64 {
         self.forward(HrTimerInstant::<T>::now(), duration)
     }
+
+    /// Returns proof that local interrupts are disabled for a hard timer callback.
+    pub fn local_interrupt_disabled(&self) -> &LocalInterruptDisabled
+    where
+        T::TimerMode: HardHrTimerMode,
+    {
+        // SAFETY: `Self` can only be constructed while running this timer's callback, and the
+        // `HardHrTimerMode` bound guarantees that the callback runs in hard interrupt context.
+        unsafe { LocalInterruptDisabled::assume_disabled() }
+    }
 }
 
 /// Use to implement the [`HasHrTimer<T>`] trait.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.