diff options
Diffstat (limited to 'coregrind/m_syswrap/.svn/text-base/syscall-ppc64-aix5.S.svn-base')
-rw-r--r-- | coregrind/m_syswrap/.svn/text-base/syscall-ppc64-aix5.S.svn-base | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/coregrind/m_syswrap/.svn/text-base/syscall-ppc64-aix5.S.svn-base b/coregrind/m_syswrap/.svn/text-base/syscall-ppc64-aix5.S.svn-base new file mode 100644 index 0000000..bbf3909 --- /dev/null +++ b/coregrind/m_syswrap/.svn/text-base/syscall-ppc64-aix5.S.svn-base @@ -0,0 +1,222 @@ + +/*--------------------------------------------------------------------*/ +/*--- Support for doing system calls. syscall-ppc64-aix5.S ---*/ +/*--------------------------------------------------------------------*/ + +/* + This file is part of Valgrind, a dynamic binary instrumentation + framework. + + Copyright (C) 2006-2009 OpenWorks LLP + info@open-works.co.uk + + Derived from Paul Mackerras' implementation of same for ppc32-linux + in syscall-ppc32-linux.S. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307, USA. + + The GNU General Public License is contained in the file COPYING. +*/ + +#include "pub_core_basics_asm.h" +#include "libvex_guest_offsets.h" + +/* kludge: from include/vki/vki-ppc64-aix5.h */ +#define VKI_SIG_SETMASK 2 + + +/*----------------------------------------------------------------*/ +/* + Perform a syscall for the client. This will run a syscall + with the client's specific per-thread signal mask. + + The structure of this function is such that, if the syscall is + interrupted by a signal, we can determine exactly what + execution state we were in with respect to the execution of + the syscall by examining the value of NIP in the signal + handler. This means that we can always do the appropriate + thing to precisely emulate the kernel's signal/syscall + interactions. + + The syscall number is taken from the argument, even though it + should also be in R2 in guest_state. The syscall result is written + back to R3 and R4 in the guest state on completion. + + Returns 0 if the syscall was successfully called (even if the + syscall itself failed), or a nonzero error code in the lowest + 8 bits if one of the sigprocmasks failed (there's no way to + determine which one failed). And there's no obvious way to + recover from that either, but nevertheless we want to know. + + VG_(fixup_guest_state_after_syscall_interrupted) does the + thread state fixup in the case where we were interrupted by a + signal. + + Prototype: + + UWord ML_(do_syscall_for_client_WRK)( + Int syscallno, // r3 + void* guest_state, // r4 + const vki_sigset_t *sysmask, // r5 + const vki_sigset_t *postmask, // r6 + Int nsigwords, // r7 + Int __nr_sigprocmask) // r8 +*/ + .file "syscall-ppc64-aix6.S" + + .toc + .csect .text[PR] + .align 2 + .globl ML_(do_syscall_for_client_WRK) + .globl .ML_(do_syscall_for_client_WRK) + .csect ML_(do_syscall_for_client_WRK)[DS] +ML_(do_syscall_for_client_WRK): + .llong .ML_(do_syscall_for_client_WRK), TOC[tc0], 0 + .csect .text[PR] +.ML_(do_syscall_for_client_WRK): + /* make a stack frame */ + stdu 1,-1024(1) + std 31,512(1) + std 30,520(1) + std 29,528(1) + std 28,536(1) + std 27,544(1) + std 26,552(1) + mflr 26 + std 26,560(1) + std 2,568(1) + mr 31,3 /* syscall number */ + mr 30,4 /* guest_state */ + mr 29,6 /* postmask */ + mr 28,7 /* nsigwords */ + mr 27,8 /* __nr_sigprocmask */ + +Lvg1: /* Even though we can't take a signal until the sigprocmask + completes, start the range early. If PC is in the range [1,2), + the syscall hasn't been started yet */ + + /* set the signal mask for doing the system call */ + /* set up for sigprocmask(SIG_SETMASK, sysmask, postmask) */ + mr 2,8 + li 3,VKI_SIG_SETMASK + mr 4,5 + mr 5,6 + mr 6,7 /* nsigwords -- needed on AIX ? */ + + /* actually do the sigprocmask */ + crorc 6,6,6 + .long 0x48000005 /* bl here+4 */ + mflr 26 + addi 26,26,16 + mtlr 26 + sc + + /* did it fail? (assuming r3 == 0 for success) */ + cmpdi 0,3,0 + bne 0,Lvg7 + + /* load up syscall args from the threadstate */ + ld 3,OFFSET_ppc64_GPR3(30) + ld 4,OFFSET_ppc64_GPR4(30) + ld 5,OFFSET_ppc64_GPR5(30) + ld 6,OFFSET_ppc64_GPR6(30) + ld 7,OFFSET_ppc64_GPR7(30) + ld 8,OFFSET_ppc64_GPR8(30) + ld 9,OFFSET_ppc64_GPR9(30) + ld 10,OFFSET_ppc64_GPR10(30) + mr 2,31 /* syscall number */ + + crorc 6,6,6 + .long 0x48000005 /* bl here+4 */ + mflr 26 + addi 26,26,16 + mtlr 26 + + /* If PC is in the range [2,2], then the syscall was either + just about to start, or was interrupted and the kernel was + restarting it. */ +Lvg2: sc /* do the syscall */ + + /* In the range [3, 4), the syscall result is in r3/r4, but + hasn't been committed to R3/R4. */ + /* put the result back in the threadstate */ + +Lvg3: std 3,OFFSET_ppc64_GPR3(30) /* gst->GPR3 = res */ + std 4,OFFSET_ppc64_GPR4(30) /* gst->GPR4 = err */ + + /* Block signals again. If PC is in [4,5), then the syscall + is complete and we needn't worry about it. */ + /* set up for sigprocmask(SIG_SETMASK, postmask, NULL) */ +Lvg4: mr 2,27 + li 3,VKI_SIG_SETMASK + mr 4,29 + li 5,0 + mr 6,28 /* nsigwords -- needed on AIX ? */ + + /* actually do the sigprocmask */ + crorc 6,6,6 + .long 0x48000005 /* bl here+4 */ + mflr 26 + addi 26,26,16 + mtlr 26 + sc + + /* did it fail? (assuming r3 == 0 for success) */ + cmpdi 0,3,0 + bne 0,Lvg7 + + /* now safe from signals */ + li 3,0 /* SUCCESS */ + + /* pop off stack frame */ +Lvg5: ld 2,568(1) + ld 26,560(1) + mtlr 26 + ld 26,552(1) + ld 27,544(1) + ld 28,536(1) + ld 29,528(1) + ld 30,520(1) + ld 31,512(1) + addi 1,1,1024 + blr + + /* failure: return 0x8000 | error code */ +Lvg7: mr 3,4 + ori 3,3,0x8000 /* FAILURE -- ensure return value is nonzero */ + b Lvg5 + +/* export the ranges so that + VG_(fixup_guest_state_after_syscall_interrupted) can do the + right thing */ + + .csect .data[RW],3 + .align 2 +.globl ML_(blksys_setup) +.globl ML_(blksys_restart) +.globl ML_(blksys_complete) +.globl ML_(blksys_committed) +.globl ML_(blksys_finished) +ML_(blksys_setup): .llong Lvg1 +ML_(blksys_restart): .llong Lvg2 +ML_(blksys_complete): .llong Lvg3 +ML_(blksys_committed): .llong Lvg4 +ML_(blksys_finished): .llong Lvg5 + + +/*--------------------------------------------------------------------*/ +/*--- end ---*/ +/*--------------------------------------------------------------------*/ |