Remove unsafe from certain IRQ related code

While turning IRQs on or off is something that "sounds critical", it is not
unsafe in these sense of compromising memory safety. Rust's unsafe should be
about memory safety only, hence removing it from certain functions.
pull/165/head
Andre Richter 2 years ago
parent f222d73b90
commit 5e1fdf8605
No known key found for this signature in database
GPG Key ID: 2116C1AB102F615E

@ -421,13 +421,9 @@ core are masked before the `f(data)` is being executed, and restored afterwards:
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }
@ -814,7 +810,7 @@ diff -uNr 12_integrated_testing/kernel/src/_arch/aarch64/exception/asynchronous.
trait DaifField { trait DaifField {
fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>; fn daif_field() -> tock_registers::fields::Field<u64, DAIF::Register>;
} }
@@ -66,6 +71,71 @@ @@ -66,6 +71,60 @@
// Public Code // Public Code
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
@ -830,42 +826,32 @@ diff -uNr 12_integrated_testing/kernel/src/_arch/aarch64/exception/asynchronous.
+/// +///
+/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional +/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
+/// synchronization." +/// synchronization."
+///
+/// # Safety
+///
+/// - Changes the HW state of the executing core.
+#[inline(always)] +#[inline(always)]
+pub unsafe fn local_irq_unmask() { +pub fn local_irq_unmask() {
+ #[rustfmt::skip] + unsafe {
+ asm!( + asm!(
+ "msr DAIFClr, {arg}", + "msr DAIFClr, {arg}",
+ arg = const daif_bits::IRQ, + arg = const daif_bits::IRQ,
+ options(nomem, nostack, preserves_flags) + options(nomem, nostack, preserves_flags)
+ ); + );
+ }
+} +}
+ +
+/// Mask IRQs on the executing core. +/// Mask IRQs on the executing core.
+///
+/// # Safety
+///
+/// - Changes the HW state of the executing core.
+#[inline(always)] +#[inline(always)]
+pub unsafe fn local_irq_mask() { +pub fn local_irq_mask() {
+ #[rustfmt::skip] + unsafe {
+ asm!( + asm!(
+ "msr DAIFSet, {arg}", + "msr DAIFSet, {arg}",
+ arg = const daif_bits::IRQ, + arg = const daif_bits::IRQ,
+ options(nomem, nostack, preserves_flags) + options(nomem, nostack, preserves_flags)
+ ); + );
+ }
+} +}
+ +
+/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). +/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
+///
+/// # Safety
+///
+/// - Changes the HW state of the executing core.
+#[inline(always)] +#[inline(always)]
+pub unsafe fn local_irq_mask_save() -> u64 { +pub fn local_irq_mask_save() -> u64 {
+ let saved = DAIF.get(); + let saved = DAIF.get();
+ local_irq_mask(); + local_irq_mask();
+ +
@ -874,12 +860,11 @@ diff -uNr 12_integrated_testing/kernel/src/_arch/aarch64/exception/asynchronous.
+ +
+/// Restore the interrupt mask bits (DAIF) using the callee's argument. +/// Restore the interrupt mask bits (DAIF) using the callee's argument.
+/// +///
+/// # Safety +/// # Invariant
+/// +///
+/// - Changes the HW state of the executing core.
+/// - No sanity checks on the input. +/// - No sanity checks on the input.
+#[inline(always)] +#[inline(always)]
+pub unsafe fn local_irq_restore(saved: u64) { +pub fn local_irq_restore(saved: u64) {
+ DAIF.set(saved); + DAIF.set(saved);
+} +}
+ +
@ -2245,7 +2230,7 @@ diff -uNr 12_integrated_testing/kernel/src/driver.rs 13_exceptions_part2_periphe
diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs
--- 12_integrated_testing/kernel/src/exception/asynchronous.rs --- 12_integrated_testing/kernel/src/exception/asynchronous.rs
+++ 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs +++ 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.rs
@@ -8,7 +8,153 @@ @@ -8,7 +8,149 @@
#[path = "../_arch/aarch64/exception/asynchronous.rs"] #[path = "../_arch/aarch64/exception/asynchronous.rs"]
mod arch_asynchronous; mod arch_asynchronous;
@ -2383,13 +2368,9 @@ diff -uNr 12_integrated_testing/kernel/src/exception/asynchronous.rs 13_exceptio
+/// previous state before returning, so this is deemed safe. +/// previous state before returning, so this is deemed safe.
+#[inline(always)] +#[inline(always)]
+pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { +pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
+ let ret: T; + let saved = local_irq_mask_save();
+ + let ret = f();
+ unsafe { + local_irq_restore(saved);
+ let saved = local_irq_mask_save();
+ ret = f();
+ local_irq_restore(saved);
+ }
+ +
+ ret + ret
+} +}
@ -2497,7 +2478,7 @@ diff -uNr 12_integrated_testing/kernel/src/panic_wait.rs 13_exceptions_part2_per
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
+ unsafe { exception::asynchronous::local_irq_mask() }; + exception::asynchronous::local_irq_mask();
+ +
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();
@ -2773,21 +2754,21 @@ diff -uNr 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs 13_excep
+ // Precondition: IRQs are unmasked. + // Precondition: IRQs are unmasked.
+ assert!(exception::asynchronous::is_local_irq_masked()); + assert!(exception::asynchronous::is_local_irq_masked());
+ +
+ unsafe { exception::asynchronous::local_irq_mask() }; + exception::asynchronous::local_irq_mask();
+ assert!(!exception::asynchronous::is_local_irq_masked()); + assert!(!exception::asynchronous::is_local_irq_masked());
+ +
+ // Restore earlier state. + // Restore earlier state.
+ unsafe { exception::asynchronous::local_irq_unmask() }; + exception::asynchronous::local_irq_unmask();
+} +}
+ +
+/// Check that IRQ unmasking works. +/// Check that IRQ unmasking works.
+#[kernel_test] +#[kernel_test]
+fn local_irq_unmask_works() { +fn local_irq_unmask_works() {
+ // Precondition: IRQs are masked. + // Precondition: IRQs are masked.
+ unsafe { exception::asynchronous::local_irq_mask() }; + exception::asynchronous::local_irq_mask();
+ assert!(!exception::asynchronous::is_local_irq_masked()); + assert!(!exception::asynchronous::is_local_irq_masked());
+ +
+ unsafe { exception::asynchronous::local_irq_unmask() }; + exception::asynchronous::local_irq_unmask();
+ assert!(exception::asynchronous::is_local_irq_masked()); + assert!(exception::asynchronous::is_local_irq_masked());
+} +}
+ +
@ -2797,13 +2778,13 @@ diff -uNr 12_integrated_testing/kernel/tests/04_exception_irq_sanity.rs 13_excep
+ // Precondition: IRQs are unmasked. + // Precondition: IRQs are unmasked.
+ assert!(exception::asynchronous::is_local_irq_masked()); + assert!(exception::asynchronous::is_local_irq_masked());
+ +
+ let first = unsafe { exception::asynchronous::local_irq_mask_save() }; + let first = exception::asynchronous::local_irq_mask_save();
+ assert!(!exception::asynchronous::is_local_irq_masked()); + assert!(!exception::asynchronous::is_local_irq_masked());
+ +
+ let second = unsafe { exception::asynchronous::local_irq_mask_save() }; + let second = exception::asynchronous::local_irq_mask_save();
+ assert_ne!(first, second); + assert_ne!(first, second);
+ +
+ unsafe { exception::asynchronous::local_irq_restore(first) }; + exception::asynchronous::local_irq_restore(first);
+ assert!(exception::asynchronous::is_local_irq_masked()); + assert!(exception::asynchronous::is_local_irq_masked());
+} +}

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -141,13 +141,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -32,21 +32,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -56,12 +56,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -2300,7 +2300,7 @@ diff -uNr 13_exceptions_part2_peripheral_IRQs/kernel/src/exception/asynchronous.
impl<'irq_context> IRQContext<'irq_context> { impl<'irq_context> IRQContext<'irq_context> {
/// Creates an IRQContext token. /// Creates an IRQContext token.
@@ -152,9 +162,17 @@ @@ -148,9 +158,17 @@
ret ret
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -44,21 +44,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -68,12 +68,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -34,21 +34,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -58,12 +58,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -34,21 +34,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -58,12 +58,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -34,21 +34,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -58,12 +58,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -34,21 +34,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -58,12 +58,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

@ -83,42 +83,32 @@ pub fn is_local_irq_masked() -> bool {
/// ///
/// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional /// "Writes to PSTATE.{PAN, D, A, I, F} occur in program order without the need for additional
/// synchronization." /// synchronization."
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_unmask() { pub fn local_irq_unmask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFClr, {arg}", "msr DAIFClr, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core. /// Mask IRQs on the executing core.
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask() { pub fn local_irq_mask() {
#[rustfmt::skip] unsafe {
asm!( asm!(
"msr DAIFSet, {arg}", "msr DAIFSet, {arg}",
arg = const daif_bits::IRQ, arg = const daif_bits::IRQ,
options(nomem, nostack, preserves_flags) options(nomem, nostack, preserves_flags)
); );
}
} }
/// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF). /// Mask IRQs on the executing core and return the previously saved interrupt mask bits (DAIF).
///
/// # Safety
///
/// - Changes the HW state of the executing core.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_mask_save() -> u64 { pub fn local_irq_mask_save() -> u64 {
let saved = DAIF.get(); let saved = DAIF.get();
local_irq_mask(); local_irq_mask();
@ -127,12 +117,11 @@ pub unsafe fn local_irq_mask_save() -> u64 {
/// Restore the interrupt mask bits (DAIF) using the callee's argument. /// Restore the interrupt mask bits (DAIF) using the callee's argument.
/// ///
/// # Safety /// # Invariant
/// ///
/// - Changes the HW state of the executing core.
/// - No sanity checks on the input. /// - No sanity checks on the input.
#[inline(always)] #[inline(always)]
pub unsafe fn local_irq_restore(saved: u64) { pub fn local_irq_restore(saved: u64) {
DAIF.set(saved); DAIF.set(saved);
} }

@ -151,13 +151,9 @@ impl<const MAX_INCLUSIVE: usize> fmt::Display for IRQNumber<{ MAX_INCLUSIVE }> {
/// previous state before returning, so this is deemed safe. /// previous state before returning, so this is deemed safe.
#[inline(always)] #[inline(always)]
pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T { pub fn exec_with_irq_masked<T>(f: impl FnOnce() -> T) -> T {
let ret: T; let saved = local_irq_mask_save();
let ret = f();
unsafe { local_irq_restore(saved);
let saved = local_irq_mask_save();
ret = f();
local_irq_restore(saved);
}
ret ret
} }

@ -61,7 +61,7 @@ fn panic_prevent_reenter() {
fn panic(info: &PanicInfo) -> ! { fn panic(info: &PanicInfo) -> ! {
use crate::time::interface::TimeManager; use crate::time::interface::TimeManager;
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
// Protect against panic infinite loops if any of the following code panics itself. // Protect against panic infinite loops if any of the following code panics itself.
panic_prevent_reenter(); panic_prevent_reenter();

@ -34,21 +34,21 @@ fn local_irq_mask_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
// Restore earlier state. // Restore earlier state.
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
} }
/// Check that IRQ unmasking works. /// Check that IRQ unmasking works.
#[kernel_test] #[kernel_test]
fn local_irq_unmask_works() { fn local_irq_unmask_works() {
// Precondition: IRQs are masked. // Precondition: IRQs are masked.
unsafe { exception::asynchronous::local_irq_mask() }; exception::asynchronous::local_irq_mask();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
unsafe { exception::asynchronous::local_irq_unmask() }; exception::asynchronous::local_irq_unmask();
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }
@ -58,12 +58,12 @@ fn local_irq_mask_save_works() {
// Precondition: IRQs are unmasked. // Precondition: IRQs are unmasked.
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
let first = unsafe { exception::asynchronous::local_irq_mask_save() }; let first = exception::asynchronous::local_irq_mask_save();
assert!(!exception::asynchronous::is_local_irq_masked()); assert!(!exception::asynchronous::is_local_irq_masked());
let second = unsafe { exception::asynchronous::local_irq_mask_save() }; let second = exception::asynchronous::local_irq_mask_save();
assert_ne!(first, second); assert_ne!(first, second);
unsafe { exception::asynchronous::local_irq_restore(first) }; exception::asynchronous::local_irq_restore(first);
assert!(exception::asynchronous::is_local_irq_masked()); assert!(exception::asynchronous::is_local_irq_masked());
} }

Loading…
Cancel
Save