1b8c92c6dSRichard Henderson/* 2b8c92c6dSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment 3b8c92c6dSRichard Henderson * to handle signals occurring at the same time as system calls. 4bbf15aafSRichard Henderson * This is intended to be included by common-user/safe-syscall.S 5b8c92c6dSRichard Henderson * 6b8c92c6dSRichard Henderson * Written by Richard Henderson <rth@twiddle.net> 7b8c92c6dSRichard Henderson * Copyright (C) 2018 Linaro, Inc. 8b8c92c6dSRichard Henderson * 9b8c92c6dSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later. 10b8c92c6dSRichard Henderson * See the COPYING file in the top-level directory. 11b8c92c6dSRichard Henderson */ 12b8c92c6dSRichard Henderson 13b8c92c6dSRichard Henderson .global safe_syscall_base 14b8c92c6dSRichard Henderson .global safe_syscall_start 15b8c92c6dSRichard Henderson .global safe_syscall_end 16b8c92c6dSRichard Henderson .type safe_syscall_base, @function 17b8c92c6dSRichard Henderson .type safe_syscall_start, @function 18b8c92c6dSRichard Henderson .type safe_syscall_end, @function 19b8c92c6dSRichard Henderson 20b8c92c6dSRichard Henderson /* 21b8c92c6dSRichard Henderson * This is the entry point for making a system call. The calling 22b8c92c6dSRichard Henderson * convention here is that of a C varargs function with the 23b8c92c6dSRichard Henderson * first argument an 'int *' to the signal_pending flag, the 24b8c92c6dSRichard Henderson * second one the system call number (as a 'long'), and all further 25b8c92c6dSRichard Henderson * arguments being syscall arguments (also 'long'). 26b8c92c6dSRichard Henderson */ 27b8c92c6dSRichard Hendersonsafe_syscall_base: 28b8c92c6dSRichard Henderson .cfi_startproc 29b8c92c6dSRichard Henderson /* 30b8c92c6dSRichard Henderson * The syscall calling convention is nearly the same as C: 31a3310c03SRichard Henderson * we enter with a0 == &signal_pending 32b8c92c6dSRichard Henderson * a1 == syscall number 33b8c92c6dSRichard Henderson * a2 ... a7 == syscall arguments 34b8c92c6dSRichard Henderson * and return the result in a0 35b8c92c6dSRichard Henderson * and the syscall instruction needs 36b8c92c6dSRichard Henderson * a7 == syscall number 37b8c92c6dSRichard Henderson * a0 ... a5 == syscall arguments 38b8c92c6dSRichard Henderson * and returns the result in a0 39b8c92c6dSRichard Henderson * Shuffle everything around appropriately. 40b8c92c6dSRichard Henderson */ 41b8c92c6dSRichard Henderson mv t0, a0 /* signal_pending pointer */ 42b8c92c6dSRichard Henderson mv t1, a1 /* syscall number */ 43b8c92c6dSRichard Henderson mv a0, a2 /* syscall arguments */ 44b8c92c6dSRichard Henderson mv a1, a3 45b8c92c6dSRichard Henderson mv a2, a4 46b8c92c6dSRichard Henderson mv a3, a5 47b8c92c6dSRichard Henderson mv a4, a6 48b8c92c6dSRichard Henderson mv a5, a7 49b8c92c6dSRichard Henderson mv a7, t1 50b8c92c6dSRichard Henderson 51b8c92c6dSRichard Henderson /* 52b8c92c6dSRichard Henderson * This next sequence of code works in conjunction with the 53b8c92c6dSRichard Henderson * rewind_if_safe_syscall_function(). If a signal is taken 54b8c92c6dSRichard Henderson * and the interrupted PC is anywhere between 'safe_syscall_start' 55b8c92c6dSRichard Henderson * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 56b8c92c6dSRichard Henderson * The code sequence must therefore be able to cope with this, and 57b8c92c6dSRichard Henderson * the syscall instruction must be the final one in the sequence. 58b8c92c6dSRichard Henderson */ 59b8c92c6dSRichard Hendersonsafe_syscall_start: 60b8c92c6dSRichard Henderson /* If signal_pending is non-zero, don't do the call */ 61b8c92c6dSRichard Henderson lw t1, 0(t0) 62a3310c03SRichard Henderson bnez t1, 2f 63b8c92c6dSRichard Henderson scall 64b8c92c6dSRichard Hendersonsafe_syscall_end: 65b8c92c6dSRichard Henderson /* code path for having successfully executed the syscall */ 66a3310c03SRichard Henderson li t2, -4096 67a3310c03SRichard Henderson bgtu a0, t2, 0f 68b8c92c6dSRichard Henderson ret 69b8c92c6dSRichard Henderson 70a3310c03SRichard Henderson /* code path setting errno */ 71a3310c03SRichard Henderson0: neg a0, a0 72*22b448ccSIcenowy Zheng tail safe_syscall_set_errno_tail 73a3310c03SRichard Henderson 74b8c92c6dSRichard Henderson /* code path when we didn't execute the syscall */ 75af254a27SRichard Henderson2: li a0, QEMU_ERESTARTSYS 76*22b448ccSIcenowy Zheng tail safe_syscall_set_errno_tail 77b8c92c6dSRichard Henderson 78a3310c03SRichard Henderson .cfi_endproc 79b8c92c6dSRichard Henderson .size safe_syscall_base, .-safe_syscall_base 80