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]
|
[dependencies]
|
||||||
contracts = "0.6.3"
|
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"
|
.attribute arch, "rv64gc"
|
||||||
|
|
||||||
.section .text.start
|
.section .text.start
|
||||||
|
|
|
@ -1,8 +1,13 @@
|
||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
|
||||||
|
mod riscv;
|
||||||
|
mod timer;
|
||||||
|
|
||||||
use core::{arch::global_asm, panic::PanicInfo, ptr};
|
use core::{arch::global_asm, panic::PanicInfo, ptr};
|
||||||
|
|
||||||
|
use timer::timer_init;
|
||||||
|
|
||||||
global_asm!(include_str!("asm/entry.S"));
|
global_asm!(include_str!("asm/entry.S"));
|
||||||
|
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
|
@ -15,6 +20,8 @@ static HELLO: &[u8] = b"meow\n";
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub unsafe extern "C" fn start() -> ! {
|
pub unsafe extern "C" fn start() -> ! {
|
||||||
|
timer_init();
|
||||||
|
|
||||||
for c in HELLO.iter() {
|
for c in HELLO.iter() {
|
||||||
while ptr::read_volatile((UART0 + 5) as *const u8) & (1 << 5) == 0 {}
|
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