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