195c021daSRichard Henderson/* 295c021daSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment 395c021daSRichard 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 595c021daSRichard Henderson * 695c021daSRichard Henderson * Written by Richard Henderson <richard.henderson@linaro.org> 795c021daSRichard Henderson * Copyright (C) 2021 Linaro, Inc. 895c021daSRichard Henderson * 995c021daSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later. 1095c021daSRichard Henderson * See the COPYING file in the top-level directory. 1195c021daSRichard Henderson */ 1295c021daSRichard Henderson 1395c021daSRichard Henderson .text 1495c021daSRichard Henderson .balign 4 1595c021daSRichard Henderson 1695c021daSRichard Henderson .register %g2, #scratch 1795c021daSRichard Henderson .register %g3, #scratch 1895c021daSRichard Henderson 1995c021daSRichard Henderson .global safe_syscall_base 2095c021daSRichard Henderson .global safe_syscall_start 2195c021daSRichard Henderson .global safe_syscall_end 2295c021daSRichard Henderson .type safe_syscall_base, @function 2395c021daSRichard Henderson .type safe_syscall_start, @function 2495c021daSRichard Henderson .type safe_syscall_end, @function 2595c021daSRichard Henderson 2695c021daSRichard 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 2995c021daSRichard Henderson 3095c021daSRichard Henderson /* 3195c021daSRichard Henderson * This is the entry point for making a system call. The calling 3295c021daSRichard Henderson * convention here is that of a C varargs function with the 3395c021daSRichard Henderson * first argument an 'int *' to the signal_pending flag, the 3495c021daSRichard Henderson * second one the system call number (as a 'long'), and all further 3595c021daSRichard Henderson * arguments being syscall arguments (also 'long'). 3695c021daSRichard Henderson */ 3795c021daSRichard Hendersonsafe_syscall_base: 3895c021daSRichard Henderson .cfi_startproc 3995c021daSRichard Henderson /* 4095c021daSRichard Henderson * The syscall calling convention isn't the same as the C one: 4195c021daSRichard Henderson * we enter with o0 == &signal_pending 4295c021daSRichard Henderson * o1 == syscall number 4395c021daSRichard Henderson * o2 ... o5, (stack) == syscall arguments 4495c021daSRichard Henderson * and return the result in x0 4595c021daSRichard Henderson * and the syscall instruction needs 4695c021daSRichard Henderson * g1 == syscall number 4795c021daSRichard Henderson * o0 ... o5 == syscall arguments 4895c021daSRichard Henderson * and returns the result in o0 4995c021daSRichard Henderson * Shuffle everything around appropriately. 5095c021daSRichard Henderson */ 5195c021daSRichard Henderson mov %o0, %g2 /* signal_pending pointer */ 5295c021daSRichard Henderson mov %o1, %g1 /* syscall number */ 5395c021daSRichard Henderson mov %o2, %o0 /* syscall arguments */ 5495c021daSRichard Henderson mov %o3, %o1 5595c021daSRichard Henderson mov %o4, %o2 5695c021daSRichard Henderson mov %o5, %o3 5795c021daSRichard Henderson ldx [%sp + PARAM(6)], %o4 5895c021daSRichard Henderson ldx [%sp + PARAM(7)], %o5 5995c021daSRichard Henderson 6095c021daSRichard Henderson /* 6195c021daSRichard Henderson * This next sequence of code works in conjunction with the 6295c021daSRichard Henderson * rewind_if_safe_syscall_function(). If a signal is taken 6395c021daSRichard Henderson * and the interrupted PC is anywhere between 'safe_syscall_start' 6495c021daSRichard Henderson * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 6595c021daSRichard Henderson * The code sequence must therefore be able to cope with this, and 6695c021daSRichard Henderson * the syscall instruction must be the final one in the sequence. 6795c021daSRichard Henderson */ 6895c021daSRichard Hendersonsafe_syscall_start: 6995c021daSRichard Henderson /* if signal_pending is non-zero, don't do the call */ 7095c021daSRichard Henderson lduw [%g2], %g3 7195c021daSRichard Henderson brnz,pn %g3, 2f 7295c021daSRichard Henderson nop 7395c021daSRichard Henderson ta 0x6d 7495c021daSRichard Hendersonsafe_syscall_end: 7595c021daSRichard Henderson /* code path for having successfully executed the syscall */ 7695c021daSRichard Henderson bcs,pn %xcc, 1f 7795c021daSRichard Henderson nop 78*620d0b49SRichard Henderson retl 7995c021daSRichard Henderson nop 8095c021daSRichard Henderson 8195c021daSRichard Henderson /* code path when we didn't execute the syscall */ 82af254a27SRichard Henderson2: set QEMU_ERESTARTSYS, %o0 8395c021daSRichard Henderson 8495c021daSRichard Henderson /* code path setting errno */ 8595c021daSRichard Henderson1: mov %o7, %g1 8695c021daSRichard Henderson call safe_syscall_set_errno_tail 8795c021daSRichard Henderson mov %g1, %o7 8895c021daSRichard Henderson 8995c021daSRichard Henderson .cfi_endproc 9095c021daSRichard Henderson .size safe_syscall_base, .-safe_syscall_base 91