Home | History | Annotate | Download | only in m_syswrap
      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