restructure interrupt handling to be architecture-specific
This commit is contained in:
parent
33e1f3d318
commit
d3d9526ffa
10
kernel/rustkernel/src/arch/interrupt.rs
Normal file
10
kernel/rustkernel/src/arch/interrupt.rs
Normal file
@ -0,0 +1,10 @@
|
||||
//! Architecture-agnostic interrupt handling.
|
||||
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::plic::plic_claim as handle_interrupt;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::plic::plic_complete as complete_interrupt;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::plic::plicinit as init;
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub use super::riscv::plic::plicinithart as inithart;
|
@ -1 +1,4 @@
|
||||
#[cfg(target_arch = "riscv64")]
|
||||
pub mod riscv;
|
||||
|
||||
pub mod interrupt;
|
||||
|
@ -23,11 +23,11 @@ pub const QEMU_POWER: u64 = 0x100000u64;
|
||||
|
||||
// QEMU puts UART registers here in physical memory.
|
||||
pub const UART0: usize = 0x10000000;
|
||||
pub const UART0_IRQ: i32 = 10;
|
||||
pub const UART0_IRQ: usize = 10;
|
||||
|
||||
// Virtio MMIO interface
|
||||
pub const VIRTIO0: u64 = 0x10001000;
|
||||
pub const VIRTIO0_IRQ: i32 = 1;
|
||||
pub const VIRTIO0: usize = 0x10001000;
|
||||
pub const VIRTIO0_IRQ: usize = 1;
|
||||
|
||||
// Core Local Interrupter (CLINT), which contains the timer.
|
||||
pub const CLINT: u64 = 0x2000000;
|
||||
@ -36,29 +36,6 @@ pub fn clint_mtimecmp(hartid: u64) -> u64 {
|
||||
CLINT + 0x4000 + (8 * hartid)
|
||||
}
|
||||
|
||||
// QEMU puts platform-level interrupt controller (PLIC) here.
|
||||
pub const PLIC: u64 = 0x0c000000;
|
||||
pub const PLIC_PRIORITY: u64 = PLIC;
|
||||
pub const PLIC_PENDING: u64 = PLIC + 0x1000;
|
||||
pub fn plic_menable(hartid: u64) -> u64 {
|
||||
PLIC + 0x2000 + (0x100 * hartid)
|
||||
}
|
||||
pub fn plic_senable(hartid: u64) -> u64 {
|
||||
PLIC + 0x2080 + (0x100 * hartid)
|
||||
}
|
||||
pub fn plic_mpriority(hartid: u64) -> u64 {
|
||||
PLIC + 0x200000 + (0x2000 * hartid)
|
||||
}
|
||||
pub fn plic_spriority(hartid: u64) -> u64 {
|
||||
PLIC + 0x201000 + (0x2000 * hartid)
|
||||
}
|
||||
pub fn plic_mclaim(hartid: u64) -> u64 {
|
||||
PLIC + 0x200004 + (0x2000 * hartid)
|
||||
}
|
||||
pub fn plic_sclaim(hartid: u64) -> u64 {
|
||||
PLIC + 0x201004 + (0x2000 * hartid)
|
||||
}
|
||||
|
||||
// The kernel expects there to be RAM
|
||||
// for use by the kernel and user pages
|
||||
// from physical address 0x80000000 to PHYSTOP.
|
||||
|
@ -1,35 +1,67 @@
|
||||
//! The RISC-V Platform Level Interrupt Controller (PLIC)
|
||||
|
||||
use crate::{
|
||||
arch::riscv::{plic_sclaim, plic_senable, plic_spriority, PLIC, UART0_IRQ, VIRTIO0_IRQ},
|
||||
arch::riscv::{UART0_IRQ, VIRTIO0_IRQ},
|
||||
proc::cpu::Cpu,
|
||||
};
|
||||
|
||||
// QEMU puts platform-level interrupt controller (PLIC) here.
|
||||
pub const PLIC: usize = 0x0c000000;
|
||||
const PLIC_PRIORITY: usize = PLIC;
|
||||
const PLIC_PENDING: usize = PLIC + 0x1000;
|
||||
const UART0_IRQ_ADDR: usize = PLIC + UART0_IRQ * 4;
|
||||
const VIRTIO0_IRQ_ADDR: usize = PLIC + VIRTIO0_IRQ * 4;
|
||||
|
||||
/// Get a pointer to the CPU-specific machine-mode enable register.
|
||||
fn plic_menable(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x2000 + (0x100 * hartid)) as *mut u32
|
||||
}
|
||||
/// Get a pointer to the CPU-specific supervisor-mode enable register.
|
||||
fn plic_senable(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x2080 + (0x100 * hartid)) as *mut u32
|
||||
}
|
||||
/// Get a pointer to the CPU-specific machine-mode priority register.
|
||||
fn plic_mpriority(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x200000 + (0x2000 * hartid)) as *mut u32
|
||||
}
|
||||
/// Get a pointer to the CPU-specific supervisor-mode priority register.
|
||||
fn plic_spriority(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x201000 + (0x2000 * hartid)) as *mut u32
|
||||
}
|
||||
/// Get a pointer to the CPU-specific machine-mode claim register.
|
||||
fn plic_mclaim(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x200004 + (0x2000 * hartid)) as *mut u32
|
||||
}
|
||||
/// Get a pointer to the CPU-specific supervisor-mode claim register.
|
||||
fn plic_sclaim(hartid: usize) -> *mut u32 {
|
||||
(PLIC + 0x201004 + (0x2000 * hartid)) as *mut u32
|
||||
}
|
||||
|
||||
pub unsafe fn plicinit() {
|
||||
// Set desired IRQ priorities non-zero (otherwise disabled).
|
||||
*((PLIC + UART0_IRQ as u64 * 4) as *mut u32) = 1;
|
||||
*((PLIC + VIRTIO0_IRQ as u64 * 4) as *mut u32) = 1;
|
||||
*(UART0_IRQ_ADDR as *mut u32) = 1;
|
||||
*(VIRTIO0_IRQ_ADDR as *mut u32) = 1;
|
||||
}
|
||||
|
||||
pub unsafe fn plicinithart() {
|
||||
let hart = Cpu::current_id() as u64;
|
||||
let hart = Cpu::current_id();
|
||||
|
||||
// Set enable bits for this hart's S-mode
|
||||
// for the UART and VIRTIO disk.
|
||||
*(plic_senable(hart) as *mut u32) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
|
||||
*plic_senable(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
|
||||
|
||||
// Set this hart's S-mode priority threshold to 0.
|
||||
*(plic_spriority(hart) as *mut u32) = 0;
|
||||
*plic_spriority(hart) = 0;
|
||||
}
|
||||
|
||||
/// Ask the PLIC what interrupt we should serve.
|
||||
pub unsafe fn plic_claim() -> i32 {
|
||||
let hart = Cpu::current_id() as u64;
|
||||
*(plic_sclaim(hart) as *const i32)
|
||||
pub unsafe fn plic_claim() -> usize {
|
||||
let hart = Cpu::current_id();
|
||||
(*plic_sclaim(hart)) as usize
|
||||
}
|
||||
|
||||
/// Tell the PLIC we've served this IRQ.
|
||||
pub unsafe fn plic_complete(irq: i32) {
|
||||
let hart = Cpu::current_id() as u64;
|
||||
*(plic_sclaim(hart) as *mut i32) = irq;
|
||||
pub unsafe fn plic_complete(irq: usize) {
|
||||
let hart = Cpu::current_id();
|
||||
*plic_sclaim(hart) = irq as u32;
|
||||
}
|
||||
|
@ -1,8 +1,6 @@
|
||||
use crate::sync::lock::Lock;
|
||||
use core::ffi::{c_char, CStr};
|
||||
|
||||
pub use crate::panic;
|
||||
|
||||
pub static PRINT_LOCK: Lock = Lock::new();
|
||||
|
||||
/// Print out formatted text to the console.
|
||||
@ -55,7 +53,6 @@ macro_rules! uprintln {
|
||||
}
|
||||
pub(crate) use uprintln;
|
||||
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn printint(n: i32) {
|
||||
print!("{}", n);
|
||||
|
@ -24,7 +24,7 @@ mod trap;
|
||||
use crate::{proc::cpu::Cpu, sync::mutex::Mutex};
|
||||
use core::ffi::{c_char, CStr};
|
||||
|
||||
pub(crate) use crate::console::printf::{print, println, uprint, uprintln};
|
||||
pub(crate) use crate::console::printf::{print, println, uprintln};
|
||||
|
||||
pub static mut STARTED: bool = false;
|
||||
pub static PANICKED: Mutex<bool> = Mutex::new(false);
|
||||
@ -65,8 +65,8 @@ pub unsafe fn main() -> ! {
|
||||
mem::virtual_memory::kvminithart();
|
||||
proc::process::procinit();
|
||||
trap::trapinithart();
|
||||
arch::riscv::plic::plicinit();
|
||||
arch::riscv::plic::plicinithart();
|
||||
arch::interrupt::init();
|
||||
arch::interrupt::inithart();
|
||||
io::bio::binit();
|
||||
fs::iinit();
|
||||
fs::file::fileinit();
|
||||
@ -79,7 +79,7 @@ pub unsafe fn main() -> ! {
|
||||
}
|
||||
mem::virtual_memory::kvminithart();
|
||||
trap::trapinithart();
|
||||
arch::riscv::plic::plicinithart();
|
||||
arch::interrupt::inithart();
|
||||
}
|
||||
|
||||
proc::scheduler::scheduler();
|
||||
|
@ -1,7 +1,21 @@
|
||||
use crate::{
|
||||
arch::riscv::{
|
||||
memlayout::{KERNBASE, PHYSTOP, TRAMPOLINE},
|
||||
*,
|
||||
memlayout::{KERNBASE, PHYSTOP, TRAMPOLINE, UART0, VIRTIO0, QEMU_POWER},
|
||||
plic::PLIC,
|
||||
asm,
|
||||
PGSIZE,
|
||||
pg_round_down,
|
||||
pg_round_up,
|
||||
Pagetable,
|
||||
PagetableEntry,
|
||||
PTE_V,
|
||||
PTE_R,
|
||||
PTE_W,
|
||||
PTE_X,
|
||||
PTE_U,
|
||||
MAXVA,
|
||||
pte2pa,
|
||||
make_satp,
|
||||
},
|
||||
mem::{
|
||||
kalloc::{kalloc, kfree},
|
||||
@ -33,10 +47,22 @@ pub unsafe fn kvmmake() -> Pagetable {
|
||||
kvmmap(pagetable, UART0 as u64, UART0 as u64, PGSIZE, PTE_R | PTE_W);
|
||||
|
||||
// VirtIO MMIO disk interface
|
||||
kvmmap(pagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
|
||||
kvmmap(
|
||||
pagetable,
|
||||
VIRTIO0 as u64,
|
||||
VIRTIO0 as u64,
|
||||
PGSIZE,
|
||||
PTE_R | PTE_W,
|
||||
);
|
||||
|
||||
// PLIC
|
||||
kvmmap(pagetable, PLIC, PLIC, 0x400000u64, PTE_R | PTE_W);
|
||||
kvmmap(
|
||||
pagetable,
|
||||
PLIC as u64,
|
||||
PLIC as u64,
|
||||
0x400000u64,
|
||||
PTE_R | PTE_W,
|
||||
);
|
||||
|
||||
let etext_addr = addr_of!(etext) as usize as u64;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::{
|
||||
arch::riscv::*,
|
||||
arch::{self, riscv::*},
|
||||
println,
|
||||
proc::{
|
||||
cpu::Cpu,
|
||||
@ -49,7 +49,7 @@ pub unsafe fn devintr() -> i32 {
|
||||
// This is a supervisor external interrupt, via PLIC.
|
||||
|
||||
// IRQ indicates which device interrupted.
|
||||
let irq = plic::plic_claim();
|
||||
let irq = arch::interrupt::handle_interrupt();
|
||||
|
||||
if irq == UART0_IRQ {
|
||||
crate::console::uart::UART0.interrupt();
|
||||
@ -63,7 +63,7 @@ pub unsafe fn devintr() -> i32 {
|
||||
// interrupt at a time; tell the PLIC the device is
|
||||
// now allowed to interrupt again.
|
||||
if irq > 0 {
|
||||
plic::plic_complete(irq);
|
||||
arch::interrupt::complete_interrupt(irq);
|
||||
}
|
||||
|
||||
1
|
||||
|
Loading…
x
Reference in New Issue
Block a user