feat: kernel/drivers/irq: switch to atomic ptr

This commit is contained in:
Paul Pan 2024-08-23 11:09:58 +08:00
parent 3da5eec0eb
commit bb54000486
2 changed files with 64 additions and 17 deletions

View File

@ -2,6 +2,7 @@ use super::IrqDriver;
use crate::drivers::Driver; use crate::drivers::Driver;
use crate::entry::HART_ID; use crate::entry::HART_ID;
use crate::plat::irq::IrqController; use crate::plat::irq::IrqController;
use core::sync::atomic::{AtomicPtr, Ordering};
use fdt::{node::FdtNode, Fdt}; use fdt::{node::FdtNode, Fdt};
use log::trace; use log::trace;
@ -27,17 +28,35 @@ struct PlicCtrl {
pub struct IrqPlic pub struct IrqPlic
where IrqPlic: IrqDriver where IrqPlic: IrqDriver
{ {
priority: *mut u32, priority: AtomicPtr<u32>,
pending: *mut u32, pending: AtomicPtr<u32>,
enable: *mut u32, enable: AtomicPtr<u32>,
control: *mut PlicCtrl, control: AtomicPtr<PlicCtrl>,
nr_irqs: usize, 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 { impl Driver for IrqPlic {
fn compatible() -> &'static [&'static str] { fn compatible() -> &'static [&'static str] {
&["riscv,plic0"] &["sifive,plic-1.0.0", "riscv,plic0"]
} }
fn setup(node: FdtNode, fdt: &Fdt) -> Self { 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 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 { Self {
priority: unsafe { base_address.add(PLIC_PRIORITY_OFFSET) as *mut u32 }, priority: AtomicPtr::new(priority),
pending: unsafe { base_address.add(PLIC_PENDING_OFFSET) as *mut u32 }, pending: AtomicPtr::new(pending),
enable: unsafe { base_address.add(PLIC_ENABLE_OFFSET + ctx_id * PLIC_ENABLE_STRIDE) as *mut u32 }, enable: AtomicPtr::new(enable),
control: unsafe { (base_address.add(PLIC_CONTROL_OFFSET) as *mut PlicCtrl).add(ctx_id) }, control: AtomicPtr::new(control),
nr_irqs: nr_irqs.unwrap(), nr_irqs: nr_irqs.unwrap(),
} }
} }
@ -107,9 +131,9 @@ impl IrqController for IrqPlic {
let word = irq / 32; let word = irq / 32;
let bit = 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); 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) { fn disable(&mut self, irq: usize) {
@ -120,9 +144,9 @@ impl IrqController for IrqPlic {
let word = irq / 32; let word = irq / 32;
let bit = 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); 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 { fn is_pending(&mut self, irq: usize) -> bool {
@ -133,12 +157,12 @@ impl IrqController for IrqPlic {
let word = irq / 32; let word = irq / 32;
let bit = 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 val & (1 << bit) != 0
} }
fn claim(&mut self) -> Option<usize> { fn claim(&mut self) -> Option<usize> {
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 { if val > 0 {
Some(val as usize) Some(val as usize)
@ -153,7 +177,7 @@ impl IrqController for IrqPlic {
} }
let val = irq as u32; 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) };
} }
} }

View File

@ -1,6 +1,7 @@
use super::utils::generate_driver; use super::utils::generate_driver;
use crate::drivers::irq::IrqPlic; use crate::drivers::irq::IrqPlic;
use crate::objects::*; use crate::objects::*;
use spin::{lazy::Lazy, Mutex};
const IRQ_NUM: usize = 32; const IRQ_NUM: usize = 32;
@ -15,7 +16,7 @@ pub enum IrqState {
generate_driver!( generate_driver!(
IrqDriver { IrqDriver {
(IrqPlic), (IrqPlic),
() (DummyIrqDriver)
} : IrqController { } : IrqController {
fn enable(&mut self, irq: usize) -> (); fn enable(&mut self, irq: usize) -> ();
fn disable(&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<usize> {
None
}
fn complete(&mut self, _: usize) {}
}
static IRQ_DRIVER: Mutex<IrqDriver> = Mutex::new(IrqDriver::DummyIrqDriver(DummyIrqDriver));
pub fn set_irq_driver(driver: IrqDriver) {
*IRQ_DRIVER.lock() = driver;
}
pub struct IrqManager { pub struct IrqManager {
handler: [CapEntry; IRQ_NUM], handler: [CapEntry; IRQ_NUM],
state: [IrqState; IRQ_NUM], state: [IrqState; IRQ_NUM],
} }
pub static IRQ_MANAGER: Mutex<Lazy<IrqManager>> = Mutex::new(Lazy::new(IrqManager::new));
impl IrqManager { impl IrqManager {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {