Skip to content

Commit

Permalink
Move away from llvm_asm to new asm.
Browse files Browse the repository at this point in the history
In my opinion, this makes the constraints a _lot_ easier to read, and
gets us things like noreturn. (Plus, it moves us off a deprecated
feature whose days are numbered.)

asm has opinions about trying to use r11. These opinions are misguided:
rust-lang/rust#73450

However, we respect them by manually moving values in and out of r11 in
the asm sequences.
  • Loading branch information
cbiffle committed Jun 19, 2020
1 parent b3b29b5 commit 57603ad
Show file tree
Hide file tree
Showing 11 changed files with 192 additions and 160 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion demo/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]

#[cfg(not(any(feature = "panic-itm", feature = "panic-semihosting")))]
compile_error!(
Expand Down
66 changes: 29 additions & 37 deletions kern/src/arch/arm_m.rs
Original file line number Diff line number Diff line change
Expand Up @@ -567,19 +567,16 @@ pub fn start_first_task(task: &task::Task) -> ! {
}

unsafe {
llvm_asm! { "
msr PSP, $0 @ set the user stack pointer
ldm $1, {r4-r11} @ restore the callee-save registers
asm!("
msr PSP, {user_sp} @ set the user stack pointer
ldm {task}, {{r4-r11}} @ restore the callee-save registers
svc #0xFF @ branch into user mode (svc # ignored)
udf #0xad @ should not return
"
:
: "r"(task.save.psp),
"r"(&task.save.r4)
: "memory"
: "volatile"
}
core::hint::unreachable_unchecked()
",
user_sp = in(reg) task.save.psp,
task = in(reg) &task.save.r4,
options(noreturn),
)
}
}

Expand All @@ -593,7 +590,7 @@ pub unsafe extern "C" fn SVCall() {
// of instructions below, though the precise details depend on how complex
// of an M-series processor you're targeting -- so I've punted on this for
// the time being.
llvm_asm! {"
asm!("
cmp lr, #0xFFFFFFF9 @ is it coming from inside the kernel?
beq 1f @ if so, we're starting the first task;
@ jump ahead.
Expand All @@ -608,7 +605,7 @@ pub unsafe extern "C" fn SVCall() {
@ fetching into r12 means the order in the stm below is right.
mrs r12, PSP
@ now, store volatile registers, plus the PSP in r12, plus LR.
stm r1, {r4-r12, lr}
stm r1, {{r4-r12, lr}}
@ syscall number is passed in r11. Move it into r0 to pass it as an
@ argument to the handler, then call the handler.
Expand All @@ -620,7 +617,7 @@ pub unsafe extern "C" fn SVCall() {
movt r0, #:upper16:CURRENT_TASK_PTR
ldr r0, [r0]
@ restore volatile registers, plus load PSP into r12
ldm r0, {r4-r12, lr}
ldm r0, {{r4-r12, lr}}
msr PSP, r12
@ resume
Expand All @@ -636,12 +633,9 @@ pub unsafe extern "C" fn SVCall() {
@ return into thread mode, PSP, FP on
bx lr @ branch into user mode
"
:
:
:
: "volatile"
}
",
options(noreturn),
)
}

/// Manufacture a mutable/exclusive reference to the task table from thin air
Expand Down Expand Up @@ -745,7 +739,7 @@ fn pend_context_switch_from_isr() {
#[naked]
#[no_mangle]
pub unsafe extern "C" fn PendSV() {
llvm_asm! {"
asm!("
@ store volatile state.
@ first, get a pointer to the current task.
movw r0, #:lower16:CURRENT_TASK_PTR
Expand All @@ -755,7 +749,7 @@ pub unsafe extern "C" fn PendSV() {
@ fetching into r12 means the order in the stm below is right.
mrs r12, PSP
@ now, store volatile registers, plus the PSP in r12, plus LR.
stm r1, {r4-r12, lr}
stm r1, {{r4-r12, lr}}
@ syscall number is passed in r11. Move it into r0 to pass it as an
@ argument to the handler, then call the handler.
Expand All @@ -766,17 +760,14 @@ pub unsafe extern "C" fn PendSV() {
movt r0, #:upper16:CURRENT_TASK_PTR
ldr r0, [r0]
@ restore volatile registers, plus load PSP into r12
ldm r0, {r4-r12, lr}
ldm r0, {{r4-r12, lr}}
msr PSP, r12
@ resume
bx lr
"
:
:
:
: "volatile"
}
",
options(noreturn),
);
}

/// The Rust side of the PendSV handler, after all volatile registers have been
Expand All @@ -803,10 +794,11 @@ pub unsafe extern "C" fn DefaultHandler() {
// We can cheaply get the identity of the interrupt that called us from the
// bottom 9 bits of IPSR.
let mut ipsr: u32;
llvm_asm! {
"mrs $0, IPSR"
: "=r"(ipsr)
}
asm!(
"mrs {}, IPSR",
out(reg) ipsr,
options(pure, nomem, preserves_flags, nostack),
);
let exception_num = ipsr & 0x1FF;

// The first 16 exceptions are architecturally defined; vendor hardware
Expand Down Expand Up @@ -882,7 +874,7 @@ pub fn enable_irq(n: u32) {
#[no_mangle]
#[naked]
pub unsafe extern "C" fn MemoryManagement() {
llvm_asm! { "
asm!("
@ Get the exc_return value into an argument register, which is
@ difficult to do from higher-level code.
mov r0, lr
Expand All @@ -891,9 +883,9 @@ pub unsafe extern "C" fn MemoryManagement() {
movt r1, #:upper16:CURRENT_TASK_PTR
ldr r1, [r1]
b mem_manage_fault
"
::::"volatile"
}
",
options(noreturn),
);
}

bitflags::bitflags! {
Expand Down
2 changes: 1 addition & 1 deletion kern/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
//! most clever algorithms used in kernels wind up requiring `unsafe`.)
#![cfg_attr(target_os = "none", no_std)]
#![feature(llvm_asm)]
#![feature(asm)]
#![feature(naked_functions)]

#[macro_use]
Expand Down
1 change: 0 additions & 1 deletion lpc55/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]

#[cfg(not(any(feature = "panic-itm", feature = "panic-semihosting")))]
compile_error!(
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain
Original file line number Diff line number Diff line change
@@ -1 +1 @@
nightly-2020-05-01
nightly-2020-06-10
1 change: 1 addition & 0 deletions task-idle/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ edition = "2018"
# suppress default features to avoid including panic message collection, to
# ensure the idle task remains tiny.
userlib = {path = "../userlib", default-features = false}
cortex-m = {version = "0.6", features = ["inline-asm"]}

[features]
default = ["standalone"]
Expand Down
10 changes: 3 additions & 7 deletions task-idle/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]

// Make sure we actually link in userlib, despite not using any of it explicitly
// - we need it for our _start routine.
Expand All @@ -9,11 +8,8 @@ extern crate userlib;
#[export_name = "main"]
fn main() -> ! {
loop {
// Safety: asm in general is unsafe, but this instruction is fine.
unsafe {
// Wait For Interrupt to pause the processor until an ISR arrives,
// which could wake some higher-priority task.
llvm_asm!("wfi"::::"volatile");
}
// Wait For Interrupt to pause the processor until an ISR arrives,
// which could wake some higher-priority task.
cortex_m::asm::wfi();
}
}
1 change: 0 additions & 1 deletion task-ping/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]

use userlib::*;

Expand Down
1 change: 0 additions & 1 deletion task-spam2/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#![no_std]
#![no_main]
#![feature(llvm_asm)]

// Make sure we actually link in userlib, despite not using any of it explicitly
// - we need it for our _start routine.
Expand Down
Loading

0 comments on commit 57603ad

Please sign in to comment.