xref: /linux/rust/kernel/interrupt.rs (revision dfa35434d7f20142fedd7120277b1044a0a2bb64)
1*c1f0451eSLyude Paul // SPDX-License-Identifier: GPL-2.0
2*c1f0451eSLyude Paul 
3*c1f0451eSLyude Paul //! Interrupt controls
4*c1f0451eSLyude Paul //!
5*c1f0451eSLyude Paul //! This module allows Rust code to annotate areas of code where local processor interrupts should
6*c1f0451eSLyude Paul //! be disabled, along with actually disabling local processor interrupts.
7*c1f0451eSLyude Paul //!
8*c1f0451eSLyude Paul //! # ⚠️ Warning! ⚠️
9*c1f0451eSLyude Paul //!
10*c1f0451eSLyude Paul //! The usage of this module can be more complicated than meets the eye, especially surrounding
11*c1f0451eSLyude Paul //! [preemptible kernels]. It's recommended to take care when using the functions and types defined
12*c1f0451eSLyude Paul //! here and familiarize yourself with the various documentation we have before using them, along
13*c1f0451eSLyude Paul //! with the various documents we link to here.
14*c1f0451eSLyude Paul //!
15*c1f0451eSLyude Paul //! # Reading material
16*c1f0451eSLyude Paul //!
17*c1f0451eSLyude Paul //! - [Software interrupts and realtime (LWN)](https://lwn.net/Articles/520076)
18*c1f0451eSLyude Paul //!
19*c1f0451eSLyude Paul //! [preemptible kernels]: https://www.kernel.org/doc/html/latest/locking/preempt-locking.html
20*c1f0451eSLyude Paul 
21*c1f0451eSLyude Paul use crate::types::NotThreadSafe;
22*c1f0451eSLyude Paul 
23*c1f0451eSLyude Paul /// A guard that represents local processor interrupt disablement on preemptible kernels.
24*c1f0451eSLyude Paul ///
25*c1f0451eSLyude Paul /// [`LocalInterruptDisabled`] is a guard type that represents that local processor interrupts have
26*c1f0451eSLyude Paul /// been disabled on a preemptible kernel.
27*c1f0451eSLyude Paul ///
28*c1f0451eSLyude Paul /// Certain functions take an immutable reference of [`LocalInterruptDisabled`] in order to require
29*c1f0451eSLyude Paul /// that they may only be run in local-interrupt-disabled contexts on preemptible kernels.
30*c1f0451eSLyude Paul ///
31*c1f0451eSLyude Paul /// This is a marker type; it has no size, and is simply used as a compile-time guarantee that local
32*c1f0451eSLyude Paul /// processor interrupts are disabled on preemptible kernels. Note that no guarantees about the
33*c1f0451eSLyude Paul /// state of interrupts are made by this type on non-preemptible kernels.
34*c1f0451eSLyude Paul ///
35*c1f0451eSLyude Paul /// # Invariants
36*c1f0451eSLyude Paul ///
37*c1f0451eSLyude Paul /// Local processor interrupts are disabled on preemptible kernels for as long as an object of this
38*c1f0451eSLyude Paul /// type exists.
39*c1f0451eSLyude Paul pub struct LocalInterruptDisabled(NotThreadSafe);
40*c1f0451eSLyude Paul 
41*c1f0451eSLyude Paul /// Disable local processor interrupts on a preemptible kernel.
42*c1f0451eSLyude Paul ///
43*c1f0451eSLyude Paul /// This function disables local processor interrupts on a preemptible kernel, and returns a
44*c1f0451eSLyude Paul /// [`LocalInterruptDisabled`] token as proof of this. On non-preemptible kernels, this function is
45*c1f0451eSLyude Paul /// a no-op.
46*c1f0451eSLyude Paul ///
47*c1f0451eSLyude Paul /// **Usage of this function is discouraged** unless you are absolutely sure you know what you are
48*c1f0451eSLyude Paul /// doing, as kernel interfaces for Rust that deal with interrupt state will typically handle local
49*c1f0451eSLyude Paul /// processor interrupt state management on their own and managing this by hand is quite error
50*c1f0451eSLyude Paul /// prone.
51*c1f0451eSLyude Paul #[inline]
52*c1f0451eSLyude Paul pub fn local_interrupt_disable() -> LocalInterruptDisabled {
53*c1f0451eSLyude Paul     // SAFETY: It's always safe to call `local_interrupt_disable()`.
54*c1f0451eSLyude Paul     unsafe { bindings::local_interrupt_disable() };
55*c1f0451eSLyude Paul 
56*c1f0451eSLyude Paul     LocalInterruptDisabled(NotThreadSafe)
57*c1f0451eSLyude Paul }
58*c1f0451eSLyude Paul 
59*c1f0451eSLyude Paul impl Drop for LocalInterruptDisabled {
60*c1f0451eSLyude Paul     #[inline]
61*c1f0451eSLyude Paul     fn drop(&mut self) {
62*c1f0451eSLyude Paul         // SAFETY: Per type invariants, a `local_interrupt_disable()` must be called to create this
63*c1f0451eSLyude Paul         // object, hence calling the corresponding `local_interrupt_enable()` is safe.
64*c1f0451eSLyude Paul         unsafe { bindings::local_interrupt_enable() };
65*c1f0451eSLyude Paul     }
66*c1f0451eSLyude Paul }
67*c1f0451eSLyude Paul 
68*c1f0451eSLyude Paul impl LocalInterruptDisabled {
69*c1f0451eSLyude Paul     /// Assume that local processor interrupts are disabled on preemptible kernels.
70*c1f0451eSLyude Paul     ///
71*c1f0451eSLyude Paul     /// This can be used for annotating code that is known to be run in contexts where local
72*c1f0451eSLyude Paul     /// processor interrupts are disabled on preemptible kernels. It makes no changes to the local
73*c1f0451eSLyude Paul     /// interrupt state on its own.
74*c1f0451eSLyude Paul     ///
75*c1f0451eSLyude Paul     /// # Safety
76*c1f0451eSLyude Paul     ///
77*c1f0451eSLyude Paul     /// For the whole life `'a`, local interrupts must be disabled on preemptible kernels. This
78*c1f0451eSLyude Paul     /// could be a context like, for example, an interrupt handler.
79*c1f0451eSLyude Paul     #[inline]
80*c1f0451eSLyude Paul     pub unsafe fn assume_disabled<'a>() -> &'a LocalInterruptDisabled {
81*c1f0451eSLyude Paul         const ASSUME_DISABLED: &LocalInterruptDisabled = &LocalInterruptDisabled(NotThreadSafe);
82*c1f0451eSLyude Paul 
83*c1f0451eSLyude Paul         // Confirm they're actually disabled if lockdep is available
84*c1f0451eSLyude Paul         // SAFETY: It's always safe to call `lockdep_assert_irqs_disabled()`.
85*c1f0451eSLyude Paul         unsafe { bindings::lockdep_assert_irqs_disabled() };
86*c1f0451eSLyude Paul 
87*c1f0451eSLyude Paul         ASSUME_DISABLED
88*c1f0451eSLyude Paul     }
89*c1f0451eSLyude Paul }
90