Skip to content

Commit d93e691

Browse files
committed
asm.bootstrap: only set CONTROL.SPSEL, mark as divergent
1 parent 3a3a812 commit d93e691

File tree

3 files changed

+28
-20
lines changed

3 files changed

+28
-20
lines changed

asm/inline.rs

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -182,17 +182,21 @@ pub unsafe fn __sh_syscall(mut nr: u32, arg: u32) -> u32 {
182182
nr
183183
}
184184

185-
/// Bootstrap: ensure we are using the main stack, then write `msp` to MSP and jump to `rv`.
185+
/// Set CONTROL.SPSEL to 0, write `msp` to MSP, branch to `rv`.
186186
#[inline(always)]
187-
pub unsafe fn __bootstrap(msp: u32, rv: u32) {
187+
pub unsafe fn __bootstrap(msp: u32, rv: u32) -> ! {
188188
asm!(
189-
"msr CONTROL, {}",
189+
"mrs {tmp}, CONTROL",
190+
"bics {tmp} {spsel}",
191+
"msr CONTROL, {tmp}",
190192
"isb",
191-
"msr MSP, {}",
192-
"bx {}",
193-
in(reg) 0,
194-
in(reg) msp,
195-
in(reg) rv,
193+
"msr MSP, {msp}",
194+
"bx {rv}",
195+
tmp = out(reg) _,
196+
spsel = in(reg) 2,
197+
msp = in(reg) msp,
198+
rv = in(reg) rv,
199+
options(noreturn),
196200
);
197201
}
198202

asm/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ shims! {
6969
fn __psp_r() -> u32;
7070
fn __psp_w(val: u32);
7171
fn __sev();
72-
fn __udf();
72+
fn __udf() -> !;
7373
fn __wfe();
7474
fn __wfi();
7575
fn __sh_syscall(nr: u32, arg: u32) -> u32;
76-
fn __bootstrap(msp: u32, rv: u32);
76+
fn __bootstrap(msp: u32, rv: u32) -> !;
7777
}
7878

7979
// v7m *AND* v8m.main, but *NOT* v8m.base

src/asm.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ pub unsafe fn bx_ns(addr: u32) {
165165
call_asm!(__bxns(addr: u32));
166166
}
167167

168-
/// Semihosing syscall.
168+
/// Semihosting syscall.
169169
///
170170
/// This method is used by cortex-m-semihosting to provide semihosting syscalls.
171171
#[inline]
@@ -175,30 +175,34 @@ pub unsafe fn sh_syscall(nr: u32, arg: u32) -> u32 {
175175

176176
/// Bootstrap.
177177
///
178-
/// Sets the active stack to the main stack, updates the main stack pointer to `msp`,
179-
/// then jumps execution to the address in `rv`.
180-
/// Writes `msp` to the MSP special register, then jumps to the address in `rv`.
178+
/// Clears CONTROL.SPSEL (setting the main stack to be the active stack),
179+
/// updates the main stack pointer to the address in `msp`, then jumps
180+
/// to the address in `rv`.
181+
///
182+
/// # Safety
183+
///
184+
/// `msp` and `rv` must point to valid stack memory and executable code,
185+
/// respectively.
181186
#[inline]
182187
pub unsafe fn bootstrap(msp: *const u32, rv: *const u32) -> ! {
188+
// Ensure thumb mode is set.
189+
let rv = (rv as u32) | 1;
183190
let msp = msp as u32;
184-
let rv = rv as u32;
185-
call_asm!(__bootstrap(msp: u32, rv: u32));
186-
core::hint::unreachable_unchecked();
191+
call_asm!(__bootstrap(msp: u32, rv: u32) -> !);
187192
}
188193

189194
/// Bootload.
190195
///
191196
/// Reads the initial stack pointer value and reset vector from
192197
/// the provided vector table address, sets the active stack to
193198
/// the main stack, sets the main stack pointer to the new initial
194-
/// stack pointer view, then jumps to the reset vector.
199+
/// stack pointer, then jumps to the reset vector.
195200
///
196201
/// # Safety
197202
///
198203
/// The provided `vector_table` must point to a valid vector
199204
/// table, with a valid stack pointer as the first word and
200-
/// a valid reset vector (in thumb mode, with the least significant
201-
/// bit cleared) as the second word.
205+
/// a valid reset vector as the second word.
202206
#[inline]
203207
pub unsafe fn bootload(vector_table: *const u32) -> ! {
204208
let msp = core::ptr::read_volatile(vector_table);

0 commit comments

Comments
 (0)