aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Adam Greig <adam@adamgreig.com> 2020-12-02 14:09:33 +0000
committerGravatar Adam Greig <adam@adamgreig.com> 2020-12-02 14:18:24 +0000
commit3b184eaa0abf147d607f918985bdffd6abe31a51 (patch)
treea6d563deedb3abb80fdbe9426d7cda310b8569fd
parent3a3a812f53d9bb66f3fe042a514f813734eac4c6 (diff)
downloadcortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.tar.gz
cortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.tar.zst
cortex-m-3b184eaa0abf147d607f918985bdffd6abe31a51.zip
asm.bootstrap: only set CONTROL.SPSEL, mark as divergent
-rw-r--r--asm/inline.rs22
-rw-r--r--asm/lib.rs4
-rw-r--r--bin/thumbv6m-none-eabi-lto.abin15792 -> 15860 bytes
-rw-r--r--bin/thumbv6m-none-eabi.abin18540 -> 18580 bytes
-rw-r--r--bin/thumbv7em-none-eabi-lto.abin19992 -> 20004 bytes
-rw-r--r--bin/thumbv7em-none-eabi.abin22952 -> 23008 bytes
-rw-r--r--bin/thumbv7em-none-eabihf-lto.abin20896 -> 20868 bytes
-rw-r--r--bin/thumbv7em-none-eabihf.abin24040 -> 24096 bytes
-rw-r--r--bin/thumbv7m-none-eabi-lto.abin18744 -> 18796 bytes
-rw-r--r--bin/thumbv7m-none-eabi.abin21784 -> 21840 bytes
-rw-r--r--bin/thumbv8m.base-none-eabi-lto.abin19056 -> 19136 bytes
-rw-r--r--bin/thumbv8m.base-none-eabi.abin22240 -> 22280 bytes
-rw-r--r--bin/thumbv8m.main-none-eabi-lto.abin23504 -> 23504 bytes
-rw-r--r--bin/thumbv8m.main-none-eabi.abin27608 -> 27664 bytes
-rw-r--r--bin/thumbv8m.main-none-eabihf-lto.abin24460 -> 24388 bytes
-rw-r--r--bin/thumbv8m.main-none-eabihf.abin28656 -> 28712 bytes
-rw-r--r--src/asm.rs24
17 files changed, 30 insertions, 20 deletions
diff --git a/asm/inline.rs b/asm/inline.rs
index bba5e6e..f2014f8 100644
--- a/asm/inline.rs
+++ b/asm/inline.rs
@@ -182,17 +182,23 @@ pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 {
nr
}
-/// Bootstrap: ensure we are using the main stack, then write `msp` to MSP and jump to `rv`.
+/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`.
#[inline(always)]
-pub unsafe fn __bootstrap(msp: u32, rv: u32) {
+pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! {
asm!(
- "msr CONTROL, {}",
+ "mrs {tmp}, CONTROL",
+ "bics {tmp}, {spsel}",
+ "msr CONTROL, {tmp}",
"isb",
- "msr MSP, {}",
- "bx {}",
- in(reg) 0,
- in(reg) msp,
- in(reg) rv,
+ "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),
);
}
diff --git a/asm/lib.rs b/asm/lib.rs
index b956d8b..fc8ddc8 100644
--- a/asm/lib.rs
+++ b/asm/lib.rs
@@ -69,11 +69,11 @@ shims! {
fn __psp_r() -> u32;
fn __psp_w(val: u32);
fn __sev();
- fn __udf();
+ fn __udf() -> !;
fn __wfe();
fn __wfi();
fn __sh_syscall(nr: u32, arg: u32) -> u32;
- fn __bootstrap(msp: u32, rv: u32);
+ fn __bootstrap(msp: u32, rv: u32) -> !;
}
// v7m *AND* v8m.main, but *NOT* v8m.base
diff --git a/bin/thumbv6m-none-eabi-lto.a b/bin/thumbv6m-none-eabi-lto.a
index bdb5314..f3858a0 100644
--- a/bin/thumbv6m-none-eabi-lto.a
+++ b/bin/thumbv6m-none-eabi-lto.a
Binary files differ
diff --git a/bin/thumbv6m-none-eabi.a b/bin/thumbv6m-none-eabi.a
index fcc94c0..571396b 100644
--- a/bin/thumbv6m-none-eabi.a
+++ b/bin/thumbv6m-none-eabi.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabi-lto.a b/bin/thumbv7em-none-eabi-lto.a
index 50e8f0f..51e02c6 100644
--- a/bin/thumbv7em-none-eabi-lto.a
+++ b/bin/thumbv7em-none-eabi-lto.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabi.a b/bin/thumbv7em-none-eabi.a
index 7bc58b8..d6ccf53 100644
--- a/bin/thumbv7em-none-eabi.a
+++ b/bin/thumbv7em-none-eabi.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabihf-lto.a b/bin/thumbv7em-none-eabihf-lto.a
index 57c1c9e..cc52e63 100644
--- a/bin/thumbv7em-none-eabihf-lto.a
+++ b/bin/thumbv7em-none-eabihf-lto.a
Binary files differ
diff --git a/bin/thumbv7em-none-eabihf.a b/bin/thumbv7em-none-eabihf.a
index adbe047..aea284d 100644
--- a/bin/thumbv7em-none-eabihf.a
+++ b/bin/thumbv7em-none-eabihf.a
Binary files differ
diff --git a/bin/thumbv7m-none-eabi-lto.a b/bin/thumbv7m-none-eabi-lto.a
index 0697bff..85720da 100644
--- a/bin/thumbv7m-none-eabi-lto.a
+++ b/bin/thumbv7m-none-eabi-lto.a
Binary files differ
diff --git a/bin/thumbv7m-none-eabi.a b/bin/thumbv7m-none-eabi.a
index 4e5b062..d9cf989 100644
--- a/bin/thumbv7m-none-eabi.a
+++ b/bin/thumbv7m-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.base-none-eabi-lto.a b/bin/thumbv8m.base-none-eabi-lto.a
index 600c26e..37e74a9 100644
--- a/bin/thumbv8m.base-none-eabi-lto.a
+++ b/bin/thumbv8m.base-none-eabi-lto.a
Binary files differ
diff --git a/bin/thumbv8m.base-none-eabi.a b/bin/thumbv8m.base-none-eabi.a
index a53abee..0660245 100644
--- a/bin/thumbv8m.base-none-eabi.a
+++ b/bin/thumbv8m.base-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabi-lto.a b/bin/thumbv8m.main-none-eabi-lto.a
index 2a761ef..4312c64 100644
--- a/bin/thumbv8m.main-none-eabi-lto.a
+++ b/bin/thumbv8m.main-none-eabi-lto.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabi.a b/bin/thumbv8m.main-none-eabi.a
index 0e2a886..59affcc 100644
--- a/bin/thumbv8m.main-none-eabi.a
+++ b/bin/thumbv8m.main-none-eabi.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabihf-lto.a b/bin/thumbv8m.main-none-eabihf-lto.a
index 98326e8..62fcad3 100644
--- a/bin/thumbv8m.main-none-eabihf-lto.a
+++ b/bin/thumbv8m.main-none-eabihf-lto.a
Binary files differ
diff --git a/bin/thumbv8m.main-none-eabihf.a b/bin/thumbv8m.main-none-eabihf.a
index 667cce9..f7795d1 100644
--- a/bin/thumbv8m.main-none-eabihf.a
+++ b/bin/thumbv8m.main-none-eabihf.a
Binary files differ
diff --git a/src/asm.rs b/src/asm.rs
index a546fe1..25eeaf8 100644
--- a/src/asm.rs
+++ b/src/asm.rs
@@ -165,7 +165,7 @@ pub unsafe fn bx_ns(addr: u32) {
call_asm!(__bxns(addr: u32));
}
-/// Semihosing syscall.
+/// Semihosting syscall.
///
/// This method is used by cortex-m-semihosting to provide semihosting syscalls.
#[inline]
@@ -175,15 +175,20 @@ pub unsafe fn sh_syscall(nr: u32, arg: u32) -> u32 {
/// Bootstrap.
///
-/// Sets the active stack to the main stack, updates the main stack pointer to `msp`,
-/// then jumps execution to the address in `rv`.
-/// Writes `msp` to the MSP special register, then jumps to the address in `rv`.
+/// 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;
- let rv = rv as u32;
- call_asm!(__bootstrap(msp: u32, rv: u32));
- core::hint::unreachable_unchecked();
+ call_asm!(__bootstrap(msp: u32, rv: u32) -> !);
}
/// Bootload.
@@ -191,14 +196,13 @@ pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
/// 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 view, then jumps to the reset vector.
+/// 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 (in thumb mode, with the least significant
-/// bit cleared) as the second word.
+/// 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);