Skip to content

Commit

Permalink
Add lock_with_ipl macro to easily create a OnDrop type to elevate IPL…
Browse files Browse the repository at this point in the history
… while holding a lock and rename spl to ipl
  • Loading branch information
Lockna committed Jan 17, 2024
1 parent 592ea24 commit d732bdb
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 13 deletions.
6 changes: 3 additions & 3 deletions xernel/kernel/src/arch/amd64/interrupts/dpc.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use alloc::boxed::Box;

use crate::{
arch::amd64::interrupts::ipl::{raise_spl, set_ipl, IPL},
arch::amd64::interrupts::ipl::{raise_ipl, set_ipl, IPL},
cpu::{current_cpu, PerCpu},
sched::scheduler::switch_threads,
};
Expand Down Expand Up @@ -43,10 +43,10 @@ impl<T> Dpc<T> {
pub fn dpc_interrupt_dispatch() {
let cpu = current_cpu();

let ipl = raise_spl(IPL::IPLDPC);
let ipl = raise_ipl(IPL::IPLDPC);

while let Some(dpc) = {
let old = raise_spl(IPL::IPLHigh);
let old = raise_ipl(IPL::IPLHigh);
let mut lock = cpu.dpc_queue.write();
let dpc = lock.dequeue();
set_ipl(old);
Expand Down
30 changes: 23 additions & 7 deletions xernel/kernel/src/arch/amd64/interrupts/ipl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,22 @@ use crate::cpu::current_cpu;

use super::dpc::dpc_interrupt_dispatch;

#[macro_export]
macro_rules! lock_with_ipl {
($name:ident) => {
{
let old = raise_ipl(IPL::IPLDPC);
OnDrop::new($name.lock(), || { set_ipl(old); })
}
};
($name:ident, $ipl:expr) => {
{
let _ = raise_ipl(IPL::IPLDPC);
OnDrop::new($name.lock(), || { set_ipl($ipl); })
}
};
}

#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
#[repr(u8)]
pub enum IPL {
Expand Down Expand Up @@ -41,7 +57,7 @@ impl From<u8> for IPL {
}
}

pub fn get_spl() -> IPL {
pub fn get_ipl() -> IPL {
let ipl: u64;

unsafe {
Expand All @@ -53,7 +69,7 @@ pub fn get_spl() -> IPL {

pub fn set_ipl(ipl: IPL) -> IPL {
let requested_ipl = ipl as u64;
let old_ipl = get_spl() as u64;
let old_ipl = get_ipl() as u64;

unsafe {
asm!("mov cr8, {}", in(reg) requested_ipl, options(nomem, nostack, preserves_flags));
Expand All @@ -66,13 +82,13 @@ pub fn set_ipl(ipl: IPL) -> IPL {
IPL::from(old_ipl)
}

pub fn raise_spl(spl: IPL) -> IPL {
let old_ipl = get_spl();
pub fn raise_ipl(ipl: IPL) -> IPL {
let old_ipl = get_ipl();

assert!(old_ipl as u64 <= spl as u64);
assert!(old_ipl as u64 <= ipl as u64);

if old_ipl < spl {
set_ipl(spl);
if old_ipl < ipl {
set_ipl(ipl);
}

old_ipl
Expand Down
6 changes: 3 additions & 3 deletions xernel/kernel/src/arch/amd64/interrupts/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use core::sync::atomic::{compiler_fence, Ordering};
use idt::{IRQHandler, IDT_ENTRIES};
use ipl::IPL;

use self::ipl::{get_spl, raise_spl, set_ipl};
use self::ipl::{get_ipl, raise_ipl, set_ipl};

use super::apic::apic_spurious_interrupt;
use libxernel::sync::{Spinlock, SpinlockIRQ};
Expand All @@ -33,11 +33,11 @@ pub fn init() {
extern "sysv64" fn generic_interrupt_handler(isr: usize, ctx: *mut TrapFrame) {
let mut ipl = IPL::from(isr >> 4);

if (ipl as u8) < (get_spl() as u8) {
if (ipl as u8) < (get_ipl() as u8) {
panic!("IPL not less or equal");
}

ipl = raise_spl(ipl);
ipl = raise_ipl(ipl);

let handlers = INTERRUPT_HANDLERS.lock();

Expand Down

0 comments on commit d732bdb

Please sign in to comment.