{"id":17304899,"url":"https://github.com/xiaoyang-sde/rust-kernel-riscv","last_synced_at":"2025-04-14T13:21:14.722Z","repository":{"id":82084498,"uuid":"219990648","full_name":"xiaoyang-sde/rust-kernel-riscv","owner":"xiaoyang-sde","description":"RISC-V kernel implemented with Rust","archived":false,"fork":false,"pushed_at":"2024-04-07T09:19:57.000Z","size":1690,"stargazers_count":98,"open_issues_count":1,"forks_count":16,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T02:25:06.584Z","etag":null,"topics":["kernel","operating-system","risc-v","rust"],"latest_commit_sha":null,"homepage":"http://rust-kernel-riscv.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/xiaoyang-sde.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-11-06T12:22:53.000Z","updated_at":"2024-11-25T23:11:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"0bb3b72b-f2ad-4b04-86e7-4cfab4d22a9d","html_url":"https://github.com/xiaoyang-sde/rust-kernel-riscv","commit_stats":null,"previous_names":["xiaoyang-sde/rust-kernel-riscv"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaoyang-sde%2Frust-kernel-riscv","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaoyang-sde%2Frust-kernel-riscv/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaoyang-sde%2Frust-kernel-riscv/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/xiaoyang-sde%2Frust-kernel-riscv/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/xiaoyang-sde","download_url":"https://codeload.github.com/xiaoyang-sde/rust-kernel-riscv/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248886334,"owners_count":21177645,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kernel","operating-system","risc-v","rust"],"created_at":"2024-10-15T11:54:08.606Z","updated_at":"2025-04-14T13:21:14.692Z","avatar_url":"https://github.com/xiaoyang-sde.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `rust-kernel-riscv`\n\n[![GitHub Actions](https://img.shields.io/github/actions/workflow/status/xiaoyang-sde/rust-kernel-riscv/cargo.yml?branch=master\u0026style=for-the-badge\u0026logo=github)](https://github.com/xiaoyang-sde/rust-kernel-riscv/actions)\n\n`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).\n\n- 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.\n\n- 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.\n\n## Build\n\n- Install the `riscv64gc-unknown-none-elf` target and related components:\n\n```console\nrustup install nightly\n\nrustup target add riscv64gc-unknown-none-elf\nrustup component add llvm-tools-preview\nrustup component add rust-src\n\ncargo install cargo-binutils\n```\n\n- Install [QEMU](https://www.qemu.org) with a package manager such as Homebrew:\n\n```console\nbrew install qemu\n```\n\n- Build and run the kernel with QEMU:\n\n```console\nmake qemu\n```\n\n## Design Document\n\n### Executor\n\nThe 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\u003cRunnable\u003e` 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`.\n\n```rs\nlazy_static! {\n    static ref TASK_QUEUE: Mutex\u003cTaskQueue\u003e = Mutex::new(TaskQueue::new());\n}\n\npub fn run_until_complete() {\n    loop {\n        let task = TASK_QUEUE.lock().pop_front();\n        if let Some(task) = task {\n            task.run();\n        } else {\n            break;\n        }\n    }\n}\n```\n\n### Trampoline\n\nThe 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.\n\nThe trampoline contains a pair of naked functions, `_enter_kernel_space` and `_enter_user_space`:\n\n- `_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.\n\n- `_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.\n\n### User Thread\n\nEach 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.\n\n```rs\nasync fn thread_loop(thread: Arc\u003cThread\u003e) {\n    loop {\n        let trap_context = thread.state().lock().user_trap_context_mut();\n        _enter_user_space(trap_context, thread.satp());\n\n        // Invokes related methods to handle the exception or interrupt,\n        // which returns a variant of the `ControlFlow` enum\n        // (Please refer to the source code)\n\n        // Decides whether to continue, yield, or terminate the thread\n        match control_flow {\n            ControlFlow::Continue =\u003e continue,\n            ControlFlow::Yield =\u003e yield_now().await,\n            ControlFlow::Exit(exit_code) =\u003e {\n                thread.exit(exit_code);\n                break;\n            }\n        }\n    }\n}\n\npub fn spawn_thread(thread: Arc\u003cThread\u003e) {\n    let (runnable, task) = executor::spawn(thread_loop(thread));\n    runnable.schedule();\n    task.detach();\n}\n```\n\n### Lifetime of a User Thread\n\n- The user thread is initiated using the spawn_thread function, which encapsulates it within the `thread_loop` future and incorporates it into the executor.\n- The executor chooses a task from the TaskQueue and polls it, executing the `thread_loop`.\n- To enter user mode, the `thread_loop` calls `_enter_user_space`.\n- The user thread operates in user mode.\n- If a trap (exception or interrupt) arises, the `_enter_kernel_space` specified in the stvec register is triggered, returning control to the `thread_loop`.\n- 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.\n\n## Development Roadmap\n\n- [ ] File system with asynchronous interface\n- [ ] Virtio driver\n- [ ] TCP/IP stack\n- [ ] Linux-compatible system call interface\n- [ ] [musl libc-test](https://wiki.musl-libc.org/libc-test.html)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiaoyang-sde%2Frust-kernel-riscv","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fxiaoyang-sde%2Frust-kernel-riscv","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fxiaoyang-sde%2Frust-kernel-riscv/lists"}