14542adefSRichard Henderson/* 24542adefSRichard Henderson * safe-syscall.inc.S : host-specific assembly fragment 34542adefSRichard 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 54542adefSRichard Henderson * 64542adefSRichard Henderson * Written by Richard Henderson <richard.henderson@linaro.org> 74542adefSRichard Henderson * Copyright (C) 2021 Linaro, Inc. 84542adefSRichard Henderson * 94542adefSRichard Henderson * This work is licensed under the terms of the GNU GPL, version 2 or later. 104542adefSRichard Henderson * See the COPYING file in the top-level directory. 114542adefSRichard Henderson */ 124542adefSRichard Henderson 134542adefSRichard Henderson#include "sys/regdef.h" 144542adefSRichard Henderson#include "sys/asm.h" 154542adefSRichard Henderson 164542adefSRichard Henderson .text 174542adefSRichard Henderson .set nomips16 184542adefSRichard Henderson .set reorder 194542adefSRichard Henderson 204542adefSRichard Henderson .global safe_syscall_start 214542adefSRichard Henderson .global safe_syscall_end 224542adefSRichard Henderson .type safe_syscall_start, @function 234542adefSRichard Henderson .type safe_syscall_end, @function 244542adefSRichard Henderson 254542adefSRichard Henderson /* 264542adefSRichard Henderson * This is the entry point for making a system call. The calling 274542adefSRichard Henderson * convention here is that of a C varargs function with the 284542adefSRichard Henderson * first argument an 'int *' to the signal_pending flag, the 294542adefSRichard Henderson * second one the system call number (as a 'long'), and all further 304542adefSRichard Henderson * arguments being syscall arguments (also 'long'). 314542adefSRichard Henderson */ 324542adefSRichard Henderson 334542adefSRichard Henderson#if _MIPS_SIM == _ABIO32 344542adefSRichard Henderson/* 8 * 4 = 32 for outgoing parameters; 1 * 4 for s0 save; 1 * 4 for align. */ 354542adefSRichard Henderson#define FRAME 40 364542adefSRichard Henderson#define OFS_S0 32 374542adefSRichard Henderson#else 384542adefSRichard Henderson/* 1 * 8 for s0 save; 1 * 8 for align. */ 394542adefSRichard Henderson#define FRAME 16 404542adefSRichard Henderson#define OFS_S0 0 414542adefSRichard Henderson#endif 424542adefSRichard Henderson 434542adefSRichard Henderson 444542adefSRichard HendersonNESTED(safe_syscall_base, FRAME, ra) 454542adefSRichard Henderson .cfi_startproc 464542adefSRichard Henderson PTR_ADDIU sp, sp, -FRAME 474542adefSRichard Henderson .cfi_adjust_cfa_offset FRAME 484542adefSRichard Henderson REG_S s0, OFS_S0(sp) 494542adefSRichard Henderson .cfi_rel_offset s0, OFS_S0 504542adefSRichard Henderson#if _MIPS_SIM == _ABIO32 514542adefSRichard Henderson /* 524542adefSRichard Henderson * The syscall calling convention is nearly the same as C: 534542adefSRichard Henderson * we enter with a0 == &signal_pending 544542adefSRichard Henderson * a1 == syscall number 554542adefSRichard Henderson * a2, a3, stack == syscall arguments 564542adefSRichard Henderson * and return the result in a0 574542adefSRichard Henderson * and the syscall instruction needs 584542adefSRichard Henderson * v0 == syscall number 594542adefSRichard Henderson * a0 ... a3, stack == syscall arguments 604542adefSRichard Henderson * and returns the result in v0 614542adefSRichard Henderson * Shuffle everything around appropriately. 624542adefSRichard Henderson */ 634542adefSRichard Henderson move s0, a0 /* signal_pending pointer */ 644542adefSRichard Henderson move v0, a1 /* syscall number */ 654542adefSRichard Henderson move a0, a2 /* syscall arguments */ 664542adefSRichard Henderson move a1, a3 674542adefSRichard Henderson lw a2, FRAME+16(sp) 684542adefSRichard Henderson lw a3, FRAME+20(sp) 694542adefSRichard Henderson lw t4, FRAME+24(sp) 704542adefSRichard Henderson lw t5, FRAME+28(sp) 714542adefSRichard Henderson lw t6, FRAME+32(sp) 724542adefSRichard Henderson lw t7, FRAME+40(sp) 734542adefSRichard Henderson sw t4, 16(sp) 744542adefSRichard Henderson sw t5, 20(sp) 754542adefSRichard Henderson sw t6, 24(sp) 764542adefSRichard Henderson sw t7, 28(sp) 774542adefSRichard Henderson#else 784542adefSRichard Henderson /* 794542adefSRichard Henderson * The syscall calling convention is nearly the same as C: 804542adefSRichard Henderson * we enter with a0 == &signal_pending 814542adefSRichard Henderson * a1 == syscall number 824542adefSRichard Henderson * a2 ... a7 == syscall arguments 834542adefSRichard Henderson * and return the result in a0 844542adefSRichard Henderson * and the syscall instruction needs 854542adefSRichard Henderson * v0 == syscall number 864542adefSRichard Henderson * a0 ... a5 == syscall arguments 874542adefSRichard Henderson * and returns the result in v0 884542adefSRichard Henderson * Shuffle everything around appropriately. 894542adefSRichard Henderson */ 904542adefSRichard Henderson move s0, a0 /* signal_pending pointer */ 914542adefSRichard Henderson move v0, a1 /* syscall number */ 924542adefSRichard Henderson move a0, a2 /* syscall arguments */ 934542adefSRichard Henderson move a1, a3 944542adefSRichard Henderson move a2, a4 954542adefSRichard Henderson move a3, a5 964542adefSRichard Henderson move a4, a6 974542adefSRichard Henderson move a5, a7 984542adefSRichard Henderson#endif 994542adefSRichard Henderson 1004542adefSRichard Henderson /* 1014542adefSRichard Henderson * This next sequence of code works in conjunction with the 1024542adefSRichard Henderson * rewind_if_safe_syscall_function(). If a signal is taken 1034542adefSRichard Henderson * and the interrupted PC is anywhere between 'safe_syscall_start' 1044542adefSRichard Henderson * and 'safe_syscall_end' then we rewind it to 'safe_syscall_start'. 1054542adefSRichard Henderson * The code sequence must therefore be able to cope with this, and 1064542adefSRichard Henderson * the syscall instruction must be the final one in the sequence. 1074542adefSRichard Henderson */ 1084542adefSRichard Hendersonsafe_syscall_start: 1094542adefSRichard Henderson /* If signal_pending is non-zero, don't do the call */ 1104542adefSRichard Henderson lw t1, 0(s0) 1114542adefSRichard Henderson bnez t1, 2f 1124542adefSRichard Henderson syscall 1134542adefSRichard Hendersonsafe_syscall_end: 1144542adefSRichard Henderson 1154542adefSRichard Henderson /* code path for having successfully executed the syscall */ 1164542adefSRichard Henderson REG_L s0, OFS_S0(sp) 1174542adefSRichard Henderson PTR_ADDIU sp, sp, FRAME 1184542adefSRichard Henderson .cfi_remember_state 1194542adefSRichard Henderson .cfi_adjust_cfa_offset -FRAME 1204542adefSRichard Henderson .cfi_restore s0 1214542adefSRichard Henderson bnez a3, 1f 1224542adefSRichard Henderson jr ra 1234542adefSRichard Henderson .cfi_restore_state 1244542adefSRichard Henderson 1254542adefSRichard Henderson /* code path when we didn't execute the syscall */ 1264542adefSRichard Henderson2: REG_L s0, OFS_S0(sp) 1274542adefSRichard Henderson PTR_ADDIU sp, sp, FRAME 1284542adefSRichard Henderson .cfi_adjust_cfa_offset -FRAME 1294542adefSRichard Henderson .cfi_restore s0 130af254a27SRichard Henderson li v0, QEMU_ERESTARTSYS 1314542adefSRichard Henderson 1324542adefSRichard Henderson /* code path setting errno */ 1334542adefSRichard Henderson /* 1344542adefSRichard Henderson * We didn't setup GP on entry, optimistic of the syscall success. 1354542adefSRichard Henderson * We must do so now to load the address of the helper, as required 1364542adefSRichard Henderson * by the ABI, into t9. 1374542adefSRichard Henderson * 1384542adefSRichard Henderson * Note that SETUP_GPX and SETUP_GPX64 are themselves conditional, 1394542adefSRichard Henderson * so we can simply let the one that's not empty succeed. 1404542adefSRichard Henderson */ 1414542adefSRichard Henderson1: USE_ALT_CP(t0) 1424542adefSRichard Henderson SETUP_GPX(t1) 1434542adefSRichard Henderson SETUP_GPX64(t0, t1) 144*d7478d42SRichard Henderson move a0, v0 1454542adefSRichard Henderson PTR_LA t9, safe_syscall_set_errno_tail 1464542adefSRichard Henderson jr t9 1474542adefSRichard Henderson 1484542adefSRichard Henderson .cfi_endproc 1494542adefSRichard HendersonEND(safe_syscall_base) 150