; vim:ft=arm64asm .macro ldr_got reg, sym #ifdef __MACH__ adrp \reg, \sym\()@GOTPAGE ldr \reg, [\reg, \sym\()@GOTPAGEOFF] #else // !defined(__MACH__) adrp \reg, :got:\sym ldr \reg, [\reg, :got_lo12:\sym] #endif // __MACH__ .endm .macro swapcontext stp x27, x28, [sp, -0x10]! stp x25, x26, [sp, -0x10]! stp x23, x24, [sp, -0x10]! stp x21, x22, [sp, -0x10]! stp x19, x20, [sp, -0x10]! stp d14, d15, [sp, -0x10]! stp d12, d13, [sp, -0x10]! stp d10, d11, [sp, -0x10]! stp d8, d9, [sp, -0x10]! // Store the stack pointer with the saved context. ldr_got x1, rt_context_prev ldr x1, [x1] mov x2, sp str x2, [x1] // Switch to the new task stack. mov sp, x0 clrex ldp d8, d9, [sp], 0x10 ldp d10, d11, [sp], 0x10 ldp d12, d13, [sp], 0x10 ldp d14, d15, [sp], 0x10 ldp x19, x20, [sp], 0x10 ldp x21, x22, [sp], 0x10 ldp x23, x24, [sp], 0x10 ldp x25, x26, [sp], 0x10 ldp x27, x28, [sp], 0x10 .endm .macro sysreturn /* If returning into a task that isn't in a pending syscall handler, we * need to unblock pending syscalls on return. Tasks that are in a pending * syscall handler will do this automatically during the signal return. */ ldp fp, lr, [sp], 0x10 tbnz lr, 0, 0f b rt_unblock_pending_syscalls 0: bic lr, lr, 0x1 ret .endm .text .global rt_syscall_0, rt_syscall_1, rt_syscall_2, rt_syscall_3 rt_syscall_0: rt_syscall_1: rt_syscall_2: rt_syscall_3: rt_syscall: stp fp, lr, [sp, -0x10]! // Save the syscall arguments before calling rt_block_pending_syscalls. stp x2, x3, [sp, -0x10]! stp x0, x1, [sp, -0x10]! bl rt_block_pending_syscalls // Restore the syscall arguments. ldp x0, x1, [sp], 0x10 ldp x2, x3, [sp], 0x10 bl rt_syscall_run cbnz x0, 0f ldp fp, lr, [sp], 0x10 b rt_unblock_pending_syscalls 0: swapcontext sysreturn .global rt_pending_syscall_handler rt_pending_syscall_handler: // Record that this task is in a signal handler. orr lr, lr, 0x1 stp fp, lr, [sp, -0x10]! bl rt_syscall_run_pending cbnz x0, 0f ldp fp, lr, [sp], 0x10 bic lr, lr, 0x1 ret 0: swapcontext sysreturn .global rt_start rt_start: bl rt_start_context // Set the stack pointer, skipping d8-d15. add sp, x0, 0x40 // Load x19, x20, skip x21-x28. ldp x19, x20, [sp], 0x50 ldp fp, lr, [sp], 0x10 b rt_unblock_pending_syscalls .global rt_task_entry rt_task_entry: mov x0, x20 blr x19 b rt_task_exit