From 370aae96978c1b947f46eb6250b185043ff74333 Mon Sep 17 00:00:00 2001 From: Matthew Leach Date: Wed, 29 Apr 2026 15:19:06 +0100 Subject: [PATCH] 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. --- libkernel/src/lib.rs | 10 ++++++++-- libkernel/src/sync/per_cpu.rs | 8 +++++--- libkernel/src/sync/spinlock.rs | 2 +- src/arch/arm64/cpu_ops.rs | 8 ++++---- src/arch/arm64/memory/heap.rs | 2 +- src/arch/arm64/mod.rs | 6 ++++-- 6 files changed, 23 insertions(+), 13 deletions(-) diff --git a/libkernel/src/lib.rs b/libkernel/src/lib.rs index f508a8a..9979254 100644 --- a/libkernel/src/lib.rs +++ b/libkernel/src/lib.rs @@ -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 } diff --git a/libkernel/src/sync/per_cpu.rs b/libkernel/src/sync/per_cpu.rs index 13630fc..70f8496 100644 --- a/libkernel/src/sync/per_cpu.rs +++ b/libkernel/src/sync/per_cpu.rs @@ -22,12 +22,12 @@ use crate::CpuOps; /// A wrapper for a RefCell guard (G) that restores interrupts on drop. pub struct IrqGuard { guard: ManuallyDrop, - flags: usize, + flags: CPU::InterruptFlags, _phantom: PhantomData, } impl IrqGuard { - 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>, - flags: usize, + flags: CPU::InterruptFlags, _phantom: PhantomData, } @@ -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()) } diff --git a/libkernel/src/sync/spinlock.rs b/libkernel/src/sync/spinlock.rs index 0ba14b0..6712454 100644 --- a/libkernel/src/sync/spinlock.rs +++ b/libkernel/src/sync/spinlock.rs @@ -66,7 +66,7 @@ impl SpinLockIrq { #[must_use] pub struct SpinLockIrqGuard<'a, T: ?Sized + 'a, CPU: CpuOps> { lock: &'a SpinLockIrq, - irq_flags: usize, // The saved DAIF register state + irq_flags: CPU::InterruptFlags, _marker: PhantomData<*const ()>, // !Send } diff --git a/src/arch/arm64/cpu_ops.rs b/src/arch/arm64/cpu_ops.rs index 2ac3ecf..b9ebc95 100644 --- a/src/arch/arm64/cpu_ops.rs +++ b/src/arch/arm64/cpu_ops.rs @@ -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) ); } diff --git a/src/arch/arm64/memory/heap.rs b/src/arch/arm64/memory/heap.rs index d0b179a..c8b367f 100644 --- a/src/arch/arm64/memory/heap.rs +++ b/src/arch/arm64/memory/heap.rs @@ -30,7 +30,7 @@ impl SlabGetter for StaticSlabGet } pub struct PerCpuCache { - flags: usize, + flags: u64, } impl PerCpuCache { diff --git a/src/arch/arm64/mod.rs b/src/arch/arm64/mod.rs index f23db95..e01c8a2 100644 --- a/src/arch/arm64/mod.rs +++ b/src/arch/arm64/mod.rs @@ -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); }