]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/valgrind/src/valgrind-3.6.0-svn/coregrind/m_syswrap/syscall-s390x-linux.S
update
[l4.git] / l4 / pkg / valgrind / src / valgrind-3.6.0-svn / coregrind / m_syswrap / syscall-s390x-linux.S
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-2011
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 /*--------------------------------------------------------------------*/