6 releases
Uses new Rust 2024
new 0.2.1 | Jun 13, 2025 |
---|---|
0.2.0 | Jun 10, 2025 |
0.1.3 | May 6, 2025 |
0.1.1 | Mar 27, 2025 |
#779 in Embedded development
1,003 downloads per month
Used in osdemo
28KB
411 lines
Startup code for bare-metal aarch64
This crate provides entry point and exception handling for bare-metal Rust binaries on aarch64 Cortex-A processors.
This is not an officially supported Google product.
Usage
Use the entry!
macro to mark your main function:
use aarch64_rt::entry;
entry!(main);
fn main(arg0: u64, arg1: u64, arg2: u64, arg3: u64) -> ! {
// ...
}
arg0
through arg3
will contain the initial values of registers x0
–x3
. These are often used
to pass arguments from the previous-stage bootloader, such as the address of the device tree.
You'll need to provide the image origin (which will be the entry point address) and maximum size in a linker script, e.g.:
MEMORY
{
image : ORIGIN = 0x40080000, LENGTH = 2M
}
You'll need to tell Rust to use both this and the aarch64-rt
linker script in your build.rs
.
Assuming your linker script is called memory.ld
:
fn main() {
println!("cargo:rustc-link-arg=-Timage.ld");
println!("cargo:rustc-link-arg=-Tmemory.ld");
println!("cargo:rerun-if-changed=memory.ld");
}
Features
el1
, exceptions
, initial-pagetable
and psci
are enabled by default.
el1
If the exceptions
feature is also enabled then uses vbar_el1
for the exception vector. If
initial-pagetable
is also enabled then uses ttbr0_el1
for the page table, and other EL1 MMU
configuration registers.
el2
If the exceptions
feature is also enabled then uses vbar_el2
for the exception vector. If
initial-pagetable
is also enabled then uses ttbr0_el2
for the page table, and other EL2 MMU
configuration registers.
el3
If the exceptions
feature is also enabled then uses vbar_el3
for the exception vector. If
initial-pagetable
is also enabled then uses ttbr0_el3
for the page table, and other EL3 MMU
configuration registers.
exceptions
Provides an exception vector table, and sets it in the appropriate vbar
system register for the
selected exception level. You must provide handlers for each exception like so:
#[unsafe(no_mangle)]
extern "C" fn sync_exception_current(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn irq_current(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn fiq_current(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn serr_current(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn sync_lower(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn irq_lower(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn fiq_lower(_elr: u64, _spsr: u64) {
}
#[unsafe(no_mangle)]
extern "C" fn serr_lower(_elr: u64, _spsr: u64) {
}
initial-pagetable
Sets an initial pagetable in the appropriate TTBR and enables the MMU and cache before running any Rust code or writing to any memory.
This is especially important if running at EL1 in a VM, as accessing memory with the cache disabled while the hypervisor or host has cacheable aliases to the same memory can lead to cache coherency issues. Even if the host doesn't explicitly access the memory, speculative accesses can lead to cache fills.
psci
Adds the start_core
function to start another CPU core via a PSCI CPU_ON
call. This adds a
dependency on the smccc
crate.
License
Licensed under either of
- Apache License, Version 2.0 (LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license (LICENSE-MIT or http://opensource.org/licenses/MIT)
at your option.
Contributing
If you want to contribute to the project, see details of how we accept contributions.
Dependencies
~105KB