add some more docs about timer
This commit is contained in:
parent
e90a19d3a2
commit
f9fba69adb
7 changed files with 72 additions and 0 deletions
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"rust-analyzer.cargo.allTargets": false,
|
||||
"rust-analyzer.cargo.extraArgs": [
|
||||
"--target",
|
||||
"riscv64gc-unknown-none-elf"
|
||||
]
|
||||
}
|
|
@ -11,3 +11,5 @@ panic = "abort"
|
|||
|
||||
[dependencies]
|
||||
contracts = "0.6.3"
|
||||
|
||||
[features]
|
||||
|
|
6
scripts/start.ps1
Normal file
6
scripts/start.ps1
Normal file
|
@ -0,0 +1,6 @@
|
|||
qemu-system-riscv64.exe `
|
||||
-nographic `
|
||||
-machine virt `
|
||||
-bios none `
|
||||
-m 3G `
|
||||
-kernel "$($args[0])"
|
|
@ -1,3 +1,12 @@
|
|||
// This is the assembly entry point of the language
|
||||
|
||||
// It is "called" by:
|
||||
// 1. It's included as global_asm! into the kernel binary (see main.rs)
|
||||
// 2. It's set as the entry point as set by the ELF file in the linker script
|
||||
|
||||
// It then sets up a stack and calls the rust start
|
||||
// idk how the asm works yet, I just cribbed it from xv6
|
||||
|
||||
.attribute arch, "rv64gc"
|
||||
|
||||
.section .text.start
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
#![no_std]
|
||||
#![no_main]
|
||||
|
||||
mod riscv;
|
||||
mod timer;
|
||||
|
||||
use core::{arch::global_asm, panic::PanicInfo, ptr};
|
||||
|
||||
use timer::timer_init;
|
||||
|
||||
global_asm!(include_str!("asm/entry.S"));
|
||||
|
||||
#[panic_handler]
|
||||
|
@ -15,6 +20,8 @@ static HELLO: &[u8] = b"meow\n";
|
|||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn start() -> ! {
|
||||
timer_init();
|
||||
|
||||
for c in HELLO.iter() {
|
||||
while ptr::read_volatile((UART0 + 5) as *const u8) & (1 << 5) == 0 {}
|
||||
|
||||
|
|
21
src/riscv.rs
Normal file
21
src/riscv.rs
Normal file
|
@ -0,0 +1,21 @@
|
|||
// Here lie RISC-V-specific procedures and constants
|
||||
// Cribbed shamelessly from https://github.com/mit-pdos/xv6-riscv/blob/de247db5e6384b138f270e0a7c745989b5a9c23b/kernel/riscv.h#L99
|
||||
|
||||
use core::arch::asm;
|
||||
|
||||
/// Machine interrupt enable
|
||||
pub const MIE_STIE: u64 = 1 << 5;
|
||||
|
||||
/// Read from the "Machine interrupt-enable" register
|
||||
#[inline]
|
||||
pub unsafe fn r_mie() -> u64 {
|
||||
let value: u64;
|
||||
asm!("csrr {value}, mie", value = out(reg) value);
|
||||
value
|
||||
}
|
||||
|
||||
/// Write to the "Machine interrupt-enable" register
|
||||
#[inline]
|
||||
pub unsafe fn w_mie(value: u64) {
|
||||
asm!("csrw mie, {value}", value = in(reg) value)
|
||||
}
|
20
src/timer.rs
Normal file
20
src/timer.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
// Set up timer interrupts for pre-emption
|
||||
// Every now and then we want the timer to pause a running process
|
||||
// and return control to the operating system so we can do some scheduling
|
||||
// otherwise the process could retain full control for a very long time
|
||||
// and starve other processes
|
||||
|
||||
// This is done in xv6 here:
|
||||
// https://github.com/mit-pdos/xv6-riscv/blob/de247db5e6384b138f270e0a7c745989b5a9c23b/kernel/start.c#L53
|
||||
// This implementation seems to be using some CSR (control/status registers) in RISC-V
|
||||
// This page also documents some:
|
||||
// https://book.rvemu.app/hardware-components/03-csrs.html
|
||||
|
||||
use crate::riscv::{r_mie, w_mie, MIE_STIE};
|
||||
|
||||
/// Ask the hardware to provide clock interrupts
|
||||
pub fn timer_init() {
|
||||
unsafe {
|
||||
w_mie(r_mie() | MIE_STIE);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue