• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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