move start and timer into arch
This commit is contained in:
parent
20071883ab
commit
b64809e9b5
52
kernel/rustkernel/src/arch/riscv/clint.rs
Normal file
52
kernel/rustkernel/src/arch/riscv/clint.rs
Normal file
@ -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);
|
||||||
|
}
|
@ -29,13 +29,6 @@ pub const UART0_IRQ: usize = 10;
|
|||||||
pub const VIRTIO0: usize = 0x10001000;
|
pub const VIRTIO0: usize = 0x10001000;
|
||||||
pub const VIRTIO0_IRQ: usize = 1;
|
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
|
// The kernel expects there to be RAM
|
||||||
// for use by the kernel and user pages
|
// for use by the kernel and user pages
|
||||||
// from physical address 0x80000000 to PHYSTOP.
|
// from physical address 0x80000000 to PHYSTOP.
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
pub mod asm;
|
pub mod asm;
|
||||||
|
pub mod clint;
|
||||||
pub mod memlayout;
|
pub mod memlayout;
|
||||||
pub mod plic;
|
pub mod plic;
|
||||||
|
pub mod start;
|
||||||
|
|
||||||
pub use asm::*;
|
pub use asm::*;
|
||||||
pub use memlayout::*;
|
pub use memlayout::*;
|
||||||
|
41
kernel/rustkernel/src/arch/riscv/start.rs
Normal file
41
kernel/rustkernel/src/arch/riscv/start.rs
Normal file
@ -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");
|
||||||
|
}
|
@ -15,7 +15,6 @@ mod io;
|
|||||||
mod mem;
|
mod mem;
|
||||||
mod proc;
|
mod proc;
|
||||||
mod queue;
|
mod queue;
|
||||||
mod start;
|
|
||||||
mod string;
|
mod string;
|
||||||
mod sync;
|
mod sync;
|
||||||
mod syscall;
|
mod syscall;
|
||||||
|
@ -1,21 +1,10 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
arch::riscv::{
|
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,
|
plic::PLIC,
|
||||||
asm,
|
pte2pa, Pagetable, PagetableEntry, MAXVA, PGSIZE, PTE_R, PTE_U, PTE_V, PTE_W, PTE_X,
|
||||||
PGSIZE,
|
|
||||||
pg_round_down,
|
|
||||||
pg_round_up,
|
|
||||||
Pagetable,
|
|
||||||
PagetableEntry,
|
|
||||||
PTE_V,
|
|
||||||
PTE_R,
|
|
||||||
PTE_W,
|
|
||||||
PTE_X,
|
|
||||||
PTE_U,
|
|
||||||
MAXVA,
|
|
||||||
pte2pa,
|
|
||||||
make_satp,
|
|
||||||
},
|
},
|
||||||
mem::{
|
mem::{
|
||||||
kalloc::{kalloc, kfree},
|
kalloc::{kalloc, kfree},
|
||||||
|
@ -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);
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user