Compare commits

...

2 Commits

4 changed files with 45 additions and 27 deletions

4
.vscode/launch.json vendored
View File

@ -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": [
{

View File

@ -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 {

View File

@ -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) };
}
}

View File

@ -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) {