1/* 2 * safe-syscall.inc.S : host-specific assembly fragment 3 * to handle signals occurring at the same time as system calls. 4 * This is intended to be included by common-user/safe-syscall.S 5 * 6 * Written by Richard Henderson <richard.henderson@linaro.org> 7 * Copyright (C) 2021 Linaro, Inc. 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 .text 14 .balign 4 15 16 .register %g2, #scratch 17 .register %g3, #scratch 18 19 .global safe_syscall_base 20 .global safe_syscall_start 21 .global safe_syscall_end 22 .type safe_syscall_base, @function 23 .type safe_syscall_start, @function 24 .type safe_syscall_end, @function 25 26#define STACK_BIAS 2047 27#define PARAM(N) STACK_BIAS + N*8 28 29 /* 30 * This is the entry point for making a system call. The calling 31 * convention here is that of a C varargs function with the 32 * first argument an 'int *' to the signal_pending flag, the 33 * second one the system call number (as a 'long'), and all further 34 * arguments being syscall arguments (also 'long'). 35 */ 36safe_syscall_base: 37 .cfi_startproc 38 /* 39 * The syscall calling convention isn't the same as the C one: 40 * we enter with o0 == &signal_pending 41 * o1 == syscall number 42 * o2 ... o5, (stack) == syscall arguments 43 * and return the result in x0 44 * and the syscall instruction needs 45 * g1 == syscall number 46 * o0 ... o5 == syscall arguments 47 * and returns the result in o0 48 * Shuffle everything around appropriately. 49 */ 50 mov %o0, %g2 /* signal_pending pointer */ 51 mov %o1, %g1 /* syscall number */ 52 mov %o2, %o0 /* syscall arguments */ 53 mov %o3, %o1 54 mov %o4, %o2 55 mov %o5, %o3 56 ldx [%sp + PARAM(6)], %o4 57 ldx [%sp + PARAM(7)], %o5 58 59 /* 60 * This next sequence of code works in conjunction with the 61 * rewind_if_safe_syscall_function(). If a signal is taken 62 * and the interrupted PC is anywhere between 'safe_syscall_start' 63 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 64 * The code sequence must therefore be able to cope with this, and 65 * the syscall instruction must be the final one in the sequence. 66 */ 67safe_syscall_start: 68 /* if signal_pending is non-zero, don't do the call */ 69 lduw [%g2], %g3 70 brnz,pn %g3, 2f 71 nop 72 ta 0x6d 73safe_syscall_end: 74 /* code path for having successfully executed the syscall */ 75 bcs,pn %xcc, 1f 76 nop 77 ret 78 nop 79 80 /* code path when we didn't execute the syscall */ 812: set QEMU_ERESTARTSYS, %o0 82 83 /* code path setting errno */ 841: mov %o7, %g1 85 call safe_syscall_set_errno_tail 86 mov %g1, %o7 87 88 .cfi_endproc 89 .size safe_syscall_base, .-safe_syscall_base 90