This Month in Rust OSDev: June 2023
Welcome to a new issue of "This Month in Rust OSDev". In these posts, we give a regular overview of notable changes in the Rust operating system development ecosystem.
This series is openly developed on GitHub. Feel free to open pull requests there with content you would like to see in the next issue. If you find some issues on this page, please report them by creating an issue or using our comment form at the bottom of this page.
Announcements, News, and Blog Posts
Here we collect news, blog posts, etc. related to OS development in Rust.
- Redox OS elects its first Board of Directors
- Frida 16.1.0 Released
- Intercepting Allocations with the Global Allocator
- Building an out-of-tree Rust Kernel Module Part Three
- Discussion: How hard would it be to port the Rust toolchain to a new non-POSIX OS written in Rust and get it to host its own development?
- Discussion: Will there be fewer jailbreaks in the future if operating systems like iOS start adopting rust?
Infrastructure and Tooling
In this section, we collect recent updates to rustc
, cargo
, and other tooling that are relevant to Rust OS development.
No updates were proposed for this section this month.
rust-osdev
Projects
In this section, we give an overview of notable changes to the projects hosted under the rust-osdev
organization.
volatile
Maintained by @phil-opp
The volatile
crate provides a safe wrapper type for implementing volatile read and write operations. This is useful for accessing memory regions that have side-effects, such as memory-mapped hardware registers or framebuffers.
Unfortunately, the design crate had a soundness issue because it used reference types for accessing the volatile memory. This is problematic because the Rust compiler marks references are "dereferenceable", which allows LLVM to insert spurious read operations. This is fine for accessing "normal" memory, but it can lead to correctness issues when used in combination with memory-mapped device registers. These registers look like normal memory, but they are actually accessing some device-specific registers, which might change at any time. So they might change between spurious reads, which violates the assumptions of LLVM and can lead to undefined behavior.
To solve this issue, we started a full redesign of the crate that uses raw pointers only. This solves the issue because raw pointers are not considered "dereferenceable", so LLVM is not allowed to insert spurious reads. While we started working on the new design more than 2 years ago, we didn't merge it until this month because we weren't sure about the implementation details. The main discussion point was whether we should treat the proposed VolatilePointer
type like Rust's reference types or like Rust's raw pointer types. The difference is that raw pointers implement the Copy
trait, but are not Send
to prevent aliasing. References, on the other hand, can safely implement Send
because they're only Copy
if the reference is read-only.
After a lot of back and forth, we decided to provide both options and finally publish volatile v0.5
. So the new design has two wrapper types, VolatilePtr
(behaves like a raw pointer) and VolatileRef
(behaves like a reference). We hope that we support most use cases this way!
Note that there is also some ongoing discussion about a potential VolatileCell
type to wrap values in-place. Most implementations of such a type would require support from the Rust compiler, which needs an RFC. However, there is one promising design based on zero-sized types and proc-macros by @Freax13 that should not require any new language features. We will continue to investigate.
multiboot2
Maintained by @phip1611
The multiboot2 and the multiboot2-header crates got a big overhaul. The list of new features includes but is not limited to:
- use DSTs for tags where applicable (#134)
- model the MBI as DST (#155)
- add a runtime builder for an MBI (#133)
Huge thanks to YtvwlD / Niklas for this great external contribution - added an integration test including a multiboot2 chainloader for better test coverage (#129)
- added miri to the CI for more memory safety (#128)
- several fixes and small improvements
multiboot2
was updated from 0.15.1
to 0.16.0
and multiboot2-header
was updated from 0.2.0
to 0.3.0
. Both
releases come with a large amount of breaking changes.
However, after a sensible consideration, they are all worth it for a more streamlined API and more memory safety.
Merged pull requests:
- Add a builder to multiboot2
- treewide: code improvements and other stuff
- various fixes + cleanup + bump crate versions
- streamline default derives
- tree-wide: rename builder structs (remove Multiboot2 prefix)
- tree-wide: streamline default derives (also Hash everywhere)
- workspace: use workspace dependencies
- fix memory issue in memory-map
- multiboot2: memory-map: derive Eq + uefi-raw@0.3.0
- multiboot2: more tag name streamlining
- multiboot2: fix memory issue in boxed_dst_tag
- multiboot2: builder: add terminating null-bytes to tags that hold a string
- multiboot2: load: remove odd offset thingy
- various cleanups
- multiboot2: model MBI as DST
- various fixes
- builder: use new abstraction to guarantee alignment
- Add Integration Test
- multiboot2: create DSTs: hopefully better memory fix
- integration-test: cargo update
- ci: run miri + adjustments for miri
- ci: integrationtest: use magic nix cache
- Make InformationBuilder adhere the API guidelines.
x86_64
Maintained by @phil-opp, @josephlr, and @Freax13
The x86_64
crate provides various abstractions for x86_64
systems, including wrappers for CPU instructions, access to processor-specific registers, and abstraction types for architecture-specific structures such as page tables and descriptor tables.
We merged the following changes this month:
- Change Star::write() to use checked subtractions
- Bump bitflags to 2.3.2
- add workaround for recursive page tables with recursive index 511
- Fix off-by-one in documentation
Thanks to @Qix-, @grant0417, and @Egggggg for their contributions!
vga
Maintained by @RKennedy9064
The work-in-progress vga
crate allows the configuration of the VGA hardware, e.g. switching from text-based mode to a pixel-based graphics mode. This month, we merged the following pull request:
Thanks to @tsatke for their contribution!
uefi-rs
Maintained by @GabrielMajeri, @nicholasbishop, and @phip1611
The uefi
crate provides safe and performant wrappers for UEFI,
the successor to the BIOS firmware. It empowers everyone to write EFI-
applications with Rust in a convenient way, such as your own bootloader.
In June, we added multiple small improvements for developers using
Nix(OS) and simplifications for working with device
paths. Additionally, we moved more definitions to the new uefi-raw
crate.
Furthermore, we'd like to mention the new high-level File-System API. It was merged in April actually, but not mentioned in this newsletter so far. Feel free to give it a try!
We merged the following PRs this month:
- Release uefi-raw-0.2.0, uefi-0.22.0, and uefi-services-0.19.0
- Fix various CI failures
- uefi: Fix wrong install_configuration_table() signature
- Release uefi-0.23.0 and uefi-services-0.20.0
- build(deps): bump tempfile from 3.5.0 to 3.6.0
- device_path: add more convenience (part 2)
- Make UEFI shell protocols testable
- Add DevicePathProtocol to uefi-raw
- Integration test for boot service function load_image
- cargo: Use
[workspace.package]
to deduplicate metadata - uefi: Update MSRV policy language
- uefi: Remove some uses of MaybeUninit in BootServices
- nix: add more convenience for Nix/NixOS users
- ci: Fix developer_productivity push error
- uefi-raw: Add BootServices table
- uefi: Add raw pointer Event/Handle methods
- uefi: Make BootServices fn ptrs unsafe
- xtask: add "cargo xtask fmt" (and formatting for nix and yml files)
- build(deps): bump ureq from 2.6.2 to 2.7.0
- uefi-raw: Fix arg type in connect_controller
- uefi: Improve support for null protocol interfaces
- uefi: Make
BootServices
a wrapper arounduefi_raw::table::boot::BootServices
- uefi-raw: Add common derives to
EventType
- xtask: Improve an error location in check-raw
- uefi-raw: Add ConfigurationTable
- uefi-raw: Add SimpleTextInputProtocol and SimpleTextOutputProtocol
- uefi-raw: Add SystemTable
- uefi-raw: Fill in a few more BootServices function pointers
- uefi-raw: derive all the things
- device_path: add more convenience (part 1)
- Release uefi-raw-0.3.0, uefi-0.24.0, uefi-services-0.21.0
- uefi-raw: Add LoadedImageProtocol
- uefi: Check for null pointer in config_table
- test-runner: Simplify an iterator chain
- build(deps): bump itertools from 0.10.5 to 0.11.0
- uefi: Use uefi_raw's
SimpleTextInputProtocol
inInput
- uefi: Use uefi_raw's
SimpleTextOutputProtocol
inOutput
- uefi: Use uefi_raw's
LoadedImageProtocol
to implementLoadedImage
- uefi: Fix warnings when compiling without the alloc feature
- uefi-raw: Add
SimplePointerProtocol
- uefi: Use uefi_raw's SystemTable to implement SystemTable
Thanks to @medhefgo for their contribution!
Other Projects
In this section, we describe updates to Rust OS projects that are not directly related to the rust-osdev
organization. Feel free to create a pull request with the updates of your OS project for the next post.
hermitcore/rusty-hermit
(Section written by @mkroening)
The Hermit library operating system allows you to bundle a whole OS directly with your application, creating a freestanding, bootable Unikernel image. This month, we achieved several milestones for reaching more users with Hermit:
-
Stable Rust support.
You can now compile your programs for Hermit using the stable Rust toolchain! 🥳
While the Hermit targets (
x86_64-unknown-hermit
andaarch64-unknown-hermit
) are still at tier 3, we now distribute pre-built artifacts of the Rust standard library for use with stable toolchains! This means, no more-Zbuild-std
, resulting in faster builds, and the bliss of the stable Rust compiler.See
hermitcore/rust-std-hermit
for details on ourrust-std
artifacts. -
Windows support.
Thanks to Rust's awesome cross-compilation capabilities, you can now compile Hermit applications from anywhere! 😎
We have resolved a longstanding issue when building Hermit applications on Windows (hermitcore/rusty-hermit#431). The issue is all sorted out now and Windows, macOS, and Linux are tested and verified by our CI.
-
AArch64 (ARM64) support.
You can now run real applications on AArch64, with scheduling, network and everything! 🤯
-
PCI now works on AArch64, which allows us to use the network devices (hermitcore/libhermit-rs#748).
-
We merged scheduling support for AArch64 (hermitcore/libhermit-rs#765).
-
You can also now chainload Hermit apps for AArch64 using our loader (hermitcore/rusty-loader#201).
This means, you don't have to statically compile the full application into the final loader image anymore.
-
We'd love if you gave Hermit a try. Just start with our "Hello, World!" application template: hermitcore/rusty-demo
.
Join Us?
Are you interested in Rust-based operating system development? Our rust-osdev
organization is always open to new members and new projects. Just let us know if you want to join! A good way for getting in touch is our Zulip chat.