Work around OpenSolaris sys/regset.h namespace pollution
[qemu] / bsd-user / syscall.c
1 /*
2  *  BSD syscalls
3  *
4  *  Copyright (c) 2003 - 2008 Fabrice Bellard
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <stdint.h>
22 #include <stdarg.h>
23 #include <string.h>
24 #include <errno.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <time.h>
28 #include <limits.h>
29 #include <sys/types.h>
30 #include <sys/mman.h>
31 #include <sys/syscall.h>
32 #include <signal.h>
33 #include <utime.h>
34
35 #include "qemu.h"
36 #include "qemu-common.h"
37
38 //#define DEBUG
39
40 static abi_ulong target_brk;
41 static abi_ulong target_original_brk;
42
43 #define get_errno(x) (x)
44 #define target_to_host_bitmask(x, tbl) (x)
45
46 void target_set_brk(abi_ulong new_brk)
47 {
48     target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
49 }
50
51 /* do_syscall() should always have a single exit point at the end so
52    that actions, such as logging of syscall results, can be performed.
53    All errnos that do_syscall() returns must be -TARGET_<errcode>. */
54 abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
55                             abi_long arg2, abi_long arg3, abi_long arg4,
56                             abi_long arg5, abi_long arg6)
57 {
58     abi_long ret;
59     void *p;
60
61 #ifdef DEBUG
62     gemu_log("freebsd syscall %d\n", num);
63 #endif
64     if(do_strace)
65         print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
66
67     switch(num) {
68     case TARGET_FREEBSD_NR_exit:
69 #ifdef TARGET_GPROF
70         _mcleanup();
71 #endif
72         gdb_exit(cpu_env, arg1);
73         /* XXX: should free thread stack and CPU env */
74         _exit(arg1);
75         ret = 0; /* avoid warning */
76         break;
77     case TARGET_FREEBSD_NR_read:
78         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
79             goto efault;
80         ret = get_errno(read(arg1, p, arg3));
81         unlock_user(p, arg2, ret);
82         break;
83     case TARGET_FREEBSD_NR_write:
84         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
85             goto efault;
86         ret = get_errno(write(arg1, p, arg3));
87         unlock_user(p, arg2, 0);
88         break;
89     case TARGET_FREEBSD_NR_open:
90         if (!(p = lock_user_string(arg1)))
91             goto efault;
92         ret = get_errno(open(path(p),
93                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
94                              arg3));
95         unlock_user(p, arg1, 0);
96         break;
97     case TARGET_FREEBSD_NR_mmap:
98         ret = get_errno(target_mmap(arg1, arg2, arg3,
99                                     target_to_host_bitmask(arg4, mmap_flags_tbl),
100                                     arg5,
101                                     arg6));
102         break;
103     case TARGET_FREEBSD_NR_mprotect:
104         ret = get_errno(target_mprotect(arg1, arg2, arg3));
105         break;
106     case TARGET_FREEBSD_NR_syscall:
107     case TARGET_FREEBSD_NR___syscall:
108         ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
109         break;
110     default:
111         ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
112         break;
113     }
114  fail:
115 #ifdef DEBUG
116     gemu_log(" = %ld\n", ret);
117 #endif
118     if (do_strace)
119         print_freebsd_syscall_ret(num, ret);
120     return ret;
121  efault:
122     ret = -TARGET_EFAULT;
123     goto fail;
124 }
125
126 abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
127                            abi_long arg2, abi_long arg3, abi_long arg4,
128                            abi_long arg5, abi_long arg6)
129 {
130     abi_long ret;
131     void *p;
132
133 #ifdef DEBUG
134     gemu_log("netbsd syscall %d\n", num);
135 #endif
136     if(do_strace)
137         print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
138
139     switch(num) {
140     case TARGET_NETBSD_NR_exit:
141 #ifdef TARGET_GPROF
142         _mcleanup();
143 #endif
144         gdb_exit(cpu_env, arg1);
145         /* XXX: should free thread stack and CPU env */
146         _exit(arg1);
147         ret = 0; /* avoid warning */
148         break;
149     case TARGET_NETBSD_NR_read:
150         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
151             goto efault;
152         ret = get_errno(read(arg1, p, arg3));
153         unlock_user(p, arg2, ret);
154         break;
155     case TARGET_NETBSD_NR_write:
156         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
157             goto efault;
158         ret = get_errno(write(arg1, p, arg3));
159         unlock_user(p, arg2, 0);
160         break;
161     case TARGET_NETBSD_NR_open:
162         if (!(p = lock_user_string(arg1)))
163             goto efault;
164         ret = get_errno(open(path(p),
165                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
166                              arg3));
167         unlock_user(p, arg1, 0);
168         break;
169     case TARGET_NETBSD_NR_mmap:
170         ret = get_errno(target_mmap(arg1, arg2, arg3,
171                                     target_to_host_bitmask(arg4, mmap_flags_tbl),
172                                     arg5,
173                                     arg6));
174         break;
175     case TARGET_NETBSD_NR_mprotect:
176         ret = get_errno(target_mprotect(arg1, arg2, arg3));
177         break;
178     case TARGET_NETBSD_NR_syscall:
179     case TARGET_NETBSD_NR___syscall:
180         ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
181         break;
182     default:
183         ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
184         break;
185     }
186  fail:
187 #ifdef DEBUG
188     gemu_log(" = %ld\n", ret);
189 #endif
190     if (do_strace)
191         print_netbsd_syscall_ret(num, ret);
192     return ret;
193  efault:
194     ret = -TARGET_EFAULT;
195     goto fail;
196 }
197
198 abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
199                             abi_long arg2, abi_long arg3, abi_long arg4,
200                             abi_long arg5, abi_long arg6)
201 {
202     abi_long ret;
203     void *p;
204
205 #ifdef DEBUG
206     gemu_log("openbsd syscall %d\n", num);
207 #endif
208     if(do_strace)
209         print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
210
211     switch(num) {
212     case TARGET_OPENBSD_NR_exit:
213 #ifdef TARGET_GPROF
214         _mcleanup();
215 #endif
216         gdb_exit(cpu_env, arg1);
217         /* XXX: should free thread stack and CPU env */
218         _exit(arg1);
219         ret = 0; /* avoid warning */
220         break;
221     case TARGET_OPENBSD_NR_read:
222         if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
223             goto efault;
224         ret = get_errno(read(arg1, p, arg3));
225         unlock_user(p, arg2, ret);
226         break;
227     case TARGET_OPENBSD_NR_write:
228         if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
229             goto efault;
230         ret = get_errno(write(arg1, p, arg3));
231         unlock_user(p, arg2, 0);
232         break;
233     case TARGET_OPENBSD_NR_open:
234         if (!(p = lock_user_string(arg1)))
235             goto efault;
236         ret = get_errno(open(path(p),
237                              target_to_host_bitmask(arg2, fcntl_flags_tbl),
238                              arg3));
239         unlock_user(p, arg1, 0);
240         break;
241     case TARGET_OPENBSD_NR_mmap:
242         ret = get_errno(target_mmap(arg1, arg2, arg3,
243                                     target_to_host_bitmask(arg4, mmap_flags_tbl),
244                                     arg5,
245                                     arg6));
246         break;
247     case TARGET_OPENBSD_NR_mprotect:
248         ret = get_errno(target_mprotect(arg1, arg2, arg3));
249         break;
250     case TARGET_OPENBSD_NR_syscall:
251     case TARGET_OPENBSD_NR___syscall:
252         ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
253         break;
254     default:
255         ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
256         break;
257     }
258  fail:
259 #ifdef DEBUG
260     gemu_log(" = %ld\n", ret);
261 #endif
262     if (do_strace)
263         print_openbsd_syscall_ret(num, ret);
264     return ret;
265  efault:
266     ret = -TARGET_EFAULT;
267     goto fail;
268 }
269
270 void syscall_init(void)
271 {
272 }