Skip to content

Expose __syscall and add new bootstrap method #299

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 5 commits into from
Dec 2, 2020
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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

### Added

- New assembly methods `asm::semihosting_syscall`, `asm::bootstrap`, and
`asm::bootload`.

## [v0.7.0] - 2020-11-09

### Added
Expand Down
22 changes: 21 additions & 1 deletion asm/inline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,31 @@ pub unsafe fn __wfi() {

/// Semihosting syscall.
#[inline(always)]
pub unsafe fn __syscall(mut nr: u32, arg: u32) -> u32 {
pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 {
asm!("bkpt #0xab", inout("r0") nr, in("r1") arg);
nr
}

/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`.
#[inline(always)]
pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! {
asm!(
"mrs {tmp}, CONTROL",
"bics {tmp}, {spsel}",
"msr CONTROL, {tmp}",
"isb",
"msr MSP, {msp}",
"bx {rv}",
// `out(reg) _` is not permitted in a `noreturn` asm! call,
// so instead use `in(reg) 0` and don't restore it afterwards.
tmp = in(reg) 0,
spsel = in(reg) 2,
msp = in(reg) msp,
rv = in(reg) rv,
options(noreturn),
);
}

// v7m *AND* v8m.main, but *NOT* v8m.base
#[cfg(any(armv7m, armv8m_main))]
pub use self::v7m::*;
Expand Down
5 changes: 3 additions & 2 deletions asm/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,11 @@ shims! {
fn __psp_r() -> u32;
fn __psp_w(val: u32);
fn __sev();
fn __udf();
fn __udf() -> !;
fn __wfe();
fn __wfi();
fn __syscall(nr: u32, arg: u32) -> u32;
fn __sh_syscall(nr: u32, arg: u32) -> u32;
fn __bootstrap(msp: u32, rv: u32) -> !;
}

// v7m *AND* v8m.main, but *NOT* v8m.base
Expand Down
Binary file modified bin/thumbv6m-none-eabi-lto.a
Binary file not shown.
Binary file modified bin/thumbv6m-none-eabi.a
Binary file not shown.
Binary file modified bin/thumbv7em-none-eabi-lto.a
Binary file not shown.
Binary file modified bin/thumbv7em-none-eabi.a
Binary file not shown.
Binary file modified bin/thumbv7em-none-eabihf-lto.a
Binary file not shown.
Binary file modified bin/thumbv7em-none-eabihf.a
Binary file not shown.
Binary file modified bin/thumbv7m-none-eabi-lto.a
Binary file not shown.
Binary file modified bin/thumbv7m-none-eabi.a
Binary file not shown.
Binary file modified bin/thumbv8m.base-none-eabi-lto.a
Binary file not shown.
Binary file modified bin/thumbv8m.base-none-eabi.a
Binary file not shown.
Binary file modified bin/thumbv8m.main-none-eabi-lto.a
Binary file not shown.
Binary file modified bin/thumbv8m.main-none-eabi.a
Binary file not shown.
Binary file modified bin/thumbv8m.main-none-eabihf-lto.a
Binary file not shown.
Binary file modified bin/thumbv8m.main-none-eabihf.a
Binary file not shown.
45 changes: 45 additions & 0 deletions src/asm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,3 +164,48 @@ pub fn ttat(addr: *mut u32) -> u32 {
pub unsafe fn bx_ns(addr: u32) {
call_asm!(__bxns(addr: u32));
}

/// Semihosting syscall.
///
/// This method is used by cortex-m-semihosting to provide semihosting syscalls.
#[inline]
pub unsafe fn semihosting_syscall(nr: u32, arg: u32) -> u32 {
call_asm!(__sh_syscall(nr: u32, arg: u32) -> u32)
}

/// Bootstrap.
///
/// Clears CONTROL.SPSEL (setting the main stack to be the active stack),
/// updates the main stack pointer to the address in `msp`, then jumps
/// to the address in `rv`.
///
/// # Safety
///
/// `msp` and `rv` must point to valid stack memory and executable code,
/// respectively.
#[inline]
pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
// Ensure thumb mode is set.
let rv = (rv as u32) | 1;
let msp = msp as u32;
call_asm!(__bootstrap(msp: u32, rv: u32) -> !);
}

/// Bootload.
///
/// Reads the initial stack pointer value and reset vector from
/// the provided vector table address, sets the active stack to
/// the main stack, sets the main stack pointer to the new initial
/// stack pointer, then jumps to the reset vector.
///
/// # Safety
///
/// The provided `vector_table` must point to a valid vector
/// table, with a valid stack pointer as the first word and
/// a valid reset vector as the second word.
#[inline]
pub unsafe fn bootload(vector_table: *const u32) -> ! {
let msp = core::ptr::read_volatile(vector_table);
let rv = core::ptr::read_volatile(vector_table.offset(1));
bootstrap(msp as *const u32, rv as *const u32);
}