Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
feat(riscv-rt): dedicated trap regions
Placed behind the `region-trap` feature flag.
  • Loading branch information
gibbz00 committed Jul 2, 2025
commit 2d75b1523209f6d2e38822cb94744e6d96cdcc69
2 changes: 2 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ jobs:
run: RUSTFLAGS="-C link-arg=-Tmemory.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features device
- name: Build (include memory.x)
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features memory
- name: Build (include memory.x, use trap region)
run: RUSTFLAGS="-C link-arg=-Tdevice.x -C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features memory,trap-region
- name: Build (include device.x and memory.x)
run: RUSTFLAGS="-C link-arg=-Tlink.x" cargo build --package tests-build --target ${{ matrix.target }} --example ${{ matrix.example }} --features device,memory

Expand Down
1 change: 1 addition & 0 deletions riscv-rt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,4 @@ no-interrupts = []
no-exceptions = []
device = []
memory = []
trap-region = []
28 changes: 20 additions & 8 deletions riscv-rt/link.x.in
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,16 @@ PROVIDE(_max_hart_id = 0);
PROVIDE(_hart_stack_size = SIZEOF(.stack) / (_max_hart_id + 1));
PROVIDE(_heap_size = 0);

{% set trap_regions %}
. = ALIGN(4);
KEEP(*(.trap.vector)); /* for _trap_vector (vectored mode only) */
KEEP(*(.trap.start)); /* for _start_trap routine */
KEEP(*(.trap.start.*)); /* for _start_INTERRUPT_trap routines (vectored mode only) */
KEEP(*(.trap.continue)); /* for _continue_trap routine (vectored mode only) */
KEEP(*(.trap.rust)); /* for _start_trap_rust Rust function */
KEEP(*(.trap .trap.*)); /* Other .trap symbols at the end */
{% endset %}

SECTIONS
{
.text.dummy (NOLOAD) :
Expand All @@ -143,14 +153,9 @@ SECTIONS
/* point of the program. */
KEEP(*(.init));

. = ALIGN(4);
KEEP(*(.trap.vector)); /* for _trap_vector (vectored mode only) */
KEEP(*(.trap.start)); /* for _start_trap routine */
KEEP(*(.trap.start.*)); /* for _start_INTERRUPT_trap routines (vectored mode only) */
KEEP(*(.trap.continue)); /* for _continue_trap routine (vectored mode only) */
KEEP(*(.trap.rust)); /* for _start_trap_rust Rust function */
KEEP(*(.trap .trap.*)); /* Other .trap symbols at the end */

{% if not contains(cfg.feature, "trap-region") %}
{{ trap_regions }}
{% endif %}
*(.text.abort);
*(.text .text.*);

Expand All @@ -173,6 +178,13 @@ SECTIONS
__erodata = .;
} > REGION_RODATA

{% if contains(cfg.feature, "trap-region") %}
.trap : ALIGN(4)
{
{{ trap_regions }}
} > REGION_TRAP
{% endif %}

.data : ALIGN({{ cfg.arch_width }})
{
. = ALIGN({{ cfg.arch_width }});
Expand Down
11 changes: 11 additions & 0 deletions riscv-rt/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,17 @@
//! because when booting from elf, U-boot passes `argc` and `argv`. This feature also implies `single-hart`.
//! The only way to get boot-hart is through fdt, so other harts initialization is up to you.
//!
//! ## `trap-region`
//!
//! Adds a dedicated trap memory region, `REGION_TRAP`, for placing `.trap` sections into. Enabling
//! this feature and adding `REGION_ALIAS("REGION_TRAP", RAM);` to `memory.x` would for example place
//! it in `RAM`.
//!
//! `REGION_TEXT` is usually placed in flash memory with a cache in front. Having a separate trap
//! memory region makes it possible to always store interrupt and exceptions handlers in RAM,
//! effectively bypassing cache contention and variable trap latency at the cost of increased RAM
//! usage.
//!
//! [attr-entry]: attr.entry.html
//! [attr-exception]: attr.exception.html
//! [attr-external-interrupt]: attr.external_interrupt.html
Expand Down
4 changes: 4 additions & 0 deletions tests-build/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ panic-halt = "1.0"
riscv = { path = "../riscv" }
riscv-rt = { path = "../riscv-rt" }

[build-dependencies]
minilink = "0.2"

[features]
pre-init = ["riscv-rt/pre-init"]
single-hart = ["riscv-rt/single-hart"]
Expand All @@ -16,3 +19,4 @@ device = ["riscv-rt/device"]
memory = ["riscv-rt/memory"]
no-exceptions = ["riscv-rt/no-exceptions"]
no-interrupts = ["riscv-rt/no-interrupts"]
trap-region = ["riscv-rt/trap-region"]
22 changes: 2 additions & 20 deletions tests-build/build.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,4 @@
use std::{env, fs::File, io::Write, path::PathBuf};

fn main() {
// Put device.x somewhere the linker can find it
let out = &PathBuf::from(env::var_os("OUT_DIR").unwrap());
File::create(out.join("device.x"))
.unwrap()
.write_all(include_bytes!("device.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=device.x");

// Put memory.x somewhere the linker can find it
File::create(out.join("memory.x"))
.unwrap()
.write_all(include_bytes!("memory.x"))
.unwrap();
println!("cargo:rustc-link-search={}", out.display());
println!("cargo:rerun-if-changed=memory.x");

println!("cargo:rerun-if-changed=build.rs");
minilink::register_template("device.x", "device.x");
minilink::register_template("memory.x", "memory.x");
}
4 changes: 4 additions & 0 deletions tests-build/memory.x
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@ REGION_ALIAS("REGION_DATA", RAM);
REGION_ALIAS("REGION_BSS", RAM);
REGION_ALIAS("REGION_HEAP", RAM);
REGION_ALIAS("REGION_STACK", RAM);

{% if contains(cfg.feature, "trap-region") %}
REGION_ALIAS("REGION_TRAP", RAM);
{% endif %}
Loading