Compare commits
No commits in common. "d2560cca8660ee5e6727dceef53fbae5a6463afe" and "304152dbeb25186be3f39264859e4cb002ff1c61" have entirely different histories.
d2560cca86
...
304152dbeb
Binary file not shown.
Before Width: | Height: | Size: 62 KiB |
33
README.md
33
README.md
|
@ -1,21 +1,38 @@
|
||||||
---
|
---
|
||||||
created: 2024-05-13T14:28:49-05:00
|
created: 2024-05-13T14:28:49-05:00
|
||||||
modified: 2024-05-19T17:41:01-05:00
|
modified: 2024-05-13T14:28:52-05:00
|
||||||
---
|
---
|
||||||
|
|
||||||
A kernel for RISC-V written in Rust. Currently focused on running on QEMU generic riscv64, advice and assistance welcome & encouraged.
|
A kernel for RISC-V written in Rust. Currently focused on running on QEMU generic riscv64, advice and assistance welcome & encouraged.
|
||||||
|
|
||||||
# Progress
|
# Reading list
|
||||||
|
|
||||||
* **2024-05-19:** As of right now, the basic "stuff" for initializing the kernel is there. The diagram below shows what I'm thinking as far as what the init process should be. This is what I'm currently working on implementing, and I will update this chart (and prettify it) more
|
## Beginner tutorial
|
||||||
|
- Meyer Zinn's RISC-V kernel guide (right now, code is just copied from this - will diverge later)
|
||||||
|
- [Part 0](https://www.meyerzinn.tech/posts/2023/03/05/running-rust-code-on-risc-v-in-qemu/)
|
||||||
|
- [Part 1](https://www.meyerzinn.tech/posts/2023/03/08/p1-printing-and-allocating/)
|
||||||
|
|
||||||
![Flowchart (tentatively) showing the plan for the kernel's initialization process. On the left is hart 0, the main hardware thread, and on the right is hart 1...n, all other hardware threads. All harts will set the global, stack, and thread pointers, disable paging, and set the mstatus and mepc control status registers, before doing their own independent init processes. Hart 0 will disable interrupts and enter the primary initialization function, kinit, before starting the first user process. Other harts will enable interrupts, do their own init, kinit_hart, then wait for a software inter-processor interrupt.](20240519-kernel_init_diagram.png)
|
## Other reading
|
||||||
|
- https://osblog.stephenmarz.com/ch1.html
|
||||||
|
- https://os.phil-opp.com/
|
||||||
|
- https://github.com/skyzh/core-os-riscv
|
||||||
|
- https://twilco.github.io/riscv-from-scratch/2019/04/27/riscv-from-scratch-2.html
|
||||||
|
- https://danielmangum.com/categories/risc-v-bytes/
|
||||||
|
|
||||||
# Research and implement
|
## RISC-V Spec
|
||||||
|
- [Volume I: Unprivileged](https://riscv.org/wp-content/uploads/2019/12/riscv-spec-20191213.pdf)
|
||||||
|
- [Volume II: Privileged](https://riscv.org/wp-content/uploads/2019/08/riscv-privileged-20190608-1.pdf)
|
||||||
|
|
||||||
|
## Videos
|
||||||
|
- [Sarah Jamie Lewis's "Let's Build An OS" series](https://www.youtube.com/watch?v=s_4tFz52jbc) (Note: it *can* run Doom)
|
||||||
|
- [Dr. Harry Porter's lectures on the xv6 kernel](https://www.youtube.com/watch?v=fWUJKH0RNFE&list=PLbtzT1TYeoMhTPzyTZboW_j7TPAnjv9XB)
|
||||||
|
- [LaurieWired's RISC-V Assembly primer](https://www.youtube.com/watch?v=0IeOaiKszLk)
|
||||||
|
|
||||||
|
# TODO Research and implement
|
||||||
|
|
||||||
- [ ] Basics
|
- [ ] Basics
|
||||||
- [ ] Processes
|
- [ ] Processes
|
||||||
- [ ] Virtual address spaces, page tables
|
- [ ] Virtual addrxess spaces, page tables
|
||||||
- [ ] Files, directories
|
- [ ] Files, directories
|
||||||
- [ ] Pipes
|
- [ ] Pipes
|
||||||
- [ ] Multitasking, time-slicing
|
- [ ] Multitasking, time-slicing
|
||||||
|
@ -29,7 +46,3 @@ A kernel for RISC-V written in Rust. Currently focused on running on QEMU generi
|
||||||
- [ ] Interprocess communication
|
- [ ] Interprocess communication
|
||||||
- [ ] Device drivers
|
- [ ] Device drivers
|
||||||
- [ ] User applications
|
- [ ] User applications
|
||||||
|
|
||||||
# Resources
|
|
||||||
|
|
||||||
See [RESOURCES.md](/RESOURCES.md)
|
|
26
RESOURCES.md
26
RESOURCES.md
|
@ -1,26 +0,0 @@
|
||||||
---
|
|
||||||
created: 2024-05-19T17:41:08-05:00
|
|
||||||
modified: 2024-05-19T17:41:12-05:00
|
|
||||||
---
|
|
||||||
|
|
||||||
# Reading list
|
|
||||||
|
|
||||||
In addition to the below list, I also heavily consulted the [RISC-V ISA specifications](https://riscv.org/technical/specifications/) which, at the time of writing, were last ratified and published on April 11, 2024.
|
|
||||||
|
|
||||||
## Guides
|
|
||||||
- [*Writing a RISC-V operating system kernel in Rust* series](https://www.meyerzinn.tech/posts/2023/03/04/rust-operating-system-intro/), Meyer Zinn, 2023
|
|
||||||
- [*The Adventures of OS*](https://osblog.stephenmarz.com/), Stephen Marz, 2019
|
|
||||||
- [*Writing an OS in Rust*](https://os.phil-opp.com/), Philipp Oppermann
|
|
||||||
|
|
||||||
## Other reading
|
|
||||||
- https://twilco.github.io/riscv-from-scratch/2019/04/27/riscv-from-scratch-2.html
|
|
||||||
- https://danielmangum.com/categories/risc-v-bytes/
|
|
||||||
|
|
||||||
## Other projects
|
|
||||||
- [skyzh/core-os-riscv](https://github.com/skyzh/core-os-riscv)
|
|
||||||
- [mit-pdos/xv6-riscv](https://github.com/mit-pdos/xv6-riscv)
|
|
||||||
|
|
||||||
## Videos
|
|
||||||
- [Sarah Jamie Lewis's "Let's Build An OS" series](https://www.youtube.com/watch?v=s_4tFz52jbc) (Note: it *can* run Doom)
|
|
||||||
- [Dr. Harry Porter's lectures on the xv6 kernel](https://www.youtube.com/watch?v=fWUJKH0RNFE&list=PLbtzT1TYeoMhTPzyTZboW_j7TPAnjv9XB)
|
|
||||||
- [LaurieWired's RISC-V Assembly primer](https://www.youtube.com/watch?v=0IeOaiKszLk)
|
|
114
src/entry.rs
114
src/entry.rs
|
@ -1,49 +1,54 @@
|
||||||
// src/entry.rs
|
// src/entry.rs
|
||||||
|
|
||||||
/// This is the first function called when the system boots. In this function,
|
|
||||||
/// we set up important control status registers (CSR) such as `mstatus` and
|
|
||||||
/// `satp`. The global, stack, and thread pointers are also configured here.
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".text.init"]
|
#[link_section = ".text.init"]
|
||||||
unsafe extern "C" fn entry() {
|
unsafe extern "C" fn _entry() {
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
use riscv::register::{mhartid, mstatus, satp, sstatus};
|
// let id = riscv::register::mhartid::read();
|
||||||
|
// write_tp(&id);
|
||||||
|
// TODO set up stack for all harts
|
||||||
|
// TODO set up CSRs for all harts
|
||||||
|
// if id != 0 { abort(); }
|
||||||
|
|
||||||
// Global pointer `gp`
|
|
||||||
//
|
|
||||||
// Push current option stack to temporarily disable relaxation, load
|
|
||||||
// _global_pointer symbol (provided by linker), then pop option stack.
|
|
||||||
//
|
|
||||||
// Important to keep relaxation off for this instruction, so that
|
|
||||||
// the instruction is emitted as:
|
|
||||||
// 1:
|
|
||||||
// auipc gp, %pcrel_hi(_global_pointer)
|
|
||||||
// addi gp, gp, %pcrel_lo(1b)"
|
|
||||||
// instead of:
|
|
||||||
// mv gp, gp
|
|
||||||
asm!(
|
asm!(
|
||||||
|
/* Global pointer register `gp`
|
||||||
|
|
||||||
|
Push current option stack to temporarily disable relaxation, load
|
||||||
|
_global_pointer symbol (provided by linker), then pop option stack.
|
||||||
|
|
||||||
|
Important to keep relaxation off for this instruction, so that
|
||||||
|
the instruction is emitted as:
|
||||||
|
1:
|
||||||
|
auipc gp, %pcrel_hi(_global_pointer)
|
||||||
|
addi gp, gp, %pcrel_lo(1b)"
|
||||||
|
instead of:
|
||||||
|
mv gp, gp
|
||||||
|
which would do nothing. */
|
||||||
".option push",
|
".option push",
|
||||||
".option norelax",
|
".option norelax",
|
||||||
"la gp, _global_pointer",
|
"la gp, _global_pointer",
|
||||||
".option pop",
|
".option pop",
|
||||||
);
|
);
|
||||||
|
|
||||||
// Stack pointer `sp`
|
riscv::register::satp::write(0);
|
||||||
//
|
|
||||||
// Set up the stack pointer for each hart, since each hart will have its own stack.
|
|
||||||
asm!("la sp, _stack_end");
|
|
||||||
|
|
||||||
// Thread pointer `tp`
|
let id = riscv::register::mhartid::read();
|
||||||
//
|
if id != 0 { crate::abort(); }
|
||||||
// Set up the thread pointer, which will hold the hart id for each hart.
|
|
||||||
write_tp(&mhartid::read());
|
|
||||||
|
|
||||||
satp::write(0);
|
|
||||||
|
|
||||||
mstatus::set_mpp(mstatus::MPP::Machine);
|
|
||||||
mstatus::set_fs(sstatus::FS::Initial);
|
|
||||||
|
|
||||||
|
// Clear BSS section
|
||||||
asm!(
|
asm!(
|
||||||
|
"la t0, _bss_start",
|
||||||
|
"la t1, _bss_end",
|
||||||
|
"bgeu t0, t1, 2f",
|
||||||
|
"1:",
|
||||||
|
"sb zero, 0(t0)",
|
||||||
|
"addi t0, t0, 1",
|
||||||
|
"bne t0, t1, 1b",
|
||||||
|
|
||||||
|
"2:",
|
||||||
|
"la sp, _stack_end",
|
||||||
|
|
||||||
|
"li t0, (0b11 << 11) | (1 << 13)",
|
||||||
|
"csrw mstatus, t0",
|
||||||
"csrw mie, x0",
|
"csrw mie, x0",
|
||||||
|
|
||||||
"la t1, {kinit}",
|
"la t1, {kinit}",
|
||||||
|
@ -56,65 +61,20 @@ unsafe extern "C" fn entry() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn start() {
|
|
||||||
// TODO start (start for hart 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[no_mangle]
|
|
||||||
extern "C" fn hstart() {
|
|
||||||
// TODO starth (start for other harts)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO ...then kinit
|
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn kinit() {
|
extern "C" fn kinit() {
|
||||||
use crate::uart;
|
use crate::uart;
|
||||||
use core::arch::asm;
|
|
||||||
uart::Device::new(0x1000_0000);
|
uart::Device::new(0x1000_0000);
|
||||||
|
|
||||||
if read_tp() == 0 {
|
|
||||||
// Clear bss and set stack pointer
|
|
||||||
// Only hart 0 does this
|
|
||||||
unsafe {
|
|
||||||
asm!(
|
|
||||||
"la t0, _bss_start",
|
|
||||||
"la t1, _bss_end",
|
|
||||||
"bgeu t0, t1, 2f",
|
|
||||||
"1:",
|
|
||||||
"sw x0, (t0)", // Store zero as word at t0
|
|
||||||
"addi t0, t0, 4",
|
|
||||||
"bne t0, t1, 1b",
|
|
||||||
"2:",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
extern "C" fn kinit_hart() {}
|
extern "C" fn kinit_hart() {}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn read_tp() -> usize {
|
unsafe fn write_tp(id: &usize) {
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
let id: usize;
|
|
||||||
unsafe {
|
|
||||||
asm!(
|
|
||||||
"mv {id}, tp",
|
|
||||||
id = out(reg) id,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
id
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_tp(id: &usize) {
|
|
||||||
use core::arch::asm;
|
|
||||||
unsafe {
|
|
||||||
asm!(
|
asm!(
|
||||||
"csrw mhartid, {id}",
|
"csrw mhartid, {id}",
|
||||||
id = in(reg) id,
|
id = in(reg) id,
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -14,7 +14,7 @@ mod uart;
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
#[link_section = ".text.init"]
|
#[link_section = ".text.init"]
|
||||||
unsafe extern "C" fn _enter() -> ! {
|
unsafe extern "C" fn _enter() -> ! {
|
||||||
// FIXME see if possible to replace this somehow...
|
// TODO see if possible to replace this somehow...
|
||||||
use core::arch::asm;
|
use core::arch::asm;
|
||||||
asm!(
|
asm!(
|
||||||
// load hartid into `tp``
|
// load hartid into `tp``
|
||||||
|
|
|
@ -34,15 +34,13 @@ SECTIONS {
|
||||||
.data : { # and the data section
|
.data : { # and the data section
|
||||||
. = ALIGN(4096);
|
. = ALIGN(4096);
|
||||||
PROVIDE(_data_start = .);
|
PROVIDE(_data_start = .);
|
||||||
*(.sdata .sdata.*)
|
*(.sdata .sdata.*) *(.data .data.*)
|
||||||
*(.data .data.*)
|
|
||||||
PROVIDE(_data_end = .);
|
PROVIDE(_data_end = .);
|
||||||
} >ram AT>ram :data # this will go into the data segment
|
} >ram AT>ram :data # this will go into the data segment
|
||||||
|
|
||||||
.bss :{ # finally, the BSS
|
.bss :{ # finally, the BSS
|
||||||
PROVIDE(_bss_start = .); # define a variable for the start of this section
|
PROVIDE(_bss_start = .); # define a variable for the start of this section
|
||||||
*(.sbss .sbss.*)
|
*(.sbss .sbss.*) *(.bss .bss.*)
|
||||||
*(.bss .bss.*)
|
|
||||||
PROVIDE(_bss_end = .); # ... and one at the end
|
PROVIDE(_bss_end = .); # ... and one at the end
|
||||||
} >ram AT>ram :bss # and this goes into the bss segment
|
} >ram AT>ram :bss # and this goes into the bss segment
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue