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_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.
|
||||
|
@ -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::*;
|
||||
|
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 proc;
|
||||
mod queue;
|
||||
mod start;
|
||||
mod string;
|
||||
mod sync;
|
||||
mod syscall;
|
||||
|
@ -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},
|
||||
|
@ -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