From b64809e9b56217f4cfd3f4c2dd064488b1e375e5 Mon Sep 17 00:00:00 2001 From: Garen Tyler Date: Thu, 9 Nov 2023 18:49:52 -0700 Subject: [PATCH] move start and timer into arch --- kernel/rustkernel/src/arch/riscv/clint.rs | 52 ++++++++++++ kernel/rustkernel/src/arch/riscv/memlayout.rs | 7 -- kernel/rustkernel/src/arch/riscv/mod.rs | 2 + kernel/rustkernel/src/arch/riscv/start.rs | 41 ++++++++++ kernel/rustkernel/src/lib.rs | 1 - kernel/rustkernel/src/mem/virtual_memory.rs | 19 +---- kernel/rustkernel/src/start.rs | 82 ------------------- 7 files changed, 99 insertions(+), 105 deletions(-) create mode 100644 kernel/rustkernel/src/arch/riscv/clint.rs create mode 100644 kernel/rustkernel/src/arch/riscv/start.rs delete mode 100644 kernel/rustkernel/src/start.rs diff --git a/kernel/rustkernel/src/arch/riscv/clint.rs b/kernel/rustkernel/src/arch/riscv/clint.rs new file mode 100644 index 0000000..45a9e78 --- /dev/null +++ b/kernel/rustkernel/src/arch/riscv/clint.rs @@ -0,0 +1,52 @@ +use super::{asm, MIE_MTIE, MSTATUS_MIE}; +use crate::NCPU; +use core::ptr::addr_of; + +// Core Local Interrupter (CLINT), which contains the timer. +pub const CLINT: usize = 0x2000000; +const CLINT_MTIME: usize = CLINT + 0xbff8; + +extern "C" { + pub fn timervec(); +} + +#[no_mangle] +pub static mut timer_scratch: [[u64; 5]; NCPU] = [[0u64; 5]; NCPU]; + +fn clint_mtimecmp(hartid: usize) -> *mut u64 { + (CLINT + 0x4000 + (8 * hartid)) as *mut u64 +} + +/// Arrange to receive timer interrupts. +/// +/// They will arrive in machine mode at +/// at timervec in kernelvec.S, +/// which turns them into software interrupts for +/// devintr() in trap.c. +pub unsafe fn timerinit() { + // Each CPU has a separate source of timer interrupts. + let id = asm::r_mhartid() as usize; + + // Ask the CLINT for a timer interrupt. + // cycles, about 1/10th second in qemu + let interval = 1_000_000u64; + *clint_mtimecmp(id) = *(CLINT_MTIME as *const u64) + interval; + + // Prepare information in scratch[] for timervec. + // scratch[0..=2]: Space for timervec to save registers. + // scratch[3]: Address of CLINT MTIMECMP register. + // scratch[4]: Desired interval (in cycles) between timer interrupts. + let scratch: &mut [u64; 5] = &mut timer_scratch[id]; + scratch[3] = clint_mtimecmp(id) as usize as u64; + scratch[4] = interval; + asm::w_mscratch(addr_of!(scratch[0]) as usize as u64); + + // Set the machine-mode trap handler. + asm::w_mtvec(timervec as usize as u64); + + // Enable machine-mode interrupts. + asm::w_mstatus(asm::r_mstatus() | MSTATUS_MIE); + + // Enable machine-mode timer interrupts. + asm::w_mie(asm::r_mie() | MIE_MTIE); +} diff --git a/kernel/rustkernel/src/arch/riscv/memlayout.rs b/kernel/rustkernel/src/arch/riscv/memlayout.rs index e5bfd0a..64901fb 100644 --- a/kernel/rustkernel/src/arch/riscv/memlayout.rs +++ b/kernel/rustkernel/src/arch/riscv/memlayout.rs @@ -29,13 +29,6 @@ pub const UART0_IRQ: usize = 10; pub const VIRTIO0: usize = 0x10001000; pub const VIRTIO0_IRQ: usize = 1; -// Core Local Interrupter (CLINT), which contains the timer. -pub const CLINT: u64 = 0x2000000; -pub const CLINT_MTIME: u64 = CLINT + 0xbff8; -pub fn clint_mtimecmp(hartid: u64) -> u64 { - CLINT + 0x4000 + (8 * 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/mod.rs b/kernel/rustkernel/src/arch/riscv/mod.rs index ba5d4ee..c982135 100644 --- a/kernel/rustkernel/src/arch/riscv/mod.rs +++ b/kernel/rustkernel/src/arch/riscv/mod.rs @@ -1,6 +1,8 @@ pub mod asm; +pub mod clint; pub mod memlayout; pub mod plic; +pub mod start; pub use asm::*; pub use memlayout::*; diff --git a/kernel/rustkernel/src/arch/riscv/start.rs b/kernel/rustkernel/src/arch/riscv/start.rs new file mode 100644 index 0000000..784ac8d --- /dev/null +++ b/kernel/rustkernel/src/arch/riscv/start.rs @@ -0,0 +1,41 @@ +use super::{asm, clint, MSTATUS_MPP_MASK, MSTATUS_MPP_S, SIE_SEIE, SIE_SSIE, SIE_STIE}; +use crate::{main, NCPU}; +use core::arch::asm; + +#[no_mangle] +pub static mut stack0: [u8; 4096 * NCPU] = [0u8; 4096 * NCPU]; + +// entry.S jumps here in machine mode on stack0 +#[no_mangle] +pub unsafe extern "C" fn start() { + // Set M Previous Privilege mode to Supervisor, for mret. + let mut x = asm::r_mstatus(); + x &= !MSTATUS_MPP_MASK; + x |= MSTATUS_MPP_S; + asm::w_mstatus(x); + + // Set M Exception Program Counter to main, for mret. + asm::w_mepc(main as usize as u64); + + // Disable paging for now. + asm::w_satp(0); + + // Delegate all interrupts and exceptions to supervisor mode. + asm::w_medeleg(0xffffu64); + asm::w_mideleg(0xffffu64); + asm::w_sie(asm::r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE); + + // Configure Physical Memory Protection to give + // supervisor mode access to all of physical memory. + asm::w_pmpaddr0(0x3fffffffffffffu64); + asm::w_pmpcfg0(0xf); + + // Ask for clock interrupts. + clint::timerinit(); + + // Keep each CPU's hartid in its tp register, for Cpu::current_id(). + asm::w_tp(asm::r_mhartid()); + + // Switch to supervisor mode and jump to main(). + asm!("mret"); +} diff --git a/kernel/rustkernel/src/lib.rs b/kernel/rustkernel/src/lib.rs index 62cc173..2d72fb2 100644 --- a/kernel/rustkernel/src/lib.rs +++ b/kernel/rustkernel/src/lib.rs @@ -15,7 +15,6 @@ mod io; mod mem; mod proc; mod queue; -mod start; mod string; mod sync; mod syscall; diff --git a/kernel/rustkernel/src/mem/virtual_memory.rs b/kernel/rustkernel/src/mem/virtual_memory.rs index 7cebc6a..18450ec 100644 --- a/kernel/rustkernel/src/mem/virtual_memory.rs +++ b/kernel/rustkernel/src/mem/virtual_memory.rs @@ -1,21 +1,10 @@ use crate::{ arch::riscv::{ - memlayout::{KERNBASE, PHYSTOP, TRAMPOLINE, UART0, VIRTIO0, QEMU_POWER}, + asm, make_satp, + memlayout::{KERNBASE, PHYSTOP, QEMU_POWER, TRAMPOLINE, UART0, VIRTIO0}, + pg_round_down, pg_round_up, 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, + pte2pa, Pagetable, PagetableEntry, MAXVA, PGSIZE, PTE_R, PTE_U, PTE_V, PTE_W, PTE_X, }, mem::{ kalloc::{kalloc, kfree}, diff --git a/kernel/rustkernel/src/start.rs b/kernel/rustkernel/src/start.rs deleted file mode 100644 index 70f84c1..0000000 --- a/kernel/rustkernel/src/start.rs +++ /dev/null @@ -1,82 +0,0 @@ -use crate::{arch::riscv::*, main, NCPU}; -use core::{arch::asm, ptr::addr_of}; - -extern "C" { - pub fn timervec(); -} - -#[no_mangle] -pub static mut timer_scratch: [[u64; 5]; NCPU] = [[0u64; 5]; NCPU]; - -// The original C has this aligned to 16 - hopefully that's not a problem. -#[no_mangle] -pub static mut stack0: [u8; 4096 * NCPU] = [0u8; 4096 * NCPU]; - -// entry.S jumps here in machine mode on stack0 -#[no_mangle] -pub unsafe extern "C" fn start() { - // Set M Previous Privilege mode to Supervisor, for mret. - let mut x = r_mstatus(); - x &= !MSTATUS_MPP_MASK; - x |= MSTATUS_MPP_S; - w_mstatus(x); - - // Set M Exception Program Counter to main, for mret. - w_mepc(main as usize as u64); - - // Disable paging for now. - w_satp(0); - - // Delegate all interrupts and exceptions to supervisor mode. - w_medeleg(0xffffu64); - w_mideleg(0xffffu64); - w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE); - - // Configure Physical Memory Protection to give - // supervisor mode access to all of physical memory. - w_pmpaddr0(0x3fffffffffffffu64); - w_pmpcfg0(0xf); - - // Ask for clock interrupts. - timerinit(); - - // Keep each CPU's hartid in its tp register, for Cpu::current_id(). - w_tp(r_mhartid()); - - // Switch to supervisor mode and jump to main(). - asm!("mret"); -} - -/// Arrange to receive timer interrupts. -/// -/// They will arrive in machine mode at -/// at timervec in kernelvec.S, -/// which turns them into software interrupts for -/// devintr() in trap.c. -pub unsafe fn timerinit() { - // Each CPU has a separate source of timer interrupts. - let id = r_mhartid(); - - // Ask the CLINT for a timer interrupt. - // cycles, about 1/10th second in qemu - let interval = 1_000_000u64; - *(clint_mtimecmp(id) as *mut u64) = *(CLINT_MTIME as *const u64) + interval; - - // Prepare information in scratch[] for timervec. - // scratch[0..=2]: Space for timervec to save registers. - // scratch[3]: Address of CLINT MTIMECMP register. - // scratch[4]: Desired interval (in cycles) between timer interrupts. - let scratch: &mut [u64; 5] = &mut timer_scratch[id as usize]; - scratch[3] = clint_mtimecmp(id); - scratch[4] = interval; - w_mscratch(addr_of!(scratch[0]) as usize as u64); - - // Set the machine-mode trap handler. - w_mtvec(timervec as usize as u64); - - // Enable machine-mode interrupts. - w_mstatus(r_mstatus() | MSTATUS_MIE); - - // Enable machine-mode timer interrupts. - w_mie(r_mie() | MIE_MTIE); -}