1/*--------------------------------------------------------------------*/ 2/*--- Support for doing system calls. syscall-tilegx-linux.S ---*/ 3/*--------------------------------------------------------------------*/ 4 5/* 6 This file is part of Valgrind, a dynamic binary instrumentation 7 framework. 8 9 Copyright (C) 2010-2012 Tilera Corp. 10 11 This program is free software; you can redistribute it and/or 12 modify it under the terms of the GNU General Public License as 13 published by the Free Software Foundation; either version 2 of the 14 License, or (at your option) any later version. 15 16 This program is distributed in the hope that it will be useful, but 17 WITHOUT ANY WARRANTY; without even the implied warranty of 18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 19 General Public License for more details. 20 21 You should have received a copy of the GNU General Public License 22 along with this program; if not, write to the Free Software 23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 24 02111-1307, USA. 25 26 The GNU General Public License is contained in the file COPYING. 27*/ 28 29/* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */ 30 31#include "pub_core_basics_asm.h" 32 33#if defined(VGP_tilegx_linux) 34 35#include "pub_core_vkiscnums_asm.h" 36#include "libvex_guest_offsets.h" 37 38 39/*----------------------------------------------------------------*/ 40/* 41 Perform a syscall for the client. This will run a syscall 42 with the client's specific per-thread signal mask. 43 44 The structure of this function is such that, if the syscall is 45 interrupted by a signal, we can determine exactly what 46 execution state we were in with respect to the execution of 47 the syscall by examining the value of IP in the signal 48 handler. This means that we can always do the appropriate 49 thing to precisely emulate the kernel's signal/syscall 50 interactions. 51 52 The syscall number is taken from the argument, even though it 53 should also be in regs->v0. The syscall result is written 54 back to regs->v0 on completion. 55 56 Returns 0 if the syscall was successfully called (even if the 57 syscall itself failed), or a nonzero error code in the lowest 58 8 bits if one of the sigprocmasks failed (there's no way to 59 determine which one failed). And there's no obvious way to 60 recover from that either, but nevertheless we want to know. 61 62 VG_(fixup_guest_state_after_syscall_interrupted) does the 63 thread state fixup in the case where we were interrupted by a 64 signal. 65 66 Prototype: 67 68 UWord ML_(do_syscall_for_client_WRK)( 69 Int syscallno, // r0 70 void* guest_state, // r1 71 const vki_sigset_t *sysmask, // r2 72 const vki_sigset_t *postmask, // r3 73 Int nsigwords) // r4 74*/ 75/* from vki_arch.h */ 76#define VKI_SIG_SETMASK 2 77 78.globl ML_(do_syscall_for_client_WRK) 79ML_(do_syscall_for_client_WRK): 80 81 addli sp, sp, -64 // alloc 64B new stack space 82 addli r29, sp, 56 // r29 points to offset 56 above sp 83 st_add r29, r0, -8 // save r0 84 // offset 48 85 st_add r29, r1, -8 // save r1 86 // offset 40 87 st_add r29, r2, -8 // save r2 88 // offset 32 89 st_add r29, r3, -8 // save r3 90 // offset 24 91 st_add r29, r4, -8 // save r4 92 // offset 16 93 st r29, lr // save lr 941: 95 { 96 moveli r10, __NR_rt_sigprocmask 97 moveli r0, VKI_SIG_SETMASK 98 } 99 { 100 move r1, r2 101 move r2, r3 102 } 103 move r3, r4 104 swint1 105 106 // error, go 7f 107 bnez r1, 7f 108 109 /* Get registers from guest_state. */ 110 addli r29, sp, 56 // get syscallno 111 ld r10, r29 112 addli r29, sp, 48 113 ld r29, r29 // r29 points to guest_state 114 ld_add r0, r29, 8 // read r0 115 ld_add r1, r29, 8 // read r1 116 ld_add r2, r29, 8 // read r2 117 ld_add r3, r29, 8 // read r3 118 ld_add r4, r29, 8 // read r4 119 ld_add r5, r29, 8 // read r5 120 1212: swint1 // syscall 1223: 123 // Write register into guest_state 124 addli r29, sp, 48 125 ld r29, r29 126 st_add r29, r0, 8 127 st_add r29, r1, 8 128 st_add r29, r2, 8 129 st_add r29, r3, 8 130 st_add r29, r4, 8 131 st_add r29, r5, 8 132 nop 1334: 134 { 135 moveli r10, __NR_rt_sigprocmask 136 moveli r0, VKI_SIG_SETMASK 137 } 138 addli r29, sp, 32 139 { 140 ld r1, r29 141 movei r2, 0 142 } 143 addli r29, sp, 24 144 ld r3, r29 145 146 swint1 147 // error, go 7f 148 bnez r1, 7f 149 nop 1505: addli r29, sp, 16 151 { 152 ld lr, r29 // restore lr 153 addli sp, sp, 64 154 } 155 jr lr 156 1577: addi r29, sp, 16 158 { 159 ld lr, r29 // restore lr 160 addi sp, sp, 64 161 } 162 { 163 // r0 = 0x8000 164 shl16insli r0, zero, -0x8000 165 jr lr 166 } 167 168 .section .rodata 169 /* export the ranges so that 170 VG_(fixup_guest_state_after_syscall_interrupted) can do the 171 right thing */ 172 173 .globl ML_(blksys_setup) 174 .globl ML_(blksys_restart) 175 .globl ML_(blksys_complete) 176 .globl ML_(blksys_committed) 177 .globl ML_(blksys_finished) 178 ML_(blksys_setup): .quad 1b 179 ML_(blksys_restart): .quad 2b 180 ML_(blksys_complete): .quad 3b 181 ML_(blksys_committed): .quad 4b 182 ML_(blksys_finished): .quad 5b 183 .previous 184 185#endif /* defined(VGP_tilegx_linux) */ 186 187/* Let the linker know we don't need an executable stack */ 188MARK_STACK_NO_EXEC 189 190/*--------------------------------------------------------------------*/ 191/*--- end ---*/ 192/*--------------------------------------------------------------------*/ 193 194