diff --git a/CHANGELOG.md b/CHANGELOG.md index 8761c3c..051566f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - New GitHub workflow for checking invalid labels in PRs - New GitHub workflow for checking modifications on CHANGELOG.md - New GitHub workflow for checking clippy lints in PRs +- Optional cargo feature `single-hart` for single CPU targets ### Changed @@ -20,6 +21,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - `start_trap_rust` is now marked as `unsafe` - Implement `r0` as inline assembly - Use `${ARCH_WIDTH}` in `link.x.in` to adapt to different archs +- mhartid CSR is no longer read in single-hart mode, assumed zero +- Ensure stack pointer is 16-byte aligned before jumping to Rust entry point ## [v0.11.0] - 2023-01-18 diff --git a/src/asm.rs b/src/asm.rs index c29d918..0eedebe 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -85,7 +85,8 @@ _abs_start: .option push .option norelax la gp, __global_pointer$ - .option pop", + .option pop + // Allocate stacks", #[cfg(all(not(feature = "single-hart"), feature = "s-mode"))] "mv t2, a0 // the hartid is passed as parameter by SMODE", #[cfg(all(not(feature = "single-hart"), not(feature = "s-mode")))] @@ -93,9 +94,7 @@ _abs_start: #[cfg(not(feature = "single-hart"))] "lui t0, %hi(_max_hart_id) add t0, t0, %lo(_max_hart_id) - bgtu t2, t0, abort", - "// Allocate stacks - la sp, _stack_start + bgtu t2, t0, abort lui t0, %hi(_hart_stack_size) add t0, t0, %lo(_hart_stack_size)", #[cfg(all(not(feature = "single-hart"), riscvm))] @@ -109,8 +108,10 @@ _abs_start: addi t1, t1, -1 bnez t1, 1b 2: ", - "sub sp, sp, t0 - + "la t1, _stack_start", + #[cfg(not(feature = "single-hart"))] + "sub t1, t1, t0", + "andi sp, t1, -16 // Force 16-byte alignment // Set frame pointer add s0, sp, zero @@ -135,6 +136,8 @@ _abs_start: #[rustfmt::skip] macro_rules! trap_handler { ($STORE:ident, $LOAD:ident, $BYTES:literal, $TRAP_SIZE:literal, [$(($REG:ident, $LOCATION:literal)),*]) => { + // ensure we do not break that sp is 16-byte aligned + const _: () = assert!(($TRAP_SIZE * $BYTES) % 16 == 0); global_asm!( " .section .trap, \"ax\" diff --git a/src/lib.rs b/src/lib.rs index 3e86c49..54e5c01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -327,7 +327,7 @@ //! //! ## `single-hart` //! -//! This feature saves a little code size by removing unnecessary stack space calculation if there is only one hart on the target. +//! This feature saves a little code size if there is only one hart on the target. //! //! ## `s-mode` //! @@ -372,7 +372,10 @@ use core::sync::atomic::{compiler_fence, Ordering}; use riscv::register::{scause as xcause, stvec as xtvec, stvec::TrapMode as xTrapMode}; #[cfg(not(feature = "s-mode"))] -use riscv::register::{mcause as xcause, mhartid, mtvec as xtvec, mtvec::TrapMode as xTrapMode}; +use riscv::register::{mcause as xcause, mtvec as xtvec, mtvec::TrapMode as xTrapMode}; + +#[cfg(all(not(feature = "single-hart"), not(feature = "s-mode")))] +use riscv::register::mhartid; pub use riscv_rt_macros::{entry, pre_init}; @@ -404,13 +407,20 @@ pub unsafe extern "C" fn start_rust(a0: usize, a1: usize, a2: usize) -> ! { fn _mp_hook(hartid: usize) -> bool; } - // sbi passes hartid as first parameter (a0) - #[cfg(feature = "s-mode")] - let hartid = a0; - #[cfg(not(feature = "s-mode"))] - let hartid = mhartid::read(); + #[cfg(not(feature = "single-hart"))] + let run_init = { + // sbi passes hartid as first parameter (a0) + #[cfg(feature = "s-mode")] + let hartid = a0; + #[cfg(not(feature = "s-mode"))] + let hartid = mhartid::read(); + + _mp_hook(hartid) + }; + #[cfg(feature = "single-hart")] + let run_init = true; - if _mp_hook(hartid) { + if run_init { __pre_init(); // Initialize RAM @@ -661,6 +671,7 @@ pub unsafe extern "Rust" fn default_pre_init() {} #[doc(hidden)] #[no_mangle] #[rustfmt::skip] +#[cfg(not(feature = "single-hart"))] pub extern "Rust" fn default_mp_hook(hartid: usize) -> bool { match hartid { 0 => true,