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