1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
//! ARM Cortex-M implementation of [`ISyscall`]. use crate::arch::Arch; use crate::syscall::ISyscall; impl ISyscall for Arch { #[inline(always)] fn syscall(service: u8, arg0: usize, arg1: usize, arg2: usize) -> usize { // we need to move the arguments to the correct registers, because the // function is inlined let ret; unsafe { asm!( "push {{r4}}", "svc 0", "mov r0, r4", "pop {{r4}}", in("r0") service, in("r1") arg0, in("r2") arg1, in("r3") arg2, lateout("r0") ret, )} ret } } /// Extract and prepare system call for Rust handler. /// r0 is used to store the service id, r1-r3 can contain call parameter. /// /// The system call service id (`svc xy`) is not passed on, we have to /// retrieve it from code memory. Thus we load the stack pointer from the /// callee and read the link register. The link register is pointing to /// instruction just after the system call, the system call service id is /// placed two bytes before that. /// /// The exception link register tells SVC which privilege mode the callee used /// | EXC_RETURN (lr) | Privilege Mode | Stack | /// |-----------------|--------------------|------ | /// | 0xFFFFFFF1 | Handler Mode | MSP | /// | 0xFFFFFFF9 | Thread Mode | MSP | /// | 0xFFFFFFFD | Thread Mode | PSP | /// | 0xFFFFFFE1 | Handler Mode (FPU) | MSP | /// | 0xFFFFFFE9 | Thread Mode (FPU) | MSP | /// | 0xFFFFFFED | Thread Mode (FPU) | PSP | #[no_mangle] #[naked] unsafe extern "C" fn SVCall() { asm!( "push {{lr}}", "bl syscall_handler", "mov r4, r0", // let's use r4 as return value, because r0 is popped from stack "pop {{lr}}", "bx lr", options(noreturn), ); }