1 2 /*--------------------------------------------------------------------*/ 3 /*--- Support for doing system calls. syscall-ppc32-aix5.S ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2006-2010 OpenWorks LLP 11 info (at) open-works.co.uk 12 13 Derived from Paul Mackerras' implementation of same for ppc32-linux 14 in syscall-ppc32-linux.S. 15 16 This program is free software; you can redistribute it and/or 17 modify it under the terms of the GNU General Public License as 18 published by the Free Software Foundation; either version 2 of the 19 License, or (at your option) any later version. 20 21 This program is distributed in the hope that it will be useful, but 22 WITHOUT ANY WARRANTY; without even the implied warranty of 23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 24 General Public License for more details. 25 26 You should have received a copy of the GNU General Public License 27 along with this program; if not, write to the Free Software 28 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 29 02111-1307, USA. 30 31 The GNU General Public License is contained in the file COPYING. 32 */ 33 34 #if defined(VGP_ppc32_aix5) 35 36 #include "pub_core_basics_asm.h" 37 #include "libvex_guest_offsets.h" 38 39 /* kludge: from include/vki/vki-ppc32-aix5.h */ 40 #define VKI_SIG_SETMASK 2 41 42 43 /*----------------------------------------------------------------*/ 44 /* 45 Perform a syscall for the client. This will run a syscall 46 with the client's specific per-thread signal mask. 47 48 The structure of this function is such that, if the syscall is 49 interrupted by a signal, we can determine exactly what 50 execution state we were in with respect to the execution of 51 the syscall by examining the value of NIP in the signal 52 handler. This means that we can always do the appropriate 53 thing to precisely emulate the kernel's signal/syscall 54 interactions. 55 56 The syscall number is taken from the argument, even though it 57 should also be in R2 in guest_state. The syscall result is written 58 back to R3 and R4 in the guest state on completion. 59 60 Returns 0 if the syscall was successfully called (even if the 61 syscall itself failed), or a nonzero error code in the lowest 62 8 bits if one of the sigprocmasks failed (there's no way to 63 determine which one failed). And there's no obvious way to 64 recover from that either, but nevertheless we want to know. 65 66 VG_(fixup_guest_state_after_syscall_interrupted) does the 67 thread state fixup in the case where we were interrupted by a 68 signal. 69 70 Prototype: 71 72 UWord ML_(do_syscall_for_client_WRK)( 73 Int syscallno, // r3 74 void* guest_state, // r4 75 const vki_sigset_t *sysmask, // r5 76 const vki_sigset_t *postmask, // r6 77 Int sigsetSzB, // r7 78 Int __nr_sigprocmask) // r8 79 */ 80 .file "syscall-ppc32-aix6.S" 81 82 .toc 83 .csect .text[PR] 84 .align 2 85 .globl ML_(do_syscall_for_client_WRK) 86 .globl .ML_(do_syscall_for_client_WRK) 87 .csect ML_(do_syscall_for_client_WRK)[DS] 88 ML_(do_syscall_for_client_WRK): 89 .long .ML_(do_syscall_for_client_WRK), TOC[tc0], 0 90 .csect .text[PR] 91 .ML_(do_syscall_for_client_WRK): 92 /* make a stack frame */ 93 stwu 1,-512(1) 94 stw 31,256(1) 95 stw 30,260(1) 96 stw 29,264(1) 97 stw 28,268(1) 98 stw 27,272(1) 99 stw 26,276(1) 100 mflr 26 101 stw 26,280(1) 102 stw 2,284(1) 103 mr 31,3 /* syscall number */ 104 mr 30,4 /* guest_state */ 105 mr 29,6 /* postmask */ 106 mr 28,7 /* sigsetSzB */ 107 mr 27,8 /* __nr_sigprocmask */ 108 109 Lvg1: /* Even though we can't take a signal until the sigprocmask 110 completes, start the range early. If PC is in the range [1,2), 111 the syscall hasn't been started yet */ 112 113 /* set the signal mask for doing the system call */ 114 /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */ 115 mr 2,8 116 li 3,VKI_SIG_SETMASK 117 mr 4,5 118 mr 5,6 119 mr 6,7 /* sigsetSzB -- needed on AIX ? */ 120 121 /* actually do the sigprocmask */ 122 crorc 6,6,6 123 .long 0x48000005 /* bl here+4 */ 124 mflr 26 125 addi 26,26,16 126 mtlr 26 127 sc 128 129 /* did it fail? (assuming r3 == 0 for success) */ 130 cmpwi 0,3,0 131 bne 0,Lvg7 132 133 /* load up syscall args from the threadstate */ 134 lwz 3,OFFSET_ppc32_GPR3(30) 135 lwz 4,OFFSET_ppc32_GPR4(30) 136 lwz 5,OFFSET_ppc32_GPR5(30) 137 lwz 6,OFFSET_ppc32_GPR6(30) 138 lwz 7,OFFSET_ppc32_GPR7(30) 139 lwz 8,OFFSET_ppc32_GPR8(30) 140 lwz 9,OFFSET_ppc32_GPR9(30) 141 lwz 10,OFFSET_ppc32_GPR10(30) 142 mr 2,31 /* syscall number */ 143 144 crorc 6,6,6 145 .long 0x48000005 /* bl here+4 */ 146 mflr 26 147 addi 26,26,16 148 mtlr 26 149 150 /* If PC is in the range [2,2], then the syscall was either 151 just about to start, or was interrupted and the kernel was 152 restarting it. */ 153 Lvg2: sc /* do the syscall */ 154 155 /* In the range [3, 4), the syscall result is in r3/r4, but 156 hasn't been committed to R3/R4. */ 157 /* put the result back in the threadstate */ 158 159 Lvg3: stw 3,OFFSET_ppc32_GPR3(30) /* gst->GPR3 = res */ 160 stw 4,OFFSET_ppc32_GPR4(30) /* gst->GPR4 = err */ 161 162 /* Block signals again. If PC is in [4,5), then the syscall 163 is complete and we needn't worry about it. */ 164 /* set up for sigprocmask(SIG_SETMASK, postmask, NULL) */ 165 Lvg4: mr 2,27 166 li 3,VKI_SIG_SETMASK 167 mr 4,29 168 li 5,0 169 mr 6,28 /* sigsetSzB -- needed on AIX ? */ 170 171 /* actually do the sigprocmask */ 172 crorc 6,6,6 173 .long 0x48000005 /* bl here+4 */ 174 mflr 26 175 addi 26,26,16 176 mtlr 26 177 sc 178 179 /* did it fail? (assuming r3 == 0 for success) */ 180 cmpwi 0,3,0 181 bne 0,Lvg7 182 183 /* now safe from signals */ 184 li 3,0 /* SUCCESS */ 185 186 /* pop off stack frame */ 187 Lvg5: lwz 2,284(1) 188 lwz 26,280(1) 189 mtlr 26 190 lwz 26,276(1) 191 lwz 27,272(1) 192 lwz 28,268(1) 193 lwz 29,264(1) 194 lwz 30,260(1) 195 lwz 31,256(1) 196 addi 1,1,512 197 blr 198 199 /* failure: return 0x8000 | error code */ 200 Lvg7: mr 3,4 201 ori 3,3,0x8000 /* FAILURE -- ensure return value is nonzero */ 202 b Lvg5 203 204 /* export the ranges so that 205 VG_(fixup_guest_state_after_syscall_interrupted) can do the 206 right thing */ 207 208 .csect .data[RW],3 209 .align 2 210 .globl ML_(blksys_setup) 211 .globl ML_(blksys_restart) 212 .globl ML_(blksys_complete) 213 .globl ML_(blksys_committed) 214 .globl ML_(blksys_finished) 215 ML_(blksys_setup): .long Lvg1 216 ML_(blksys_restart): .long Lvg2 217 ML_(blksys_complete): .long Lvg3 218 ML_(blksys_committed): .long Lvg4 219 ML_(blksys_finished): .long Lvg5 220 221 #endif // defined(VGP_ppc32_aix5) 222 223 /*--------------------------------------------------------------------*/ 224 /*--- end ---*/ 225 /*--------------------------------------------------------------------*/ 226