sewardj | 112711a | 2015-04-10 12:30:09 +0000 | [diff] [blame] | 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 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 31 | #include "pub_core_basics_asm.h" |
| 32 | |
sewardj | 112711a | 2015-04-10 12:30:09 +0000 | [diff] [blame] | 33 | #if defined(VGP_tilegx_linux) |
| 34 | |
sewardj | 112711a | 2015-04-10 12:30:09 +0000 | [diff] [blame] | 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) |
| 79 | ML_(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 |
| 94 | 1: |
| 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 | |
| 121 | 2: swint1 // syscall |
| 122 | 3: |
| 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 |
| 133 | 4: |
| 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 |
| 150 | 5: addli r29, sp, 16 |
| 151 | { |
| 152 | ld lr, r29 // restore lr |
| 153 | addli sp, sp, 64 |
| 154 | } |
| 155 | jr lr |
| 156 | |
| 157 | 7: 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 |
sewardj | 112711a | 2015-04-10 12:30:09 +0000 | [diff] [blame] | 184 | |
| 185 | #endif /* defined(VGP_tilegx_linux) */ |
| 186 | |
florian | 3f1d613 | 2015-09-30 20:30:48 +0000 | [diff] [blame] | 187 | /* Let the linker know we don't need an executable stack */ |
| 188 | MARK_STACK_NO_EXEC |
| 189 | |
sewardj | 112711a | 2015-04-10 12:30:09 +0000 | [diff] [blame] | 190 | /*--------------------------------------------------------------------*/ |
| 191 | /*--- end ---*/ |
| 192 | /*--------------------------------------------------------------------*/ |
| 193 | |