diff --git a/kernel/src/drivers/irq/plic.rs b/kernel/src/drivers/irq/plic.rs index f8de629..28ca3d0 100644 --- a/kernel/src/drivers/irq/plic.rs +++ b/kernel/src/drivers/irq/plic.rs @@ -2,6 +2,7 @@ use super::IrqDriver; use crate::drivers::Driver; use crate::entry::HART_ID; use crate::plat::irq::IrqController; +use core::sync::atomic::{AtomicPtr, Ordering}; use fdt::{node::FdtNode, Fdt}; use log::trace; @@ -27,17 +28,35 @@ struct PlicCtrl { pub struct IrqPlic where IrqPlic: IrqDriver { - priority: *mut u32, - pending: *mut u32, - enable: *mut u32, - control: *mut PlicCtrl, + priority: AtomicPtr, + pending: AtomicPtr, + enable: AtomicPtr, + control: AtomicPtr, nr_irqs: usize, } +impl IrqPlic { + fn priority(&self) -> *mut u32 { + self.priority.load(Ordering::Relaxed) + } + + fn pending(&self) -> *mut u32 { + self.pending.load(Ordering::Relaxed) + } + + fn enable(&self) -> *mut u32 { + self.enable.load(Ordering::Relaxed) + } + + fn control(&self) -> *mut PlicCtrl { + self.control.load(Ordering::Relaxed) + } +} + impl Driver for IrqPlic { fn compatible() -> &'static [&'static str] { - &["riscv,plic0"] + &["sifive,plic-1.0.0", "riscv,plic0"] } fn setup(node: FdtNode, fdt: &Fdt) -> Self { @@ -88,11 +107,16 @@ impl Driver for IrqPlic { let ctx_id = ctx_id.expect("No PLIC context found for us"); + let priority = unsafe { base_address.add(PLIC_PRIORITY_OFFSET) as *mut u32 }; + let pending = unsafe { base_address.add(PLIC_PENDING_OFFSET) as *mut u32 }; + let enable = unsafe { base_address.add(PLIC_ENABLE_OFFSET + ctx_id * PLIC_ENABLE_STRIDE) as *mut u32 }; + let control = unsafe { (base_address.add(PLIC_CONTROL_OFFSET) as *mut PlicCtrl).add(ctx_id) }; + Self { - priority: unsafe { base_address.add(PLIC_PRIORITY_OFFSET) as *mut u32 }, - pending: unsafe { base_address.add(PLIC_PENDING_OFFSET) as *mut u32 }, - enable: unsafe { base_address.add(PLIC_ENABLE_OFFSET + ctx_id * PLIC_ENABLE_STRIDE) as *mut u32 }, - control: unsafe { (base_address.add(PLIC_CONTROL_OFFSET) as *mut PlicCtrl).add(ctx_id) }, + priority: AtomicPtr::new(priority), + pending: AtomicPtr::new(pending), + enable: AtomicPtr::new(enable), + control: AtomicPtr::new(control), nr_irqs: nr_irqs.unwrap(), } } @@ -107,9 +131,9 @@ impl IrqController for IrqPlic { let word = irq / 32; let bit = irq % 32; - let val = unsafe { self.enable.add(word).read_volatile() }; + let val = unsafe { IrqPlic::enable(self).add(word).read_volatile() }; let val = val | (1 << bit); - unsafe { self.enable.add(word).write_volatile(val) }; + unsafe { IrqPlic::enable(self).add(word).write_volatile(val) }; } fn disable(&mut self, irq: usize) { @@ -120,9 +144,9 @@ impl IrqController for IrqPlic { let word = irq / 32; let bit = irq % 32; - let val = unsafe { self.enable.add(word).read_volatile() }; + let val = unsafe { IrqPlic::enable(self).add(word).read_volatile() }; let val = val & !(1 << bit); - unsafe { self.enable.add(word).write_volatile(val) }; + unsafe { IrqPlic::enable(self).add(word).write_volatile(val) }; } fn is_pending(&mut self, irq: usize) -> bool { @@ -133,12 +157,12 @@ impl IrqController for IrqPlic { let word = irq / 32; let bit = irq % 32; - let val = unsafe { self.pending.add(word).read_volatile() }; + let val = unsafe { IrqPlic::pending(self).add(word).read_volatile() }; val & (1 << bit) != 0 } fn claim(&mut self) -> Option { - let val = unsafe { self.control.as_ref().unwrap().claim.read_volatile() }; + let val = unsafe { IrqPlic::control(self).as_ref().unwrap().claim.read_volatile() }; if val > 0 { Some(val as usize) @@ -153,7 +177,7 @@ impl IrqController for IrqPlic { } let val = irq as u32; - unsafe { self.control.as_ref().unwrap().claim.write_volatile(val) }; + unsafe { IrqPlic::control(self).as_ref().unwrap().claim.write_volatile(val) }; } } diff --git a/kernel/src/plat/irq.rs b/kernel/src/plat/irq.rs index 9524f39..a5b7978 100644 --- a/kernel/src/plat/irq.rs +++ b/kernel/src/plat/irq.rs @@ -1,6 +1,7 @@ use super::utils::generate_driver; use crate::drivers::irq::IrqPlic; use crate::objects::*; +use spin::{lazy::Lazy, Mutex}; const IRQ_NUM: usize = 32; @@ -15,7 +16,7 @@ pub enum IrqState { generate_driver!( IrqDriver { (IrqPlic), - () + (DummyIrqDriver) } : IrqController { fn enable(&mut self, irq: usize) -> (); fn disable(&mut self, irq: usize) -> (); @@ -25,11 +26,33 @@ generate_driver!( } ); +pub struct DummyIrqDriver; + +impl IrqController for DummyIrqDriver { + fn enable(&mut self, _: usize) {} + fn disable(&mut self, _: usize) {} + fn is_pending(&mut self, _: usize) -> bool { + false + } + fn claim(&mut self) -> Option { + None + } + fn complete(&mut self, _: usize) {} +} + +static IRQ_DRIVER: Mutex = Mutex::new(IrqDriver::DummyIrqDriver(DummyIrqDriver)); + +pub fn set_irq_driver(driver: IrqDriver) { + *IRQ_DRIVER.lock() = driver; +} + pub struct IrqManager { handler: [CapEntry; IRQ_NUM], state: [IrqState; IRQ_NUM], } +pub static IRQ_MANAGER: Mutex> = Mutex::new(Lazy::new(IrqManager::new)); + impl IrqManager { pub fn new() -> Self { Self {