net: handle EAGAIN from tapfd write()
[qemu/aliguori-queue.git] / bsd-user / syscall.c
blob15c70e3d2e6aa2ae1fadf90735e216c447d369bf
1 /*
2 * BSD syscalls
4 * Copyright (c) 2003 - 2008 Fabrice Bellard
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.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
21 #include <stdlib.h>
22 #include <stdio.h>
23 #include <stdint.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <errno.h>
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <time.h>
30 #include <limits.h>
31 #include <sys/types.h>
32 #include <sys/mman.h>
33 #include <sys/syscall.h>
34 #include <signal.h>
35 #include <utime.h>
37 #include "qemu.h"
38 #include "qemu-common.h"
40 //#define DEBUG
42 static abi_ulong target_brk;
43 static abi_ulong target_original_brk;
45 #define get_errno(x) (x)
46 #define target_to_host_bitmask(x, tbl) (x)
48 void target_set_brk(abi_ulong new_brk)
50 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
53 /* do_syscall() should always have a single exit point at the end so
54 that actions, such as logging of syscall results, can be performed.
55 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
56 abi_long do_freebsd_syscall(void *cpu_env, int num, abi_long arg1,
57 abi_long arg2, abi_long arg3, abi_long arg4,
58 abi_long arg5, abi_long arg6)
60 abi_long ret;
61 void *p;
63 #ifdef DEBUG
64 gemu_log("freebsd syscall %d\n", num);
65 #endif
66 if(do_strace)
67 print_freebsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
69 switch(num) {
70 case TARGET_FREEBSD_NR_exit:
71 #ifdef HAVE_GPROF
72 _mcleanup();
73 #endif
74 gdb_exit(cpu_env, arg1);
75 /* XXX: should free thread stack and CPU env */
76 _exit(arg1);
77 ret = 0; /* avoid warning */
78 break;
79 case TARGET_FREEBSD_NR_read:
80 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
81 goto efault;
82 ret = get_errno(read(arg1, p, arg3));
83 unlock_user(p, arg2, ret);
84 break;
85 case TARGET_FREEBSD_NR_write:
86 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
87 goto efault;
88 ret = get_errno(write(arg1, p, arg3));
89 unlock_user(p, arg2, 0);
90 break;
91 case TARGET_FREEBSD_NR_open:
92 if (!(p = lock_user_string(arg1)))
93 goto efault;
94 ret = get_errno(open(path(p),
95 target_to_host_bitmask(arg2, fcntl_flags_tbl),
96 arg3));
97 unlock_user(p, arg1, 0);
98 break;
99 case TARGET_FREEBSD_NR_mmap:
100 ret = get_errno(target_mmap(arg1, arg2, arg3,
101 target_to_host_bitmask(arg4, mmap_flags_tbl),
102 arg5,
103 arg6));
104 break;
105 case TARGET_FREEBSD_NR_mprotect:
106 ret = get_errno(target_mprotect(arg1, arg2, arg3));
107 break;
108 case TARGET_FREEBSD_NR_syscall:
109 case TARGET_FREEBSD_NR___syscall:
110 ret = do_freebsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
111 break;
112 default:
113 ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
114 break;
116 fail:
117 #ifdef DEBUG
118 gemu_log(" = %ld\n", ret);
119 #endif
120 if (do_strace)
121 print_freebsd_syscall_ret(num, ret);
122 return ret;
123 efault:
124 ret = -TARGET_EFAULT;
125 goto fail;
128 abi_long do_netbsd_syscall(void *cpu_env, int num, abi_long arg1,
129 abi_long arg2, abi_long arg3, abi_long arg4,
130 abi_long arg5, abi_long arg6)
132 abi_long ret;
133 void *p;
135 #ifdef DEBUG
136 gemu_log("netbsd syscall %d\n", num);
137 #endif
138 if(do_strace)
139 print_netbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
141 switch(num) {
142 case TARGET_NETBSD_NR_exit:
143 #ifdef HAVE_GPROF
144 _mcleanup();
145 #endif
146 gdb_exit(cpu_env, arg1);
147 /* XXX: should free thread stack and CPU env */
148 _exit(arg1);
149 ret = 0; /* avoid warning */
150 break;
151 case TARGET_NETBSD_NR_read:
152 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
153 goto efault;
154 ret = get_errno(read(arg1, p, arg3));
155 unlock_user(p, arg2, ret);
156 break;
157 case TARGET_NETBSD_NR_write:
158 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
159 goto efault;
160 ret = get_errno(write(arg1, p, arg3));
161 unlock_user(p, arg2, 0);
162 break;
163 case TARGET_NETBSD_NR_open:
164 if (!(p = lock_user_string(arg1)))
165 goto efault;
166 ret = get_errno(open(path(p),
167 target_to_host_bitmask(arg2, fcntl_flags_tbl),
168 arg3));
169 unlock_user(p, arg1, 0);
170 break;
171 case TARGET_NETBSD_NR_mmap:
172 ret = get_errno(target_mmap(arg1, arg2, arg3,
173 target_to_host_bitmask(arg4, mmap_flags_tbl),
174 arg5,
175 arg6));
176 break;
177 case TARGET_NETBSD_NR_mprotect:
178 ret = get_errno(target_mprotect(arg1, arg2, arg3));
179 break;
180 case TARGET_NETBSD_NR_syscall:
181 case TARGET_NETBSD_NR___syscall:
182 ret = do_netbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
183 break;
184 default:
185 ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
186 break;
188 fail:
189 #ifdef DEBUG
190 gemu_log(" = %ld\n", ret);
191 #endif
192 if (do_strace)
193 print_netbsd_syscall_ret(num, ret);
194 return ret;
195 efault:
196 ret = -TARGET_EFAULT;
197 goto fail;
200 abi_long do_openbsd_syscall(void *cpu_env, int num, abi_long arg1,
201 abi_long arg2, abi_long arg3, abi_long arg4,
202 abi_long arg5, abi_long arg6)
204 abi_long ret;
205 void *p;
207 #ifdef DEBUG
208 gemu_log("openbsd syscall %d\n", num);
209 #endif
210 if(do_strace)
211 print_openbsd_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
213 switch(num) {
214 case TARGET_OPENBSD_NR_exit:
215 #ifdef HAVE_GPROF
216 _mcleanup();
217 #endif
218 gdb_exit(cpu_env, arg1);
219 /* XXX: should free thread stack and CPU env */
220 _exit(arg1);
221 ret = 0; /* avoid warning */
222 break;
223 case TARGET_OPENBSD_NR_read:
224 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
225 goto efault;
226 ret = get_errno(read(arg1, p, arg3));
227 unlock_user(p, arg2, ret);
228 break;
229 case TARGET_OPENBSD_NR_write:
230 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
231 goto efault;
232 ret = get_errno(write(arg1, p, arg3));
233 unlock_user(p, arg2, 0);
234 break;
235 case TARGET_OPENBSD_NR_open:
236 if (!(p = lock_user_string(arg1)))
237 goto efault;
238 ret = get_errno(open(path(p),
239 target_to_host_bitmask(arg2, fcntl_flags_tbl),
240 arg3));
241 unlock_user(p, arg1, 0);
242 break;
243 case TARGET_OPENBSD_NR_mmap:
244 ret = get_errno(target_mmap(arg1, arg2, arg3,
245 target_to_host_bitmask(arg4, mmap_flags_tbl),
246 arg5,
247 arg6));
248 break;
249 case TARGET_OPENBSD_NR_mprotect:
250 ret = get_errno(target_mprotect(arg1, arg2, arg3));
251 break;
252 case TARGET_OPENBSD_NR_syscall:
253 case TARGET_OPENBSD_NR___syscall:
254 ret = do_openbsd_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
255 break;
256 default:
257 ret = syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
258 break;
260 fail:
261 #ifdef DEBUG
262 gemu_log(" = %ld\n", ret);
263 #endif
264 if (do_strace)
265 print_openbsd_syscall_ret(num, ret);
266 return ret;
267 efault:
268 ret = -TARGET_EFAULT;
269 goto fail;
272 void syscall_init(void)