Skip to content

_default_start_trap and _default_setup_interrupts #279

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
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
3 changes: 3 additions & 0 deletions riscv-rt/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Replace weak definition of `_pre_init_trap` with `PROVIDE(_pre_init_trap = _default_abort)`.
- Now, `_default_abort` is 4-byte aligned (required by `_pre_init_trap`)
- Removed `.init.trap` section, as it is no longer required.
- Replace weak definition of `_start_trap` with `PROVIDE(_start_trap = _default_start_trap)`.
- Replace weak definition of `_setup_interrupts` with `PROVIDE(_setup_interrupts = _default_setup_interrupts)`.
- Now, `_default_start_trap` is 4-byte aligned instead of target width-aligned.

## [v0.14.0] - 2025-02-18

Expand Down
19 changes: 15 additions & 4 deletions riscv-rt/link.x.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,18 @@ PROVIDE(abort = _default_abort);
_pre_init_trap defaults to _default_abort. Note that _pre_init_trap must be 4-byte aligned */
PROVIDE(_pre_init_trap = _default_abort);

/* Default trap entry point. The riscv-rt crate provides a weak alias of this function,
which saves caller saved registers, calls _start_trap_rust, restores caller saved registers
and then returns. Users can override this alias by defining the symbol themselves */
EXTERN(_start_trap);
/* Default trap entry point. If not _start_trap symbol is provided, then _start_trap maps to
_default_start_trap, which saves caller saved registers, calls _start_trap_rust, restores
caller saved registers and then returns. Note that _start_trap must be 4-byte aligned */
EXTERN(_default_start_trap);
PROVIDE(_start_trap = _default_start_trap);

/* Default interrupt setup entry point. If not _setup_interrupts symbol is provided, then
_setup_interrupts maps to _default_setup_interrupts, which in direct mode sets the value
of the xtvec register to _start_trap and, in vectored mode, sets its value to
_vector_table and enables vectored mode. */
EXTERN(_default_setup_interrupts);
PROVIDE(_setup_interrupts = _default_setup_interrupts);

/* Default exception handler. By default, the exception handler is abort.
Users can override this alias by defining the symbol themselves */
Expand Down Expand Up @@ -195,6 +203,9 @@ BUG(riscv-rt): start of .heap is not 4-byte aligned");
ASSERT(_pre_init_trap % 4 == 0, "
BUG(riscv-rt): _pre_init_trap is not 4-byte aligned");

ASSERT(_start_trap % 4 == 0, "
BUG(riscv-rt): _start_trap is not 4-byte aligned");

ASSERT(_stext + SIZEOF(.text) < ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT), "
ERROR(riscv-rt): The .text section must be placed inside the REGION_TEXT region.
Set _stext to an address smaller than 'ORIGIN(REGION_TEXT) + LENGTH(REGION_TEXT)'");
Expand Down
11 changes: 6 additions & 5 deletions riscv-rt/macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,12 +475,13 @@ pub fn llvm_arch_patch(_input: TokenStream) -> TokenStream {
q.into()
}

/// Generates weak `_start_trap` function in assembly.
/// Generates `_default_start_trap` function in assembly.
/// If no `_start_trap` function is defined, the linker will use this function as the default.
///
/// This implementation stores all registers in the trap frame and calls `_start_trap_rust`.
/// The trap frame is allocated on the stack and deallocated after the call.
#[proc_macro]
pub fn weak_start_trap(_input: TokenStream) -> TokenStream {
pub fn default_start_trap(_input: TokenStream) -> TokenStream {
let arch = RiscvArch::try_from_env().unwrap();

let width = arch.width();
Expand All @@ -504,9 +505,9 @@ pub fn weak_start_trap(_input: TokenStream) -> TokenStream {
r#"
core::arch::global_asm!(
".section .trap, \"ax\"
.align {width}
.weak _start_trap
_start_trap:
.align 4 /* Alignment required for xtvec */
.global _default_start_trap
_default_start_trap:
addi sp, sp, - {trap_size} * {width}
{store}
add a0, sp, zero
Expand Down
13 changes: 7 additions & 6 deletions riscv-rt/src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,23 +237,24 @@ _mp_hook:
j 1b
2: li a0, 1
ret",
// Default implementation of `_setup_interrupts` sets the trap vector to `_start_trap`.
// Default implementation of `_setup_interrupts` sets the trap vector to `_start_trap` in direct mode.
// In vectored mode, it sets the trap vector to `_vector_table`.
// Users can override this function by defining their own `_setup_interrupts`
".weak _setup_interrupts
_setup_interrupts:",
".global _default_setup_interrupts
_default_setup_interrupts:",
#[cfg(not(feature = "v-trap"))]
"la t0, _start_trap", // _start_trap is 16-byte aligned, so it corresponds to the Direct trap mode
"la t0, _start_trap", // _start_trap is 4-byte aligned, so it corresponds to the Direct trap mode
#[cfg(feature = "v-trap")]
"la t0, _vector_table
ori t0, t0, 0x1", // _vector_table is 16-byte aligned, so we must set the bit 0 to activate the Vectored trap mode
ori t0, t0, 0x1", // _vector_table is at least 4-byte aligned, so we must set the bit 0 to activate the Vectored trap mode
#[cfg(feature = "s-mode")]
"csrw stvec, t0",
#[cfg(not(feature = "s-mode"))]
"csrw mtvec, t0",
"ret",
);

riscv_rt_macros::weak_start_trap!();
riscv_rt_macros::default_start_trap!();

#[cfg(feature = "v-trap")]
riscv_rt_macros::vectored_interrupt_trap!();
Expand Down