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 WINDOW_SIZE 16 * 8 28#define PARAM(N) STACK_BIAS + WINDOW_SIZE + N * 8 29 30 /* 31 * This is the entry point for making a system call. The calling 32 * convention here is that of a C varargs function with the 33 * first argument an 'int *' to the signal_pending flag, the 34 * second one the system call number (as a 'long'), and all further 35 * arguments being syscall arguments (also 'long'). 36 */ 37safe_syscall_base: 38 .cfi_startproc 39 /* 40 * The syscall calling convention isn't the same as the C one: 41 * we enter with o0 == &signal_pending 42 * o1 == syscall number 43 * o2 ... o5, (stack) == syscall arguments 44 * and return the result in x0 45 * and the syscall instruction needs 46 * g1 == syscall number 47 * o0 ... o5 == syscall arguments 48 * and returns the result in o0 49 * Shuffle everything around appropriately. 50 */ 51 mov %o0, %g2 /* signal_pending pointer */ 52 mov %o1, %g1 /* syscall number */ 53 mov %o2, %o0 /* syscall arguments */ 54 mov %o3, %o1 55 mov %o4, %o2 56 mov %o5, %o3 57 ldx [%sp + PARAM(6)], %o4 58 ldx [%sp + PARAM(7)], %o5 59 60 /* 61 * This next sequence of code works in conjunction with the 62 * rewind_if_safe_syscall_function(). If a signal is taken 63 * and the interrupted PC is anywhere between 'safe_syscall_start' 64 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 65 * The code sequence must therefore be able to cope with this, and 66 * the syscall instruction must be the final one in the sequence. 67 */ 68safe_syscall_start: 69 /* if signal_pending is non-zero, don't do the call */ 70 lduw [%g2], %g3 71 brnz,pn %g3, 2f 72 nop 73 ta 0x6d 74safe_syscall_end: 75 /* code path for having successfully executed the syscall */ 76 bcs,pn %xcc, 1f 77 nop 78 retl 79 nop 80 81 /* code path when we didn't execute the syscall */ 822: set QEMU_ERESTARTSYS, %o0 83 84 /* code path setting errno */ 851: mov %o7, %g1 86 call safe_syscall_set_errno_tail 87 mov %g1, %o7 88 89 .cfi_endproc 90 .size safe_syscall_base, .-safe_syscall_base 91