Rust ported to CHERIoT platform with 54 commits integrated
Summary
Rust is being ported to CHERIoT. Progress includes adapting the compiler for 64-bit capabilities on a 32-bit platform, compiling core/alloc, setting up CI, and fixing a CHERIoT-LLVM bug.
Developers port Rust to CHERIoT platform
A dedicated engineering team has spent the last six months porting the Rust programming language to the CHERIoT platform. The project focuses on adapting the Rust compiler, rustc, to support the unique memory safety requirements of CHERI-based hardware.
The team has already integrated 54 commits into a specialized beta branch of the Rust repository. This work involved modifying 84 files, adding 805 lines of code, and removing 280 lines to accommodate the new target. These changes allow the compiler to produce functioning code for the riscv32cheriot-unknown-cheriotrtos target.
The porting process relies heavily on the strict-provenance effort within the Rust community. This initiative simplifies the task of tracking how pointers are derived from original allocations. Because CHERI architectures treat pointers as capabilities rather than simple integers, this clear distinction is vital for stability.
Redefining how Rust handles memory pointers
The most significant challenge in this port involves how the compiler perceives memory addresses. On standard 32-bit systems, a pointer and a memory address are typically the same size. CHERIoT breaks this assumption by using 32-bit addresses but 64-bit capabilities.
A CHERIoT capability includes four bytes for the memory address and an additional four bytes for metadata. This metadata defines what the program is allowed to do with that specific pointer. The compiler must now understand that the size of a pointer in memory is not necessarily the same as the size of the address it references.
To fix this, the team updated the internal datalayout string within the compiler. This change allows rustc to distinguish between the pointer_size and the pointer_offset. The following list highlights the core technical shifts required for this architecture:
- The compiler now uses address space 200 by default to represent CHERI capabilities.
- Internal scalar representations are split into two distinct size methods for data capacity versus memory storage.
- The LLVM backend was updated to a custom version that understands CHERIoT-specific calling conventions.
- The
coreandalloclibraries now compile specifically for the purecap RISC-V target.
Debugging a complex register corruption error
During testing on the Sail simulator, the team identified a critical bug involving the format! macro. While simple string formatting worked, using the "alternate" flag like {x:#b} caused the system to crash. The error manifested as a PermitExecuteViolation, indicating the processor tried to execute memory it didn't have permission to access.
The investigation traced the crash to a tail call optimization bug within the CHERIoT-LLVM backend. In Rust, an Option<&str> is often optimized so that a null value represents None. When the code attempted to call the write_str function, the compiler incorrectly assigned a callee-saved register to store the jump address.
This caused the program to overwrite the jump destination right before attempting to execute the function. The team successfully patched LLVM to ensure the virtual register rewriter no longer uses protected registers for these specific jumps. This fix prevents runtime traps that would otherwise break standard formatting operations in embedded environments.
Support for atomics and core libraries
The team has successfully enabled AtomicPtr support for the CHERIoT target. Because pointers on this platform are 64 bits wide, the compiler must explicitly support atomic operations on values of that size. This is unusual for a 32-bit platform, but necessary to maintain Rust's concurrency guarantees.
The project also required forking several third-party crates to add CHERI-specific flags. The object crate, which handles binary file formats, did not initially recognize the e_flags used by CHERIoT. These patched versions are now hosted in a new GitHub organization dedicated to the project.
Testing remains a primary focus as the port moves toward stability. The team currently runs codegen-llvm tests to ensure the generated intermediate representation is correct. They also use a custom test runner to execute code on the Sail simulator, which mimics the actual hardware behavior of the CHERIoT processor.
Building the CHERIoT compiler today
The entire project is hosted in a public repository for developers to test and contribute. Building the toolchain requires a specific bootstrap script that compiles both Clang and the Rust compiler. The team recommends using a Linux environment for the build process to ensure compatibility with the RISC-V toolchain.
Developers can begin the build process by cloning the cheri-rust repository and running the provided generation scripts. Once the compiler is built, it can target riscv32cheriot-unknown-cheriotrtos to produce binaries for the simulator. The team plans to provide more frequent, in-depth updates as they refine the Foreign Function Interface (FFI) and improve library support.
To build the compiler from source, follow these steps:
- Clone the cheri-rust repository from the CHERIoT-Platform GitHub account.
- Run
./cheri/gen_bootstrap.sh --build-clangto prepare the backend. - Execute
./x build compiler std --target=riscv32cheriot-unknown-cheriotrtosto compile the standard library. - Verify the installation by running the Sail simulator tests.
The team is currently soliciting feedback through a public Signal chat and GitHub issues. They aim to make Rust a first-class citizen on CHERI hardware, providing a memory-safe language for a memory-safe processor architecture. Future updates will focus on non-transmuting casts and further refinements to the MIR (Mid-level Intermediate Representation) passes.
Related Articles
Developer abandons Rust web app after years, migrates to Node.js
A programmer's journey from Pascal to C, then web dev in PHP/Python, and finally Rust for a web app. Despite loving Rust's control and safety, they switched to Node.js due to faster iteration, better web ecosystem, and type-safe templates, concluding Rust excels in CPU-heavy tasks but Node.js is more practical for dynamic web development.
Weathr terminal app shows real-time weather with animated ASCII art
Weathr is a terminal weather app with ASCII animations for rain, snow, and more, using real-time data from Open-Meteo. It supports auto-location, configurable units, and offline simulation.
Stay in the loop
Get the best AI-curated news delivered to your inbox. No spam, unsubscribe anytime.
