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