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::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) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user