Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/xiaoyang-sde/rust-kernel-riscv
RISC-V kernel implemented with Rust
https://github.com/xiaoyang-sde/rust-kernel-riscv
kernel operating-system risc-v rust
Last synced: 2 months ago
JSON representation
RISC-V kernel implemented with Rust
- Host: GitHub
- URL: https://github.com/xiaoyang-sde/rust-kernel-riscv
- Owner: xiaoyang-sde
- License: mit
- Created: 2019-11-06T12:22:53.000Z (about 5 years ago)
- Default Branch: master
- Last Pushed: 2024-04-07T09:19:57.000Z (9 months ago)
- Last Synced: 2024-10-15T11:54:06.704Z (2 months ago)
- Topics: kernel, operating-system, risc-v, rust
- Language: Rust
- Homepage: http://rust-kernel-riscv.com
- Size: 1.61 MB
- Stars: 97
- Watchers: 3
- Forks: 15
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# `rust-kernel-riscv`
[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/xiaoyang-sde/rust-kernel-riscv/cargo.yml?branch=master&style=for-the-badge&logo=github)](https://github.com/xiaoyang-sde/rust-kernel-riscv/actions)
`rust-kernel-riscv` is an open-source project that implements an operating system kernel on RISC-V architecture with Rust programming language. The project draws inspiration from several open-source implementations, such as [xv6-riscv](https://github.com/mit-pdos/xv6-riscv) and [zCore](https://github.com/rcore-os/zCore).
- The kernel leverages Rust's asynchronous programming model to schedule threads in both the kernel and user space, which makes context switching more efficient and eliminates the need of allocating a separate kernel stack for each user process.
- The kernel implements the kernel page-table isolation, which prevents the kernel space and the user space to share the same page table and mitigates potential Meltdown attacks.
## Build
- Install the `riscv64gc-unknown-none-elf` target and related components:
```console
rustup install nightlyrustup target add riscv64gc-unknown-none-elf
rustup component add llvm-tools-preview
rustup component add rust-srccargo install cargo-binutils
```- Install [QEMU](https://www.qemu.org) with a package manager such as Homebrew:
```console
brew install qemu
```- Build and run the kernel with QEMU:
```console
make qemu
```## Design Document
### Executor
The kernel executor handles the management and execution of tasks, which can be either user threads or kernel threads. As of the current implementation, the `TaskQueue` is a wrapper around the `VecDeque` type, which store and execute tasks in a FIFO order. The `run_until_complete` function blocks the calling thread and runs all the tasks in the `TaskQueue`.
```rs
lazy_static! {
static ref TASK_QUEUE: Mutex = Mutex::new(TaskQueue::new());
}pub fn run_until_complete() {
loop {
let task = TASK_QUEUE.lock().pop_front();
if let Some(task) = task {
task.run();
} else {
break;
}
}
}
```### Trampoline
The trampoline is a dedicated page that acts as a bridge for transferring control between supervisor and user modes, which is located at the same address (`0xFFFFFFFFFFFFF000`) in both kernel and user thread page tables. Identical mapping is required because the program counter must point to a valid location after switching the page table.
The trampoline contains a pair of naked functions, `_enter_kernel_space` and `_enter_user_space`:
- `_enter_user_space` stores callee-saved registers on the kernel stack, switches to the page table of the user thread, and restores the context (registers, `sstatuc`, `sepc`) of the user thread from a `TrapContext`. Following these steps, it uses a `sret` instruction to return to user mode.
- `_enter_kernel_space` stores the context (registers, `sstatuc`, `sepc`) of the user thread to a `TrapContext`, switch to the page table of the kernel, and restores the callee-saved registers from the kernel stack. Following these steps, it uses a `ret` instruction to jump to the `thread_loop`, which will handle the exception or interrupt.
### User Thread
Each user thread is represented with the `executor::future::thread_loop` future. The executor runs a future with its `poll` method, and the `thread_loop` invokes `_enter_user_space` function to enter the user mode. The `_enter_user_space` returns when an exception or interrupt occurs, and the `thread_loop` handles them and decide whether to continue, yield, or terminate the thread. The `spawn_thread` function is used to add a new user thread to the executor.
```rs
async fn thread_loop(thread: Arc) {
loop {
let trap_context = thread.state().lock().user_trap_context_mut();
_enter_user_space(trap_context, thread.satp());// Invokes related methods to handle the exception or interrupt,
// which returns a variant of the `ControlFlow` enum
// (Please refer to the source code)// Decides whether to continue, yield, or terminate the thread
match control_flow {
ControlFlow::Continue => continue,
ControlFlow::Yield => yield_now().await,
ControlFlow::Exit(exit_code) => {
thread.exit(exit_code);
break;
}
}
}
}pub fn spawn_thread(thread: Arc) {
let (runnable, task) = executor::spawn(thread_loop(thread));
runnable.schedule();
task.detach();
}
```### Lifetime of a User Thread
- The user thread is initiated using the spawn_thread function, which encapsulates it within the `thread_loop` future and incorporates it into the executor.
- The executor chooses a task from the TaskQueue and polls it, executing the `thread_loop`.
- To enter user mode, the `thread_loop` calls `_enter_user_space`.
- The user thread operates in user mode.
- If a trap (exception or interrupt) arises, the `_enter_kernel_space` specified in the stvec register is triggered, returning control to the `thread_loop`.
- The `thread_loop` manages the trap and determines whether to continue, yield, or terminate the thread. If it chooses to continue, the `thread_loop` moves on to the next iteration.## Development Roadmap
- [ ] File system with asynchronous interface
- [ ] Virtio driver
- [ ] TCP/IP stack
- [ ] Linux-compatible system call interface
- [ ] [musl libc-test](https://wiki.musl-libc.org/libc-test.html)