diff --git a/kernel/rustkernel/src/arch/interrupt.rs b/kernel/rustkernel/src/arch/interrupt.rs new file mode 100644 index 0000000..b7869ca --- /dev/null +++ b/kernel/rustkernel/src/arch/interrupt.rs @@ -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; diff --git a/kernel/rustkernel/src/arch/mod.rs b/kernel/rustkernel/src/arch/mod.rs index fb27202..632c9a7 100644 --- a/kernel/rustkernel/src/arch/mod.rs +++ b/kernel/rustkernel/src/arch/mod.rs @@ -1 +1,4 @@ +#[cfg(target_arch = "riscv64")] pub mod riscv; + +pub mod interrupt; diff --git a/kernel/rustkernel/src/arch/riscv/memlayout.rs b/kernel/rustkernel/src/arch/riscv/memlayout.rs index 058e526..e5bfd0a 100644 --- a/kernel/rustkernel/src/arch/riscv/memlayout.rs +++ b/kernel/rustkernel/src/arch/riscv/memlayout.rs @@ -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. diff --git a/kernel/rustkernel/src/arch/riscv/plic.rs b/kernel/rustkernel/src/arch/riscv/plic.rs index 3729c72..1414f5f 100644 --- a/kernel/rustkernel/src/arch/riscv/plic.rs +++ b/kernel/rustkernel/src/arch/riscv/plic.rs @@ -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; } diff --git a/kernel/rustkernel/src/console/printf.rs b/kernel/rustkernel/src/console/printf.rs index eb25650..abf358e 100644 --- a/kernel/rustkernel/src/console/printf.rs +++ b/kernel/rustkernel/src/console/printf.rs @@ -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. @@ -40,7 +38,7 @@ macro_rules! uprint { // only uses the &mut reference immutably. let uart: *const Uart = &$crate::console::uart::UART0 as *const Uart; let uart: &mut Uart = unsafe { &mut *uart.cast_mut() }; - + let _ = core::write!(uart, $($arg)*); }}; } @@ -55,7 +53,6 @@ macro_rules! uprintln { } pub(crate) use uprintln; - #[no_mangle] pub extern "C" fn printint(n: i32) { print!("{}", n); diff --git a/kernel/rustkernel/src/lib.rs b/kernel/rustkernel/src/lib.rs index fca33ad..62cc173 100644 --- a/kernel/rustkernel/src/lib.rs +++ b/kernel/rustkernel/src/lib.rs @@ -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 = 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(); diff --git a/kernel/rustkernel/src/mem/virtual_memory.rs b/kernel/rustkernel/src/mem/virtual_memory.rs index b0d976e..7cebc6a 100644 --- a/kernel/rustkernel/src/mem/virtual_memory.rs +++ b/kernel/rustkernel/src/mem/virtual_memory.rs @@ -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; diff --git a/kernel/rustkernel/src/trap.rs b/kernel/rustkernel/src/trap.rs index 8573f88..7868503 100644 --- a/kernel/rustkernel/src/trap.rs +++ b/kernel/rustkernel/src/trap.rs @@ -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