1bbf15aafSRichard Henderson/* 2bbf15aafSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment 3bbf15aafSRichard 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 5bbf15aafSRichard Henderson * 6bbf15aafSRichard Henderson * Written by Richard Henderson <richard.henderson@linaro.org> 7bbf15aafSRichard Henderson * Copyright (C) 2021 Linaro, Inc. 8bbf15aafSRichard Henderson * 9bbf15aafSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later. 10bbf15aafSRichard Henderson * See the COPYING file in the top-level directory. 11bbf15aafSRichard Henderson */ 12bbf15aafSRichard Henderson 13bbf15aafSRichard Henderson .text 14bbf15aafSRichard Henderson .balign 4 15bbf15aafSRichard Henderson 16bbf15aafSRichard Henderson .register %g2, #scratch 17bbf15aafSRichard Henderson .register %g3, #scratch 18bbf15aafSRichard Henderson 19bbf15aafSRichard Henderson .global safe_syscall_base 20bbf15aafSRichard Henderson .global safe_syscall_start 21bbf15aafSRichard Henderson .global safe_syscall_end 22bbf15aafSRichard Henderson .type safe_syscall_base, @function 23bbf15aafSRichard Henderson .type safe_syscall_start, @function 24bbf15aafSRichard Henderson .type safe_syscall_end, @function 25bbf15aafSRichard Henderson 26bbf15aafSRichard Henderson#define STACK_BIAS 2047 27*620d0b49SRichard Henderson#define WINDOW_SIZE 16 * 8 28*620d0b49SRichard Henderson#define PARAM(N) STACK_BIAS + WINDOW_SIZE + N * 8 29bbf15aafSRichard Henderson 30bbf15aafSRichard Henderson /* 31bbf15aafSRichard Henderson * This is the entry point for making a system call. The calling 32bbf15aafSRichard Henderson * convention here is that of a C varargs function with the 33bbf15aafSRichard Henderson * first argument an 'int *' to the signal_pending flag, the 34bbf15aafSRichard Henderson * second one the system call number (as a 'long'), and all further 35bbf15aafSRichard Henderson * arguments being syscall arguments (also 'long'). 36bbf15aafSRichard Henderson */ 37bbf15aafSRichard Hendersonsafe_syscall_base: 38bbf15aafSRichard Henderson .cfi_startproc 39bbf15aafSRichard Henderson /* 40bbf15aafSRichard Henderson * The syscall calling convention isn't the same as the C one: 41bbf15aafSRichard Henderson * we enter with o0 == &signal_pending 42bbf15aafSRichard Henderson * o1 == syscall number 43bbf15aafSRichard Henderson * o2 ... o5, (stack) == syscall arguments 44bbf15aafSRichard Henderson * and return the result in x0 45bbf15aafSRichard Henderson * and the syscall instruction needs 46bbf15aafSRichard Henderson * g1 == syscall number 47bbf15aafSRichard Henderson * o0 ... o5 == syscall arguments 48bbf15aafSRichard Henderson * and returns the result in o0 49bbf15aafSRichard Henderson * Shuffle everything around appropriately. 50bbf15aafSRichard Henderson */ 51bbf15aafSRichard Henderson mov %o0, %g2 /* signal_pending pointer */ 52bbf15aafSRichard Henderson mov %o1, %g1 /* syscall number */ 53bbf15aafSRichard Henderson mov %o2, %o0 /* syscall arguments */ 54bbf15aafSRichard Henderson mov %o3, %o1 55bbf15aafSRichard Henderson mov %o4, %o2 56bbf15aafSRichard Henderson mov %o5, %o3 57bbf15aafSRichard Henderson ldx [%sp + PARAM(6)], %o4 58bbf15aafSRichard Henderson ldx [%sp + PARAM(7)], %o5 59bbf15aafSRichard Henderson 60bbf15aafSRichard Henderson /* 61bbf15aafSRichard Henderson * This next sequence of code works in conjunction with the 62bbf15aafSRichard Henderson * rewind_if_safe_syscall_function(). If a signal is taken 63bbf15aafSRichard Henderson * and the interrupted PC is anywhere between 'safe_syscall_start' 64bbf15aafSRichard Henderson * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 65bbf15aafSRichard Henderson * The code sequence must therefore be able to cope with this, and 66bbf15aafSRichard Henderson * the syscall instruction must be the final one in the sequence. 67bbf15aafSRichard Henderson */ 68bbf15aafSRichard Hendersonsafe_syscall_start: 69bbf15aafSRichard Henderson /* if signal_pending is non-zero, don't do the call */ 70bbf15aafSRichard Henderson lduw [%g2], %g3 71bbf15aafSRichard Henderson brnz,pn %g3, 2f 72bbf15aafSRichard Henderson nop 73bbf15aafSRichard Henderson ta 0x6d 74bbf15aafSRichard Hendersonsafe_syscall_end: 75bbf15aafSRichard Henderson /* code path for having successfully executed the syscall */ 76bbf15aafSRichard Henderson bcs,pn %xcc, 1f 77bbf15aafSRichard Henderson nop 78*620d0b49SRichard Henderson retl 79bbf15aafSRichard Henderson nop 80bbf15aafSRichard Henderson 81bbf15aafSRichard Henderson /* code path when we didn't execute the syscall */ 82bbf15aafSRichard Henderson2: set QEMU_ERESTARTSYS, %o0 83bbf15aafSRichard Henderson 84bbf15aafSRichard Henderson /* code path setting errno */ 85bbf15aafSRichard Henderson1: mov %o7, %g1 86bbf15aafSRichard Henderson call safe_syscall_set_errno_tail 87bbf15aafSRichard Henderson mov %g1, %o7 88bbf15aafSRichard Henderson 89bbf15aafSRichard Henderson .cfi_endproc 90bbf15aafSRichard Henderson .size safe_syscall_base, .-safe_syscall_base 91