move start and timer into arch

This commit is contained in:
Garen Tyler 2023-11-09 18:49:52 -07:00
parent 20071883ab
commit b64809e9b5
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
7 changed files with 99 additions and 105 deletions

View 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);
}

View File

@ -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.

View File

@ -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::*;

View 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");
}

View File

@ -15,7 +15,6 @@ mod io;
mod mem;
mod proc;
mod queue;
mod start;
mod string;
mod sync;
mod syscall;

View File

@ -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},

View File

@ -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);
}