1112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--------------------------------------------------------------------*/
2112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--- Support for doing system calls.      syscall-tilegx-linux.S  ---*/
3112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--------------------------------------------------------------------*/
4112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
5112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*
6112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   This file is part of Valgrind, a dynamic binary instrumentation
7112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   framework.
8112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
9112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   Copyright (C) 2010-2012 Tilera Corp.
10112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
11112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   This program is free software; you can redistribute it and/or
12112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   modify it under the terms of the GNU General Public License as
13112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   published by the Free Software Foundation; either version 2 of the
14112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   License, or (at your option) any later version.
15112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
16112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   This program is distributed in the hope that it will be useful, but
17112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   WITHOUT ANY WARRANTY; without even the implied warranty of
18112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   General Public License for more details.
20112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
21112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   You should have received a copy of the GNU General Public License
22112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   along with this program; if not, write to the Free Software
23112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   02111-1307, USA.
25112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
26112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   The GNU General Public License is contained in the file COPYING.
27112711afefcfcd43680c7c4aa8d38ef180e8811esewardj*/
28112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
29112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/* Contributed by Zhi-Gang Liu <zliu at tilera dot com> */
30112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
31112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#if defined(VGP_tilegx_linux)
32112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
33112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#include "pub_core_basics_asm.h"
34112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#include "pub_core_vkiscnums_asm.h"
35112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#include "libvex_guest_offsets.h"
36112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
37112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
38112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*----------------------------------------------------------------*/
39112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*
40112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   Perform a syscall for the client.  This will run a syscall
41112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   with the client's specific per-thread signal mask.
42112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
43112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   The structure of this function is such that, if the syscall is
44112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   interrupted by a signal, we can determine exactly what
45112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   execution state we were in with respect to the execution of
46112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   the syscall by examining the value of IP in the signal
47112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   handler.  This means that we can always do the appropriate
48112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   thing to precisely emulate the kernel's signal/syscall
49112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   interactions.
50112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
51112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   The syscall number is taken from the argument, even though it
52112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   should also be in regs->v0.  The syscall result is written
53112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   back to regs->v0 on completion.
54112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
55112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   Returns 0 if the syscall was successfully called (even if the
56112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   syscall itself failed), or a nonzero error code in the lowest
57112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   8 bits if one of the sigprocmasks failed (there's no way to
58112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   determine which one failed).  And there's no obvious way to
59112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   recover from that either, but nevertheless we want to know.
60112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
61112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   VG_(fixup_guest_state_after_syscall_interrupted) does the
62112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   thread state fixup in the case where we were interrupted by a
63112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   signal.
64112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
65112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   Prototype:
66112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
67112711afefcfcd43680c7c4aa8d38ef180e8811esewardj   UWord ML_(do_syscall_for_client_WRK)(
68112711afefcfcd43680c7c4aa8d38ef180e8811esewardj        Int syscallno,                 // r0
69112711afefcfcd43680c7c4aa8d38ef180e8811esewardj        void* guest_state,             // r1
70112711afefcfcd43680c7c4aa8d38ef180e8811esewardj        const vki_sigset_t *sysmask,   // r2
71112711afefcfcd43680c7c4aa8d38ef180e8811esewardj        const vki_sigset_t *postmask,  // r3
72112711afefcfcd43680c7c4aa8d38ef180e8811esewardj        Int nsigwords)                 // r4
73112711afefcfcd43680c7c4aa8d38ef180e8811esewardj*/
74112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/* from vki_arch.h */
75112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#define VKI_SIG_SETMASK 2
76112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
77112711afefcfcd43680c7c4aa8d38ef180e8811esewardj.globl ML_(do_syscall_for_client_WRK)
78112711afefcfcd43680c7c4aa8d38ef180e8811esewardjML_(do_syscall_for_client_WRK):
79112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
80112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  sp,  sp, -64   // alloc 64B new stack space
81112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 56    // r29 points to offset 56 above sp
82112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r0, -8    // save r0
83112711afefcfcd43680c7c4aa8d38ef180e8811esewardj                          // offset 48
84112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r1, -8    // save r1
85112711afefcfcd43680c7c4aa8d38ef180e8811esewardj                          // offset 40
86112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r2, -8    // save r2
87112711afefcfcd43680c7c4aa8d38ef180e8811esewardj                          // offset 32
88112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r3, -8    // save r3
89112711afefcfcd43680c7c4aa8d38ef180e8811esewardj                          // offset 24
90112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r4, -8    // save r4
91112711afefcfcd43680c7c4aa8d38ef180e8811esewardj                          // offset 16
92112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st     r29, lr        // save lr
93112711afefcfcd43680c7c4aa8d38ef180e8811esewardj1:
94112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
95112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     moveli r10, __NR_rt_sigprocmask
96112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     moveli r0, VKI_SIG_SETMASK
97112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
98112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
99112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     move   r1, r2
100112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     move   r2, r3
101112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
102112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    move   r3, r4
103112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    swint1
104112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
105112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    // error, go 7f
106112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    bnez  r1, 7f
107112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
108112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    /* Get registers from guest_state. */
109112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 56    // get syscallno
110112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld     r10, r29
111112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 48
112112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld     r29, r29       // r29 points to guest_state
113112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r0, r29, 8     // read r0
114112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r1, r29, 8     // read r1
115112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r2, r29, 8     // read r2
116112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r3, r29, 8     // read r3
117112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r4, r29, 8     // read r4
118112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld_add r5, r29, 8     // read r5
119112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
120112711afefcfcd43680c7c4aa8d38ef180e8811esewardj2:  swint1                // syscall
121112711afefcfcd43680c7c4aa8d38ef180e8811esewardj3:
122112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    // Write register into guest_state
123112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 48
124112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld     r29, r29
125112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r0, 8
126112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r1, 8
127112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r2, 8
128112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r3, 8
129112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r4, 8
130112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    st_add r29, r5, 8
131112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    nop
132112711afefcfcd43680c7c4aa8d38ef180e8811esewardj4:
133112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
134112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     moveli r10, __NR_rt_sigprocmask
135112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     moveli r0, VKI_SIG_SETMASK
136112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
137112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 32
138112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
139112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     ld     r1, r29
140112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     movei  r2, 0
141112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
142112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    addli  r29, sp, 24
143112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ld     r3, r29
144112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
145112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    swint1
146112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    // error, go 7f
147112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    bnez  r1, 7f
148112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    nop
149112711afefcfcd43680c7c4aa8d38ef180e8811esewardj5:  addli  r29, sp, 16
150112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
151112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     ld     lr, r29       // restore lr
152112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     addli  sp, sp,  64
153112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
154112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    jr lr
155112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
156112711afefcfcd43680c7c4aa8d38ef180e8811esewardj7:  addi   r29, sp, 16
157112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
158112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     ld     lr, r29       // restore lr
159112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     addi   sp, sp, 64
160112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
161112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    {
162112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     // r0 = 0x8000
163112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     shl16insli r0, zero, -0x8000
164112711afefcfcd43680c7c4aa8d38ef180e8811esewardj     jr lr
165112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    }
166112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
167112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .section .rodata
168112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    /* export the ranges so that
169112711afefcfcd43680c7c4aa8d38ef180e8811esewardj       VG_(fixup_guest_state_after_syscall_interrupted) can do the
170112711afefcfcd43680c7c4aa8d38ef180e8811esewardj       right thing */
171112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
172112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .globl ML_(blksys_setup)
173112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .globl ML_(blksys_restart)
174112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .globl ML_(blksys_complete)
175112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .globl ML_(blksys_committed)
176112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .globl ML_(blksys_finished)
177112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ML_(blksys_setup):      .quad 1b
178112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ML_(blksys_restart):    .quad 2b
179112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ML_(blksys_complete):   .quad 3b
180112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ML_(blksys_committed):  .quad 4b
181112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    ML_(blksys_finished):   .quad 5b
182112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .previous
183112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    /* Let the linker know we don't need an executable stack */
184112711afefcfcd43680c7c4aa8d38ef180e8811esewardj    .section .note.GNU-stack,"",%progbits
185112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
186112711afefcfcd43680c7c4aa8d38ef180e8811esewardj#endif /* defined(VGP_tilegx_linux) */
187112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
188112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--------------------------------------------------------------------*/
189112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--- end                                                          ---*/
190112711afefcfcd43680c7c4aa8d38ef180e8811esewardj/*--------------------------------------------------------------------*/
191112711afefcfcd43680c7c4aa8d38ef180e8811esewardj
192