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 * Copyright (C) 2022 Linaro, Ltd. 7 * 8 * This work is licensed under the terms of the GNU GPL, version 2 or later. 9 * See the COPYING file in the top-level directory. 10 */ 11 12/* 13 * Standardize on the _CALL_FOO symbols used by GCC: 14 * Apple XCode does not define _CALL_DARWIN. 15 * Clang defines _CALL_ELF (64-bit) but not _CALL_SYSV (32-bit). 16 */ 17#if !defined(_CALL_SYSV) && \ 18 !defined(_CALL_DARWIN) && \ 19 !defined(_CALL_AIX) && \ 20 !defined(_CALL_ELF) 21# if defined(__APPLE__) 22# define _CALL_DARWIN 23# elif defined(__ELF__) && TCG_TARGET_REG_BITS == 32 24# define _CALL_SYSV 25# else 26# error "Unknown ABI" 27# endif 28#endif 29 30#ifndef _CALL_SYSV 31# error "Unsupported ABI" 32#endif 33 34 35 .global safe_syscall_base 36 .global safe_syscall_start 37 .global safe_syscall_end 38 .type safe_syscall_base, @function 39 40 .text 41 42 /* 43 * This is the entry point for making a system call. The calling 44 * convention here is that of a C varargs function with the 45 * first argument an 'int *' to the signal_pending flag, the 46 * second one the system call number (as a 'long'), and all further 47 * arguments being syscall arguments (also 'long'). 48 */ 49safe_syscall_base: 50 .cfi_startproc 51 stwu 1, -8(1) 52 .cfi_def_cfa_offset 8 53 stw 30, 4(1) 54 .cfi_offset 30, -4 55 56 /* 57 * We enter with r3 == &signal_pending 58 * r4 == syscall number 59 * r5 ... r10 == syscall arguments 60 * and return the result in r3 61 * and the syscall instruction needs 62 * r0 == syscall number 63 * r3 ... r8 == syscall arguments 64 * and returns the result in r3 65 * Shuffle everything around appropriately. 66 */ 67 mr 30, 3 /* signal_pending */ 68 mr 0, 4 /* syscall number */ 69 mr 3, 5 /* syscall arguments */ 70 mr 4, 6 71 mr 5, 7 72 mr 6, 8 73 mr 7, 9 74 mr 8, 10 75 76 /* 77 * This next sequence of code works in conjunction with the 78 * rewind_if_safe_syscall_function(). If a signal is taken 79 * and the interrupted PC is anywhere between 'safe_syscall_start' 80 * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 81 * The code sequence must therefore be able to cope with this, and 82 * the syscall instruction must be the final one in the sequence. 83 */ 84safe_syscall_start: 85 /* if signal_pending is non-zero, don't do the call */ 86 lwz 12, 0(30) 87 cmpwi 0, 12, 0 88 bne- 2f 89 sc 90safe_syscall_end: 91 /* code path when we did execute the syscall */ 92 lwz 30, 4(1) /* restore r30 */ 93 addi 1, 1, 8 /* restore stack */ 94 .cfi_restore 30 95 .cfi_def_cfa_offset 0 96 bnslr+ /* return on success */ 97 b safe_syscall_set_errno_tail 98 99 /* code path when we didn't execute the syscall */ 1002: lwz 30, 4(1) 101 addi 1, 1, 8 102 addi 3, 0, QEMU_ERESTARTSYS 103 b safe_syscall_set_errno_tail 104 105 .cfi_endproc 106 107 .size safe_syscall_base, .-safe_syscall_base 108