libkernel: CpuOps: make interrupt flags a associated type

Rather than hard-coding the interrupt flags as a `usize`. Allow each CPU
architecture to define it's own interrupt flags type via an associated
type.
This commit is contained in:
Matthew Leach
2026-04-29 15:19:06 +01:00
committed by Ashwin Naren
parent 20c17b69c5
commit 370aae9697
6 changed files with 23 additions and 13 deletions

View File

@@ -83,6 +83,7 @@ extern crate alloc;
/// struct MockCpu;
///
/// impl CpuOps for MockCpu {
/// type InterruptFlags = usize;
/// fn id() -> usize { 0 }
/// fn halt() -> ! { loop { core::hint::spin_loop() } }
/// fn disable_interrupts() -> usize { 0 }
@@ -91,6 +92,9 @@ extern crate alloc;
/// }
/// ```
pub trait CpuOps: 'static {
/// The type of the register that contains the interrupt flag enable state.
type InterruptFlags: Clone + Copy;
/// Returns the ID of the currently executing core.
fn id() -> usize;
@@ -99,10 +103,10 @@ pub trait CpuOps: 'static {
/// Disables all maskable interrupts on the current CPU core, returning the
/// previous state prior to masking.
fn disable_interrupts() -> usize;
fn disable_interrupts() -> Self::InterruptFlags;
/// Restore the previous interrupt state obtained from `disable_interrupts`.
fn restore_interrupt_state(flags: usize);
fn restore_interrupt_state(flags: Self::InterruptFlags);
/// Explicitly enables maskable interrupts on the current CPU core.
fn enable_interrupts();
@@ -119,6 +123,8 @@ pub mod test {
pub struct MockCpuOps {}
impl CpuOps for MockCpuOps {
type InterruptFlags = usize;
fn id() -> usize {
0
}

View File

@@ -22,12 +22,12 @@ use crate::CpuOps;
/// A wrapper for a RefCell guard (G) that restores interrupts on drop.
pub struct IrqGuard<G, CPU: CpuOps> {
guard: ManuallyDrop<G>,
flags: usize,
flags: CPU::InterruptFlags,
_phantom: PhantomData<CPU>,
}
impl<G, CPU: CpuOps> IrqGuard<G, CPU> {
fn new(guard: G, flags: usize) -> Self {
fn new(guard: G, flags: CPU::InterruptFlags) -> Self {
Self {
guard: ManuallyDrop::new(guard),
flags,
@@ -68,7 +68,7 @@ where
/// A mutable borrow of per-CPU data that restores interrupts on drop.
pub struct IrqSafeRefMut<'a, T, CPU: CpuOps> {
borrow: ManuallyDrop<RefMut<'a, T>>,
flags: usize,
flags: CPU::InterruptFlags,
_phantom: PhantomData<CPU>,
}
@@ -316,6 +316,8 @@ mod tests {
struct MockArch;
impl CpuOps for MockArch {
type InterruptFlags = usize;
fn id() -> usize {
MOCK_CPU_ID.with(|id| id.get())
}

View File

@@ -66,7 +66,7 @@ impl<T: ?Sized, CPU: CpuOps> SpinLockIrq<T, CPU> {
#[must_use]
pub struct SpinLockIrqGuard<'a, T: ?Sized + 'a, CPU: CpuOps> {
lock: &'a SpinLockIrq<T, CPU>,
irq_flags: usize, // The saved DAIF register state
irq_flags: CPU::InterruptFlags,
_marker: PhantomData<*const ()>, // !Send
}

View File

@@ -2,7 +2,7 @@ use core::arch::asm;
/// Returns the current state of the interrupt flags (DAIF register) and disables IRQs.
#[inline(always)]
pub fn local_irq_save() -> usize {
pub fn local_irq_save() -> u64 {
let flags: u64;
unsafe {
asm!(
@@ -12,16 +12,16 @@ pub fn local_irq_save() -> usize {
options(nomem, nostack)
);
}
flags as _
flags
}
/// Restores the interrupt flags to a previously saved state.
#[inline(always)]
pub fn local_irq_restore(flags: usize) {
pub fn local_irq_restore(flags: u64) {
unsafe {
asm!(
"msr daif, {0}", // Write flags back to DAIF
in(reg) flags as u64,
in(reg) flags,
options(nomem, nostack)
);
}

View File

@@ -30,7 +30,7 @@ impl SlabGetter<ArchImpl, PgAllocGetter, PageOffsetTranslator> for StaticSlabGet
}
pub struct PerCpuCache {
flags: usize,
flags: u64,
}
impl PerCpuCache {

View File

@@ -48,6 +48,8 @@ pub mod ptrace;
pub struct Aarch64 {}
impl CpuOps for Aarch64 {
type InterruptFlags = u64;
fn id() -> usize {
MPIDR_EL1.read(MPIDR_EL1::Aff0) as _
}
@@ -58,11 +60,11 @@ impl CpuOps for Aarch64 {
}
}
fn disable_interrupts() -> usize {
fn disable_interrupts() -> Self::InterruptFlags {
local_irq_save()
}
fn restore_interrupt_state(state: usize) {
fn restore_interrupt_state(state: Self::InterruptFlags) {
local_irq_restore(state);
}