1 2/*--------------------------------------------------------------------*/ 3/*--- Support for doing system calls. syscall-ppc64-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@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_ppc64_aix5) 35 36#include "pub_core_basics_asm.h" 37#include "libvex_guest_offsets.h" 38 39/* kludge: from include/vki/vki-ppc64-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-ppc64-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] 88ML_(do_syscall_for_client_WRK): 89 .llong .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 stdu 1,-1024(1) 94 std 31,512(1) 95 std 30,520(1) 96 std 29,528(1) 97 std 28,536(1) 98 std 27,544(1) 99 std 26,552(1) 100 mflr 26 101 std 26,560(1) 102 std 2,568(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 109Lvg1: /* 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 cmpdi 0,3,0 131 bne 0,Lvg7 132 133 /* load up syscall args from the threadstate */ 134 ld 3,OFFSET_ppc64_GPR3(30) 135 ld 4,OFFSET_ppc64_GPR4(30) 136 ld 5,OFFSET_ppc64_GPR5(30) 137 ld 6,OFFSET_ppc64_GPR6(30) 138 ld 7,OFFSET_ppc64_GPR7(30) 139 ld 8,OFFSET_ppc64_GPR8(30) 140 ld 9,OFFSET_ppc64_GPR9(30) 141 ld 10,OFFSET_ppc64_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. */ 153Lvg2: 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 159Lvg3: std 3,OFFSET_ppc64_GPR3(30) /* gst->GPR3 = res */ 160 std 4,OFFSET_ppc64_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) */ 165Lvg4: 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 cmpdi 0,3,0 181 bne 0,Lvg7 182 183 /* now safe from signals */ 184 li 3,0 /* SUCCESS */ 185 186 /* pop off stack frame */ 187Lvg5: ld 2,568(1) 188 ld 26,560(1) 189 mtlr 26 190 ld 26,552(1) 191 ld 27,544(1) 192 ld 28,536(1) 193 ld 29,528(1) 194 ld 30,520(1) 195 ld 31,512(1) 196 addi 1,1,1024 197 blr 198 199 /* failure: return 0x8000 | error code */ 200Lvg7: 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) 215ML_(blksys_setup): .llong Lvg1 216ML_(blksys_restart): .llong Lvg2 217ML_(blksys_complete): .llong Lvg3 218ML_(blksys_committed): .llong Lvg4 219ML_(blksys_finished): .llong Lvg5 220 221#endif // defined(VGP_ppc64_aix5) 222 223/*--------------------------------------------------------------------*/ 224/*--- end ---*/ 225/*--------------------------------------------------------------------*/ 226