mirror of
https://github.com/panpaul/tiny_os
synced 2024-09-20 09:45:19 +08:00
Compare commits
2 Commits
9b2cca3f69
...
753515700f
Author | SHA1 | Date | |
---|---|---|---|
753515700f | |||
d0bf1b876b |
4
.vscode/launch.json
vendored
4
.vscode/launch.json
vendored
@ -9,7 +9,7 @@
|
||||
"program": "${workspaceFolder}/target/test_exe",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb-multiarch",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"miDebuggerServerAddress": "localhost:1234",
|
||||
"setupCommands": [
|
||||
{
|
||||
@ -35,7 +35,7 @@
|
||||
"program": "${workspaceFolder}/target/kernel_exe",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"MIMode": "gdb",
|
||||
"miDebuggerPath": "/usr/bin/gdb-multiarch",
|
||||
"miDebuggerPath": "/usr/bin/gdb",
|
||||
"miDebuggerServerAddress": "localhost:1234",
|
||||
"setupCommands": [
|
||||
{
|
||||
|
@ -29,7 +29,10 @@ impl TrapOps for Trap {
|
||||
// anyway, clear sscratch
|
||||
riscv::register::sscratch::write(0);
|
||||
// set trap_entry
|
||||
unsafe { riscv::register::stvec::write(trap_entry as usize, TrapMode::Direct) }
|
||||
unsafe { riscv::register::stvec::write(trap_entry as usize, TrapMode::Direct) };
|
||||
// enable interrupt
|
||||
unsafe { riscv::register::sie::set_ssoft() };
|
||||
unsafe { riscv::register::sie::set_sext() };
|
||||
}
|
||||
}
|
||||
|
||||
@ -88,6 +91,7 @@ impl TrapContextOps for TrapContext {
|
||||
},
|
||||
T::Interrupt(I::SupervisorExternal) => {
|
||||
// TODO: handle external interrupt, e.g. plic
|
||||
panic_fatal!("Unhandled External Interrupt");
|
||||
},
|
||||
T::Exception(E::InstructionPageFault) | T::Exception(E::LoadPageFault) | T::Exception(E::StorePageFault) => {
|
||||
if from_kernel {
|
||||
|
@ -1,10 +1,12 @@
|
||||
use super::IrqDriver;
|
||||
use crate::arch::layout::mmap_phys_to_virt;
|
||||
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;
|
||||
use utils::addr::PhysAddr;
|
||||
|
||||
const IRQ_OCCUPIED: usize = u32::MAX as usize; // OpenSBI will rewrite IRQ_M_EXT to this value
|
||||
const IRQ_S_EXT: usize = 9;
|
||||
@ -17,13 +19,6 @@ const PLIC_ENABLE_STRIDE: usize = 0x80;
|
||||
const PLIC_CONTROL_OFFSET: usize = 0x200000;
|
||||
const PLIC_CONTROL_STRIDE: usize = 0x1000;
|
||||
|
||||
#[repr(C, align(0x1000))]
|
||||
#[derive(Debug)]
|
||||
struct PlicCtrl {
|
||||
threshold: *mut u32,
|
||||
claim: *mut u32,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct IrqPlic
|
||||
where IrqPlic: IrqDriver
|
||||
@ -31,7 +26,8 @@ where IrqPlic: IrqDriver
|
||||
priority: AtomicPtr<u32>,
|
||||
pending: AtomicPtr<u32>,
|
||||
enable: AtomicPtr<u32>,
|
||||
control: AtomicPtr<PlicCtrl>,
|
||||
threshold: AtomicPtr<u32>,
|
||||
claim: AtomicPtr<u32>,
|
||||
|
||||
nr_irqs: usize,
|
||||
}
|
||||
@ -49,8 +45,12 @@ impl IrqPlic {
|
||||
self.enable.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn control(&self) -> *mut PlicCtrl {
|
||||
self.control.load(Ordering::Relaxed)
|
||||
fn threshold(&self) -> *mut u32 {
|
||||
self.threshold.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
fn claim(&self) -> *mut u32 {
|
||||
self.claim.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,7 +65,9 @@ impl Driver for IrqPlic {
|
||||
.expect("no PLIC base address available")
|
||||
.next()
|
||||
.unwrap()
|
||||
.starting_address as *mut u8;
|
||||
.starting_address;
|
||||
let base_address = unsafe { mmap_phys_to_virt(PhysAddr::from(base_address)) };
|
||||
let base_address: *mut u8 = base_address.into();
|
||||
|
||||
let nr_irqs = node
|
||||
.property("riscv,ndev")
|
||||
@ -110,13 +112,18 @@ impl Driver for IrqPlic {
|
||||
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) };
|
||||
let threshold = unsafe { base_address.add(PLIC_CONTROL_OFFSET + ctx_id * PLIC_CONTROL_STRIDE) as *mut u32 };
|
||||
let claim = unsafe { threshold.add(1) };
|
||||
|
||||
// Reset context threshold to 0
|
||||
unsafe { threshold.write_volatile(0) };
|
||||
|
||||
Self {
|
||||
priority: AtomicPtr::new(priority),
|
||||
pending: AtomicPtr::new(pending),
|
||||
enable: AtomicPtr::new(enable),
|
||||
control: AtomicPtr::new(control),
|
||||
threshold: AtomicPtr::new(threshold),
|
||||
claim: AtomicPtr::new(claim),
|
||||
nr_irqs: nr_irqs.unwrap(),
|
||||
}
|
||||
}
|
||||
@ -128,9 +135,12 @@ impl IrqController for IrqPlic {
|
||||
return;
|
||||
}
|
||||
|
||||
// set priority = 1
|
||||
unsafe { IrqPlic::priority(self).add(irq).write_volatile(1) };
|
||||
|
||||
// set enable = 1
|
||||
let word = irq / 32;
|
||||
let bit = irq % 32;
|
||||
|
||||
let val = unsafe { IrqPlic::enable(self).add(word).read_volatile() };
|
||||
let val = val | (1 << bit);
|
||||
unsafe { IrqPlic::enable(self).add(word).write_volatile(val) };
|
||||
@ -141,12 +151,15 @@ impl IrqController for IrqPlic {
|
||||
return;
|
||||
}
|
||||
|
||||
// set enable = 0
|
||||
let word = irq / 32;
|
||||
let bit = irq % 32;
|
||||
|
||||
let val = unsafe { IrqPlic::enable(self).add(word).read_volatile() };
|
||||
let val = val & !(1 << bit);
|
||||
unsafe { IrqPlic::enable(self).add(word).write_volatile(val) };
|
||||
|
||||
// set priority = 0
|
||||
unsafe { IrqPlic::priority(self).add(irq).write_volatile(0) };
|
||||
}
|
||||
|
||||
fn is_pending(&mut self, irq: usize) -> bool {
|
||||
@ -162,7 +175,7 @@ impl IrqController for IrqPlic {
|
||||
}
|
||||
|
||||
fn claim(&mut self) -> Option<usize> {
|
||||
let val = unsafe { IrqPlic::control(self).as_ref().unwrap().claim.read_volatile() };
|
||||
let val = unsafe { IrqPlic::claim(self).read_volatile() };
|
||||
|
||||
if val > 0 {
|
||||
Some(val as usize)
|
||||
@ -177,7 +190,7 @@ impl IrqController for IrqPlic {
|
||||
}
|
||||
|
||||
let val = irq as u32;
|
||||
unsafe { IrqPlic::control(self).as_ref().unwrap().claim.write_volatile(val) };
|
||||
unsafe { IrqPlic::claim(self).write_volatile(val) };
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,7 @@ impl IrqController for DummyIrqDriver {
|
||||
fn complete(&mut self, _: usize) {}
|
||||
}
|
||||
|
||||
// TODO: per-core irq driver
|
||||
static IRQ_DRIVER: Mutex<IrqDriver> = Mutex::new(IrqDriver::DummyIrqDriver(DummyIrqDriver));
|
||||
|
||||
pub fn set_irq_driver(driver: IrqDriver) {
|
||||
|
Loading…
Reference in New Issue
Block a user