mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
feat: kernel/drivers/irq: switch to atomic ptr
This commit is contained in:
parent
3da5eec0eb
commit
bb54000486
@ -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) };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user