Home | History | Annotate | Download | only in m_syswrap
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- Support for doing system calls.        syscall-s390x-linux.S ---*/
      4 /*--------------------------------------------------------------------*/
      5 
      6 /*
      7    This file is part of Valgrind, a dynamic binary instrumentation
      8    framework.
      9 
     10    Copyright IBM Corp. 2010-2012
     11 
     12    This program is free software; you can redistribute it and/or
     13    modify it under the terms of the GNU General Public License as
     14    published by the Free Software Foundation; either version 2 of the
     15    License, or (at your option) any later version.
     16 
     17    This program is distributed in the hope that it will be useful, but
     18    WITHOUT ANY WARRANTY; without even the implied warranty of
     19    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     20    General Public License for more details.
     21 
     22    You should have received a copy of the GNU General Public License
     23    along with this program; if not, write to the Free Software
     24    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     25    02111-1307, USA.
     26 
     27    The GNU General Public License is contained in the file COPYING.
     28 */
     29 
     30 /* Contributed by Christian Borntraeger */
     31 
     32 #include "pub_core_basics_asm.h"
     33 #include "pub_core_vkiscnums_asm.h"
     34 #include "libvex_guest_offsets.h"
     35 
     36 #if defined(VGA_s390x)
     37 
     38 /*----------------------------------------------------------------*/
     39 /*
     40         Perform a syscall for the client.  This will run a syscall
     41         with the client's specific per-thread signal mask.
     42 
     43         The structure of this function is such that, if the syscall is
     44         interrupted by a signal, we can determine exactly what
     45         execution state we were in with respect to the execution of
     46         the syscall by examining the value of NIP in the signal
     47         handler.  This means that we can always do the appropriate
     48         thing to precisely emulate the kernel's signal/syscall
     49         interactions.
     50 
     51         The syscall number is taken from the argument, since the syscall
     52         number can be encoded in the svc instruction itself.
     53         The syscall result is written back to guest register r2.
     54 
     55         Returns 0 if the syscall was successfully called (even if the
     56         syscall itself failed), or a nonzero error code in the lowest
     57 	8 bits if one of the sigprocmasks failed (there's no way to
     58 	determine which one failed).  And there's no obvious way to
     59 	recover from that either, but nevertheless we want to know.
     60 
     61         VG_(fixup_guest_state_after_syscall_interrupted) does the
     62 	thread state fixup in the case where we were interrupted by a
     63 	signal.
     64 
     65         Prototype:
     66 
     67 	UWord ML_(do_syscall_for_client_WRK)(
     68 				  Int syscallno,		// r2
     69 				  void* guest_state,		// r3
     70 				  const vki_sigset_t *sysmask,	// r4
     71 				  const vki_sigset_t *postmask,	// r5
     72 				  Int nsigwords)		// r6
     73 */
     74 /* from vki_arch.h */
     75 #define VKI_SIG_SETMASK 2
     76 
     77 #define SP_SAVE 16
     78 #define SP_R2	SP_SAVE + 0*8
     79 #define SP_R3	SP_SAVE + 1*8
     80 #define SP_R4	SP_SAVE + 2*8
     81 #define SP_R5	SP_SAVE + 3*8
     82 #define SP_R6	SP_SAVE + 4*8
     83 #define SP_R7	SP_SAVE + 5*8
     84 #define SP_R8	SP_SAVE + 6*8
     85 #define SP_R9	SP_SAVE + 7*8
     86 
     87 .align 4
     88 .globl ML_(do_syscall_for_client_WRK)
     89 ML_(do_syscall_for_client_WRK):
     90 1:	/* Even though we can't take a signal until the sigprocmask completes,
     91 	start the range early.
     92 	If IA is in the range [1,2), the syscall hasn't been started yet */
     93 
     94 	/* Set the signal mask which should be current during the syscall. */
     95 	/* Save and restore all the parameters and all the registers that
     96 	   we clobber (r6-r9) */
     97 	stmg	%r2,%r9, SP_R2(%r15)
     98 
     99 	lghi	%r2, VKI_SIG_SETMASK		/* how */
    100 	lgr	%r3, %r4			/* sysmask */
    101 	lgr	%r4, %r5			/* postmask */
    102 	lgr	%r5, %r6			/* nsigwords */
    103 	svc	__NR_rt_sigprocmask
    104 	cghi	%r2, 0x0
    105 	jne	7f				/* sigprocmask failed */
    106 
    107 	/* OK, that worked.  Now do the syscall proper. */
    108 	lg	%r9, SP_R3(%r15)		/* guest state --> r9 */
    109 	lg	%r2, OFFSET_s390x_r2(%r9)	/* guest r2 --> real r2 */
    110 	lg	%r3, OFFSET_s390x_r3(%r9)	/* guest r3 --> real r3 */
    111 	lg	%r4, OFFSET_s390x_r4(%r9)	/* guest r4 --> real r4 */
    112 	lg	%r5, OFFSET_s390x_r5(%r9)	/* guest r5 --> real r5 */
    113 	lg	%r6, OFFSET_s390x_r6(%r9)	/* guest r6 --> real r6 */
    114 	lg	%r7, OFFSET_s390x_r7(%r9)	/* guest r7 --> real r7 */
    115 	lg	%r1, SP_R2(%r15)		/* syscallno -> r1 */
    116 
    117 2:	svc	0
    118 
    119 3:
    120 	stg	%r2, OFFSET_s390x_r2(%r9)
    121 
    122 4:	/* Re-block signals.  If IA is in [4,5), then the syscall
    123 	   is complete and we needn't worry about it. */
    124 	lghi	%r2, VKI_SIG_SETMASK		/* how */
    125 	lg	%r3, SP_R5(%r15)		/* postmask */
    126 	lghi	%r4, 0x0			/* NULL */
    127 	lg	%r5, SP_R6(%r15)		/* nsigwords */
    128 	svc	__NR_rt_sigprocmask
    129 	cghi	%r2, 0x0
    130 	jne	7f				/* sigprocmask failed */
    131 
    132 5:	/* Everyting ok. Return 0 and restore the call-saved
    133 	   registers, that we have clobbered */
    134 	lghi	%r2, 0x0
    135 	lmg	%r6,%r9, SP_R6(%r15)
    136 	br	%r14
    137 
    138 7:	/* Some problem. Return 0x8000 | error and restore the call-saved
    139 	   registers we have clobbered. */
    140 	nill	%r2, 0x7fff
    141 	oill	%r2, 0x8000
    142 	lmg	%r6,%r9, SP_R6(%r15)
    143 	br	%r14
    144 
    145 .section .rodata
    146 /* Export the ranges so that
    147    VG_(fixup_guest_state_after_syscall_interrupted) can do the
    148    right thing */
    149 
    150 .globl ML_(blksys_setup)
    151 .globl ML_(blksys_restart)
    152 .globl ML_(blksys_complete)
    153 .globl ML_(blksys_committed)
    154 .globl ML_(blksys_finished)
    155 
    156 /* The compiler can assume that 8 byte data elements are aligned on 8 byte */
    157 .align 8
    158 ML_(blksys_setup):     .quad 1b
    159 ML_(blksys_restart):   .quad 2b
    160 ML_(blksys_complete):  .quad 3b
    161 ML_(blksys_committed): .quad 4b
    162 ML_(blksys_finished):  .quad 5b
    163 .previous
    164 
    165 /* Let the linker know we don't need an executable stack */
    166 .section .note.GNU-stack,"",@progbits
    167 
    168 #endif /* VGA_s390x */
    169 
    170 /*--------------------------------------------------------------------*/
    171 /*--- end                                                          ---*/
    172 /*--------------------------------------------------------------------*/
    173