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::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<u32>,
pending: AtomicPtr<u32>,
enable: AtomicPtr<u32>,
control: AtomicPtr<PlicCtrl>,
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<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 {
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) };
}
}

View File

@ -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<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 {
handler: [CapEntry; IRQ_NUM],
state: [IrqState; IRQ_NUM],
}
pub static IRQ_MANAGER: Mutex<Lazy<IrqManager>> = Mutex::new(Lazy::new(IrqManager::new));
impl IrqManager {
pub fn new() -> Self {
Self {