From d2560cca8660ee5e6727dceef53fbae5a6463afe Mon Sep 17 00:00:00 2001 From: gil Date: Sun, 19 May 2024 17:42:50 -0500 Subject: [PATCH] Update readme and init --- 20240519-kernel_init_diagram.png | Bin 0 -> 63193 bytes README.md | 33 +++----- RESOURCES.md | 26 +++++++ src/entry.rs | 124 +++++++++++++++++++------------ src/main.rs | 2 +- src/script.lds | 6 +- 6 files changed, 119 insertions(+), 72 deletions(-) create mode 100644 20240519-kernel_init_diagram.png create mode 100644 RESOURCES.md diff --git a/20240519-kernel_init_diagram.png b/20240519-kernel_init_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..34193649f5c796ac26f416ddff6bbe134ec27a14 GIT binary patch literal 63193 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 literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 6c9e350..10669b2 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,21 @@ --- created: 2024-05-13T14:28:49-05:00 -modified: 2024-05-13T14:28:52-05:00 +modified: 2024-05-19T17:41:01-05:00 --- A kernel for RISC-V written in Rust. Currently focused on running on QEMU generic riscv64, advice and assistance welcome & encouraged. -# Reading list +# Progress -## 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/) +* **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 -## 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/ +![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) -## 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 +# Research and implement - [ ] Basics - [ ] Processes - - [ ] Virtual addrxess spaces, page tables + - [ ] Virtual address spaces, page tables - [ ] Files, directories - [ ] Pipes - [ ] Multitasking, time-slicing @@ -46,3 +29,7 @@ A kernel for RISC-V written in Rust. Currently focused on running on QEMU generi - [ ] Interprocess communication - [ ] Device drivers - [ ] User applications + +# Resources + +See [RESOURCES.md](/RESOURCES.md) \ No newline at end of file diff --git a/RESOURCES.md b/RESOURCES.md new file mode 100644 index 0000000..06531e6 --- /dev/null +++ b/RESOURCES.md @@ -0,0 +1,26 @@ +--- +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) \ No newline at end of file diff --git a/src/entry.rs b/src/entry.rs index 9843fa7..e075f2b 100644 --- a/src/entry.rs +++ b/src/entry.rs @@ -1,57 +1,45 @@ // src/entry.rs -use riscv::register::mepc; - +/// 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] #[link_section = ".text.init"] -unsafe extern "C" fn _entry() { +unsafe extern "C" fn entry() { use core::arch::asm; - use riscv::register::{mhartid, satp, mstatus, 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(); } + use riscv::register::{mhartid, mstatus, satp, sstatus}; + // 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!( - /* 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 norelax", "la gp, _global_pointer", ".option pop", ); + // Stack pointer `sp` + // + // Set up the stack pointer for each hart, since each hart will have its own stack. + asm!("la sp, _stack_end"); + + // Thread pointer `tp` + // + // Set up the thread pointer, which will hold the hart id for each hart. + write_tp(&mhartid::read()); + satp::write(0); - let id = mhartid::read(); - if id != 0 { crate::abort(); } - - // Clear BSS section - 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" - ); - mstatus::set_mpp(mstatus::MPP::Machine); mstatus::set_fs(sstatus::FS::Initial); @@ -66,23 +54,67 @@ unsafe extern "C" fn _entry() { "2:", kinit = sym kinit, ); - } +#[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] extern "C" fn kinit() { use crate::uart; + use core::arch::asm; 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] extern "C" fn kinit_hart() {} #[inline] -unsafe fn write_tp(id: &usize) { +fn read_tp() -> usize { use core::arch::asm; - asm!( - "csrw mhartid, {id}", - id = in(reg) id, - ); -} \ No newline at end of file + 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!( + "csrw mhartid, {id}", + id = in(reg) id, + ); + } +} diff --git a/src/main.rs b/src/main.rs index b693c53..5bf3808 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ mod uart; #[no_mangle] #[link_section = ".text.init"] unsafe extern "C" fn _enter() -> ! { - // TODO see if possible to replace this somehow... + // FIXME see if possible to replace this somehow... use core::arch::asm; asm!( // load hartid into `tp`` diff --git a/src/script.lds b/src/script.lds index 16d432c..4d94276 100644 --- a/src/script.lds +++ b/src/script.lds @@ -34,13 +34,15 @@ SECTIONS { .data : { # and the data section . = ALIGN(4096); PROVIDE(_data_start = .); - *(.sdata .sdata.*) *(.data .data.*) + *(.sdata .sdata.*) + *(.data .data.*) PROVIDE(_data_end = .); } >ram AT>ram :data # this will go into the data segment .bss :{ # finally, the BSS PROVIDE(_bss_start = .); # define a variable for the start of this section - *(.sbss .sbss.*) *(.bss .bss.*) + *(.sbss .sbss.*) + *(.bss .bss.*) PROVIDE(_bss_end = .); # ... and one at the end } >ram AT>ram :bss # and this goes into the bss segment