]> git.ipfire.org Git - thirdparty/qemu.git/blame - linux-user/syscall.c
ppc-linux-user: handle EXCP_DEBUG
[thirdparty/qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * Copyright (c) 2003 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, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
04369ff2 23#include <string.h>
31e31b8a
FB
24#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
7854b056 29#include <time.h>
82e671d9 30#include <limits.h>
31e31b8a 31#include <sys/types.h>
d08d3bb8
TS
32#include <sys/ipc.h>
33#include <sys/msg.h>
31e31b8a
FB
34#include <sys/wait.h>
35#include <sys/time.h>
36#include <sys/stat.h>
37#include <sys/mount.h>
39b9aae1 38#include <sys/prctl.h>
31e31b8a
FB
39#include <sys/resource.h>
40#include <sys/mman.h>
41#include <sys/swap.h>
42#include <signal.h>
43#include <sched.h>
44#include <sys/socket.h>
45#include <sys/uio.h>
9de5e440 46#include <sys/poll.h>
32f36bce 47#include <sys/times.h>
8853f86e 48#include <sys/shm.h>
fa294816 49#include <sys/sem.h>
56c8f68f 50#include <sys/statfs.h>
ebc05488 51#include <utime.h>
a5448a7d 52#include <sys/sysinfo.h>
72f03900 53//#include <sys/user.h>
8853f86e 54#include <netinet/ip.h>
7854b056 55#include <netinet/tcp.h>
0b6d3ae0 56#include <qemu-common.h>
6d946cda
AJ
57#ifdef HAVE_GPROF
58#include <sys/gmon.h>
59#endif
31e31b8a
FB
60
61#define termios host_termios
62#define winsize host_winsize
63#define termio host_termio
04369ff2
FB
64#define sgttyb host_sgttyb /* same as target */
65#define tchars host_tchars /* same as target */
66#define ltchars host_ltchars /* same as target */
31e31b8a
FB
67
68#include <linux/termios.h>
69#include <linux/unistd.h>
70#include <linux/utsname.h>
71#include <linux/cdrom.h>
72#include <linux/hdreg.h>
73#include <linux/soundcard.h>
19b84f3c 74#include <linux/kd.h>
8fbd6b52 75#include <linux/mtio.h>
d7e4036e 76#include "linux_loop.h"
31e31b8a 77
3ef693a0 78#include "qemu.h"
526ccb7a 79#include "qemu-common.h"
31e31b8a 80
30813cea
PB
81#if defined(USE_NPTL)
82#include <linux/futex.h>
d865bab5
PB
83#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
84 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
85#else
86/* XXX: Hardcode the above values. */
87#define CLONE_NPTL_FLAGS2 0
30813cea
PB
88#endif
89
72f03900 90//#define DEBUG
31e31b8a 91
e6e5906b 92#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
48733d19 93 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
67867308
FB
94/* 16 bit uid wrappers emulation */
95#define USE_UID16
96#endif
97
1a9353d2 98//#include <linux/msdos_fs.h>
6556a833
AJ
99#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
100#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
1a9353d2 101
70a194b9 102
70a194b9
FB
103#undef _syscall0
104#undef _syscall1
105#undef _syscall2
106#undef _syscall3
107#undef _syscall4
108#undef _syscall5
83fcb515 109#undef _syscall6
70a194b9 110
83fcb515 111#define _syscall0(type,name) \
8fcd3692 112static type name (void) \
83fcb515
FB
113{ \
114 return syscall(__NR_##name); \
115}
70a194b9 116
83fcb515 117#define _syscall1(type,name,type1,arg1) \
8fcd3692 118static type name (type1 arg1) \
83fcb515
FB
119{ \
120 return syscall(__NR_##name, arg1); \
70a194b9
FB
121}
122
83fcb515 123#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 124static type name (type1 arg1,type2 arg2) \
83fcb515
FB
125{ \
126 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
127}
128
83fcb515 129#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 130static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
131{ \
132 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
133}
134
83fcb515 135#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 136static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
137{ \
138 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
139}
140
83fcb515
FB
141#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
142 type5,arg5) \
8fcd3692 143static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
144{ \
145 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
146}
147
83fcb515
FB
148
149#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
150 type5,arg5,type6,arg6) \
8fcd3692
BS
151static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
152 type6 arg6) \
83fcb515
FB
153{ \
154 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 155}
83fcb515 156
70a194b9 157
a2f86d8e 158#define __NR_sys_exit __NR_exit
31e31b8a 159#define __NR_sys_uname __NR_uname
92a34c10 160#define __NR_sys_faccessat __NR_faccessat
814d7977 161#define __NR_sys_fchmodat __NR_fchmodat
ccfa72b7 162#define __NR_sys_fchownat __NR_fchownat
6a24a778 163#define __NR_sys_fstatat64 __NR_fstatat64
ac8a6556 164#define __NR_sys_futimesat __NR_futimesat
72f03900 165#define __NR_sys_getcwd1 __NR_getcwd
72f03900 166#define __NR_sys_getdents __NR_getdents
dab2ed99 167#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 168#define __NR_sys_getpriority __NR_getpriority
64f0ce4c 169#define __NR_sys_linkat __NR_linkat
4472ad0d 170#define __NR_sys_mkdirat __NR_mkdirat
75ac37a0 171#define __NR_sys_mknodat __NR_mknodat
82424832 172#define __NR_sys_openat __NR_openat
5e0ccb18 173#define __NR_sys_readlinkat __NR_readlinkat
722183f6 174#define __NR_sys_renameat __NR_renameat
66fb9763 175#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
f0b6243d 176#define __NR_sys_symlinkat __NR_symlinkat
7494b0f9 177#define __NR_sys_syslog __NR_syslog
71455574 178#define __NR_sys_tgkill __NR_tgkill
4cae1d16 179#define __NR_sys_tkill __NR_tkill
8170f56b 180#define __NR_sys_unlinkat __NR_unlinkat
9007f0ef 181#define __NR_sys_utimensat __NR_utimensat
bd0c5661 182#define __NR_sys_futex __NR_futex
39b59763
AJ
183#define __NR_sys_inotify_init __NR_inotify_init
184#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
185#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
31e31b8a 186
bc51c5c9 187#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
9af9eaaa
FB
188#define __NR__llseek __NR_lseek
189#endif
190
72f03900 191#ifdef __NR_gettid
31e31b8a 192_syscall0(int, gettid)
72f03900 193#else
0da46a6e
TS
194/* This is a replacement for the host gettid() and must return a host
195 errno. */
72f03900
FB
196static int gettid(void) {
197 return -ENOSYS;
198}
199#endif
a2f86d8e 200_syscall1(int,sys_exit,int,status)
31e31b8a 201_syscall1(int,sys_uname,struct new_utsname *,buf)
92a34c10
TS
202#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
203_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
204#endif
814d7977
TS
205#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
206_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
207 mode_t,mode,int,flags)
208#endif
4583f589 209#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
ccfa72b7
TS
210_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
211 uid_t,owner,gid_t,group,int,flags)
212#endif
6a24a778
AZ
213#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
214_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
215 struct stat *,buf,int,flags)
216#endif
ac8a6556
AZ
217#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
218_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
219 const struct timeval *,times)
220#endif
72f03900 221_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
4583f589 222#if TARGET_ABI_BITS == 32
6556a833 223_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
4583f589 224#endif
3ae43202 225#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
6556a833 226_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
3ae43202 227#endif
c6cda17a 228_syscall2(int, sys_getpriority, int, which, int, who);
8fcd3692 229#if !defined (__x86_64__)
31e31b8a
FB
230_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
231 loff_t *, res, uint, wh);
8fcd3692 232#endif
64f0ce4c
TS
233#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
234_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
235 int,newdirfd,const char *,newpath,int,flags)
236#endif
4472ad0d
TS
237#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
238_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
239#endif
75ac37a0
TS
240#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
241_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
242 mode_t,mode,dev_t,dev)
243#endif
82424832
TS
244#if defined(TARGET_NR_openat) && defined(__NR_openat)
245_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
246#endif
5e0ccb18
TS
247#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
248_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
249 char *,buf,size_t,bufsize)
250#endif
722183f6
TS
251#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
252_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
253 int,newdirfd,const char *,newpath)
254#endif
66fb9763 255_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
b51eaa82 256#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
f0b6243d
TS
257_syscall3(int,sys_symlinkat,const char *,oldpath,
258 int,newdirfd,const char *,newpath)
259#endif
7494b0f9 260_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
3ae43202 261#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 262_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
4cae1d16 263#endif
3ae43202 264#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16
TS
265_syscall2(int,sys_tkill,int,tid,int,sig)
266#endif
ec86b0fb
FB
267#ifdef __NR_exit_group
268_syscall1(int,exit_group,int,error_code)
269#endif
6f5b89a0
TS
270#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
271_syscall1(int,set_tid_address,int *,tidptr)
272#endif
8170f56b
TS
273#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
274_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
275#endif
9007f0ef
TS
276#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
277_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
278 const struct timespec *,tsp,int,flags)
279#endif
39b59763
AJ
280#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
281_syscall0(int,sys_inotify_init)
282#endif
283#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
284_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask)
285#endif
286#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
287_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
288#endif
8fcd3692 289#if defined(USE_NPTL)
bd0c5661
PB
290#if defined(TARGET_NR_futex) && defined(__NR_futex)
291_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
292 const struct timespec *,timeout,int *,uaddr2,int,val3)
8fcd3692 293#endif
bd0c5661 294#endif
66fb9763
FB
295
296extern int personality(int);
9de5e440
FB
297extern int flock(int, int);
298extern int setfsuid(int);
299extern int setfsgid(int);
19b84f3c 300extern int setgroups(int, gid_t *);
31e31b8a 301
b92c47c1
TS
302#define ERRNO_TABLE_SIZE 1200
303
304/* target_to_host_errno_table[] is initialized from
305 * host_to_target_errno_table[] in syscall_init(). */
306static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
307};
308
637947f1 309/*
fe8f096b 310 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
311 * minus the errnos that are not actually generic to all archs.
312 */
b92c47c1 313static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
314 [EIDRM] = TARGET_EIDRM,
315 [ECHRNG] = TARGET_ECHRNG,
316 [EL2NSYNC] = TARGET_EL2NSYNC,
317 [EL3HLT] = TARGET_EL3HLT,
318 [EL3RST] = TARGET_EL3RST,
319 [ELNRNG] = TARGET_ELNRNG,
320 [EUNATCH] = TARGET_EUNATCH,
321 [ENOCSI] = TARGET_ENOCSI,
322 [EL2HLT] = TARGET_EL2HLT,
323 [EDEADLK] = TARGET_EDEADLK,
324 [ENOLCK] = TARGET_ENOLCK,
325 [EBADE] = TARGET_EBADE,
326 [EBADR] = TARGET_EBADR,
327 [EXFULL] = TARGET_EXFULL,
328 [ENOANO] = TARGET_ENOANO,
329 [EBADRQC] = TARGET_EBADRQC,
330 [EBADSLT] = TARGET_EBADSLT,
331 [EBFONT] = TARGET_EBFONT,
332 [ENOSTR] = TARGET_ENOSTR,
333 [ENODATA] = TARGET_ENODATA,
334 [ETIME] = TARGET_ETIME,
335 [ENOSR] = TARGET_ENOSR,
336 [ENONET] = TARGET_ENONET,
337 [ENOPKG] = TARGET_ENOPKG,
338 [EREMOTE] = TARGET_EREMOTE,
339 [ENOLINK] = TARGET_ENOLINK,
340 [EADV] = TARGET_EADV,
341 [ESRMNT] = TARGET_ESRMNT,
342 [ECOMM] = TARGET_ECOMM,
343 [EPROTO] = TARGET_EPROTO,
344 [EDOTDOT] = TARGET_EDOTDOT,
345 [EMULTIHOP] = TARGET_EMULTIHOP,
346 [EBADMSG] = TARGET_EBADMSG,
347 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
348 [EOVERFLOW] = TARGET_EOVERFLOW,
349 [ENOTUNIQ] = TARGET_ENOTUNIQ,
350 [EBADFD] = TARGET_EBADFD,
351 [EREMCHG] = TARGET_EREMCHG,
352 [ELIBACC] = TARGET_ELIBACC,
353 [ELIBBAD] = TARGET_ELIBBAD,
354 [ELIBSCN] = TARGET_ELIBSCN,
355 [ELIBMAX] = TARGET_ELIBMAX,
356 [ELIBEXEC] = TARGET_ELIBEXEC,
357 [EILSEQ] = TARGET_EILSEQ,
358 [ENOSYS] = TARGET_ENOSYS,
359 [ELOOP] = TARGET_ELOOP,
360 [ERESTART] = TARGET_ERESTART,
361 [ESTRPIPE] = TARGET_ESTRPIPE,
362 [ENOTEMPTY] = TARGET_ENOTEMPTY,
363 [EUSERS] = TARGET_EUSERS,
364 [ENOTSOCK] = TARGET_ENOTSOCK,
365 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
366 [EMSGSIZE] = TARGET_EMSGSIZE,
367 [EPROTOTYPE] = TARGET_EPROTOTYPE,
368 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
369 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
370 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
371 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
372 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
373 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
374 [EADDRINUSE] = TARGET_EADDRINUSE,
375 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
376 [ENETDOWN] = TARGET_ENETDOWN,
377 [ENETUNREACH] = TARGET_ENETUNREACH,
378 [ENETRESET] = TARGET_ENETRESET,
379 [ECONNABORTED] = TARGET_ECONNABORTED,
380 [ECONNRESET] = TARGET_ECONNRESET,
381 [ENOBUFS] = TARGET_ENOBUFS,
382 [EISCONN] = TARGET_EISCONN,
383 [ENOTCONN] = TARGET_ENOTCONN,
384 [EUCLEAN] = TARGET_EUCLEAN,
385 [ENOTNAM] = TARGET_ENOTNAM,
386 [ENAVAIL] = TARGET_ENAVAIL,
387 [EISNAM] = TARGET_EISNAM,
388 [EREMOTEIO] = TARGET_EREMOTEIO,
389 [ESHUTDOWN] = TARGET_ESHUTDOWN,
390 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
391 [ETIMEDOUT] = TARGET_ETIMEDOUT,
392 [ECONNREFUSED] = TARGET_ECONNREFUSED,
393 [EHOSTDOWN] = TARGET_EHOSTDOWN,
394 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
395 [EALREADY] = TARGET_EALREADY,
396 [EINPROGRESS] = TARGET_EINPROGRESS,
397 [ESTALE] = TARGET_ESTALE,
398 [ECANCELED] = TARGET_ECANCELED,
399 [ENOMEDIUM] = TARGET_ENOMEDIUM,
400 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 401#ifdef ENOKEY
637947f1 402 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
403#endif
404#ifdef EKEYEXPIRED
637947f1 405 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
406#endif
407#ifdef EKEYREVOKED
637947f1 408 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
409#endif
410#ifdef EKEYREJECTED
637947f1 411 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
412#endif
413#ifdef EOWNERDEAD
637947f1 414 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
415#endif
416#ifdef ENOTRECOVERABLE
637947f1 417 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 418#endif
b92c47c1 419};
637947f1
TS
420
421static inline int host_to_target_errno(int err)
422{
423 if(host_to_target_errno_table[err])
424 return host_to_target_errno_table[err];
425 return err;
426}
427
b92c47c1
TS
428static inline int target_to_host_errno(int err)
429{
430 if (target_to_host_errno_table[err])
431 return target_to_host_errno_table[err];
432 return err;
433}
434
992f48a0 435static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
436{
437 if (ret == -1)
637947f1 438 return -host_to_target_errno(errno);
31e31b8a
FB
439 else
440 return ret;
441}
442
992f48a0 443static inline int is_error(abi_long ret)
31e31b8a 444{
992f48a0 445 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
446}
447
b92c47c1
TS
448char *target_strerror(int err)
449{
450 return strerror(target_to_host_errno(err));
451}
452
992f48a0
BS
453static abi_ulong target_brk;
454static abi_ulong target_original_brk;
31e31b8a 455
992f48a0 456void target_set_brk(abi_ulong new_brk)
31e31b8a 457{
4c1de73d 458 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
31e31b8a
FB
459}
460
0da46a6e 461/* do_brk() must return target values and target errnos. */
992f48a0 462abi_long do_brk(abi_ulong new_brk)
31e31b8a 463{
992f48a0
BS
464 abi_ulong brk_page;
465 abi_long mapped_addr;
31e31b8a
FB
466 int new_alloc_size;
467
468 if (!new_brk)
53a5960a 469 return target_brk;
31e31b8a 470 if (new_brk < target_original_brk)
7ab240ad 471 return target_brk;
3b46e624 472
53a5960a 473 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
474
475 /* If the new brk is less than this, set it and we're done... */
476 if (new_brk < brk_page) {
477 target_brk = new_brk;
53a5960a 478 return target_brk;
31e31b8a
FB
479 }
480
481 /* We need to allocate more memory after the brk... */
54936004 482 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
5fafdf24 483 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004
FB
484 PROT_READ|PROT_WRITE,
485 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
7ab240ad
AZ
486
487 if (!is_error(mapped_addr))
31e31b8a 488 target_brk = new_brk;
7ab240ad
AZ
489
490 return target_brk;
31e31b8a
FB
491}
492
26edcf41
TS
493static inline abi_long copy_from_user_fdset(fd_set *fds,
494 abi_ulong target_fds_addr,
495 int n)
31e31b8a 496{
26edcf41
TS
497 int i, nw, j, k;
498 abi_ulong b, *target_fds;
499
500 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
501 if (!(target_fds = lock_user(VERIFY_READ,
502 target_fds_addr,
503 sizeof(abi_ulong) * nw,
504 1)))
505 return -TARGET_EFAULT;
506
507 FD_ZERO(fds);
508 k = 0;
509 for (i = 0; i < nw; i++) {
510 /* grab the abi_ulong */
511 __get_user(b, &target_fds[i]);
512 for (j = 0; j < TARGET_ABI_BITS; j++) {
513 /* check the bit inside the abi_ulong */
514 if ((b >> j) & 1)
515 FD_SET(k, fds);
516 k++;
31e31b8a 517 }
31e31b8a 518 }
26edcf41
TS
519
520 unlock_user(target_fds, target_fds_addr, 0);
521
522 return 0;
31e31b8a
FB
523}
524
26edcf41
TS
525static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
526 const fd_set *fds,
527 int n)
31e31b8a 528{
31e31b8a 529 int i, nw, j, k;
992f48a0 530 abi_long v;
26edcf41 531 abi_ulong *target_fds;
31e31b8a 532
26edcf41
TS
533 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
534 if (!(target_fds = lock_user(VERIFY_WRITE,
535 target_fds_addr,
536 sizeof(abi_ulong) * nw,
537 0)))
538 return -TARGET_EFAULT;
539
540 k = 0;
541 for (i = 0; i < nw; i++) {
542 v = 0;
543 for (j = 0; j < TARGET_ABI_BITS; j++) {
544 v |= ((FD_ISSET(k, fds) != 0) << j);
545 k++;
31e31b8a 546 }
26edcf41 547 __put_user(v, &target_fds[i]);
31e31b8a 548 }
26edcf41
TS
549
550 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
551
552 return 0;
31e31b8a
FB
553}
554
c596ed17
FB
555#if defined(__alpha__)
556#define HOST_HZ 1024
557#else
558#define HOST_HZ 100
559#endif
560
992f48a0 561static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
562{
563#if HOST_HZ == TARGET_HZ
564 return ticks;
565#else
566 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
567#endif
568}
569
579a97f7
FB
570static inline abi_long host_to_target_rusage(abi_ulong target_addr,
571 const struct rusage *rusage)
b409186b 572{
53a5960a
PB
573 struct target_rusage *target_rusage;
574
579a97f7
FB
575 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
576 return -TARGET_EFAULT;
b409186b
FB
577 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
578 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
579 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
580 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
581 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
582 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
583 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
584 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
585 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
586 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
587 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
588 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
589 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
590 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
591 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
592 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
593 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
594 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
53a5960a 595 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
596
597 return 0;
b409186b
FB
598}
599
788f5ec4
TS
600static inline abi_long copy_from_user_timeval(struct timeval *tv,
601 abi_ulong target_tv_addr)
31e31b8a 602{
53a5960a
PB
603 struct target_timeval *target_tv;
604
788f5ec4 605 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 606 return -TARGET_EFAULT;
788f5ec4
TS
607
608 __get_user(tv->tv_sec, &target_tv->tv_sec);
609 __get_user(tv->tv_usec, &target_tv->tv_usec);
610
611 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
612
613 return 0;
31e31b8a
FB
614}
615
788f5ec4
TS
616static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
617 const struct timeval *tv)
31e31b8a 618{
53a5960a
PB
619 struct target_timeval *target_tv;
620
788f5ec4 621 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 622 return -TARGET_EFAULT;
788f5ec4
TS
623
624 __put_user(tv->tv_sec, &target_tv->tv_sec);
625 __put_user(tv->tv_usec, &target_tv->tv_usec);
626
627 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
628
629 return 0;
31e31b8a
FB
630}
631
632
0da46a6e 633/* do_select() must return target values and target errnos. */
992f48a0 634static abi_long do_select(int n,
26edcf41
TS
635 abi_ulong rfd_addr, abi_ulong wfd_addr,
636 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
637{
638 fd_set rfds, wfds, efds;
639 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
640 struct timeval tv, *tv_ptr;
992f48a0 641 abi_long ret;
31e31b8a 642
26edcf41
TS
643 if (rfd_addr) {
644 if (copy_from_user_fdset(&rfds, rfd_addr, n))
645 return -TARGET_EFAULT;
646 rfds_ptr = &rfds;
53a5960a 647 } else {
53a5960a
PB
648 rfds_ptr = NULL;
649 }
26edcf41
TS
650 if (wfd_addr) {
651 if (copy_from_user_fdset(&wfds, wfd_addr, n))
652 return -TARGET_EFAULT;
653 wfds_ptr = &wfds;
53a5960a 654 } else {
53a5960a
PB
655 wfds_ptr = NULL;
656 }
26edcf41
TS
657 if (efd_addr) {
658 if (copy_from_user_fdset(&efds, efd_addr, n))
659 return -TARGET_EFAULT;
660 efds_ptr = &efds;
53a5960a 661 } else {
53a5960a
PB
662 efds_ptr = NULL;
663 }
3b46e624 664
26edcf41 665 if (target_tv_addr) {
788f5ec4
TS
666 if (copy_from_user_timeval(&tv, target_tv_addr))
667 return -TARGET_EFAULT;
31e31b8a
FB
668 tv_ptr = &tv;
669 } else {
670 tv_ptr = NULL;
671 }
26edcf41 672
31e31b8a 673 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 674
26edcf41
TS
675 if (!is_error(ret)) {
676 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
677 return -TARGET_EFAULT;
678 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
679 return -TARGET_EFAULT;
680 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
681 return -TARGET_EFAULT;
31e31b8a 682
788f5ec4
TS
683 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
684 return -TARGET_EFAULT;
31e31b8a 685 }
579a97f7 686
31e31b8a
FB
687 return ret;
688}
689
579a97f7
FB
690static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
691 abi_ulong target_addr,
692 socklen_t len)
7854b056 693{
53a5960a
PB
694 struct target_sockaddr *target_saddr;
695
579a97f7
FB
696 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
697 if (!target_saddr)
698 return -TARGET_EFAULT;
53a5960a
PB
699 memcpy(addr, target_saddr, len);
700 addr->sa_family = tswap16(target_saddr->sa_family);
701 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
702
703 return 0;
7854b056
FB
704}
705
579a97f7
FB
706static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
707 struct sockaddr *addr,
708 socklen_t len)
7854b056 709{
53a5960a
PB
710 struct target_sockaddr *target_saddr;
711
579a97f7
FB
712 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
713 if (!target_saddr)
714 return -TARGET_EFAULT;
53a5960a
PB
715 memcpy(target_saddr, addr, len);
716 target_saddr->sa_family = tswap16(addr->sa_family);
717 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
718
719 return 0;
7854b056
FB
720}
721
53a5960a 722/* ??? Should this also swap msgh->name? */
5a4a898d
FB
723static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
724 struct target_msghdr *target_msgh)
7854b056
FB
725{
726 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
727 abi_long msg_controllen;
728 abi_ulong target_cmsg_addr;
729 struct target_cmsghdr *target_cmsg;
7854b056 730 socklen_t space = 0;
5a4a898d
FB
731
732 msg_controllen = tswapl(target_msgh->msg_controllen);
733 if (msg_controllen < sizeof (struct target_cmsghdr))
734 goto the_end;
735 target_cmsg_addr = tswapl(target_msgh->msg_control);
736 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
737 if (!target_cmsg)
738 return -TARGET_EFAULT;
7854b056
FB
739
740 while (cmsg && target_cmsg) {
741 void *data = CMSG_DATA(cmsg);
742 void *target_data = TARGET_CMSG_DATA(target_cmsg);
743
5fafdf24 744 int len = tswapl(target_cmsg->cmsg_len)
7854b056
FB
745 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
746
747 space += CMSG_SPACE(len);
748 if (space > msgh->msg_controllen) {
749 space -= CMSG_SPACE(len);
31febb71 750 gemu_log("Host cmsg overflow\n");
7854b056
FB
751 break;
752 }
753
754 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
755 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
756 cmsg->cmsg_len = CMSG_LEN(len);
757
3532fa74 758 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
759 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
760 memcpy(data, target_data, len);
761 } else {
762 int *fd = (int *)data;
763 int *target_fd = (int *)target_data;
764 int i, numfds = len / sizeof(int);
765
766 for (i = 0; i < numfds; i++)
767 fd[i] = tswap32(target_fd[i]);
768 }
769
770 cmsg = CMSG_NXTHDR(msgh, cmsg);
771 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
772 }
5a4a898d
FB
773 unlock_user(target_cmsg, target_cmsg_addr, 0);
774 the_end:
7854b056 775 msgh->msg_controllen = space;
5a4a898d 776 return 0;
7854b056
FB
777}
778
53a5960a 779/* ??? Should this also swap msgh->name? */
5a4a898d
FB
780static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
781 struct msghdr *msgh)
7854b056
FB
782{
783 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
784 abi_long msg_controllen;
785 abi_ulong target_cmsg_addr;
786 struct target_cmsghdr *target_cmsg;
7854b056
FB
787 socklen_t space = 0;
788
5a4a898d
FB
789 msg_controllen = tswapl(target_msgh->msg_controllen);
790 if (msg_controllen < sizeof (struct target_cmsghdr))
791 goto the_end;
792 target_cmsg_addr = tswapl(target_msgh->msg_control);
793 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
794 if (!target_cmsg)
795 return -TARGET_EFAULT;
796
7854b056
FB
797 while (cmsg && target_cmsg) {
798 void *data = CMSG_DATA(cmsg);
799 void *target_data = TARGET_CMSG_DATA(target_cmsg);
800
801 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
802
803 space += TARGET_CMSG_SPACE(len);
5a4a898d 804 if (space > msg_controllen) {
7854b056 805 space -= TARGET_CMSG_SPACE(len);
31febb71 806 gemu_log("Target cmsg overflow\n");
7854b056
FB
807 break;
808 }
809
810 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
811 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
812 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
813
3532fa74 814 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
815 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
816 memcpy(target_data, data, len);
817 } else {
818 int *fd = (int *)data;
819 int *target_fd = (int *)target_data;
820 int i, numfds = len / sizeof(int);
821
822 for (i = 0; i < numfds; i++)
823 target_fd[i] = tswap32(fd[i]);
824 }
825
826 cmsg = CMSG_NXTHDR(msgh, cmsg);
827 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
828 }
5a4a898d
FB
829 unlock_user(target_cmsg, target_cmsg_addr, space);
830 the_end:
831 target_msgh->msg_controllen = tswapl(space);
832 return 0;
7854b056
FB
833}
834
0da46a6e 835/* do_setsockopt() Must return target values and target errnos. */
992f48a0 836static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 837 abi_ulong optval_addr, socklen_t optlen)
7854b056 838{
992f48a0 839 abi_long ret;
32407103 840 int val;
3b46e624 841
8853f86e
FB
842 switch(level) {
843 case SOL_TCP:
7854b056 844 /* TCP options all take an 'int' value. */
7854b056 845 if (optlen < sizeof(uint32_t))
0da46a6e 846 return -TARGET_EINVAL;
3b46e624 847
2f619698
FB
848 if (get_user_u32(val, optval_addr))
849 return -TARGET_EFAULT;
8853f86e
FB
850 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
851 break;
852 case SOL_IP:
853 switch(optname) {
2efbe911
FB
854 case IP_TOS:
855 case IP_TTL:
8853f86e 856 case IP_HDRINCL:
2efbe911
FB
857 case IP_ROUTER_ALERT:
858 case IP_RECVOPTS:
859 case IP_RETOPTS:
860 case IP_PKTINFO:
861 case IP_MTU_DISCOVER:
862 case IP_RECVERR:
863 case IP_RECVTOS:
864#ifdef IP_FREEBIND
865 case IP_FREEBIND:
866#endif
867 case IP_MULTICAST_TTL:
868 case IP_MULTICAST_LOOP:
8853f86e
FB
869 val = 0;
870 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
871 if (get_user_u32(val, optval_addr))
872 return -TARGET_EFAULT;
8853f86e 873 } else if (optlen >= 1) {
2f619698
FB
874 if (get_user_u8(val, optval_addr))
875 return -TARGET_EFAULT;
8853f86e
FB
876 }
877 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
878 break;
879 default:
880 goto unimplemented;
881 }
882 break;
3532fa74 883 case TARGET_SOL_SOCKET:
8853f86e
FB
884 switch (optname) {
885 /* Options with 'int' argument. */
3532fa74
FB
886 case TARGET_SO_DEBUG:
887 optname = SO_DEBUG;
888 break;
889 case TARGET_SO_REUSEADDR:
890 optname = SO_REUSEADDR;
891 break;
892 case TARGET_SO_TYPE:
893 optname = SO_TYPE;
894 break;
895 case TARGET_SO_ERROR:
896 optname = SO_ERROR;
897 break;
898 case TARGET_SO_DONTROUTE:
899 optname = SO_DONTROUTE;
900 break;
901 case TARGET_SO_BROADCAST:
902 optname = SO_BROADCAST;
903 break;
904 case TARGET_SO_SNDBUF:
905 optname = SO_SNDBUF;
906 break;
907 case TARGET_SO_RCVBUF:
908 optname = SO_RCVBUF;
909 break;
910 case TARGET_SO_KEEPALIVE:
911 optname = SO_KEEPALIVE;
912 break;
913 case TARGET_SO_OOBINLINE:
914 optname = SO_OOBINLINE;
915 break;
916 case TARGET_SO_NO_CHECK:
917 optname = SO_NO_CHECK;
918 break;
919 case TARGET_SO_PRIORITY:
920 optname = SO_PRIORITY;
921 break;
5e83e8e3 922#ifdef SO_BSDCOMPAT
3532fa74
FB
923 case TARGET_SO_BSDCOMPAT:
924 optname = SO_BSDCOMPAT;
925 break;
5e83e8e3 926#endif
3532fa74
FB
927 case TARGET_SO_PASSCRED:
928 optname = SO_PASSCRED;
929 break;
930 case TARGET_SO_TIMESTAMP:
931 optname = SO_TIMESTAMP;
932 break;
933 case TARGET_SO_RCVLOWAT:
934 optname = SO_RCVLOWAT;
935 break;
936 case TARGET_SO_RCVTIMEO:
937 optname = SO_RCVTIMEO;
938 break;
939 case TARGET_SO_SNDTIMEO:
940 optname = SO_SNDTIMEO;
941 break;
8853f86e
FB
942 break;
943 default:
944 goto unimplemented;
945 }
3532fa74 946 if (optlen < sizeof(uint32_t))
2f619698 947 return -TARGET_EINVAL;
3532fa74 948
2f619698
FB
949 if (get_user_u32(val, optval_addr))
950 return -TARGET_EFAULT;
3532fa74 951 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 952 break;
7854b056 953 default:
8853f86e
FB
954 unimplemented:
955 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
6fa13c17 956 ret = -TARGET_ENOPROTOOPT;
7854b056 957 }
8853f86e 958 return ret;
7854b056
FB
959}
960
0da46a6e 961/* do_getsockopt() Must return target values and target errnos. */
992f48a0 962static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 963 abi_ulong optval_addr, abi_ulong optlen)
7854b056 964{
992f48a0 965 abi_long ret;
b55266b5
BS
966 int len, val;
967 socklen_t lv;
8853f86e
FB
968
969 switch(level) {
3532fa74
FB
970 case TARGET_SOL_SOCKET:
971 level = SOL_SOCKET;
8853f86e 972 switch (optname) {
3532fa74
FB
973 case TARGET_SO_LINGER:
974 case TARGET_SO_RCVTIMEO:
975 case TARGET_SO_SNDTIMEO:
976 case TARGET_SO_PEERCRED:
977 case TARGET_SO_PEERNAME:
8853f86e
FB
978 /* These don't just return a single integer */
979 goto unimplemented;
980 default:
2efbe911
FB
981 goto int_case;
982 }
983 break;
984 case SOL_TCP:
985 /* TCP options all take an 'int' value. */
986 int_case:
2f619698
FB
987 if (get_user_u32(len, optlen))
988 return -TARGET_EFAULT;
2efbe911 989 if (len < 0)
0da46a6e 990 return -TARGET_EINVAL;
2efbe911
FB
991 lv = sizeof(int);
992 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
993 if (ret < 0)
994 return ret;
995 val = tswap32(val);
996 if (len > lv)
997 len = lv;
2f619698
FB
998 if (len == 4) {
999 if (put_user_u32(val, optval_addr))
1000 return -TARGET_EFAULT;
1001 } else {
1002 if (put_user_u8(val, optval_addr))
1003 return -TARGET_EFAULT;
1004 }
1005 if (put_user_u32(len, optlen))
1006 return -TARGET_EFAULT;
2efbe911
FB
1007 break;
1008 case SOL_IP:
1009 switch(optname) {
1010 case IP_TOS:
1011 case IP_TTL:
1012 case IP_HDRINCL:
1013 case IP_ROUTER_ALERT:
1014 case IP_RECVOPTS:
1015 case IP_RETOPTS:
1016 case IP_PKTINFO:
1017 case IP_MTU_DISCOVER:
1018 case IP_RECVERR:
1019 case IP_RECVTOS:
1020#ifdef IP_FREEBIND
1021 case IP_FREEBIND:
1022#endif
1023 case IP_MULTICAST_TTL:
1024 case IP_MULTICAST_LOOP:
2f619698
FB
1025 if (get_user_u32(len, optlen))
1026 return -TARGET_EFAULT;
8853f86e 1027 if (len < 0)
0da46a6e 1028 return -TARGET_EINVAL;
8853f86e
FB
1029 lv = sizeof(int);
1030 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1031 if (ret < 0)
1032 return ret;
2efbe911 1033 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1034 len = 1;
2f619698
FB
1035 if (put_user_u32(len, optlen)
1036 || put_user_u8(val, optval_addr))
1037 return -TARGET_EFAULT;
2efbe911 1038 } else {
2efbe911
FB
1039 if (len > sizeof(int))
1040 len = sizeof(int);
2f619698
FB
1041 if (put_user_u32(len, optlen)
1042 || put_user_u32(val, optval_addr))
1043 return -TARGET_EFAULT;
2efbe911 1044 }
8853f86e 1045 break;
2efbe911 1046 default:
c02f499e
TS
1047 ret = -TARGET_ENOPROTOOPT;
1048 break;
8853f86e
FB
1049 }
1050 break;
1051 default:
1052 unimplemented:
1053 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1054 level, optname);
c02f499e 1055 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1056 break;
1057 }
1058 return ret;
7854b056
FB
1059}
1060
579a97f7
FB
1061/* FIXME
1062 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1063 * other lock functions have a return code of 0 for failure.
1064 */
1065static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1066 int count, int copy)
53a5960a
PB
1067{
1068 struct target_iovec *target_vec;
992f48a0 1069 abi_ulong base;
d732dcb4 1070 int i;
53a5960a 1071
579a97f7
FB
1072 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1073 if (!target_vec)
1074 return -TARGET_EFAULT;
53a5960a
PB
1075 for(i = 0;i < count; i++) {
1076 base = tswapl(target_vec[i].iov_base);
1077 vec[i].iov_len = tswapl(target_vec[i].iov_len);
41df8411
FB
1078 if (vec[i].iov_len != 0) {
1079 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
d732dcb4
AZ
1080 /* Don't check lock_user return value. We must call writev even
1081 if a element has invalid base address. */
41df8411
FB
1082 } else {
1083 /* zero length pointer is ignored */
1084 vec[i].iov_base = NULL;
1085 }
579a97f7
FB
1086 }
1087 unlock_user (target_vec, target_addr, 0);
1088 return 0;
53a5960a
PB
1089}
1090
579a97f7
FB
1091static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1092 int count, int copy)
53a5960a
PB
1093{
1094 struct target_iovec *target_vec;
992f48a0 1095 abi_ulong base;
53a5960a
PB
1096 int i;
1097
579a97f7
FB
1098 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1099 if (!target_vec)
1100 return -TARGET_EFAULT;
53a5960a 1101 for(i = 0;i < count; i++) {
d732dcb4
AZ
1102 if (target_vec[i].iov_base) {
1103 base = tswapl(target_vec[i].iov_base);
1104 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1105 }
53a5960a
PB
1106 }
1107 unlock_user (target_vec, target_addr, 0);
579a97f7
FB
1108
1109 return 0;
53a5960a
PB
1110}
1111
0da46a6e 1112/* do_socket() Must return target values and target errnos. */
992f48a0 1113static abi_long do_socket(int domain, int type, int protocol)
3532fa74
FB
1114{
1115#if defined(TARGET_MIPS)
1116 switch(type) {
1117 case TARGET_SOCK_DGRAM:
1118 type = SOCK_DGRAM;
1119 break;
1120 case TARGET_SOCK_STREAM:
1121 type = SOCK_STREAM;
1122 break;
1123 case TARGET_SOCK_RAW:
1124 type = SOCK_RAW;
1125 break;
1126 case TARGET_SOCK_RDM:
1127 type = SOCK_RDM;
1128 break;
1129 case TARGET_SOCK_SEQPACKET:
1130 type = SOCK_SEQPACKET;
1131 break;
1132 case TARGET_SOCK_PACKET:
1133 type = SOCK_PACKET;
1134 break;
1135 }
1136#endif
12bc92ab
AZ
1137 if (domain == PF_NETLINK)
1138 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
3532fa74
FB
1139 return get_errno(socket(domain, type, protocol));
1140}
1141
0da46a6e 1142/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1143static abi_long do_bind(int sockfd, abi_ulong target_addr,
1144 socklen_t addrlen)
3532fa74
FB
1145{
1146 void *addr = alloca(addrlen);
3b46e624 1147
3532fa74
FB
1148 target_to_host_sockaddr(addr, target_addr, addrlen);
1149 return get_errno(bind(sockfd, addr, addrlen));
1150}
1151
0da46a6e 1152/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1153static abi_long do_connect(int sockfd, abi_ulong target_addr,
1154 socklen_t addrlen)
3532fa74
FB
1155{
1156 void *addr = alloca(addrlen);
3b46e624 1157
3532fa74
FB
1158 target_to_host_sockaddr(addr, target_addr, addrlen);
1159 return get_errno(connect(sockfd, addr, addrlen));
1160}
1161
0da46a6e 1162/* do_sendrecvmsg() Must return target values and target errnos. */
992f48a0
BS
1163static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1164 int flags, int send)
3532fa74 1165{
6de645c7 1166 abi_long ret, len;
3532fa74
FB
1167 struct target_msghdr *msgp;
1168 struct msghdr msg;
1169 int count;
1170 struct iovec *vec;
992f48a0 1171 abi_ulong target_vec;
3532fa74 1172
579a97f7
FB
1173 /* FIXME */
1174 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1175 msgp,
1176 target_msg,
1177 send ? 1 : 0))
1178 return -TARGET_EFAULT;
3532fa74
FB
1179 if (msgp->msg_name) {
1180 msg.msg_namelen = tswap32(msgp->msg_namelen);
1181 msg.msg_name = alloca(msg.msg_namelen);
1182 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1183 msg.msg_namelen);
1184 } else {
1185 msg.msg_name = NULL;
1186 msg.msg_namelen = 0;
1187 }
1188 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1189 msg.msg_control = alloca(msg.msg_controllen);
1190 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 1191
3532fa74
FB
1192 count = tswapl(msgp->msg_iovlen);
1193 vec = alloca(count * sizeof(struct iovec));
1194 target_vec = tswapl(msgp->msg_iov);
579a97f7 1195 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
3532fa74
FB
1196 msg.msg_iovlen = count;
1197 msg.msg_iov = vec;
3b46e624 1198
3532fa74 1199 if (send) {
5a4a898d
FB
1200 ret = target_to_host_cmsg(&msg, msgp);
1201 if (ret == 0)
1202 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
1203 } else {
1204 ret = get_errno(recvmsg(fd, &msg, flags));
6de645c7
AZ
1205 if (!is_error(ret)) {
1206 len = ret;
5a4a898d 1207 ret = host_to_target_cmsg(msgp, &msg);
6de645c7
AZ
1208 if (!is_error(ret))
1209 ret = len;
1210 }
3532fa74
FB
1211 }
1212 unlock_iovec(vec, target_vec, count, !send);
579a97f7 1213 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
1214 return ret;
1215}
1216
0da46a6e 1217/* do_accept() Must return target values and target errnos. */
992f48a0 1218static abi_long do_accept(int fd, abi_ulong target_addr,
2f619698 1219 abi_ulong target_addrlen_addr)
1be9e1dc 1220{
2f619698
FB
1221 socklen_t addrlen;
1222 void *addr;
992f48a0 1223 abi_long ret;
1be9e1dc 1224
2f619698
FB
1225 if (get_user_u32(addrlen, target_addrlen_addr))
1226 return -TARGET_EFAULT;
1227
1228 addr = alloca(addrlen);
1229
1be9e1dc
PB
1230 ret = get_errno(accept(fd, addr, &addrlen));
1231 if (!is_error(ret)) {
1232 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1233 if (put_user_u32(addrlen, target_addrlen_addr))
1234 ret = -TARGET_EFAULT;
1be9e1dc
PB
1235 }
1236 return ret;
1237}
1238
0da46a6e 1239/* do_getpeername() Must return target values and target errnos. */
992f48a0 1240static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 1241 abi_ulong target_addrlen_addr)
1be9e1dc 1242{
2f619698
FB
1243 socklen_t addrlen;
1244 void *addr;
992f48a0 1245 abi_long ret;
1be9e1dc 1246
2f619698
FB
1247 if (get_user_u32(addrlen, target_addrlen_addr))
1248 return -TARGET_EFAULT;
1249
1250 addr = alloca(addrlen);
1251
1be9e1dc
PB
1252 ret = get_errno(getpeername(fd, addr, &addrlen));
1253 if (!is_error(ret)) {
1254 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1255 if (put_user_u32(addrlen, target_addrlen_addr))
1256 ret = -TARGET_EFAULT;
1be9e1dc
PB
1257 }
1258 return ret;
1259}
1260
0da46a6e 1261/* do_getsockname() Must return target values and target errnos. */
992f48a0 1262static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 1263 abi_ulong target_addrlen_addr)
1be9e1dc 1264{
2f619698
FB
1265 socklen_t addrlen;
1266 void *addr;
992f48a0 1267 abi_long ret;
1be9e1dc 1268
2f619698
FB
1269 if (get_user_u32(addrlen, target_addrlen_addr))
1270 return -TARGET_EFAULT;
1271
1272 addr = alloca(addrlen);
1273
1be9e1dc
PB
1274 ret = get_errno(getsockname(fd, addr, &addrlen));
1275 if (!is_error(ret)) {
1276 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1277 if (put_user_u32(addrlen, target_addrlen_addr))
1278 ret = -TARGET_EFAULT;
1be9e1dc
PB
1279 }
1280 return ret;
1281}
1282
0da46a6e 1283/* do_socketpair() Must return target values and target errnos. */
992f48a0 1284static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 1285 abi_ulong target_tab_addr)
1be9e1dc
PB
1286{
1287 int tab[2];
992f48a0 1288 abi_long ret;
1be9e1dc
PB
1289
1290 ret = get_errno(socketpair(domain, type, protocol, tab));
1291 if (!is_error(ret)) {
2f619698
FB
1292 if (put_user_s32(tab[0], target_tab_addr)
1293 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1294 ret = -TARGET_EFAULT;
1be9e1dc
PB
1295 }
1296 return ret;
1297}
1298
0da46a6e 1299/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
1300static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1301 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
1302{
1303 void *addr;
1304 void *host_msg;
992f48a0 1305 abi_long ret;
1be9e1dc 1306
579a97f7
FB
1307 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1308 if (!host_msg)
1309 return -TARGET_EFAULT;
1be9e1dc
PB
1310 if (target_addr) {
1311 addr = alloca(addrlen);
1312 target_to_host_sockaddr(addr, target_addr, addrlen);
1313 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1314 } else {
1315 ret = get_errno(send(fd, host_msg, len, flags));
1316 }
1317 unlock_user(host_msg, msg, 0);
1318 return ret;
1319}
1320
0da46a6e 1321/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
1322static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1323 abi_ulong target_addr,
1324 abi_ulong target_addrlen)
1be9e1dc
PB
1325{
1326 socklen_t addrlen;
1327 void *addr;
1328 void *host_msg;
992f48a0 1329 abi_long ret;
1be9e1dc 1330
579a97f7
FB
1331 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1332 if (!host_msg)
1333 return -TARGET_EFAULT;
1be9e1dc 1334 if (target_addr) {
2f619698
FB
1335 if (get_user_u32(addrlen, target_addrlen)) {
1336 ret = -TARGET_EFAULT;
1337 goto fail;
1338 }
1be9e1dc
PB
1339 addr = alloca(addrlen);
1340 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1341 } else {
1342 addr = NULL; /* To keep compiler quiet. */
1343 ret = get_errno(recv(fd, host_msg, len, flags));
1344 }
1345 if (!is_error(ret)) {
1346 if (target_addr) {
1347 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
1348 if (put_user_u32(addrlen, target_addrlen)) {
1349 ret = -TARGET_EFAULT;
1350 goto fail;
1351 }
1be9e1dc
PB
1352 }
1353 unlock_user(host_msg, msg, len);
1354 } else {
2f619698 1355fail:
1be9e1dc
PB
1356 unlock_user(host_msg, msg, 0);
1357 }
1358 return ret;
1359}
1360
32407103 1361#ifdef TARGET_NR_socketcall
0da46a6e 1362/* do_socketcall() Must return target values and target errnos. */
992f48a0 1363static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 1364{
992f48a0
BS
1365 abi_long ret;
1366 const int n = sizeof(abi_ulong);
31e31b8a
FB
1367
1368 switch(num) {
1369 case SOCKOP_socket:
7854b056 1370 {
2f619698
FB
1371 int domain, type, protocol;
1372
1373 if (get_user_s32(domain, vptr)
1374 || get_user_s32(type, vptr + n)
1375 || get_user_s32(protocol, vptr + 2 * n))
1376 return -TARGET_EFAULT;
1377
3532fa74 1378 ret = do_socket(domain, type, protocol);
7854b056 1379 }
31e31b8a
FB
1380 break;
1381 case SOCKOP_bind:
7854b056 1382 {
2f619698
FB
1383 int sockfd;
1384 abi_ulong target_addr;
1385 socklen_t addrlen;
1386
1387 if (get_user_s32(sockfd, vptr)
1388 || get_user_ual(target_addr, vptr + n)
1389 || get_user_u32(addrlen, vptr + 2 * n))
1390 return -TARGET_EFAULT;
1391
3532fa74 1392 ret = do_bind(sockfd, target_addr, addrlen);
7854b056 1393 }
31e31b8a
FB
1394 break;
1395 case SOCKOP_connect:
7854b056 1396 {
2f619698
FB
1397 int sockfd;
1398 abi_ulong target_addr;
1399 socklen_t addrlen;
1400
1401 if (get_user_s32(sockfd, vptr)
1402 || get_user_ual(target_addr, vptr + n)
1403 || get_user_u32(addrlen, vptr + 2 * n))
1404 return -TARGET_EFAULT;
1405
3532fa74 1406 ret = do_connect(sockfd, target_addr, addrlen);
7854b056 1407 }
31e31b8a
FB
1408 break;
1409 case SOCKOP_listen:
7854b056 1410 {
2f619698
FB
1411 int sockfd, backlog;
1412
1413 if (get_user_s32(sockfd, vptr)
1414 || get_user_s32(backlog, vptr + n))
1415 return -TARGET_EFAULT;
1416
7854b056
FB
1417 ret = get_errno(listen(sockfd, backlog));
1418 }
31e31b8a
FB
1419 break;
1420 case SOCKOP_accept:
1421 {
2f619698
FB
1422 int sockfd;
1423 abi_ulong target_addr, target_addrlen;
1424
1425 if (get_user_s32(sockfd, vptr)
1426 || get_user_ual(target_addr, vptr + n)
1427 || get_user_u32(target_addrlen, vptr + 2 * n))
1428 return -TARGET_EFAULT;
1429
1be9e1dc 1430 ret = do_accept(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1431 }
1432 break;
1433 case SOCKOP_getsockname:
1434 {
2f619698
FB
1435 int sockfd;
1436 abi_ulong target_addr, target_addrlen;
1437
1438 if (get_user_s32(sockfd, vptr)
1439 || get_user_ual(target_addr, vptr + n)
1440 || get_user_u32(target_addrlen, vptr + 2 * n))
1441 return -TARGET_EFAULT;
1442
1be9e1dc 1443 ret = do_getsockname(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1444 }
1445 break;
1446 case SOCKOP_getpeername:
1447 {
2f619698
FB
1448 int sockfd;
1449 abi_ulong target_addr, target_addrlen;
1450
1451 if (get_user_s32(sockfd, vptr)
1452 || get_user_ual(target_addr, vptr + n)
1453 || get_user_u32(target_addrlen, vptr + 2 * n))
1454 return -TARGET_EFAULT;
1455
1be9e1dc 1456 ret = do_getpeername(sockfd, target_addr, target_addrlen);
31e31b8a
FB
1457 }
1458 break;
1459 case SOCKOP_socketpair:
1460 {
2f619698
FB
1461 int domain, type, protocol;
1462 abi_ulong tab;
1463
1464 if (get_user_s32(domain, vptr)
1465 || get_user_s32(type, vptr + n)
1466 || get_user_s32(protocol, vptr + 2 * n)
1467 || get_user_ual(tab, vptr + 3 * n))
1468 return -TARGET_EFAULT;
1469
1be9e1dc 1470 ret = do_socketpair(domain, type, protocol, tab);
31e31b8a
FB
1471 }
1472 break;
1473 case SOCKOP_send:
7854b056 1474 {
2f619698
FB
1475 int sockfd;
1476 abi_ulong msg;
1477 size_t len;
1478 int flags;
1479
1480 if (get_user_s32(sockfd, vptr)
1481 || get_user_ual(msg, vptr + n)
1482 || get_user_ual(len, vptr + 2 * n)
1483 || get_user_s32(flags, vptr + 3 * n))
1484 return -TARGET_EFAULT;
1485
1be9e1dc 1486 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
7854b056 1487 }
31e31b8a
FB
1488 break;
1489 case SOCKOP_recv:
7854b056 1490 {
2f619698
FB
1491 int sockfd;
1492 abi_ulong msg;
1493 size_t len;
1494 int flags;
1495
1496 if (get_user_s32(sockfd, vptr)
1497 || get_user_ual(msg, vptr + n)
1498 || get_user_ual(len, vptr + 2 * n)
1499 || get_user_s32(flags, vptr + 3 * n))
1500 return -TARGET_EFAULT;
1501
1be9e1dc 1502 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
7854b056 1503 }
31e31b8a
FB
1504 break;
1505 case SOCKOP_sendto:
7854b056 1506 {
2f619698
FB
1507 int sockfd;
1508 abi_ulong msg;
1509 size_t len;
1510 int flags;
1511 abi_ulong addr;
1512 socklen_t addrlen;
1513
1514 if (get_user_s32(sockfd, vptr)
1515 || get_user_ual(msg, vptr + n)
1516 || get_user_ual(len, vptr + 2 * n)
1517 || get_user_s32(flags, vptr + 3 * n)
1518 || get_user_ual(addr, vptr + 4 * n)
1519 || get_user_u32(addrlen, vptr + 5 * n))
1520 return -TARGET_EFAULT;
1521
1be9e1dc 1522 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
7854b056 1523 }
31e31b8a
FB
1524 break;
1525 case SOCKOP_recvfrom:
1526 {
2f619698
FB
1527 int sockfd;
1528 abi_ulong msg;
1529 size_t len;
1530 int flags;
1531 abi_ulong addr;
1532 socklen_t addrlen;
1533
1534 if (get_user_s32(sockfd, vptr)
1535 || get_user_ual(msg, vptr + n)
1536 || get_user_ual(len, vptr + 2 * n)
1537 || get_user_s32(flags, vptr + 3 * n)
1538 || get_user_ual(addr, vptr + 4 * n)
1539 || get_user_u32(addrlen, vptr + 5 * n))
1540 return -TARGET_EFAULT;
1541
1be9e1dc 1542 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
31e31b8a
FB
1543 }
1544 break;
1545 case SOCKOP_shutdown:
7854b056 1546 {
2f619698
FB
1547 int sockfd, how;
1548
1549 if (get_user_s32(sockfd, vptr)
1550 || get_user_s32(how, vptr + n))
1551 return -TARGET_EFAULT;
7854b056
FB
1552
1553 ret = get_errno(shutdown(sockfd, how));
1554 }
31e31b8a
FB
1555 break;
1556 case SOCKOP_sendmsg:
1557 case SOCKOP_recvmsg:
1a9353d2
FB
1558 {
1559 int fd;
992f48a0 1560 abi_ulong target_msg;
3532fa74 1561 int flags;
1a9353d2 1562
2f619698
FB
1563 if (get_user_s32(fd, vptr)
1564 || get_user_ual(target_msg, vptr + n)
1565 || get_user_s32(flags, vptr + 2 * n))
1566 return -TARGET_EFAULT;
3532fa74 1567
5fafdf24 1568 ret = do_sendrecvmsg(fd, target_msg, flags,
3532fa74 1569 (num == SOCKOP_sendmsg));
1a9353d2
FB
1570 }
1571 break;
31e31b8a 1572 case SOCKOP_setsockopt:
7854b056 1573 {
2f619698
FB
1574 int sockfd;
1575 int level;
1576 int optname;
1577 abi_ulong optval;
1578 socklen_t optlen;
1579
1580 if (get_user_s32(sockfd, vptr)
1581 || get_user_s32(level, vptr + n)
1582 || get_user_s32(optname, vptr + 2 * n)
1583 || get_user_ual(optval, vptr + 3 * n)
1584 || get_user_u32(optlen, vptr + 4 * n))
1585 return -TARGET_EFAULT;
7854b056
FB
1586
1587 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1588 }
1589 break;
31e31b8a 1590 case SOCKOP_getsockopt:
7854b056 1591 {
2f619698
FB
1592 int sockfd;
1593 int level;
1594 int optname;
1595 abi_ulong optval;
1596 socklen_t optlen;
1597
1598 if (get_user_s32(sockfd, vptr)
1599 || get_user_s32(level, vptr + n)
1600 || get_user_s32(optname, vptr + 2 * n)
1601 || get_user_ual(optval, vptr + 3 * n)
1602 || get_user_u32(optlen, vptr + 4 * n))
1603 return -TARGET_EFAULT;
7854b056 1604
2f619698 1605 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
7854b056
FB
1606 }
1607 break;
31e31b8a
FB
1608 default:
1609 gemu_log("Unsupported socketcall: %d\n", num);
0da46a6e 1610 ret = -TARGET_ENOSYS;
31e31b8a
FB
1611 break;
1612 }
1613 return ret;
1614}
32407103 1615#endif
31e31b8a 1616
8853f86e
FB
1617#define N_SHM_REGIONS 32
1618
1619static struct shm_region {
5a4a898d
FB
1620 abi_ulong start;
1621 abi_ulong size;
8853f86e
FB
1622} shm_regions[N_SHM_REGIONS];
1623
3eb6b044
TS
1624struct target_ipc_perm
1625{
992f48a0
BS
1626 abi_long __key;
1627 abi_ulong uid;
1628 abi_ulong gid;
1629 abi_ulong cuid;
1630 abi_ulong cgid;
3eb6b044
TS
1631 unsigned short int mode;
1632 unsigned short int __pad1;
1633 unsigned short int __seq;
1634 unsigned short int __pad2;
992f48a0
BS
1635 abi_ulong __unused1;
1636 abi_ulong __unused2;
3eb6b044
TS
1637};
1638
1639struct target_semid_ds
1640{
1641 struct target_ipc_perm sem_perm;
992f48a0
BS
1642 abi_ulong sem_otime;
1643 abi_ulong __unused1;
1644 abi_ulong sem_ctime;
1645 abi_ulong __unused2;
1646 abi_ulong sem_nsems;
1647 abi_ulong __unused3;
1648 abi_ulong __unused4;
3eb6b044
TS
1649};
1650
579a97f7
FB
1651static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1652 abi_ulong target_addr)
3eb6b044
TS
1653{
1654 struct target_ipc_perm *target_ip;
1655 struct target_semid_ds *target_sd;
1656
579a97f7
FB
1657 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1658 return -TARGET_EFAULT;
3eb6b044
TS
1659 target_ip=&(target_sd->sem_perm);
1660 host_ip->__key = tswapl(target_ip->__key);
1661 host_ip->uid = tswapl(target_ip->uid);
1662 host_ip->gid = tswapl(target_ip->gid);
1663 host_ip->cuid = tswapl(target_ip->cuid);
1664 host_ip->cgid = tswapl(target_ip->cgid);
1665 host_ip->mode = tswapl(target_ip->mode);
1666 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 1667 return 0;
3eb6b044
TS
1668}
1669
579a97f7
FB
1670static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1671 struct ipc_perm *host_ip)
3eb6b044
TS
1672{
1673 struct target_ipc_perm *target_ip;
1674 struct target_semid_ds *target_sd;
1675
579a97f7
FB
1676 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1677 return -TARGET_EFAULT;
3eb6b044
TS
1678 target_ip = &(target_sd->sem_perm);
1679 target_ip->__key = tswapl(host_ip->__key);
1680 target_ip->uid = tswapl(host_ip->uid);
1681 target_ip->gid = tswapl(host_ip->gid);
1682 target_ip->cuid = tswapl(host_ip->cuid);
1683 target_ip->cgid = tswapl(host_ip->cgid);
1684 target_ip->mode = tswapl(host_ip->mode);
1685 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 1686 return 0;
3eb6b044
TS
1687}
1688
579a97f7
FB
1689static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1690 abi_ulong target_addr)
3eb6b044
TS
1691{
1692 struct target_semid_ds *target_sd;
1693
579a97f7
FB
1694 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1695 return -TARGET_EFAULT;
3eb6b044
TS
1696 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1697 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1698 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1699 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1700 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 1701 return 0;
3eb6b044
TS
1702}
1703
579a97f7
FB
1704static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1705 struct semid_ds *host_sd)
3eb6b044
TS
1706{
1707 struct target_semid_ds *target_sd;
1708
579a97f7
FB
1709 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1710 return -TARGET_EFAULT;
3eb6b044
TS
1711 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1712 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1713 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1714 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1715 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 1716 return 0;
3eb6b044
TS
1717}
1718
fa294816
TS
1719union semun {
1720 int val;
3eb6b044 1721 struct semid_ds *buf;
fa294816
TS
1722 unsigned short *array;
1723};
1724
3eb6b044
TS
1725union target_semun {
1726 int val;
992f48a0 1727 abi_long buf;
3eb6b044
TS
1728 unsigned short int *array;
1729};
1730
579a97f7
FB
1731static inline abi_long target_to_host_semun(int cmd,
1732 union semun *host_su,
1733 abi_ulong target_addr,
1734 struct semid_ds *ds)
3eb6b044
TS
1735{
1736 union target_semun *target_su;
1737
1738 switch( cmd ) {
1739 case IPC_STAT:
1740 case IPC_SET:
579a97f7
FB
1741 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1742 return -TARGET_EFAULT;
3eb6b044
TS
1743 target_to_host_semid_ds(ds,target_su->buf);
1744 host_su->buf = ds;
1745 unlock_user_struct(target_su, target_addr, 0);
1746 break;
1747 case GETVAL:
1748 case SETVAL:
579a97f7
FB
1749 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1750 return -TARGET_EFAULT;
3eb6b044
TS
1751 host_su->val = tswapl(target_su->val);
1752 unlock_user_struct(target_su, target_addr, 0);
1753 break;
1754 case GETALL:
1755 case SETALL:
579a97f7
FB
1756 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1757 return -TARGET_EFAULT;
3eb6b044
TS
1758 *host_su->array = tswap16(*target_su->array);
1759 unlock_user_struct(target_su, target_addr, 0);
1760 break;
1761 default:
1762 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1763 }
579a97f7 1764 return 0;
3eb6b044
TS
1765}
1766
579a97f7
FB
1767static inline abi_long host_to_target_semun(int cmd,
1768 abi_ulong target_addr,
1769 union semun *host_su,
1770 struct semid_ds *ds)
3eb6b044
TS
1771{
1772 union target_semun *target_su;
1773
1774 switch( cmd ) {
1775 case IPC_STAT:
1776 case IPC_SET:
579a97f7
FB
1777 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1778 return -TARGET_EFAULT;
3eb6b044
TS
1779 host_to_target_semid_ds(target_su->buf,ds);
1780 unlock_user_struct(target_su, target_addr, 1);
1781 break;
1782 case GETVAL:
1783 case SETVAL:
579a97f7
FB
1784 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1785 return -TARGET_EFAULT;
3eb6b044
TS
1786 target_su->val = tswapl(host_su->val);
1787 unlock_user_struct(target_su, target_addr, 1);
1788 break;
1789 case GETALL:
1790 case SETALL:
579a97f7
FB
1791 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1792 return -TARGET_EFAULT;
3eb6b044
TS
1793 *target_su->array = tswap16(*host_su->array);
1794 unlock_user_struct(target_su, target_addr, 1);
1795 break;
1796 default:
1797 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1798 }
579a97f7 1799 return 0;
3eb6b044
TS
1800}
1801
992f48a0
BS
1802static inline abi_long do_semctl(int first, int second, int third,
1803 abi_long ptr)
3eb6b044
TS
1804{
1805 union semun arg;
1806 struct semid_ds dsarg;
1807 int cmd = third&0xff;
992f48a0 1808 abi_long ret = 0;
3eb6b044
TS
1809
1810 switch( cmd ) {
1811 case GETVAL:
1812 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1813 ret = get_errno(semctl(first, second, cmd, arg));
1814 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1815 break;
1816 case SETVAL:
1817 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1818 ret = get_errno(semctl(first, second, cmd, arg));
1819 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1820 break;
1821 case GETALL:
1822 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1823 ret = get_errno(semctl(first, second, cmd, arg));
1824 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1825 break;
1826 case SETALL:
1827 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1828 ret = get_errno(semctl(first, second, cmd, arg));
1829 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1830 break;
1831 case IPC_STAT:
1832 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1833 ret = get_errno(semctl(first, second, cmd, arg));
1834 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1835 break;
1836 case IPC_SET:
1837 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1838 ret = get_errno(semctl(first, second, cmd, arg));
1839 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1840 break;
1841 default:
1842 ret = get_errno(semctl(first, second, cmd, arg));
1843 }
1844
1845 return ret;
1846}
1847
1bc012f6
TS
1848struct target_msqid_ds
1849{
1c54ff97
AJ
1850 struct target_ipc_perm msg_perm;
1851 abi_ulong msg_stime;
1852#if TARGET_ABI_BITS == 32
1853 abi_ulong __unused1;
1854#endif
1855 abi_ulong msg_rtime;
1856#if TARGET_ABI_BITS == 32
1857 abi_ulong __unused2;
1858#endif
1859 abi_ulong msg_ctime;
1860#if TARGET_ABI_BITS == 32
1861 abi_ulong __unused3;
1862#endif
1863 abi_ulong __msg_cbytes;
1864 abi_ulong msg_qnum;
1865 abi_ulong msg_qbytes;
1866 abi_ulong msg_lspid;
1867 abi_ulong msg_lrpid;
1868 abi_ulong __unused4;
1869 abi_ulong __unused5;
1bc012f6
TS
1870};
1871
579a97f7
FB
1872static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1873 abi_ulong target_addr)
1bc012f6
TS
1874{
1875 struct target_msqid_ds *target_md;
1876
579a97f7
FB
1877 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1878 return -TARGET_EFAULT;
1c54ff97
AJ
1879 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
1880 return -TARGET_EFAULT;
1bc012f6
TS
1881 host_md->msg_stime = tswapl(target_md->msg_stime);
1882 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1883 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1884 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1885 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1886 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1887 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1888 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1889 unlock_user_struct(target_md, target_addr, 0);
579a97f7 1890 return 0;
1bc012f6
TS
1891}
1892
579a97f7
FB
1893static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1894 struct msqid_ds *host_md)
1bc012f6
TS
1895{
1896 struct target_msqid_ds *target_md;
1897
579a97f7
FB
1898 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1899 return -TARGET_EFAULT;
1c54ff97
AJ
1900 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
1901 return -TARGET_EFAULT;
1bc012f6
TS
1902 target_md->msg_stime = tswapl(host_md->msg_stime);
1903 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1904 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1905 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1906 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1907 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1908 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1909 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1910 unlock_user_struct(target_md, target_addr, 1);
579a97f7 1911 return 0;
1bc012f6
TS
1912}
1913
1c54ff97
AJ
1914struct target_msginfo {
1915 int msgpool;
1916 int msgmap;
1917 int msgmax;
1918 int msgmnb;
1919 int msgmni;
1920 int msgssz;
1921 int msgtql;
1922 unsigned short int msgseg;
1923};
1924
1925static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
1926 struct msginfo *host_msginfo)
1927{
1928 struct target_msginfo *target_msginfo;
1929 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
1930 return -TARGET_EFAULT;
1931 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
1932 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
1933 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
1934 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
1935 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
1936 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
1937 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
1938 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
1939 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 1940 return 0;
1c54ff97
AJ
1941}
1942
1943static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
1944{
1945 struct msqid_ds dsarg;
1c54ff97
AJ
1946 struct msginfo msginfo;
1947 abi_long ret = -TARGET_EINVAL;
1948
1949 cmd &= 0xff;
1950
1951 switch (cmd) {
1bc012f6
TS
1952 case IPC_STAT:
1953 case IPC_SET:
1c54ff97
AJ
1954 case MSG_STAT:
1955 if (target_to_host_msqid_ds(&dsarg,ptr))
1956 return -TARGET_EFAULT;
1957 ret = get_errno(msgctl(msgid, cmd, &dsarg));
1958 if (host_to_target_msqid_ds(ptr,&dsarg))
1959 return -TARGET_EFAULT;
1960 break;
1961 case IPC_RMID:
1962 ret = get_errno(msgctl(msgid, cmd, NULL));
1963 break;
1964 case IPC_INFO:
1965 case MSG_INFO:
1966 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
1967 if (host_to_target_msginfo(ptr, &msginfo))
1968 return -TARGET_EFAULT;
1969 break;
1bc012f6 1970 }
1c54ff97 1971
1bc012f6
TS
1972 return ret;
1973}
1974
1975struct target_msgbuf {
1c54ff97
AJ
1976 abi_long mtype;
1977 char mtext[1];
1bc012f6
TS
1978};
1979
992f48a0
BS
1980static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1981 unsigned int msgsz, int msgflg)
1bc012f6
TS
1982{
1983 struct target_msgbuf *target_mb;
1984 struct msgbuf *host_mb;
992f48a0 1985 abi_long ret = 0;
1bc012f6 1986
579a97f7
FB
1987 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1988 return -TARGET_EFAULT;
1bc012f6 1989 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
1990 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
1991 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6
TS
1992 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1993 free(host_mb);
1994 unlock_user_struct(target_mb, msgp, 0);
1995
1996 return ret;
1997}
1998
992f48a0 1999static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 2000 unsigned int msgsz, abi_long msgtyp,
992f48a0 2001 int msgflg)
1bc012f6
TS
2002{
2003 struct target_msgbuf *target_mb;
579a97f7 2004 char *target_mtext;
1bc012f6 2005 struct msgbuf *host_mb;
992f48a0 2006 abi_long ret = 0;
1bc012f6 2007
579a97f7
FB
2008 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2009 return -TARGET_EFAULT;
1c54ff97 2010
1bc012f6 2011 host_mb = malloc(msgsz+sizeof(long));
1c54ff97
AJ
2012 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2013
579a97f7
FB
2014 if (ret > 0) {
2015 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2016 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2017 if (!target_mtext) {
2018 ret = -TARGET_EFAULT;
2019 goto end;
2020 }
1c54ff97 2021 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
2022 unlock_user(target_mtext, target_mtext_addr, ret);
2023 }
1c54ff97 2024
1bc012f6
TS
2025 target_mb->mtype = tswapl(host_mb->mtype);
2026 free(host_mb);
1bc012f6 2027
579a97f7
FB
2028end:
2029 if (target_mb)
2030 unlock_user_struct(target_mb, msgp, 1);
1bc012f6
TS
2031 return ret;
2032}
2033
1c54ff97 2034#ifdef TARGET_NR_ipc
53a5960a 2035/* ??? This only works with linear mappings. */
0da46a6e 2036/* do_ipc() must return target values and target errnos. */
992f48a0
BS
2037static abi_long do_ipc(unsigned int call, int first,
2038 int second, int third,
2039 abi_long ptr, abi_long fifth)
8853f86e
FB
2040{
2041 int version;
992f48a0 2042 abi_long ret = 0;
8853f86e
FB
2043 struct shmid_ds shm_info;
2044 int i;
2045
2046 version = call >> 16;
2047 call &= 0xffff;
2048
2049 switch (call) {
fa294816 2050 case IPCOP_semop:
579a97f7 2051 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
fa294816
TS
2052 break;
2053
2054 case IPCOP_semget:
2055 ret = get_errno(semget(first, second, third));
2056 break;
2057
2058 case IPCOP_semctl:
3eb6b044 2059 ret = do_semctl(first, second, third, ptr);
fa294816
TS
2060 break;
2061
2062 case IPCOP_semtimedop:
32407103 2063 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 2064 ret = -TARGET_ENOSYS;
fa294816 2065 break;
d96372ef 2066
1c54ff97
AJ
2067 case IPCOP_msgget:
2068 ret = get_errno(msgget(first, second));
2069 break;
d96372ef 2070
1c54ff97
AJ
2071 case IPCOP_msgsnd:
2072 ret = do_msgsnd(first, ptr, second, third);
2073 break;
d96372ef 2074
1c54ff97
AJ
2075 case IPCOP_msgctl:
2076 ret = do_msgctl(first, second, ptr);
2077 break;
d96372ef 2078
1c54ff97
AJ
2079 case IPCOP_msgrcv:
2080 switch (version) {
2081 case 0:
2082 {
2083 struct target_ipc_kludge {
2084 abi_long msgp;
2085 abi_long msgtyp;
2086 } *tmp;
2087
2088 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2089 ret = -TARGET_EFAULT;
2090 break;
2091 }
d96372ef 2092
1c54ff97 2093 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
d96372ef 2094
1c54ff97
AJ
2095 unlock_user_struct(tmp, ptr, 0);
2096 break;
2097 }
2098 default:
2099 ret = do_msgrcv(first, ptr, second, fifth, third);
2100 }
2101 break;
d96372ef 2102
8853f86e 2103 case IPCOP_shmat:
5a4a898d
FB
2104 {
2105 abi_ulong raddr;
2106 void *host_addr;
2107 /* SHM_* flags are the same on all linux platforms */
2108 host_addr = shmat(first, (void *)g2h(ptr), second);
2109 if (host_addr == (void *)-1) {
2110 ret = get_errno((long)host_addr);
8853f86e 2111 break;
5a4a898d
FB
2112 }
2113 raddr = h2g((unsigned long)host_addr);
2114 /* find out the length of the shared memory segment */
2115
2116 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2117 if (is_error(ret)) {
2118 /* can't get length, bail out */
2119 shmdt(host_addr);
2120 break;
2121 }
2122 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2123 PAGE_VALID | PAGE_READ |
2124 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2125 for (i = 0; i < N_SHM_REGIONS; ++i) {
2126 if (shm_regions[i].start == 0) {
2127 shm_regions[i].start = raddr;
2128 shm_regions[i].size = shm_info.shm_segsz;
2129 break;
2130 }
2131 }
2f619698 2132 if (put_user_ual(raddr, third))
5a4a898d
FB
2133 return -TARGET_EFAULT;
2134 ret = 0;
2135 }
8853f86e
FB
2136 break;
2137 case IPCOP_shmdt:
2138 for (i = 0; i < N_SHM_REGIONS; ++i) {
2139 if (shm_regions[i].start == ptr) {
2140 shm_regions[i].start = 0;
2141 page_set_flags(ptr, shm_regions[i].size, 0);
2142 break;
2143 }
2144 }
5a4a898d 2145 ret = get_errno(shmdt((void *)g2h(ptr)));
8853f86e
FB
2146 break;
2147
2148 case IPCOP_shmget:
2149 /* IPC_* flag values are the same on all linux platforms */
2150 ret = get_errno(shmget(first, second, third));
2151 break;
2152
2153 /* IPC_* and SHM_* command values are the same on all linux platforms */
2154 case IPCOP_shmctl:
2155 switch(second) {
2156 case IPC_RMID:
2157 case SHM_LOCK:
2158 case SHM_UNLOCK:
2159 ret = get_errno(shmctl(first, second, NULL));
2160 break;
2161 default:
2162 goto unimplemented;
2163 }
2164 break;
2165 default:
2166 unimplemented:
32407103 2167 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 2168 ret = -TARGET_ENOSYS;
8853f86e
FB
2169 break;
2170 }
2171 return ret;
2172}
32407103 2173#endif
8853f86e 2174
31e31b8a
FB
2175/* kernel structure types definitions */
2176#define IFNAMSIZ 16
2177
2178#define STRUCT(name, list...) STRUCT_ ## name,
2179#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2180enum {
2181#include "syscall_types.h"
2182};
2183#undef STRUCT
2184#undef STRUCT_SPECIAL
2185
60dd316e 2186#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
31e31b8a
FB
2187#define STRUCT_SPECIAL(name)
2188#include "syscall_types.h"
2189#undef STRUCT
2190#undef STRUCT_SPECIAL
2191
2192typedef struct IOCTLEntry {
2ab83ea7
FB
2193 unsigned int target_cmd;
2194 unsigned int host_cmd;
31e31b8a
FB
2195 const char *name;
2196 int access;
1a9353d2 2197 const argtype arg_type[5];
31e31b8a
FB
2198} IOCTLEntry;
2199
2200#define IOC_R 0x0001
2201#define IOC_W 0x0002
2202#define IOC_RW (IOC_R | IOC_W)
2203
2204#define MAX_STRUCT_SIZE 4096
2205
9f106a75 2206static IOCTLEntry ioctl_entries[] = {
31e31b8a
FB
2207#define IOCTL(cmd, access, types...) \
2208 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2209#include "ioctls.h"
2210 { 0, 0, },
2211};
2212
53a5960a 2213/* ??? Implement proper locking for ioctls. */
0da46a6e 2214/* do_ioctl() Must return target values and target errnos. */
992f48a0 2215static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
2216{
2217 const IOCTLEntry *ie;
2218 const argtype *arg_type;
992f48a0 2219 abi_long ret;
31e31b8a 2220 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
2221 int target_size;
2222 void *argptr;
31e31b8a
FB
2223
2224 ie = ioctl_entries;
2225 for(;;) {
2226 if (ie->target_cmd == 0) {
32407103 2227 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 2228 return -TARGET_ENOSYS;
31e31b8a
FB
2229 }
2230 if (ie->target_cmd == cmd)
2231 break;
2232 ie++;
2233 }
2234 arg_type = ie->arg_type;
9de5e440 2235#if defined(DEBUG)
32407103 2236 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 2237#endif
31e31b8a
FB
2238 switch(arg_type[0]) {
2239 case TYPE_NULL:
2240 /* no argument */
2241 ret = get_errno(ioctl(fd, ie->host_cmd));
2242 break;
2243 case TYPE_PTRVOID:
2244 case TYPE_INT:
2245 /* int argment */
2246 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2247 break;
2248 case TYPE_PTR:
2249 arg_type++;
53a5960a 2250 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
2251 switch(ie->access) {
2252 case IOC_R:
2253 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2254 if (!is_error(ret)) {
579a97f7
FB
2255 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2256 if (!argptr)
2257 return -TARGET_EFAULT;
53a5960a
PB
2258 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2259 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2260 }
2261 break;
2262 case IOC_W:
579a97f7
FB
2263 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2264 if (!argptr)
2265 return -TARGET_EFAULT;
53a5960a
PB
2266 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2267 unlock_user(argptr, arg, 0);
31e31b8a
FB
2268 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2269 break;
2270 default:
2271 case IOC_RW:
579a97f7
FB
2272 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2273 if (!argptr)
2274 return -TARGET_EFAULT;
53a5960a
PB
2275 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2276 unlock_user(argptr, arg, 0);
31e31b8a
FB
2277 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2278 if (!is_error(ret)) {
579a97f7
FB
2279 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2280 if (!argptr)
2281 return -TARGET_EFAULT;
53a5960a
PB
2282 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2283 unlock_user(argptr, arg, target_size);
31e31b8a
FB
2284 }
2285 break;
2286 }
2287 break;
2288 default:
32407103
JM
2289 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2290 (long)cmd, arg_type[0]);
0da46a6e 2291 ret = -TARGET_ENOSYS;
31e31b8a
FB
2292 break;
2293 }
2294 return ret;
2295}
2296
b39bc503 2297static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
2298 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2299 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2300 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2301 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2302 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2303 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2304 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2305 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2306 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2307 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2308 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2309 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2310 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2311 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2312 { 0, 0, 0, 0 }
2313};
2314
b39bc503 2315static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
2316 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2317 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2318 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2319 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2320 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2321 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2322 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2323 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2324 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2325 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2326 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2327 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2328 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2329 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2330 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2331 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2332 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2333 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2334 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2335 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2336 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2337 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2338 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2339 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2340 { 0, 0, 0, 0 }
2341};
2342
b39bc503 2343static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
2344 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2345 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2346 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2347 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2348 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2349 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2350 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2351 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2352 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2353 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2354 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2355 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2356 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2357 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2358 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2359 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2360 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2361 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2362 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2363 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2364 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2365 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2366 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2367 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2368 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2369 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2370 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2371 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2372 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2373 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2374 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2375 { 0, 0, 0, 0 }
2376};
2377
b39bc503 2378static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
2379 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2380 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2381 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2382 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2383 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2384 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2385 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2386 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2387 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2388 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2389 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2390 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2391 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2392 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2393 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2394 { 0, 0, 0, 0 }
2395};
2396
2397static void target_to_host_termios (void *dst, const void *src)
2398{
2399 struct host_termios *host = dst;
2400 const struct target_termios *target = src;
3b46e624 2401
5fafdf24 2402 host->c_iflag =
31e31b8a 2403 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 2404 host->c_oflag =
31e31b8a 2405 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 2406 host->c_cflag =
31e31b8a 2407 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 2408 host->c_lflag =
31e31b8a
FB
2409 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2410 host->c_line = target->c_line;
3b46e624 2411
5fafdf24
TS
2412 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2413 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 2414 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 2415 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 2416 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 2417 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 2418 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 2419 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 2420 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
2421 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2422 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
2423 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2424 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2425 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2426 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2427 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 2428 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 2429}
3b46e624 2430
31e31b8a
FB
2431static void host_to_target_termios (void *dst, const void *src)
2432{
2433 struct target_termios *target = dst;
2434 const struct host_termios *host = src;
2435
5fafdf24 2436 target->c_iflag =
31e31b8a 2437 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 2438 target->c_oflag =
31e31b8a 2439 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 2440 target->c_cflag =
31e31b8a 2441 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 2442 target->c_lflag =
31e31b8a
FB
2443 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2444 target->c_line = host->c_line;
3b46e624 2445
31e31b8a
FB
2446 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2447 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2448 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2449 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2450 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2451 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2452 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2453 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2454 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2455 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2456 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2457 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2458 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2459 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2460 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2461 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2462 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2463}
2464
8e853dc7 2465static const StructEntry struct_termios_def = {
31e31b8a
FB
2466 .convert = { host_to_target_termios, target_to_host_termios },
2467 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2468 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2469};
2470
5286db75
FB
2471static bitmask_transtbl mmap_flags_tbl[] = {
2472 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2473 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2474 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2475 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2476 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2477 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2478 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2479 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2480 { 0, 0, 0, 0 }
2481};
2482
ffa65c3b
FB
2483static bitmask_transtbl fcntl_flags_tbl[] = {
2484 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2485 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2486 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2487 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2488 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2489 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2490 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2491 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2492 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2493 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2494 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2495 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2496 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
121061dc 2497#if defined(O_DIRECT)
ffa65c3b 2498 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
121061dc 2499#endif
ffa65c3b
FB
2500 { 0, 0, 0, 0 }
2501};
2502
2ab83ea7 2503#if defined(TARGET_I386)
6dbad63e
FB
2504
2505/* NOTE: there is really one LDT for all the threads */
b1d8e52e 2506static uint8_t *ldt_table;
6dbad63e 2507
03acab66 2508static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
2509{
2510 int size;
53a5960a 2511 void *p;
6dbad63e
FB
2512
2513 if (!ldt_table)
2514 return 0;
2515 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2516 if (size > bytecount)
2517 size = bytecount;
579a97f7
FB
2518 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2519 if (!p)
03acab66 2520 return -TARGET_EFAULT;
579a97f7 2521 /* ??? Should this by byteswapped? */
53a5960a
PB
2522 memcpy(p, ldt_table, size);
2523 unlock_user(p, ptr, size);
6dbad63e
FB
2524 return size;
2525}
2526
2527/* XXX: add locking support */
03acab66
FB
2528static abi_long write_ldt(CPUX86State *env,
2529 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
2530{
2531 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 2532 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 2533 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 2534 int seg_not_present, useable, lm;
6dbad63e
FB
2535 uint32_t *lp, entry_1, entry_2;
2536
2537 if (bytecount != sizeof(ldt_info))
03acab66 2538 return -TARGET_EINVAL;
579a97f7 2539 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 2540 return -TARGET_EFAULT;
53a5960a
PB
2541 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2542 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2543 ldt_info.limit = tswap32(target_ldt_info->limit);
2544 ldt_info.flags = tswap32(target_ldt_info->flags);
2545 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 2546
6dbad63e 2547 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 2548 return -TARGET_EINVAL;
6dbad63e
FB
2549 seg_32bit = ldt_info.flags & 1;
2550 contents = (ldt_info.flags >> 1) & 3;
2551 read_exec_only = (ldt_info.flags >> 3) & 1;
2552 limit_in_pages = (ldt_info.flags >> 4) & 1;
2553 seg_not_present = (ldt_info.flags >> 5) & 1;
2554 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
2555#ifdef TARGET_ABI32
2556 lm = 0;
2557#else
2558 lm = (ldt_info.flags >> 7) & 1;
2559#endif
6dbad63e
FB
2560 if (contents == 3) {
2561 if (oldmode)
03acab66 2562 return -TARGET_EINVAL;
6dbad63e 2563 if (seg_not_present == 0)
03acab66 2564 return -TARGET_EINVAL;
6dbad63e
FB
2565 }
2566 /* allocate the LDT */
2567 if (!ldt_table) {
e441570f
AZ
2568 env->ldt.base = target_mmap(0,
2569 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
2570 PROT_READ|PROT_WRITE,
2571 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
2572 if (env->ldt.base == -1)
03acab66 2573 return -TARGET_ENOMEM;
e441570f
AZ
2574 memset(g2h(env->ldt.base), 0,
2575 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 2576 env->ldt.limit = 0xffff;
e441570f 2577 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
2578 }
2579
2580 /* NOTE: same code as Linux kernel */
2581 /* Allow LDTs to be cleared by the user. */
2582 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2583 if (oldmode ||
2584 (contents == 0 &&
2585 read_exec_only == 1 &&
2586 seg_32bit == 0 &&
2587 limit_in_pages == 0 &&
2588 seg_not_present == 1 &&
2589 useable == 0 )) {
2590 entry_1 = 0;
2591 entry_2 = 0;
2592 goto install;
2593 }
2594 }
3b46e624 2595
6dbad63e
FB
2596 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2597 (ldt_info.limit & 0x0ffff);
2598 entry_2 = (ldt_info.base_addr & 0xff000000) |
2599 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2600 (ldt_info.limit & 0xf0000) |
2601 ((read_exec_only ^ 1) << 9) |
2602 (contents << 10) |
2603 ((seg_not_present ^ 1) << 15) |
2604 (seg_32bit << 22) |
2605 (limit_in_pages << 23) |
8d18e893 2606 (lm << 21) |
6dbad63e
FB
2607 0x7000;
2608 if (!oldmode)
2609 entry_2 |= (useable << 20);
14ae3ba7 2610
6dbad63e
FB
2611 /* Install the new entry ... */
2612install:
2613 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2614 lp[0] = tswap32(entry_1);
2615 lp[1] = tswap32(entry_2);
2616 return 0;
2617}
2618
2619/* specific and weird i386 syscalls */
8fcd3692
BS
2620static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2621 unsigned long bytecount)
6dbad63e 2622{
03acab66 2623 abi_long ret;
3b46e624 2624
6dbad63e
FB
2625 switch (func) {
2626 case 0:
2627 ret = read_ldt(ptr, bytecount);
2628 break;
2629 case 1:
2630 ret = write_ldt(env, ptr, bytecount, 1);
2631 break;
2632 case 0x11:
2633 ret = write_ldt(env, ptr, bytecount, 0);
2634 break;
03acab66
FB
2635 default:
2636 ret = -TARGET_ENOSYS;
2637 break;
6dbad63e
FB
2638 }
2639 return ret;
2640}
1b6b029e 2641
4583f589 2642#if defined(TARGET_I386) && defined(TARGET_ABI32)
8fcd3692 2643static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
2644{
2645 uint64_t *gdt_table = g2h(env->gdt.base);
2646 struct target_modify_ldt_ldt_s ldt_info;
2647 struct target_modify_ldt_ldt_s *target_ldt_info;
2648 int seg_32bit, contents, read_exec_only, limit_in_pages;
2649 int seg_not_present, useable, lm;
2650 uint32_t *lp, entry_1, entry_2;
2651 int i;
2652
2653 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2654 if (!target_ldt_info)
2655 return -TARGET_EFAULT;
2656 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2657 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2658 ldt_info.limit = tswap32(target_ldt_info->limit);
2659 ldt_info.flags = tswap32(target_ldt_info->flags);
2660 if (ldt_info.entry_number == -1) {
2661 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2662 if (gdt_table[i] == 0) {
2663 ldt_info.entry_number = i;
2664 target_ldt_info->entry_number = tswap32(i);
2665 break;
2666 }
2667 }
2668 }
2669 unlock_user_struct(target_ldt_info, ptr, 1);
2670
2671 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2672 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2673 return -TARGET_EINVAL;
2674 seg_32bit = ldt_info.flags & 1;
2675 contents = (ldt_info.flags >> 1) & 3;
2676 read_exec_only = (ldt_info.flags >> 3) & 1;
2677 limit_in_pages = (ldt_info.flags >> 4) & 1;
2678 seg_not_present = (ldt_info.flags >> 5) & 1;
2679 useable = (ldt_info.flags >> 6) & 1;
2680#ifdef TARGET_ABI32
2681 lm = 0;
2682#else
2683 lm = (ldt_info.flags >> 7) & 1;
2684#endif
2685
2686 if (contents == 3) {
2687 if (seg_not_present == 0)
2688 return -TARGET_EINVAL;
2689 }
2690
2691 /* NOTE: same code as Linux kernel */
2692 /* Allow LDTs to be cleared by the user. */
2693 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2694 if ((contents == 0 &&
2695 read_exec_only == 1 &&
2696 seg_32bit == 0 &&
2697 limit_in_pages == 0 &&
2698 seg_not_present == 1 &&
2699 useable == 0 )) {
2700 entry_1 = 0;
2701 entry_2 = 0;
2702 goto install;
2703 }
2704 }
2705
2706 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2707 (ldt_info.limit & 0x0ffff);
2708 entry_2 = (ldt_info.base_addr & 0xff000000) |
2709 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2710 (ldt_info.limit & 0xf0000) |
2711 ((read_exec_only ^ 1) << 9) |
2712 (contents << 10) |
2713 ((seg_not_present ^ 1) << 15) |
2714 (seg_32bit << 22) |
2715 (limit_in_pages << 23) |
2716 (useable << 20) |
2717 (lm << 21) |
2718 0x7000;
2719
2720 /* Install the new entry ... */
2721install:
2722 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2723 lp[0] = tswap32(entry_1);
2724 lp[1] = tswap32(entry_2);
2725 return 0;
2726}
2727
8fcd3692 2728static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
2729{
2730 struct target_modify_ldt_ldt_s *target_ldt_info;
2731 uint64_t *gdt_table = g2h(env->gdt.base);
2732 uint32_t base_addr, limit, flags;
2733 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2734 int seg_not_present, useable, lm;
2735 uint32_t *lp, entry_1, entry_2;
2736
2737 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2738 if (!target_ldt_info)
2739 return -TARGET_EFAULT;
2740 idx = tswap32(target_ldt_info->entry_number);
2741 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2742 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2743 unlock_user_struct(target_ldt_info, ptr, 1);
2744 return -TARGET_EINVAL;
2745 }
2746 lp = (uint32_t *)(gdt_table + idx);
2747 entry_1 = tswap32(lp[0]);
2748 entry_2 = tswap32(lp[1]);
2749
2750 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2751 contents = (entry_2 >> 10) & 3;
2752 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2753 seg_32bit = (entry_2 >> 22) & 1;
2754 limit_in_pages = (entry_2 >> 23) & 1;
2755 useable = (entry_2 >> 20) & 1;
2756#ifdef TARGET_ABI32
2757 lm = 0;
2758#else
2759 lm = (entry_2 >> 21) & 1;
2760#endif
2761 flags = (seg_32bit << 0) | (contents << 1) |
2762 (read_exec_only << 3) | (limit_in_pages << 4) |
2763 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2764 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2765 base_addr = (entry_1 >> 16) |
2766 (entry_2 & 0xff000000) |
2767 ((entry_2 & 0xff) << 16);
2768 target_ldt_info->base_addr = tswapl(base_addr);
2769 target_ldt_info->limit = tswap32(limit);
2770 target_ldt_info->flags = tswap32(flags);
2771 unlock_user_struct(target_ldt_info, ptr, 1);
2772 return 0;
2773}
4583f589 2774#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 2775
d2fd1af7 2776#ifndef TARGET_ABI32
8fcd3692 2777static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7
FB
2778{
2779 abi_long ret;
2780 abi_ulong val;
2781 int idx;
2782
2783 switch(code) {
2784 case TARGET_ARCH_SET_GS:
2785 case TARGET_ARCH_SET_FS:
2786 if (code == TARGET_ARCH_SET_GS)
2787 idx = R_GS;
2788 else
2789 idx = R_FS;
2790 cpu_x86_load_seg(env, idx, 0);
2791 env->segs[idx].base = addr;
2792 break;
2793 case TARGET_ARCH_GET_GS:
2794 case TARGET_ARCH_GET_FS:
2795 if (code == TARGET_ARCH_GET_GS)
2796 idx = R_GS;
2797 else
2798 idx = R_FS;
2799 val = env->segs[idx].base;
2800 if (put_user(val, addr, abi_ulong))
2801 return -TARGET_EFAULT;
2802 break;
2803 default:
2804 ret = -TARGET_EINVAL;
2805 break;
2806 }
2807 return 0;
2808}
2809#endif
2810
2ab83ea7
FB
2811#endif /* defined(TARGET_I386) */
2812
d865bab5
PB
2813#if defined(USE_NPTL)
2814
2815#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2816
2817static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2818typedef struct {
2819 CPUState *env;
2820 pthread_mutex_t mutex;
2821 pthread_cond_t cond;
2822 pthread_t thread;
2823 uint32_t tid;
2824 abi_ulong child_tidptr;
2825 abi_ulong parent_tidptr;
2826 sigset_t sigmask;
2827} new_thread_info;
2828
2829static void *clone_func(void *arg)
2830{
2831 new_thread_info *info = arg;
2832 CPUState *env;
2833
2834 env = info->env;
2835 thread_env = env;
2836 info->tid = gettid();
2837 if (info->child_tidptr)
2838 put_user_u32(info->tid, info->child_tidptr);
2839 if (info->parent_tidptr)
2840 put_user_u32(info->tid, info->parent_tidptr);
2841 /* Enable signals. */
2842 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2843 /* Signal to the parent that we're ready. */
2844 pthread_mutex_lock(&info->mutex);
2845 pthread_cond_broadcast(&info->cond);
2846 pthread_mutex_unlock(&info->mutex);
2847 /* Wait until the parent has finshed initializing the tls state. */
2848 pthread_mutex_lock(&clone_lock);
2849 pthread_mutex_unlock(&clone_lock);
2850 cpu_loop(env);
2851 /* never exits */
2852 return NULL;
2853}
2854#else
1b6b029e
FB
2855/* this stack is the equivalent of the kernel stack associated with a
2856 thread/process */
2857#define NEW_STACK_SIZE 8192
2858
2859static int clone_func(void *arg)
2860{
2ab83ea7 2861 CPUState *env = arg;
1b6b029e
FB
2862 cpu_loop(env);
2863 /* never exits */
2864 return 0;
2865}
d865bab5 2866#endif
1b6b029e 2867
0da46a6e
TS
2868/* do_fork() Must return host values and target errnos (unlike most
2869 do_*() functions). */
d865bab5
PB
2870static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2871 abi_ulong parent_tidptr, target_ulong newtls,
2872 abi_ulong child_tidptr)
1b6b029e
FB
2873{
2874 int ret;
5cd4393b 2875 TaskState *ts;
1b6b029e 2876 uint8_t *new_stack;
2ab83ea7 2877 CPUState *new_env;
d865bab5
PB
2878#if defined(USE_NPTL)
2879 unsigned int nptl_flags;
2880 sigset_t sigmask;
2881#endif
3b46e624 2882
436d124b
AZ
2883 /* Emulate vfork() with fork() */
2884 if (flags & CLONE_VFORK)
2885 flags &= ~(CLONE_VFORK | CLONE_VM);
2886
1b6b029e 2887 if (flags & CLONE_VM) {
bd0c5661 2888#if defined(USE_NPTL)
d865bab5
PB
2889 new_thread_info info;
2890 pthread_attr_t attr;
bd0c5661 2891#endif
c3a92833 2892 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
624f7979 2893 init_task_state(ts);
5cd4393b 2894 new_stack = ts->stack;
1b6b029e 2895 /* we create a new CPU instance. */
c5be9f08 2896 new_env = cpu_copy(env);
6e68e076
PB
2897 /* Init regs that differ from the parent. */
2898 cpu_clone_regs(new_env, newsp);
5cd4393b 2899 new_env->opaque = ts;
d865bab5
PB
2900#if defined(USE_NPTL)
2901 nptl_flags = flags;
2902 flags &= ~CLONE_NPTL_FLAGS2;
2903
2904 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2905 if (nptl_flags & CLONE_SETTLS)
2906 cpu_set_tls (new_env, newtls);
2907
2908 /* Grab a mutex so that thread setup appears atomic. */
2909 pthread_mutex_lock(&clone_lock);
2910
2911 memset(&info, 0, sizeof(info));
2912 pthread_mutex_init(&info.mutex, NULL);
2913 pthread_mutex_lock(&info.mutex);
2914 pthread_cond_init(&info.cond, NULL);
2915 info.env = new_env;
2916 if (nptl_flags & CLONE_CHILD_SETTID)
2917 info.child_tidptr = child_tidptr;
2918 if (nptl_flags & CLONE_PARENT_SETTID)
2919 info.parent_tidptr = parent_tidptr;
2920
2921 ret = pthread_attr_init(&attr);
2922 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2923 /* It is not safe to deliver signals until the child has finished
2924 initializing, so temporarily block all signals. */
2925 sigfillset(&sigmask);
2926 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2927
2928 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2929
2930 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2931 pthread_attr_destroy(&attr);
2932 if (ret == 0) {
2933 /* Wait for the child to initialize. */
2934 pthread_cond_wait(&info.cond, &info.mutex);
2935 ret = info.tid;
2936 if (flags & CLONE_PARENT_SETTID)
2937 put_user_u32(ret, parent_tidptr);
2938 } else {
2939 ret = -1;
2940 }
2941 pthread_mutex_unlock(&info.mutex);
2942 pthread_cond_destroy(&info.cond);
2943 pthread_mutex_destroy(&info.mutex);
2944 pthread_mutex_unlock(&clone_lock);
2945#else
2946 if (flags & CLONE_NPTL_FLAGS2)
2947 return -EINVAL;
2948 /* This is probably going to die very quickly, but do it anyway. */
27725c1d 2949#ifdef __ia64__
fd4a43e4 2950 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
27725c1d
FB
2951#else
2952 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
d865bab5 2953#endif
27725c1d 2954#endif
1b6b029e
FB
2955 } else {
2956 /* if no CLONE_VM, we consider it is a fork */
d865bab5 2957 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
1b6b029e 2958 return -EINVAL;
d865bab5 2959 fork_start();
1b6b029e 2960 ret = fork();
d865bab5
PB
2961#if defined(USE_NPTL)
2962 /* There is a race condition here. The parent process could
2963 theoretically read the TID in the child process before the child
2964 tid is set. This would require using either ptrace
2965 (not implemented) or having *_tidptr to point at a shared memory
2966 mapping. We can't repeat the spinlock hack used above because
2967 the child process gets its own copy of the lock. */
2968 if (ret == 0) {
2969 cpu_clone_regs(env, newsp);
2970 fork_end(1);
2971 /* Child Process. */
2972 if (flags & CLONE_CHILD_SETTID)
2973 put_user_u32(gettid(), child_tidptr);
2974 if (flags & CLONE_PARENT_SETTID)
2975 put_user_u32(gettid(), parent_tidptr);
2976 ts = (TaskState *)env->opaque;
2977 if (flags & CLONE_SETTLS)
2978 cpu_set_tls (env, newtls);
2979 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2980 } else {
2981 fork_end(0);
2982 }
2983#else
6e68e076
PB
2984 if (ret == 0) {
2985 cpu_clone_regs(env, newsp);
2986 }
d865bab5 2987#endif
1b6b029e
FB
2988 }
2989 return ret;
2990}
2991
992f48a0 2992static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
2993{
2994 struct flock fl;
53a5960a 2995 struct target_flock *target_fl;
43f238d7
TS
2996 struct flock64 fl64;
2997 struct target_flock64 *target_fl64;
992f48a0 2998 abi_long ret;
53a5960a 2999
7775e9ec
FB
3000 switch(cmd) {
3001 case TARGET_F_GETLK:
579a97f7
FB
3002 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3003 return -TARGET_EFAULT;
5813427b
TS
3004 fl.l_type = tswap16(target_fl->l_type);
3005 fl.l_whence = tswap16(target_fl->l_whence);
3006 fl.l_start = tswapl(target_fl->l_start);
3007 fl.l_len = tswapl(target_fl->l_len);
3008 fl.l_pid = tswapl(target_fl->l_pid);
3009 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 3010 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 3011 if (ret == 0) {
579a97f7
FB
3012 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3013 return -TARGET_EFAULT;
7775e9ec
FB
3014 target_fl->l_type = tswap16(fl.l_type);
3015 target_fl->l_whence = tswap16(fl.l_whence);
3016 target_fl->l_start = tswapl(fl.l_start);
3017 target_fl->l_len = tswapl(fl.l_len);
3018 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 3019 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
3020 }
3021 break;
3b46e624 3022
7775e9ec
FB
3023 case TARGET_F_SETLK:
3024 case TARGET_F_SETLKW:
579a97f7
FB
3025 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3026 return -TARGET_EFAULT;
7775e9ec
FB
3027 fl.l_type = tswap16(target_fl->l_type);
3028 fl.l_whence = tswap16(target_fl->l_whence);
3029 fl.l_start = tswapl(target_fl->l_start);
3030 fl.l_len = tswapl(target_fl->l_len);
3031 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 3032 unlock_user_struct(target_fl, arg, 0);
9ee1fa2c 3033 ret = get_errno(fcntl(fd, cmd, &fl));
7775e9ec 3034 break;
3b46e624 3035
7775e9ec 3036 case TARGET_F_GETLK64:
579a97f7
FB
3037 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3038 return -TARGET_EFAULT;
5813427b
TS
3039 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3040 fl64.l_whence = tswap16(target_fl64->l_whence);
3041 fl64.l_start = tswapl(target_fl64->l_start);
3042 fl64.l_len = tswapl(target_fl64->l_len);
3043 fl64.l_pid = tswap16(target_fl64->l_pid);
3044 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 3045 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
43f238d7 3046 if (ret == 0) {
579a97f7
FB
3047 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3048 return -TARGET_EFAULT;
43f238d7
TS
3049 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3050 target_fl64->l_whence = tswap16(fl64.l_whence);
3051 target_fl64->l_start = tswapl(fl64.l_start);
3052 target_fl64->l_len = tswapl(fl64.l_len);
3053 target_fl64->l_pid = tswapl(fl64.l_pid);
3054 unlock_user_struct(target_fl64, arg, 1);
3055 }
9ee1fa2c 3056 break;
7775e9ec
FB
3057 case TARGET_F_SETLK64:
3058 case TARGET_F_SETLKW64:
579a97f7
FB
3059 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3060 return -TARGET_EFAULT;
43f238d7
TS
3061 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3062 fl64.l_whence = tswap16(target_fl64->l_whence);
3063 fl64.l_start = tswapl(target_fl64->l_start);
3064 fl64.l_len = tswapl(target_fl64->l_len);
3065 fl64.l_pid = tswap16(target_fl64->l_pid);
3066 unlock_user_struct(target_fl64, arg, 0);
9ee1fa2c 3067 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
7775e9ec
FB
3068 break;
3069
ffa65c3b 3070 case F_GETFL:
9ee1fa2c
FB
3071 ret = get_errno(fcntl(fd, cmd, arg));
3072 if (ret >= 0) {
3073 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3074 }
ffa65c3b
FB
3075 break;
3076
3077 case F_SETFL:
9ee1fa2c 3078 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
ffa65c3b
FB
3079 break;
3080
7775e9ec 3081 default:
9ee1fa2c 3082 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
3083 break;
3084 }
3085 return ret;
3086}
3087
67867308 3088#ifdef USE_UID16
7775e9ec 3089
67867308
FB
3090static inline int high2lowuid(int uid)
3091{
3092 if (uid > 65535)
3093 return 65534;
3094 else
3095 return uid;
3096}
3097
3098static inline int high2lowgid(int gid)
3099{
3100 if (gid > 65535)
3101 return 65534;
3102 else
3103 return gid;
3104}
3105
3106static inline int low2highuid(int uid)
3107{
3108 if ((int16_t)uid == -1)
3109 return -1;
3110 else
3111 return uid;
3112}
3113
3114static inline int low2highgid(int gid)
3115{
3116 if ((int16_t)gid == -1)
3117 return -1;
3118 else
3119 return gid;
3120}
3121
3122#endif /* USE_UID16 */
1b6b029e 3123
31e31b8a
FB
3124void syscall_init(void)
3125{
2ab83ea7
FB
3126 IOCTLEntry *ie;
3127 const argtype *arg_type;
3128 int size;
b92c47c1 3129 int i;
2ab83ea7 3130
5fafdf24
TS
3131#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3132#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
3133#include "syscall_types.h"
3134#undef STRUCT
3135#undef STRUCT_SPECIAL
2ab83ea7
FB
3136
3137 /* we patch the ioctl size if necessary. We rely on the fact that
3138 no ioctl has all the bits at '1' in the size field */
3139 ie = ioctl_entries;
3140 while (ie->target_cmd != 0) {
3141 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3142 TARGET_IOC_SIZEMASK) {
3143 arg_type = ie->arg_type;
3144 if (arg_type[0] != TYPE_PTR) {
5fafdf24 3145 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
3146 ie->target_cmd);
3147 exit(1);
3148 }
3149 arg_type++;
3150 size = thunk_type_size(arg_type, 0);
5fafdf24 3151 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
3152 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3153 (size << TARGET_IOC_SIZESHIFT);
3154 }
b92c47c1
TS
3155
3156 /* Build target_to_host_errno_table[] table from
3157 * host_to_target_errno_table[]. */
3158 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3159 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3160
2ab83ea7 3161 /* automatic consistency check if same arch */
872ea0c0
AZ
3162#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3163 (defined(__x86_64__) && defined(TARGET_X86_64))
3164 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3165 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3166 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
3167 }
3168#endif
3169 ie++;
3170 }
31e31b8a 3171}
c573ff67 3172
992f48a0 3173#if TARGET_ABI_BITS == 32
ce4defa0
PB
3174static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3175{
af325d36 3176#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
3177 return ((uint64_t)word0 << 32) | word1;
3178#else
3179 return ((uint64_t)word1 << 32) | word0;
3180#endif
3181}
992f48a0 3182#else /* TARGET_ABI_BITS == 32 */
32407103
JM
3183static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3184{
3185 return word0;
3186}
992f48a0 3187#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
3188
3189#ifdef TARGET_NR_truncate64
992f48a0
BS
3190static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3191 abi_long arg2,
3192 abi_long arg3,
3193 abi_long arg4)
ce4defa0
PB
3194{
3195#ifdef TARGET_ARM
3196 if (((CPUARMState *)cpu_env)->eabi)
3197 {
3198 arg2 = arg3;
3199 arg3 = arg4;
3200 }
3201#endif
3202 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3203}
3204#endif
3205
3206#ifdef TARGET_NR_ftruncate64
992f48a0
BS
3207static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3208 abi_long arg2,
3209 abi_long arg3,
3210 abi_long arg4)
ce4defa0
PB
3211{
3212#ifdef TARGET_ARM
3213 if (((CPUARMState *)cpu_env)->eabi)
3214 {
3215 arg2 = arg3;
3216 arg3 = arg4;
3217 }
3218#endif
3219 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3220}
3221#endif
3222
579a97f7
FB
3223static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3224 abi_ulong target_addr)
53a5960a
PB
3225{
3226 struct target_timespec *target_ts;
3227
579a97f7
FB
3228 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3229 return -TARGET_EFAULT;
53a5960a
PB
3230 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3231 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3232 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 3233 return 0;
53a5960a
PB
3234}
3235
579a97f7
FB
3236static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3237 struct timespec *host_ts)
53a5960a
PB
3238{
3239 struct target_timespec *target_ts;
3240
579a97f7
FB
3241 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3242 return -TARGET_EFAULT;
53a5960a
PB
3243 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3244 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3245 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 3246 return 0;
53a5960a
PB
3247}
3248
6a24a778
AZ
3249#ifdef TARGET_NR_stat64
3250static inline abi_long host_to_target_stat64(void *cpu_env,
3251 abi_ulong target_addr,
3252 struct stat *host_st)
3253{
3254#ifdef TARGET_ARM
3255 if (((CPUARMState *)cpu_env)->eabi) {
3256 struct target_eabi_stat64 *target_st;
3257
3258 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3259 return -TARGET_EFAULT;
3260 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3261 __put_user(host_st->st_dev, &target_st->st_dev);
3262 __put_user(host_st->st_ino, &target_st->st_ino);
3263#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3264 __put_user(host_st->st_ino, &target_st->__st_ino);
3265#endif
3266 __put_user(host_st->st_mode, &target_st->st_mode);
3267 __put_user(host_st->st_nlink, &target_st->st_nlink);
3268 __put_user(host_st->st_uid, &target_st->st_uid);
3269 __put_user(host_st->st_gid, &target_st->st_gid);
3270 __put_user(host_st->st_rdev, &target_st->st_rdev);
3271 __put_user(host_st->st_size, &target_st->st_size);
3272 __put_user(host_st->st_blksize, &target_st->st_blksize);
3273 __put_user(host_st->st_blocks, &target_st->st_blocks);
3274 __put_user(host_st->st_atime, &target_st->target_st_atime);
3275 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3276 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3277 unlock_user_struct(target_st, target_addr, 1);
3278 } else
3279#endif
3280 {
3281 struct target_stat64 *target_st;
3282
3283 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3284 return -TARGET_EFAULT;
3285 memset(target_st, 0, sizeof(struct target_stat64));
3286 __put_user(host_st->st_dev, &target_st->st_dev);
3287 __put_user(host_st->st_ino, &target_st->st_ino);
3288#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3289 __put_user(host_st->st_ino, &target_st->__st_ino);
3290#endif
3291 __put_user(host_st->st_mode, &target_st->st_mode);
3292 __put_user(host_st->st_nlink, &target_st->st_nlink);
3293 __put_user(host_st->st_uid, &target_st->st_uid);
3294 __put_user(host_st->st_gid, &target_st->st_gid);
3295 __put_user(host_st->st_rdev, &target_st->st_rdev);
3296 /* XXX: better use of kernel struct */
3297 __put_user(host_st->st_size, &target_st->st_size);
3298 __put_user(host_st->st_blksize, &target_st->st_blksize);
3299 __put_user(host_st->st_blocks, &target_st->st_blocks);
3300 __put_user(host_st->st_atime, &target_st->target_st_atime);
3301 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3302 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3303 unlock_user_struct(target_st, target_addr, 1);
3304 }
3305
3306 return 0;
3307}
3308#endif
3309
bd0c5661
PB
3310#if defined(USE_NPTL)
3311/* ??? Using host futex calls even when target atomic operations
3312 are not really atomic probably breaks things. However implementing
3313 futexes locally would make futexes shared between multiple processes
3314 tricky. However they're probably useless because guest atomic
3315 operations won't work either. */
8fcd3692
BS
3316static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3317 target_ulong uaddr2, int val3)
bd0c5661
PB
3318{
3319 struct timespec ts, *pts;
3320
3321 /* ??? We assume FUTEX_* constants are the same on both host
3322 and target. */
3323 switch (op) {
3324 case FUTEX_WAIT:
3325 if (timeout) {
3326 pts = &ts;
3327 target_to_host_timespec(pts, timeout);
3328 } else {
3329 pts = NULL;
3330 }
3331 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3332 pts, NULL, 0));
3333 case FUTEX_WAKE:
3334 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3335 case FUTEX_FD:
3336 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3337 case FUTEX_REQUEUE:
3338 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3339 NULL, g2h(uaddr2), 0));
3340 case FUTEX_CMP_REQUEUE:
3341 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3342 NULL, g2h(uaddr2), tswap32(val3)));
3343 default:
3344 return -TARGET_ENOSYS;
3345 }
3346}
3347#endif
3348
a745ec6d
PB
3349int get_osversion(void)
3350{
3351 static int osversion;
3352 struct new_utsname buf;
3353 const char *s;
3354 int i, n, tmp;
3355 if (osversion)
3356 return osversion;
3357 if (qemu_uname_release && *qemu_uname_release) {
3358 s = qemu_uname_release;
3359 } else {
3360 if (sys_uname(&buf))
3361 return 0;
3362 s = buf.release;
3363 }
3364 tmp = 0;
3365 for (i = 0; i < 3; i++) {
3366 n = 0;
3367 while (*s >= '0' && *s <= '9') {
3368 n *= 10;
3369 n += *s - '0';
3370 s++;
3371 }
3372 tmp = (tmp << 8) + n;
3373 if (*s == '.')
3374 s++;
3375 }
3376 osversion = tmp;
3377 return osversion;
3378}
3379
0da46a6e
TS
3380/* do_syscall() should always have a single exit point at the end so
3381 that actions, such as logging of syscall results, can be performed.
3382 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
3383abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3384 abi_long arg2, abi_long arg3, abi_long arg4,
3385 abi_long arg5, abi_long arg6)
31e31b8a 3386{
992f48a0 3387 abi_long ret;
31e31b8a 3388 struct stat st;
56c8f68f 3389 struct statfs stfs;
53a5960a 3390 void *p;
3b46e624 3391
72f03900 3392#ifdef DEBUG
c573ff67 3393 gemu_log("syscall %d", num);
72f03900 3394#endif
b92c47c1
TS
3395 if(do_strace)
3396 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3397
31e31b8a
FB
3398 switch(num) {
3399 case TARGET_NR_exit:
7d13299d
FB
3400#ifdef HAVE_GPROF
3401 _mcleanup();
3402#endif
e9009676 3403 gdb_exit(cpu_env, arg1);
1b6b029e 3404 /* XXX: should free thread stack and CPU env */
a2f86d8e 3405 sys_exit(arg1);
31e31b8a
FB
3406 ret = 0; /* avoid warning */
3407 break;
3408 case TARGET_NR_read:
579a97f7
FB
3409 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3410 goto efault;
53a5960a
PB
3411 ret = get_errno(read(arg1, p, arg3));
3412 unlock_user(p, arg2, ret);
31e31b8a
FB
3413 break;
3414 case TARGET_NR_write:
579a97f7
FB
3415 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3416 goto efault;
53a5960a
PB
3417 ret = get_errno(write(arg1, p, arg3));
3418 unlock_user(p, arg2, 0);
31e31b8a
FB
3419 break;
3420 case TARGET_NR_open:
2f619698
FB
3421 if (!(p = lock_user_string(arg1)))
3422 goto efault;
53a5960a 3423 ret = get_errno(open(path(p),
ffa65c3b
FB
3424 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3425 arg3));
53a5960a 3426 unlock_user(p, arg1, 0);
31e31b8a 3427 break;
82424832
TS
3428#if defined(TARGET_NR_openat) && defined(__NR_openat)
3429 case TARGET_NR_openat:
579a97f7
FB
3430 if (!(p = lock_user_string(arg2)))
3431 goto efault;
3432 ret = get_errno(sys_openat(arg1,
3433 path(p),
3434 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3435 arg4));
3436 unlock_user(p, arg2, 0);
82424832
TS
3437 break;
3438#endif
31e31b8a
FB
3439 case TARGET_NR_close:
3440 ret = get_errno(close(arg1));
3441 break;
3442 case TARGET_NR_brk:
53a5960a 3443 ret = do_brk(arg1);
31e31b8a
FB
3444 break;
3445 case TARGET_NR_fork:
d865bab5 3446 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
31e31b8a 3447 break;
e5febef5 3448#ifdef TARGET_NR_waitpid
31e31b8a
FB
3449 case TARGET_NR_waitpid:
3450 {
53a5960a
PB
3451 int status;
3452 ret = get_errno(waitpid(arg1, &status, arg3));
2f619698
FB
3453 if (!is_error(ret) && arg2
3454 && put_user_s32(status, arg2))
3455 goto efault;
31e31b8a
FB
3456 }
3457 break;
e5febef5 3458#endif
f0cbb613
PB
3459#ifdef TARGET_NR_waitid
3460 case TARGET_NR_waitid:
3461 {
3462 siginfo_t info;
3463 info.si_pid = 0;
3464 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3465 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3466 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3467 goto efault;
3468 host_to_target_siginfo(p, &info);
3469 unlock_user(p, arg3, sizeof(target_siginfo_t));
3470 }
3471 }
3472 break;
3473#endif
7a3148a9 3474#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 3475 case TARGET_NR_creat:
579a97f7
FB
3476 if (!(p = lock_user_string(arg1)))
3477 goto efault;
53a5960a
PB
3478 ret = get_errno(creat(p, arg2));
3479 unlock_user(p, arg1, 0);
31e31b8a 3480 break;
7a3148a9 3481#endif
31e31b8a 3482 case TARGET_NR_link:
53a5960a
PB
3483 {
3484 void * p2;
3485 p = lock_user_string(arg1);
3486 p2 = lock_user_string(arg2);
579a97f7
FB
3487 if (!p || !p2)
3488 ret = -TARGET_EFAULT;
3489 else
3490 ret = get_errno(link(p, p2));
53a5960a
PB
3491 unlock_user(p2, arg2, 0);
3492 unlock_user(p, arg1, 0);
3493 }
31e31b8a 3494 break;
64f0ce4c
TS
3495#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3496 case TARGET_NR_linkat:
64f0ce4c
TS
3497 {
3498 void * p2 = NULL;
579a97f7
FB
3499 if (!arg2 || !arg4)
3500 goto efault;
64f0ce4c
TS
3501 p = lock_user_string(arg2);
3502 p2 = lock_user_string(arg4);
579a97f7 3503 if (!p || !p2)
0da46a6e 3504 ret = -TARGET_EFAULT;
64f0ce4c
TS
3505 else
3506 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
3507 unlock_user(p, arg2, 0);
3508 unlock_user(p2, arg4, 0);
64f0ce4c
TS
3509 }
3510 break;
3511#endif
31e31b8a 3512 case TARGET_NR_unlink:
579a97f7
FB
3513 if (!(p = lock_user_string(arg1)))
3514 goto efault;
53a5960a
PB
3515 ret = get_errno(unlink(p));
3516 unlock_user(p, arg1, 0);
31e31b8a 3517 break;
8170f56b
TS
3518#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3519 case TARGET_NR_unlinkat:
579a97f7
FB
3520 if (!(p = lock_user_string(arg2)))
3521 goto efault;
3522 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3523 unlock_user(p, arg2, 0);
ed494d87 3524 break;
b7d35e65 3525#endif
31e31b8a 3526 case TARGET_NR_execve:
7854b056
FB
3527 {
3528 char **argp, **envp;
f7341ff4 3529 int argc, envc;
992f48a0
BS
3530 abi_ulong gp;
3531 abi_ulong guest_argp;
3532 abi_ulong guest_envp;
3533 abi_ulong addr;
7854b056
FB
3534 char **q;
3535
f7341ff4 3536 argc = 0;
53a5960a 3537 guest_argp = arg2;
da94d263 3538 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 3539 if (get_user_ual(addr, gp))
2f619698 3540 goto efault;
03aa1976 3541 if (!addr)
2f619698 3542 break;
7854b056 3543 argc++;
2f619698 3544 }
f7341ff4 3545 envc = 0;
53a5960a 3546 guest_envp = arg3;
da94d263 3547 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 3548 if (get_user_ual(addr, gp))
2f619698 3549 goto efault;
03aa1976 3550 if (!addr)
2f619698 3551 break;
7854b056 3552 envc++;
2f619698 3553 }
7854b056 3554
f7341ff4
FB
3555 argp = alloca((argc + 1) * sizeof(void *));
3556 envp = alloca((envc + 1) * sizeof(void *));
7854b056 3557
da94d263 3558 for (gp = guest_argp, q = argp; gp;
992f48a0 3559 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3560 if (get_user_ual(addr, gp))
3561 goto execve_efault;
53a5960a
PB
3562 if (!addr)
3563 break;
2f619698
FB
3564 if (!(*q = lock_user_string(addr)))
3565 goto execve_efault;
53a5960a 3566 }
f7341ff4
FB
3567 *q = NULL;
3568
da94d263 3569 for (gp = guest_envp, q = envp; gp;
992f48a0 3570 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3571 if (get_user_ual(addr, gp))
3572 goto execve_efault;
53a5960a
PB
3573 if (!addr)
3574 break;
2f619698
FB
3575 if (!(*q = lock_user_string(addr)))
3576 goto execve_efault;
53a5960a 3577 }
f7341ff4 3578 *q = NULL;
7854b056 3579
2f619698
FB
3580 if (!(p = lock_user_string(arg1)))
3581 goto execve_efault;
53a5960a
PB
3582 ret = get_errno(execve(p, argp, envp));
3583 unlock_user(p, arg1, 0);
3584
2f619698
FB
3585 goto execve_end;
3586
3587 execve_efault:
3588 ret = -TARGET_EFAULT;
3589
3590 execve_end:
53a5960a 3591 for (gp = guest_argp, q = argp; *q;
992f48a0 3592 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3593 if (get_user_ual(addr, gp)
3594 || !addr)
3595 break;
53a5960a
PB
3596 unlock_user(*q, addr, 0);
3597 }
3598 for (gp = guest_envp, q = envp; *q;
992f48a0 3599 gp += sizeof(abi_ulong), q++) {
2f619698
FB
3600 if (get_user_ual(addr, gp)
3601 || !addr)
3602 break;
53a5960a
PB
3603 unlock_user(*q, addr, 0);
3604 }
7854b056 3605 }
31e31b8a
FB
3606 break;
3607 case TARGET_NR_chdir:
579a97f7
FB
3608 if (!(p = lock_user_string(arg1)))
3609 goto efault;
53a5960a
PB
3610 ret = get_errno(chdir(p));
3611 unlock_user(p, arg1, 0);
31e31b8a 3612 break;
a315a145 3613#ifdef TARGET_NR_time
31e31b8a
FB
3614 case TARGET_NR_time:
3615 {
53a5960a
PB
3616 time_t host_time;
3617 ret = get_errno(time(&host_time));
2f619698
FB
3618 if (!is_error(ret)
3619 && arg1
3620 && put_user_sal(host_time, arg1))
3621 goto efault;
31e31b8a
FB
3622 }
3623 break;
a315a145 3624#endif
31e31b8a 3625 case TARGET_NR_mknod:
579a97f7
FB
3626 if (!(p = lock_user_string(arg1)))
3627 goto efault;
53a5960a
PB
3628 ret = get_errno(mknod(p, arg2, arg3));
3629 unlock_user(p, arg1, 0);
31e31b8a 3630 break;
75ac37a0
TS
3631#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3632 case TARGET_NR_mknodat:
579a97f7
FB
3633 if (!(p = lock_user_string(arg2)))
3634 goto efault;
3635 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3636 unlock_user(p, arg2, 0);
75ac37a0
TS
3637 break;
3638#endif
31e31b8a 3639 case TARGET_NR_chmod:
579a97f7
FB
3640 if (!(p = lock_user_string(arg1)))
3641 goto efault;
53a5960a
PB
3642 ret = get_errno(chmod(p, arg2));
3643 unlock_user(p, arg1, 0);
31e31b8a 3644 break;
ebc05488 3645#ifdef TARGET_NR_break
31e31b8a
FB
3646 case TARGET_NR_break:
3647 goto unimplemented;
ebc05488
FB
3648#endif
3649#ifdef TARGET_NR_oldstat
31e31b8a
FB
3650 case TARGET_NR_oldstat:
3651 goto unimplemented;
ebc05488 3652#endif
31e31b8a
FB
3653 case TARGET_NR_lseek:
3654 ret = get_errno(lseek(arg1, arg2, arg3));
3655 break;
7a3148a9
JM
3656#ifdef TARGET_NR_getxpid
3657 case TARGET_NR_getxpid:
3658#else
31e31b8a 3659 case TARGET_NR_getpid:
7a3148a9 3660#endif
31e31b8a
FB
3661 ret = get_errno(getpid());
3662 break;
3663 case TARGET_NR_mount:
80265918
TS
3664 {
3665 /* need to look at the data field */
3666 void *p2, *p3;
3667 p = lock_user_string(arg1);
3668 p2 = lock_user_string(arg2);
3669 p3 = lock_user_string(arg3);
579a97f7
FB
3670 if (!p || !p2 || !p3)
3671 ret = -TARGET_EFAULT;
3672 else
3673 /* FIXME - arg5 should be locked, but it isn't clear how to
3674 * do that since it's not guaranteed to be a NULL-terminated
3675 * string.
3676 */
3677 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3678 unlock_user(p, arg1, 0);
3679 unlock_user(p2, arg2, 0);
3680 unlock_user(p3, arg3, 0);
80265918
TS
3681 break;
3682 }
e5febef5 3683#ifdef TARGET_NR_umount
31e31b8a 3684 case TARGET_NR_umount:
579a97f7
FB
3685 if (!(p = lock_user_string(arg1)))
3686 goto efault;
53a5960a
PB
3687 ret = get_errno(umount(p));
3688 unlock_user(p, arg1, 0);
31e31b8a 3689 break;
e5febef5 3690#endif
7a3148a9 3691#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
3692 case TARGET_NR_stime:
3693 {
53a5960a 3694 time_t host_time;
2f619698
FB
3695 if (get_user_sal(host_time, arg1))
3696 goto efault;
53a5960a 3697 ret = get_errno(stime(&host_time));
31e31b8a
FB
3698 }
3699 break;
7a3148a9 3700#endif
31e31b8a
FB
3701 case TARGET_NR_ptrace:
3702 goto unimplemented;
7a3148a9 3703#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
3704 case TARGET_NR_alarm:
3705 ret = alarm(arg1);
3706 break;
7a3148a9 3707#endif
ebc05488 3708#ifdef TARGET_NR_oldfstat
31e31b8a
FB
3709 case TARGET_NR_oldfstat:
3710 goto unimplemented;
ebc05488 3711#endif
7a3148a9 3712#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
3713 case TARGET_NR_pause:
3714 ret = get_errno(pause());
3715 break;
7a3148a9 3716#endif
e5febef5 3717#ifdef TARGET_NR_utime
31e31b8a 3718 case TARGET_NR_utime:
ebc05488 3719 {
53a5960a
PB
3720 struct utimbuf tbuf, *host_tbuf;
3721 struct target_utimbuf *target_tbuf;
3722 if (arg2) {
579a97f7
FB
3723 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3724 goto efault;
53a5960a
PB
3725 tbuf.actime = tswapl(target_tbuf->actime);
3726 tbuf.modtime = tswapl(target_tbuf->modtime);
3727 unlock_user_struct(target_tbuf, arg2, 0);
3728 host_tbuf = &tbuf;
f72e8ff4 3729 } else {
53a5960a 3730 host_tbuf = NULL;
f72e8ff4 3731 }
579a97f7
FB
3732 if (!(p = lock_user_string(arg1)))
3733 goto efault;
53a5960a
PB
3734 ret = get_errno(utime(p, host_tbuf));
3735 unlock_user(p, arg1, 0);
ebc05488
FB
3736 }
3737 break;
e5febef5 3738#endif
978a66ff
FB
3739 case TARGET_NR_utimes:
3740 {
978a66ff 3741 struct timeval *tvp, tv[2];
53a5960a 3742 if (arg2) {
788f5ec4
TS
3743 if (copy_from_user_timeval(&tv[0], arg2)
3744 || copy_from_user_timeval(&tv[1],
3745 arg2 + sizeof(struct target_timeval)))
3746 goto efault;
978a66ff
FB
3747 tvp = tv;
3748 } else {
3749 tvp = NULL;
3750 }
579a97f7
FB
3751 if (!(p = lock_user_string(arg1)))
3752 goto efault;
53a5960a
PB
3753 ret = get_errno(utimes(p, tvp));
3754 unlock_user(p, arg1, 0);
978a66ff
FB
3755 }
3756 break;
ac8a6556
AZ
3757#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
3758 case TARGET_NR_futimesat:
3759 {
3760 struct timeval *tvp, tv[2];
3761 if (arg3) {
3762 if (copy_from_user_timeval(&tv[0], arg3)
3763 || copy_from_user_timeval(&tv[1],
3764 arg3 + sizeof(struct target_timeval)))
3765 goto efault;
3766 tvp = tv;
3767 } else {
3768 tvp = NULL;
3769 }
3770 if (!(p = lock_user_string(arg2)))
3771 goto efault;
3772 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
3773 unlock_user(p, arg2, 0);
3774 }
3775 break;
3776#endif
ebc05488 3777#ifdef TARGET_NR_stty
31e31b8a
FB
3778 case TARGET_NR_stty:
3779 goto unimplemented;
ebc05488
FB
3780#endif
3781#ifdef TARGET_NR_gtty
31e31b8a
FB
3782 case TARGET_NR_gtty:
3783 goto unimplemented;
ebc05488 3784#endif
31e31b8a 3785 case TARGET_NR_access:
579a97f7
FB
3786 if (!(p = lock_user_string(arg1)))
3787 goto efault;
53a5960a
PB
3788 ret = get_errno(access(p, arg2));
3789 unlock_user(p, arg1, 0);
31e31b8a 3790 break;
92a34c10
TS
3791#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3792 case TARGET_NR_faccessat:
579a97f7
FB
3793 if (!(p = lock_user_string(arg2)))
3794 goto efault;
3795 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3796 unlock_user(p, arg2, 0);
92a34c10
TS
3797 break;
3798#endif
7a3148a9 3799#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
3800 case TARGET_NR_nice:
3801 ret = get_errno(nice(arg1));
3802 break;
7a3148a9 3803#endif
ebc05488 3804#ifdef TARGET_NR_ftime
31e31b8a
FB
3805 case TARGET_NR_ftime:
3806 goto unimplemented;
ebc05488 3807#endif
31e31b8a 3808 case TARGET_NR_sync:
04369ff2
FB
3809 sync();
3810 ret = 0;
31e31b8a
FB
3811 break;
3812 case TARGET_NR_kill:
4cb05961 3813 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
3814 break;
3815 case TARGET_NR_rename:
53a5960a
PB
3816 {
3817 void *p2;
3818 p = lock_user_string(arg1);
3819 p2 = lock_user_string(arg2);
579a97f7
FB
3820 if (!p || !p2)
3821 ret = -TARGET_EFAULT;
3822 else
3823 ret = get_errno(rename(p, p2));
53a5960a
PB
3824 unlock_user(p2, arg2, 0);
3825 unlock_user(p, arg1, 0);
3826 }
31e31b8a 3827 break;
722183f6
TS
3828#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3829 case TARGET_NR_renameat:
722183f6 3830 {
579a97f7 3831 void *p2;
722183f6
TS
3832 p = lock_user_string(arg2);
3833 p2 = lock_user_string(arg4);
579a97f7 3834 if (!p || !p2)
0da46a6e 3835 ret = -TARGET_EFAULT;
722183f6
TS
3836 else
3837 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
579a97f7
FB
3838 unlock_user(p2, arg4, 0);
3839 unlock_user(p, arg2, 0);
722183f6
TS
3840 }
3841 break;
3842#endif
31e31b8a 3843 case TARGET_NR_mkdir:
579a97f7
FB
3844 if (!(p = lock_user_string(arg1)))
3845 goto efault;
53a5960a
PB
3846 ret = get_errno(mkdir(p, arg2));
3847 unlock_user(p, arg1, 0);
31e31b8a 3848 break;
4472ad0d
TS
3849#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3850 case TARGET_NR_mkdirat:
579a97f7
FB
3851 if (!(p = lock_user_string(arg2)))
3852 goto efault;
3853 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3854 unlock_user(p, arg2, 0);
4472ad0d
TS
3855 break;
3856#endif
31e31b8a 3857 case TARGET_NR_rmdir:
579a97f7
FB
3858 if (!(p = lock_user_string(arg1)))
3859 goto efault;
53a5960a
PB
3860 ret = get_errno(rmdir(p));
3861 unlock_user(p, arg1, 0);
31e31b8a
FB
3862 break;
3863 case TARGET_NR_dup:
3864 ret = get_errno(dup(arg1));
3865 break;
3866 case TARGET_NR_pipe:
3867 {
53a5960a
PB
3868 int host_pipe[2];
3869 ret = get_errno(pipe(host_pipe));
31e31b8a 3870 if (!is_error(ret)) {
c12ab05c 3871#if defined(TARGET_MIPS)
ead9360e 3872 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
b5dc7732 3873 env->active_tc.gpr[3] = host_pipe[1];
c12ab05c 3874 ret = host_pipe[0];
b5eff355
AJ
3875#elif defined(TARGET_SH4)
3876 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3877 ret = host_pipe[0];
c12ab05c 3878#else
2f619698
FB
3879 if (put_user_s32(host_pipe[0], arg1)
3880 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3881 goto efault;
c12ab05c 3882#endif
31e31b8a
FB
3883 }
3884 }
3885 break;
3886 case TARGET_NR_times:
32f36bce 3887 {
53a5960a 3888 struct target_tms *tmsp;
32f36bce
FB
3889 struct tms tms;
3890 ret = get_errno(times(&tms));
53a5960a 3891 if (arg1) {
579a97f7
FB
3892 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3893 if (!tmsp)
3894 goto efault;
c596ed17
FB
3895 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3896 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3897 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3898 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
32f36bce 3899 }
c596ed17
FB
3900 if (!is_error(ret))
3901 ret = host_to_target_clock_t(ret);
32f36bce
FB
3902 }
3903 break;
ebc05488 3904#ifdef TARGET_NR_prof
31e31b8a
FB
3905 case TARGET_NR_prof:
3906 goto unimplemented;
ebc05488 3907#endif
e5febef5 3908#ifdef TARGET_NR_signal
31e31b8a
FB
3909 case TARGET_NR_signal:
3910 goto unimplemented;
e5febef5 3911#endif
31e31b8a 3912 case TARGET_NR_acct:
579a97f7
FB
3913 if (!(p = lock_user_string(arg1)))
3914 goto efault;
24836689
PB
3915 ret = get_errno(acct(path(p)));
3916 unlock_user(p, arg1, 0);
3917 break;
7a3148a9 3918#ifdef TARGET_NR_umount2 /* not on alpha */
31e31b8a 3919 case TARGET_NR_umount2:
579a97f7
FB
3920 if (!(p = lock_user_string(arg1)))
3921 goto efault;
53a5960a
PB
3922 ret = get_errno(umount2(p, arg2));
3923 unlock_user(p, arg1, 0);
31e31b8a 3924 break;
7a3148a9 3925#endif
ebc05488 3926#ifdef TARGET_NR_lock
31e31b8a
FB
3927 case TARGET_NR_lock:
3928 goto unimplemented;
ebc05488 3929#endif
31e31b8a
FB
3930 case TARGET_NR_ioctl:
3931 ret = do_ioctl(arg1, arg2, arg3);
3932 break;
3933 case TARGET_NR_fcntl:
9ee1fa2c 3934 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 3935 break;
ebc05488 3936#ifdef TARGET_NR_mpx
31e31b8a
FB
3937 case TARGET_NR_mpx:
3938 goto unimplemented;
ebc05488 3939#endif
31e31b8a
FB
3940 case TARGET_NR_setpgid:
3941 ret = get_errno(setpgid(arg1, arg2));
3942 break;
ebc05488 3943#ifdef TARGET_NR_ulimit
31e31b8a
FB
3944 case TARGET_NR_ulimit:
3945 goto unimplemented;
ebc05488
FB
3946#endif
3947#ifdef TARGET_NR_oldolduname
31e31b8a
FB
3948 case TARGET_NR_oldolduname:
3949 goto unimplemented;
ebc05488 3950#endif
31e31b8a
FB
3951 case TARGET_NR_umask:
3952 ret = get_errno(umask(arg1));
3953 break;
3954 case TARGET_NR_chroot:
579a97f7
FB
3955 if (!(p = lock_user_string(arg1)))
3956 goto efault;
53a5960a
PB
3957 ret = get_errno(chroot(p));
3958 unlock_user(p, arg1, 0);
31e31b8a
FB
3959 break;
3960 case TARGET_NR_ustat:
3961 goto unimplemented;
3962 case TARGET_NR_dup2:
3963 ret = get_errno(dup2(arg1, arg2));
3964 break;
7a3148a9 3965#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
3966 case TARGET_NR_getppid:
3967 ret = get_errno(getppid());
3968 break;
7a3148a9 3969#endif
31e31b8a
FB
3970 case TARGET_NR_getpgrp:
3971 ret = get_errno(getpgrp());
3972 break;
3973 case TARGET_NR_setsid:
3974 ret = get_errno(setsid());
3975 break;
e5febef5 3976#ifdef TARGET_NR_sigaction
31e31b8a 3977 case TARGET_NR_sigaction:
31e31b8a 3978 {
388bb21a 3979#if !defined(TARGET_MIPS)
53a5960a 3980 struct target_old_sigaction *old_act;
66fb9763 3981 struct target_sigaction act, oact, *pact;
53a5960a 3982 if (arg2) {
579a97f7
FB
3983 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3984 goto efault;
66fb9763
FB
3985 act._sa_handler = old_act->_sa_handler;
3986 target_siginitset(&act.sa_mask, old_act->sa_mask);
3987 act.sa_flags = old_act->sa_flags;
3988 act.sa_restorer = old_act->sa_restorer;
53a5960a 3989 unlock_user_struct(old_act, arg2, 0);
66fb9763
FB
3990 pact = &act;
3991 } else {
3992 pact = NULL;
3993 }
3994 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 3995 if (!is_error(ret) && arg3) {
579a97f7
FB
3996 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3997 goto efault;
53a5960a
PB
3998 old_act->_sa_handler = oact._sa_handler;
3999 old_act->sa_mask = oact.sa_mask.sig[0];
4000 old_act->sa_flags = oact.sa_flags;
4001 old_act->sa_restorer = oact.sa_restorer;
4002 unlock_user_struct(old_act, arg3, 1);
66fb9763 4003 }
388bb21a 4004#else
106ec879
FB
4005 struct target_sigaction act, oact, *pact, *old_act;
4006
4007 if (arg2) {
579a97f7
FB
4008 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4009 goto efault;
106ec879
FB
4010 act._sa_handler = old_act->_sa_handler;
4011 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4012 act.sa_flags = old_act->sa_flags;
4013 unlock_user_struct(old_act, arg2, 0);
4014 pact = &act;
4015 } else {
4016 pact = NULL;
4017 }
4018
4019 ret = get_errno(do_sigaction(arg1, pact, &oact));
4020
4021 if (!is_error(ret) && arg3) {
579a97f7
FB
4022 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4023 goto efault;
106ec879
FB
4024 old_act->_sa_handler = oact._sa_handler;
4025 old_act->sa_flags = oact.sa_flags;
4026 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4027 old_act->sa_mask.sig[1] = 0;
4028 old_act->sa_mask.sig[2] = 0;
4029 old_act->sa_mask.sig[3] = 0;
4030 unlock_user_struct(old_act, arg3, 1);
4031 }
388bb21a 4032#endif
31e31b8a
FB
4033 }
4034 break;
e5febef5 4035#endif
66fb9763 4036 case TARGET_NR_rt_sigaction:
53a5960a
PB
4037 {
4038 struct target_sigaction *act;
4039 struct target_sigaction *oact;
4040
579a97f7
FB
4041 if (arg2) {
4042 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4043 goto efault;
4044 } else
53a5960a 4045 act = NULL;
579a97f7
FB
4046 if (arg3) {
4047 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4048 ret = -TARGET_EFAULT;
4049 goto rt_sigaction_fail;
4050 }
4051 } else
53a5960a
PB
4052 oact = NULL;
4053 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
4054 rt_sigaction_fail:
4055 if (act)
53a5960a 4056 unlock_user_struct(act, arg2, 0);
579a97f7 4057 if (oact)
53a5960a
PB
4058 unlock_user_struct(oact, arg3, 1);
4059 }
66fb9763 4060 break;
7a3148a9 4061#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 4062 case TARGET_NR_sgetmask:
66fb9763
FB
4063 {
4064 sigset_t cur_set;
992f48a0 4065 abi_ulong target_set;
66fb9763
FB
4066 sigprocmask(0, NULL, &cur_set);
4067 host_to_target_old_sigset(&target_set, &cur_set);
4068 ret = target_set;
4069 }
4070 break;
7a3148a9
JM
4071#endif
4072#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 4073 case TARGET_NR_ssetmask:
66fb9763
FB
4074 {
4075 sigset_t set, oset, cur_set;
992f48a0 4076 abi_ulong target_set = arg1;
66fb9763
FB
4077 sigprocmask(0, NULL, &cur_set);
4078 target_to_host_old_sigset(&set, &target_set);
4079 sigorset(&set, &set, &cur_set);
4080 sigprocmask(SIG_SETMASK, &set, &oset);
4081 host_to_target_old_sigset(&target_set, &oset);
4082 ret = target_set;
4083 }
4084 break;
7a3148a9 4085#endif
e5febef5 4086#ifdef TARGET_NR_sigprocmask
66fb9763
FB
4087 case TARGET_NR_sigprocmask:
4088 {
4089 int how = arg1;
4090 sigset_t set, oldset, *set_ptr;
3b46e624 4091
53a5960a 4092 if (arg2) {
66fb9763
FB
4093 switch(how) {
4094 case TARGET_SIG_BLOCK:
4095 how = SIG_BLOCK;
4096 break;
4097 case TARGET_SIG_UNBLOCK:
4098 how = SIG_UNBLOCK;
4099 break;
4100 case TARGET_SIG_SETMASK:
4101 how = SIG_SETMASK;
4102 break;
4103 default:
0da46a6e 4104 ret = -TARGET_EINVAL;
66fb9763
FB
4105 goto fail;
4106 }
579a97f7
FB
4107 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4108 goto efault;
53a5960a
PB
4109 target_to_host_old_sigset(&set, p);
4110 unlock_user(p, arg2, 0);
66fb9763
FB
4111 set_ptr = &set;
4112 } else {
4113 how = 0;
4114 set_ptr = NULL;
4115 }
4116 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
53a5960a 4117 if (!is_error(ret) && arg3) {
579a97f7
FB
4118 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4119 goto efault;
53a5960a
PB
4120 host_to_target_old_sigset(p, &oldset);
4121 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
4122 }
4123 }
4124 break;
e5febef5 4125#endif
66fb9763
FB
4126 case TARGET_NR_rt_sigprocmask:
4127 {
4128 int how = arg1;
4129 sigset_t set, oldset, *set_ptr;
3b46e624 4130
53a5960a 4131 if (arg2) {
66fb9763
FB
4132 switch(how) {
4133 case TARGET_SIG_BLOCK:
4134 how = SIG_BLOCK;
4135 break;
4136 case TARGET_SIG_UNBLOCK:
4137 how = SIG_UNBLOCK;
4138 break;
4139 case TARGET_SIG_SETMASK:
4140 how = SIG_SETMASK;
4141 break;
4142 default:
0da46a6e 4143 ret = -TARGET_EINVAL;
66fb9763
FB
4144 goto fail;
4145 }
579a97f7
FB
4146 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4147 goto efault;
53a5960a
PB
4148 target_to_host_sigset(&set, p);
4149 unlock_user(p, arg2, 0);
66fb9763
FB
4150 set_ptr = &set;
4151 } else {
4152 how = 0;
4153 set_ptr = NULL;
4154 }
4155 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
53a5960a 4156 if (!is_error(ret) && arg3) {
579a97f7
FB
4157 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4158 goto efault;
53a5960a
PB
4159 host_to_target_sigset(p, &oldset);
4160 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
4161 }
4162 }
4163 break;
e5febef5 4164#ifdef TARGET_NR_sigpending
66fb9763
FB
4165 case TARGET_NR_sigpending:
4166 {
4167 sigset_t set;
4168 ret = get_errno(sigpending(&set));
4169 if (!is_error(ret)) {
579a97f7
FB
4170 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4171 goto efault;
53a5960a
PB
4172 host_to_target_old_sigset(p, &set);
4173 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
4174 }
4175 }
4176 break;
e5febef5 4177#endif
66fb9763
FB
4178 case TARGET_NR_rt_sigpending:
4179 {
4180 sigset_t set;
4181 ret = get_errno(sigpending(&set));
4182 if (!is_error(ret)) {
579a97f7
FB
4183 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4184 goto efault;
53a5960a
PB
4185 host_to_target_sigset(p, &set);
4186 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
4187 }
4188 }
4189 break;
e5febef5 4190#ifdef TARGET_NR_sigsuspend
66fb9763
FB
4191 case TARGET_NR_sigsuspend:
4192 {
4193 sigset_t set;
579a97f7
FB
4194 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4195 goto efault;
53a5960a
PB
4196 target_to_host_old_sigset(&set, p);
4197 unlock_user(p, arg1, 0);
66fb9763
FB
4198 ret = get_errno(sigsuspend(&set));
4199 }
4200 break;
e5febef5 4201#endif
66fb9763
FB
4202 case TARGET_NR_rt_sigsuspend:
4203 {
4204 sigset_t set;
579a97f7
FB
4205 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4206 goto efault;
53a5960a
PB
4207 target_to_host_sigset(&set, p);
4208 unlock_user(p, arg1, 0);
66fb9763
FB
4209 ret = get_errno(sigsuspend(&set));
4210 }
4211 break;
4212 case TARGET_NR_rt_sigtimedwait:
4213 {
66fb9763
FB
4214 sigset_t set;
4215 struct timespec uts, *puts;
4216 siginfo_t uinfo;
3b46e624 4217
579a97f7
FB
4218 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4219 goto efault;
53a5960a
PB
4220 target_to_host_sigset(&set, p);
4221 unlock_user(p, arg1, 0);
4222 if (arg3) {
66fb9763 4223 puts = &uts;
53a5960a 4224 target_to_host_timespec(puts, arg3);
66fb9763
FB
4225 } else {
4226 puts = NULL;
4227 }
4228 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
53a5960a 4229 if (!is_error(ret) && arg2) {
e1e3f30b 4230 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
579a97f7 4231 goto efault;
53a5960a 4232 host_to_target_siginfo(p, &uinfo);
e1e3f30b 4233 unlock_user(p, arg2, sizeof(target_siginfo_t));
66fb9763
FB
4234 }
4235 }
4236 break;
4237 case TARGET_NR_rt_sigqueueinfo:
4238 {
4239 siginfo_t uinfo;
579a97f7
FB
4240 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4241 goto efault;
53a5960a
PB
4242 target_to_host_siginfo(&uinfo, p);
4243 unlock_user(p, arg1, 0);
66fb9763
FB
4244 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4245 }
4246 break;
e5febef5 4247#ifdef TARGET_NR_sigreturn
66fb9763
FB
4248 case TARGET_NR_sigreturn:
4249 /* NOTE: ret is eax, so not transcoding must be done */
4250 ret = do_sigreturn(cpu_env);
4251 break;
e5febef5 4252#endif
66fb9763
FB
4253 case TARGET_NR_rt_sigreturn:
4254 /* NOTE: ret is eax, so not transcoding must be done */
4255 ret = do_rt_sigreturn(cpu_env);
4256 break;
31e31b8a 4257 case TARGET_NR_sethostname:
579a97f7
FB
4258 if (!(p = lock_user_string(arg1)))
4259 goto efault;
53a5960a
PB
4260 ret = get_errno(sethostname(p, arg2));
4261 unlock_user(p, arg1, 0);
31e31b8a
FB
4262 break;
4263 case TARGET_NR_setrlimit:
9de5e440
FB
4264 {
4265 /* XXX: convert resource ? */
4266 int resource = arg1;
53a5960a 4267 struct target_rlimit *target_rlim;
9de5e440 4268 struct rlimit rlim;
579a97f7
FB
4269 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4270 goto efault;
9de5e440
FB
4271 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4272 rlim.rlim_max = tswapl(target_rlim->rlim_max);
53a5960a 4273 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
4274 ret = get_errno(setrlimit(resource, &rlim));
4275 }
4276 break;
31e31b8a 4277 case TARGET_NR_getrlimit:
9de5e440
FB
4278 {
4279 /* XXX: convert resource ? */
4280 int resource = arg1;
53a5960a 4281 struct target_rlimit *target_rlim;
9de5e440 4282 struct rlimit rlim;
3b46e624 4283
9de5e440
FB
4284 ret = get_errno(getrlimit(resource, &rlim));
4285 if (!is_error(ret)) {
579a97f7
FB
4286 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4287 goto efault;
53a5960a
PB
4288 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4289 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4290 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
4291 }
4292 }
4293 break;
31e31b8a 4294 case TARGET_NR_getrusage:
b409186b
FB
4295 {
4296 struct rusage rusage;
b409186b
FB
4297 ret = get_errno(getrusage(arg1, &rusage));
4298 if (!is_error(ret)) {
53a5960a 4299 host_to_target_rusage(arg2, &rusage);
b409186b
FB
4300 }
4301 }
4302 break;
31e31b8a
FB
4303 case TARGET_NR_gettimeofday:
4304 {
31e31b8a
FB
4305 struct timeval tv;
4306 ret = get_errno(gettimeofday(&tv, NULL));
4307 if (!is_error(ret)) {
788f5ec4
TS
4308 if (copy_to_user_timeval(arg1, &tv))
4309 goto efault;
31e31b8a
FB
4310 }
4311 }
4312 break;
4313 case TARGET_NR_settimeofday:
4314 {
31e31b8a 4315 struct timeval tv;
788f5ec4
TS
4316 if (copy_from_user_timeval(&tv, arg1))
4317 goto efault;
31e31b8a
FB
4318 ret = get_errno(settimeofday(&tv, NULL));
4319 }
4320 break;
048f6b4d 4321#ifdef TARGET_NR_select
31e31b8a 4322 case TARGET_NR_select:
f2674e31 4323 {
53a5960a 4324 struct target_sel_arg_struct *sel;
992f48a0 4325 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
4326 long nsel;
4327
579a97f7
FB
4328 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4329 goto efault;
53a5960a
PB
4330 nsel = tswapl(sel->n);
4331 inp = tswapl(sel->inp);
4332 outp = tswapl(sel->outp);
4333 exp = tswapl(sel->exp);
4334 tvp = tswapl(sel->tvp);
4335 unlock_user_struct(sel, arg1, 0);
4336 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31
FB
4337 }
4338 break;
048f6b4d 4339#endif
31e31b8a 4340 case TARGET_NR_symlink:
53a5960a
PB
4341 {
4342 void *p2;
4343 p = lock_user_string(arg1);
4344 p2 = lock_user_string(arg2);
579a97f7
FB
4345 if (!p || !p2)
4346 ret = -TARGET_EFAULT;
4347 else
4348 ret = get_errno(symlink(p, p2));
53a5960a
PB
4349 unlock_user(p2, arg2, 0);
4350 unlock_user(p, arg1, 0);
4351 }
31e31b8a 4352 break;
f0b6243d
TS
4353#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4354 case TARGET_NR_symlinkat:
f0b6243d 4355 {
579a97f7 4356 void *p2;
f0b6243d
TS
4357 p = lock_user_string(arg1);
4358 p2 = lock_user_string(arg3);
579a97f7 4359 if (!p || !p2)
0da46a6e 4360 ret = -TARGET_EFAULT;
f0b6243d
TS
4361 else
4362 ret = get_errno(sys_symlinkat(p, arg2, p2));
579a97f7
FB
4363 unlock_user(p2, arg3, 0);
4364 unlock_user(p, arg1, 0);
f0b6243d
TS
4365 }
4366 break;
4367#endif
ebc05488 4368#ifdef TARGET_NR_oldlstat
31e31b8a
FB
4369 case TARGET_NR_oldlstat:
4370 goto unimplemented;
ebc05488 4371#endif
31e31b8a 4372 case TARGET_NR_readlink:
53a5960a
PB
4373 {
4374 void *p2;
4375 p = lock_user_string(arg1);
579a97f7
FB
4376 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4377 if (!p || !p2)
4378 ret = -TARGET_EFAULT;
4379 else
4380 ret = get_errno(readlink(path(p), p2, arg3));
53a5960a
PB
4381 unlock_user(p2, arg2, ret);
4382 unlock_user(p, arg1, 0);
4383 }
31e31b8a 4384 break;
5e0ccb18
TS
4385#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4386 case TARGET_NR_readlinkat:
5e0ccb18 4387 {
579a97f7 4388 void *p2;
5e0ccb18 4389 p = lock_user_string(arg2);
579a97f7
FB
4390 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4391 if (!p || !p2)
0da46a6e 4392 ret = -TARGET_EFAULT;
5e0ccb18
TS
4393 else
4394 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
579a97f7
FB
4395 unlock_user(p2, arg3, ret);
4396 unlock_user(p, arg2, 0);
5e0ccb18
TS
4397 }
4398 break;
4399#endif
e5febef5 4400#ifdef TARGET_NR_uselib
31e31b8a
FB
4401 case TARGET_NR_uselib:
4402 goto unimplemented;
e5febef5
TS
4403#endif
4404#ifdef TARGET_NR_swapon
31e31b8a 4405 case TARGET_NR_swapon:
579a97f7
FB
4406 if (!(p = lock_user_string(arg1)))
4407 goto efault;
53a5960a
PB
4408 ret = get_errno(swapon(p, arg2));
4409 unlock_user(p, arg1, 0);
31e31b8a 4410 break;
e5febef5 4411#endif
31e31b8a
FB
4412 case TARGET_NR_reboot:
4413 goto unimplemented;
e5febef5 4414#ifdef TARGET_NR_readdir
31e31b8a
FB
4415 case TARGET_NR_readdir:
4416 goto unimplemented;
e5febef5
TS
4417#endif
4418#ifdef TARGET_NR_mmap
31e31b8a 4419 case TARGET_NR_mmap:
d2fd1af7 4420#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
31e31b8a 4421 {
992f48a0
BS
4422 abi_ulong *v;
4423 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
4424 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4425 goto efault;
53a5960a
PB
4426 v1 = tswapl(v[0]);
4427 v2 = tswapl(v[1]);
4428 v3 = tswapl(v[2]);
4429 v4 = tswapl(v[3]);
4430 v5 = tswapl(v[4]);
4431 v6 = tswapl(v[5]);
4432 unlock_user(v, arg1, 0);
5fafdf24 4433 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
4434 target_to_host_bitmask(v4, mmap_flags_tbl),
4435 v5, v6));
31e31b8a 4436 }
31e31b8a 4437#else
5fafdf24
TS
4438 ret = get_errno(target_mmap(arg1, arg2, arg3,
4439 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
4440 arg5,
4441 arg6));
31e31b8a 4442#endif
6fb883e8 4443 break;
e5febef5 4444#endif
a315a145 4445#ifdef TARGET_NR_mmap2
6fb883e8 4446 case TARGET_NR_mmap2:
bb7ec043 4447#ifndef MMAP_SHIFT
c573ff67 4448#define MMAP_SHIFT 12
c573ff67 4449#endif
5fafdf24
TS
4450 ret = get_errno(target_mmap(arg1, arg2, arg3,
4451 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 4452 arg5,
c573ff67 4453 arg6 << MMAP_SHIFT));
31e31b8a 4454 break;
a315a145 4455#endif
31e31b8a 4456 case TARGET_NR_munmap:
54936004 4457 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 4458 break;
9de5e440 4459 case TARGET_NR_mprotect:
54936004 4460 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 4461 break;
e5febef5 4462#ifdef TARGET_NR_mremap
9de5e440 4463 case TARGET_NR_mremap:
54936004 4464 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 4465 break;
e5febef5 4466#endif
53a5960a 4467 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 4468#ifdef TARGET_NR_msync
9de5e440 4469 case TARGET_NR_msync:
53a5960a 4470 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 4471 break;
e5febef5
TS
4472#endif
4473#ifdef TARGET_NR_mlock
9de5e440 4474 case TARGET_NR_mlock:
53a5960a 4475 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 4476 break;
e5febef5
TS
4477#endif
4478#ifdef TARGET_NR_munlock
9de5e440 4479 case TARGET_NR_munlock:
53a5960a 4480 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 4481 break;
e5febef5
TS
4482#endif
4483#ifdef TARGET_NR_mlockall
9de5e440
FB
4484 case TARGET_NR_mlockall:
4485 ret = get_errno(mlockall(arg1));
4486 break;
e5febef5
TS
4487#endif
4488#ifdef TARGET_NR_munlockall
9de5e440
FB
4489 case TARGET_NR_munlockall:
4490 ret = get_errno(munlockall());
4491 break;
e5febef5 4492#endif
31e31b8a 4493 case TARGET_NR_truncate:
579a97f7
FB
4494 if (!(p = lock_user_string(arg1)))
4495 goto efault;
53a5960a
PB
4496 ret = get_errno(truncate(p, arg2));
4497 unlock_user(p, arg1, 0);
31e31b8a
FB
4498 break;
4499 case TARGET_NR_ftruncate:
4500 ret = get_errno(ftruncate(arg1, arg2));
4501 break;
4502 case TARGET_NR_fchmod:
4503 ret = get_errno(fchmod(arg1, arg2));
4504 break;
814d7977
TS
4505#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4506 case TARGET_NR_fchmodat:
579a97f7
FB
4507 if (!(p = lock_user_string(arg2)))
4508 goto efault;
4509 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4510 unlock_user(p, arg2, 0);
814d7977
TS
4511 break;
4512#endif
31e31b8a 4513 case TARGET_NR_getpriority:
c6cda17a
TS
4514 /* libc does special remapping of the return value of
4515 * sys_getpriority() so it's just easiest to call
4516 * sys_getpriority() directly rather than through libc. */
4517 ret = sys_getpriority(arg1, arg2);
31e31b8a
FB
4518 break;
4519 case TARGET_NR_setpriority:
4520 ret = get_errno(setpriority(arg1, arg2, arg3));
4521 break;
ebc05488 4522#ifdef TARGET_NR_profil
31e31b8a
FB
4523 case TARGET_NR_profil:
4524 goto unimplemented;
ebc05488 4525#endif
31e31b8a 4526 case TARGET_NR_statfs:
579a97f7
FB
4527 if (!(p = lock_user_string(arg1)))
4528 goto efault;
53a5960a
PB
4529 ret = get_errno(statfs(path(p), &stfs));
4530 unlock_user(p, arg1, 0);
31e31b8a
FB
4531 convert_statfs:
4532 if (!is_error(ret)) {
53a5960a 4533 struct target_statfs *target_stfs;
3b46e624 4534
579a97f7
FB
4535 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4536 goto efault;
4537 __put_user(stfs.f_type, &target_stfs->f_type);
4538 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4539 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4540 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4541 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4542 __put_user(stfs.f_files, &target_stfs->f_files);
4543 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4544 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4545 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4546 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
53a5960a 4547 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
4548 }
4549 break;
4550 case TARGET_NR_fstatfs:
56c8f68f 4551 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 4552 goto convert_statfs;
56c8f68f
FB
4553#ifdef TARGET_NR_statfs64
4554 case TARGET_NR_statfs64:
579a97f7
FB
4555 if (!(p = lock_user_string(arg1)))
4556 goto efault;
53a5960a
PB
4557 ret = get_errno(statfs(path(p), &stfs));
4558 unlock_user(p, arg1, 0);
56c8f68f
FB
4559 convert_statfs64:
4560 if (!is_error(ret)) {
53a5960a 4561 struct target_statfs64 *target_stfs;
3b46e624 4562
579a97f7
FB
4563 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4564 goto efault;
4565 __put_user(stfs.f_type, &target_stfs->f_type);
4566 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4567 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4568 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4569 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4570 __put_user(stfs.f_files, &target_stfs->f_files);
4571 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4572 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4573 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4574 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4575 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
4576 }
4577 break;
4578 case TARGET_NR_fstatfs64:
4579 ret = get_errno(fstatfs(arg1, &stfs));
4580 goto convert_statfs64;
4581#endif
ebc05488 4582#ifdef TARGET_NR_ioperm
31e31b8a
FB
4583 case TARGET_NR_ioperm:
4584 goto unimplemented;
ebc05488 4585#endif
e5febef5 4586#ifdef TARGET_NR_socketcall
31e31b8a 4587 case TARGET_NR_socketcall:
53a5960a 4588 ret = do_socketcall(arg1, arg2);
31e31b8a 4589 break;
e5febef5 4590#endif
3532fa74
FB
4591#ifdef TARGET_NR_accept
4592 case TARGET_NR_accept:
1be9e1dc 4593 ret = do_accept(arg1, arg2, arg3);
3532fa74
FB
4594 break;
4595#endif
4596#ifdef TARGET_NR_bind
4597 case TARGET_NR_bind:
4598 ret = do_bind(arg1, arg2, arg3);
4599 break;
4600#endif
4601#ifdef TARGET_NR_connect
4602 case TARGET_NR_connect:
4603 ret = do_connect(arg1, arg2, arg3);
4604 break;
4605#endif
4606#ifdef TARGET_NR_getpeername
4607 case TARGET_NR_getpeername:
1be9e1dc 4608 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
4609 break;
4610#endif
4611#ifdef TARGET_NR_getsockname
4612 case TARGET_NR_getsockname:
1be9e1dc 4613 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
4614 break;
4615#endif
4616#ifdef TARGET_NR_getsockopt
4617 case TARGET_NR_getsockopt:
4618 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4619 break;
4620#endif
4621#ifdef TARGET_NR_listen
4622 case TARGET_NR_listen:
1be9e1dc 4623 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
4624 break;
4625#endif
4626#ifdef TARGET_NR_recv
4627 case TARGET_NR_recv:
214201bd 4628 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
4629 break;
4630#endif
4631#ifdef TARGET_NR_recvfrom
4632 case TARGET_NR_recvfrom:
214201bd 4633 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
4634 break;
4635#endif
4636#ifdef TARGET_NR_recvmsg
4637 case TARGET_NR_recvmsg:
4638 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4639 break;
4640#endif
4641#ifdef TARGET_NR_send
4642 case TARGET_NR_send:
1be9e1dc 4643 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
4644 break;
4645#endif
4646#ifdef TARGET_NR_sendmsg
4647 case TARGET_NR_sendmsg:
4648 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4649 break;
4650#endif
4651#ifdef TARGET_NR_sendto
4652 case TARGET_NR_sendto:
1be9e1dc 4653 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
4654 break;
4655#endif
4656#ifdef TARGET_NR_shutdown
4657 case TARGET_NR_shutdown:
1be9e1dc 4658 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
4659 break;
4660#endif
4661#ifdef TARGET_NR_socket
4662 case TARGET_NR_socket:
4663 ret = do_socket(arg1, arg2, arg3);
4664 break;
4665#endif
4666#ifdef TARGET_NR_socketpair
4667 case TARGET_NR_socketpair:
1be9e1dc 4668 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
4669 break;
4670#endif
4671#ifdef TARGET_NR_setsockopt
4672 case TARGET_NR_setsockopt:
4673 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4674 break;
4675#endif
7494b0f9 4676
31e31b8a 4677 case TARGET_NR_syslog:
579a97f7
FB
4678 if (!(p = lock_user_string(arg2)))
4679 goto efault;
e5574487
TS
4680 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4681 unlock_user(p, arg2, 0);
7494b0f9
TS
4682 break;
4683
31e31b8a 4684 case TARGET_NR_setitimer:
66fb9763 4685 {
66fb9763
FB
4686 struct itimerval value, ovalue, *pvalue;
4687
53a5960a 4688 if (arg2) {
66fb9763 4689 pvalue = &value;
788f5ec4
TS
4690 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4691 || copy_from_user_timeval(&pvalue->it_value,
4692 arg2 + sizeof(struct target_timeval)))
4693 goto efault;
66fb9763
FB
4694 } else {
4695 pvalue = NULL;
4696 }
4697 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 4698 if (!is_error(ret) && arg3) {
788f5ec4
TS
4699 if (copy_to_user_timeval(arg3,
4700 &ovalue.it_interval)
4701 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4702 &ovalue.it_value))
4703 goto efault;
66fb9763
FB
4704 }
4705 }
4706 break;
31e31b8a 4707 case TARGET_NR_getitimer:
66fb9763 4708 {
66fb9763 4709 struct itimerval value;
3b46e624 4710
66fb9763 4711 ret = get_errno(getitimer(arg1, &value));
53a5960a 4712 if (!is_error(ret) && arg2) {
788f5ec4
TS
4713 if (copy_to_user_timeval(arg2,
4714 &value.it_interval)
4715 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4716 &value.it_value))
4717 goto efault;
66fb9763
FB
4718 }
4719 }
4720 break;
31e31b8a 4721 case TARGET_NR_stat:
579a97f7
FB
4722 if (!(p = lock_user_string(arg1)))
4723 goto efault;
53a5960a
PB
4724 ret = get_errno(stat(path(p), &st));
4725 unlock_user(p, arg1, 0);
31e31b8a
FB
4726 goto do_stat;
4727 case TARGET_NR_lstat:
579a97f7
FB
4728 if (!(p = lock_user_string(arg1)))
4729 goto efault;
53a5960a
PB
4730 ret = get_errno(lstat(path(p), &st));
4731 unlock_user(p, arg1, 0);
31e31b8a
FB
4732 goto do_stat;
4733 case TARGET_NR_fstat:
4734 {
4735 ret = get_errno(fstat(arg1, &st));
4736 do_stat:
4737 if (!is_error(ret)) {
53a5960a 4738 struct target_stat *target_st;
e3584658 4739
579a97f7
FB
4740 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4741 goto efault;
d2fd1af7
FB
4742 __put_user(st.st_dev, &target_st->st_dev);
4743 __put_user(st.st_ino, &target_st->st_ino);
4744 __put_user(st.st_mode, &target_st->st_mode);
4745 __put_user(st.st_uid, &target_st->st_uid);
4746 __put_user(st.st_gid, &target_st->st_gid);
4747 __put_user(st.st_nlink, &target_st->st_nlink);
4748 __put_user(st.st_rdev, &target_st->st_rdev);
4749 __put_user(st.st_size, &target_st->st_size);
4750 __put_user(st.st_blksize, &target_st->st_blksize);
4751 __put_user(st.st_blocks, &target_st->st_blocks);
4752 __put_user(st.st_atime, &target_st->target_st_atime);
4753 __put_user(st.st_mtime, &target_st->target_st_mtime);
4754 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 4755 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
4756 }
4757 }
4758 break;
ebc05488 4759#ifdef TARGET_NR_olduname
31e31b8a
FB
4760 case TARGET_NR_olduname:
4761 goto unimplemented;
ebc05488
FB
4762#endif
4763#ifdef TARGET_NR_iopl
31e31b8a
FB
4764 case TARGET_NR_iopl:
4765 goto unimplemented;
ebc05488 4766#endif
31e31b8a
FB
4767 case TARGET_NR_vhangup:
4768 ret = get_errno(vhangup());
4769 break;
ebc05488 4770#ifdef TARGET_NR_idle
31e31b8a
FB
4771 case TARGET_NR_idle:
4772 goto unimplemented;
42ad6ae9
FB
4773#endif
4774#ifdef TARGET_NR_syscall
4775 case TARGET_NR_syscall:
4776 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4777 break;
ebc05488 4778#endif
31e31b8a
FB
4779 case TARGET_NR_wait4:
4780 {
4781 int status;
992f48a0 4782 abi_long status_ptr = arg2;
31e31b8a 4783 struct rusage rusage, *rusage_ptr;
992f48a0 4784 abi_ulong target_rusage = arg4;
31e31b8a
FB
4785 if (target_rusage)
4786 rusage_ptr = &rusage;
4787 else
4788 rusage_ptr = NULL;
4789 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4790 if (!is_error(ret)) {
2f619698
FB
4791 if (status_ptr) {
4792 if (put_user_s32(status, status_ptr))
4793 goto efault;
31e31b8a 4794 }
2f619698
FB
4795 if (target_rusage)
4796 host_to_target_rusage(target_rusage, &rusage);
31e31b8a
FB
4797 }
4798 }
4799 break;
e5febef5 4800#ifdef TARGET_NR_swapoff
31e31b8a 4801 case TARGET_NR_swapoff:
579a97f7
FB
4802 if (!(p = lock_user_string(arg1)))
4803 goto efault;
53a5960a
PB
4804 ret = get_errno(swapoff(p));
4805 unlock_user(p, arg1, 0);
31e31b8a 4806 break;
e5febef5 4807#endif
31e31b8a 4808 case TARGET_NR_sysinfo:
a5448a7d 4809 {
53a5960a 4810 struct target_sysinfo *target_value;
a5448a7d
FB
4811 struct sysinfo value;
4812 ret = get_errno(sysinfo(&value));
53a5960a 4813 if (!is_error(ret) && arg1)
a5448a7d 4814 {
579a97f7
FB
4815 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4816 goto efault;
a5448a7d
FB
4817 __put_user(value.uptime, &target_value->uptime);
4818 __put_user(value.loads[0], &target_value->loads[0]);
4819 __put_user(value.loads[1], &target_value->loads[1]);
4820 __put_user(value.loads[2], &target_value->loads[2]);
4821 __put_user(value.totalram, &target_value->totalram);
4822 __put_user(value.freeram, &target_value->freeram);
4823 __put_user(value.sharedram, &target_value->sharedram);
4824 __put_user(value.bufferram, &target_value->bufferram);
4825 __put_user(value.totalswap, &target_value->totalswap);
4826 __put_user(value.freeswap, &target_value->freeswap);
4827 __put_user(value.procs, &target_value->procs);
4828 __put_user(value.totalhigh, &target_value->totalhigh);
4829 __put_user(value.freehigh, &target_value->freehigh);
4830 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 4831 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
4832 }
4833 }
4834 break;
e5febef5 4835#ifdef TARGET_NR_ipc
31e31b8a 4836 case TARGET_NR_ipc:
8853f86e
FB
4837 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4838 break;
e5febef5 4839#endif
eeb438c1
AJ
4840
4841#ifdef TARGET_NR_msgctl
4842 case TARGET_NR_msgctl:
4843 ret = do_msgctl(arg1, arg2, arg3);
4844 break;
4845#endif
4846#ifdef TARGET_NR_msgget
4847 case TARGET_NR_msgget:
4848 ret = get_errno(msgget(arg1, arg2));
4849 break;
4850#endif
4851#ifdef TARGET_NR_msgrcv
4852 case TARGET_NR_msgrcv:
4853 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
4854 break;
4855#endif
4856#ifdef TARGET_NR_msgsnd
4857 case TARGET_NR_msgsnd:
4858 ret = do_msgsnd(arg1, arg2, arg3, arg4);
4859 break;
4860#endif
31e31b8a
FB
4861 case TARGET_NR_fsync:
4862 ret = get_errno(fsync(arg1));
4863 break;
31e31b8a 4864 case TARGET_NR_clone:
0b6d3ae0
AJ
4865#if defined(TARGET_SH4)
4866 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
4867#else
d865bab5 4868 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
0b6d3ae0 4869#endif
1b6b029e 4870 break;
ec86b0fb
FB
4871#ifdef __NR_exit_group
4872 /* new thread calls */
4873 case TARGET_NR_exit_group:
6d946cda
AJ
4874#ifdef HAVE_GPROF
4875 _mcleanup();
4876#endif
e9009676 4877 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
4878 ret = get_errno(exit_group(arg1));
4879 break;
4880#endif
31e31b8a 4881 case TARGET_NR_setdomainname:
579a97f7
FB
4882 if (!(p = lock_user_string(arg1)))
4883 goto efault;
53a5960a
PB
4884 ret = get_errno(setdomainname(p, arg2));
4885 unlock_user(p, arg1, 0);
31e31b8a
FB
4886 break;
4887 case TARGET_NR_uname:
4888 /* no need to transcode because we use the linux syscall */
29e619b1
FB
4889 {
4890 struct new_utsname * buf;
3b46e624 4891
579a97f7
FB
4892 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4893 goto efault;
29e619b1
FB
4894 ret = get_errno(sys_uname(buf));
4895 if (!is_error(ret)) {
4896 /* Overrite the native machine name with whatever is being
4897 emulated. */
4898 strcpy (buf->machine, UNAME_MACHINE);
c5937220
PB
4899 /* Allow the user to override the reported release. */
4900 if (qemu_uname_release && *qemu_uname_release)
4901 strcpy (buf->release, qemu_uname_release);
29e619b1 4902 }
53a5960a 4903 unlock_user_struct(buf, arg1, 1);
29e619b1 4904 }
31e31b8a 4905 break;
6dbad63e 4906#ifdef TARGET_I386
31e31b8a 4907 case TARGET_NR_modify_ldt:
03acab66 4908 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 4909 break;
84409ddb 4910#if !defined(TARGET_X86_64)
5cd4393b
FB
4911 case TARGET_NR_vm86old:
4912 goto unimplemented;
4913 case TARGET_NR_vm86:
53a5960a 4914 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 4915 break;
84409ddb 4916#endif
6dbad63e 4917#endif
31e31b8a
FB
4918 case TARGET_NR_adjtimex:
4919 goto unimplemented;
e5febef5 4920#ifdef TARGET_NR_create_module
31e31b8a 4921 case TARGET_NR_create_module:
e5febef5 4922#endif
31e31b8a
FB
4923 case TARGET_NR_init_module:
4924 case TARGET_NR_delete_module:
e5febef5 4925#ifdef TARGET_NR_get_kernel_syms
31e31b8a 4926 case TARGET_NR_get_kernel_syms:
e5febef5 4927#endif
31e31b8a
FB
4928 goto unimplemented;
4929 case TARGET_NR_quotactl:
4930 goto unimplemented;
4931 case TARGET_NR_getpgid:
4932 ret = get_errno(getpgid(arg1));
4933 break;
4934 case TARGET_NR_fchdir:
4935 ret = get_errno(fchdir(arg1));
4936 break;
84409ddb 4937#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
4938 case TARGET_NR_bdflush:
4939 goto unimplemented;
84409ddb 4940#endif
e5febef5 4941#ifdef TARGET_NR_sysfs
31e31b8a
FB
4942 case TARGET_NR_sysfs:
4943 goto unimplemented;
e5febef5 4944#endif
31e31b8a 4945 case TARGET_NR_personality:
1b6b029e 4946 ret = get_errno(personality(arg1));
31e31b8a 4947 break;
e5febef5 4948#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
4949 case TARGET_NR_afs_syscall:
4950 goto unimplemented;
e5febef5 4951#endif
7a3148a9 4952#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
4953 case TARGET_NR__llseek:
4954 {
4f2ac237
FB
4955#if defined (__x86_64__)
4956 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
2f619698
FB
4957 if (put_user_s64(ret, arg4))
4958 goto efault;
4f2ac237 4959#else
31e31b8a
FB
4960 int64_t res;
4961 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
2f619698
FB
4962 if (put_user_s64(res, arg4))
4963 goto efault;
4f2ac237 4964#endif
31e31b8a
FB
4965 }
4966 break;
7a3148a9 4967#endif
31e31b8a 4968 case TARGET_NR_getdents:
992f48a0 4969#if TARGET_ABI_BITS != 32
53a5960a 4970 goto unimplemented;
992f48a0 4971#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 4972 {
53a5960a 4973 struct target_dirent *target_dirp;
6556a833 4974 struct linux_dirent *dirp;
992f48a0 4975 abi_long count = arg3;
4add45b4
FB
4976
4977 dirp = malloc(count);
0da46a6e 4978 if (!dirp) {
579a97f7 4979 ret = -TARGET_ENOMEM;
0da46a6e
TS
4980 goto fail;
4981 }
3b46e624 4982
4add45b4
FB
4983 ret = get_errno(sys_getdents(arg1, dirp, count));
4984 if (!is_error(ret)) {
6556a833 4985 struct linux_dirent *de;
4add45b4
FB
4986 struct target_dirent *tde;
4987 int len = ret;
4988 int reclen, treclen;
4989 int count1, tnamelen;
4990
4991 count1 = 0;
4992 de = dirp;
579a97f7
FB
4993 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4994 goto efault;
4add45b4
FB
4995 tde = target_dirp;
4996 while (len > 0) {
4997 reclen = de->d_reclen;
992f48a0 4998 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
4add45b4
FB
4999 tde->d_reclen = tswap16(treclen);
5000 tde->d_ino = tswapl(de->d_ino);
5001 tde->d_off = tswapl(de->d_off);
992f48a0 5002 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
4add45b4
FB
5003 if (tnamelen > 256)
5004 tnamelen = 256;
80a9d035 5005 /* XXX: may not be correct */
be15b141 5006 pstrcpy(tde->d_name, tnamelen, de->d_name);
6556a833 5007 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 5008 len -= reclen;
1c5bf3bf 5009 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
5010 count1 += treclen;
5011 }
5012 ret = count1;
579a97f7 5013 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
5014 }
5015 free(dirp);
5016 }
5017#else
31e31b8a 5018 {
6556a833 5019 struct linux_dirent *dirp;
992f48a0 5020 abi_long count = arg3;
dab2ed99 5021
579a97f7
FB
5022 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5023 goto efault;
72f03900 5024 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 5025 if (!is_error(ret)) {
6556a833 5026 struct linux_dirent *de;
31e31b8a
FB
5027 int len = ret;
5028 int reclen;
5029 de = dirp;
5030 while (len > 0) {
8083a3e5 5031 reclen = de->d_reclen;
31e31b8a
FB
5032 if (reclen > len)
5033 break;
8083a3e5 5034 de->d_reclen = tswap16(reclen);
31e31b8a
FB
5035 tswapls(&de->d_ino);
5036 tswapls(&de->d_off);
6556a833 5037 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
5038 len -= reclen;
5039 }
5040 }
53a5960a 5041 unlock_user(dirp, arg2, ret);
31e31b8a 5042 }
4add45b4 5043#endif
31e31b8a 5044 break;
3ae43202 5045#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
5046 case TARGET_NR_getdents64:
5047 {
6556a833 5048 struct linux_dirent64 *dirp;
992f48a0 5049 abi_long count = arg3;
579a97f7
FB
5050 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5051 goto efault;
dab2ed99
FB
5052 ret = get_errno(sys_getdents64(arg1, dirp, count));
5053 if (!is_error(ret)) {
6556a833 5054 struct linux_dirent64 *de;
dab2ed99
FB
5055 int len = ret;
5056 int reclen;
5057 de = dirp;
5058 while (len > 0) {
8083a3e5 5059 reclen = de->d_reclen;
dab2ed99
FB
5060 if (reclen > len)
5061 break;
8083a3e5 5062 de->d_reclen = tswap16(reclen);
8582a53a
FB
5063 tswap64s((uint64_t *)&de->d_ino);
5064 tswap64s((uint64_t *)&de->d_off);
6556a833 5065 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
5066 len -= reclen;
5067 }
5068 }
53a5960a 5069 unlock_user(dirp, arg2, ret);
dab2ed99
FB
5070 }
5071 break;
a541f297 5072#endif /* TARGET_NR_getdents64 */
e5febef5 5073#ifdef TARGET_NR__newselect
31e31b8a 5074 case TARGET_NR__newselect:
53a5960a 5075 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 5076 break;
e5febef5
TS
5077#endif
5078#ifdef TARGET_NR_poll
9de5e440
FB
5079 case TARGET_NR_poll:
5080 {
53a5960a 5081 struct target_pollfd *target_pfd;
9de5e440
FB
5082 unsigned int nfds = arg2;
5083 int timeout = arg3;
5084 struct pollfd *pfd;
7854b056 5085 unsigned int i;
9de5e440 5086
579a97f7
FB
5087 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5088 if (!target_pfd)
5089 goto efault;
9de5e440
FB
5090 pfd = alloca(sizeof(struct pollfd) * nfds);
5091 for(i = 0; i < nfds; i++) {
5cd4393b
FB
5092 pfd[i].fd = tswap32(target_pfd[i].fd);
5093 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440
FB
5094 }
5095 ret = get_errno(poll(pfd, nfds, timeout));
5096 if (!is_error(ret)) {
5097 for(i = 0; i < nfds; i++) {
5cd4393b 5098 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440 5099 }
53a5960a
PB
5100 ret += nfds * (sizeof(struct target_pollfd)
5101 - sizeof(struct pollfd));
9de5e440 5102 }
53a5960a 5103 unlock_user(target_pfd, arg1, ret);
9de5e440
FB
5104 }
5105 break;
e5febef5 5106#endif
31e31b8a 5107 case TARGET_NR_flock:
9de5e440
FB
5108 /* NOTE: the flock constant seems to be the same for every
5109 Linux platform */
5110 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
5111 break;
5112 case TARGET_NR_readv:
5113 {
5114 int count = arg3;
31e31b8a 5115 struct iovec *vec;
31e31b8a
FB
5116
5117 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
5118 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5119 goto efault;
31e31b8a 5120 ret = get_errno(readv(arg1, vec, count));
53a5960a 5121 unlock_iovec(vec, arg2, count, 1);
31e31b8a
FB
5122 }
5123 break;
5124 case TARGET_NR_writev:
5125 {
5126 int count = arg3;
31e31b8a 5127 struct iovec *vec;
31e31b8a
FB
5128
5129 vec = alloca(count * sizeof(struct iovec));
41df8411
FB
5130 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5131 goto efault;
31e31b8a 5132 ret = get_errno(writev(arg1, vec, count));
53a5960a 5133 unlock_iovec(vec, arg2, count, 0);
31e31b8a
FB
5134 }
5135 break;
5136 case TARGET_NR_getsid:
5137 ret = get_errno(getsid(arg1));
5138 break;
7a3148a9 5139#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 5140 case TARGET_NR_fdatasync:
5cd4393b
FB
5141 ret = get_errno(fdatasync(arg1));
5142 break;
7a3148a9 5143#endif
31e31b8a 5144 case TARGET_NR__sysctl:
0da46a6e 5145 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 5146 return value. */
0da46a6e
TS
5147 ret = -TARGET_ENOTDIR;
5148 break;
31e31b8a 5149 case TARGET_NR_sched_setparam:
5cd4393b 5150 {
53a5960a 5151 struct sched_param *target_schp;
5cd4393b 5152 struct sched_param schp;
53a5960a 5153
579a97f7
FB
5154 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5155 goto efault;
5cd4393b 5156 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 5157 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
5158 ret = get_errno(sched_setparam(arg1, &schp));
5159 }
5160 break;
31e31b8a 5161 case TARGET_NR_sched_getparam:
5cd4393b 5162 {
53a5960a 5163 struct sched_param *target_schp;
5cd4393b
FB
5164 struct sched_param schp;
5165 ret = get_errno(sched_getparam(arg1, &schp));
5166 if (!is_error(ret)) {
579a97f7
FB
5167 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5168 goto efault;
5cd4393b 5169 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 5170 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
5171 }
5172 }
5173 break;
31e31b8a 5174 case TARGET_NR_sched_setscheduler:
5cd4393b 5175 {
53a5960a 5176 struct sched_param *target_schp;
5cd4393b 5177 struct sched_param schp;
579a97f7
FB
5178 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5179 goto efault;
5cd4393b 5180 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 5181 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
5182 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5183 }
5184 break;
31e31b8a 5185 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
5186 ret = get_errno(sched_getscheduler(arg1));
5187 break;
31e31b8a
FB
5188 case TARGET_NR_sched_yield:
5189 ret = get_errno(sched_yield());
5190 break;
5191 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
5192 ret = get_errno(sched_get_priority_max(arg1));
5193 break;
31e31b8a 5194 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
5195 ret = get_errno(sched_get_priority_min(arg1));
5196 break;
31e31b8a 5197 case TARGET_NR_sched_rr_get_interval:
5cd4393b 5198 {
5cd4393b
FB
5199 struct timespec ts;
5200 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5201 if (!is_error(ret)) {
53a5960a 5202 host_to_target_timespec(arg2, &ts);
5cd4393b
FB
5203 }
5204 }
5205 break;
31e31b8a 5206 case TARGET_NR_nanosleep:
1b6b029e 5207 {
1b6b029e 5208 struct timespec req, rem;
53a5960a 5209 target_to_host_timespec(&req, arg1);
1b6b029e 5210 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
5211 if (is_error(ret) && arg2) {
5212 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
5213 }
5214 }
5215 break;
e5febef5 5216#ifdef TARGET_NR_query_module
31e31b8a 5217 case TARGET_NR_query_module:
5cd4393b 5218 goto unimplemented;
e5febef5
TS
5219#endif
5220#ifdef TARGET_NR_nfsservctl
31e31b8a 5221 case TARGET_NR_nfsservctl:
5cd4393b 5222 goto unimplemented;
e5febef5 5223#endif
31e31b8a 5224 case TARGET_NR_prctl:
e5574487
TS
5225 switch (arg1)
5226 {
5227 case PR_GET_PDEATHSIG:
5228 {
5229 int deathsig;
5230 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
2f619698
FB
5231 if (!is_error(ret) && arg2
5232 && put_user_ual(deathsig, arg2))
5233 goto efault;
e5574487
TS
5234 }
5235 break;
5236 default:
5237 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5238 break;
5239 }
39b9aae1 5240 break;
d2fd1af7
FB
5241#ifdef TARGET_NR_arch_prctl
5242 case TARGET_NR_arch_prctl:
5243#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5244 ret = do_arch_prctl(cpu_env, arg1, arg2);
5245 break;
5246#else
5247 goto unimplemented;
5248#endif
5249#endif
67867308 5250#ifdef TARGET_NR_pread
31e31b8a 5251 case TARGET_NR_pread:
a4ae00bc
AZ
5252#ifdef TARGET_ARM
5253 if (((CPUARMState *)cpu_env)->eabi)
5254 arg4 = arg5;
5255#endif
579a97f7
FB
5256 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5257 goto efault;
53a5960a
PB
5258 ret = get_errno(pread(arg1, p, arg3, arg4));
5259 unlock_user(p, arg2, ret);
206f0fa7 5260 break;
31e31b8a 5261 case TARGET_NR_pwrite:
a4ae00bc
AZ
5262#ifdef TARGET_ARM
5263 if (((CPUARMState *)cpu_env)->eabi)
5264 arg4 = arg5;
5265#endif
579a97f7
FB
5266 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5267 goto efault;
53a5960a
PB
5268 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5269 unlock_user(p, arg2, 0);
206f0fa7 5270 break;
f2c7ba15
AJ
5271#endif
5272#ifdef TARGET_NR_pread64
5273 case TARGET_NR_pread64:
5274 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5275 goto efault;
5276 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5277 unlock_user(p, arg2, ret);
5278 break;
5279 case TARGET_NR_pwrite64:
5280 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5281 goto efault;
5282 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5283 unlock_user(p, arg2, 0);
5284 break;
67867308 5285#endif
31e31b8a 5286 case TARGET_NR_getcwd:
579a97f7
FB
5287 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5288 goto efault;
53a5960a
PB
5289 ret = get_errno(sys_getcwd1(p, arg2));
5290 unlock_user(p, arg1, ret);
31e31b8a
FB
5291 break;
5292 case TARGET_NR_capget:
5cd4393b 5293 goto unimplemented;
31e31b8a 5294 case TARGET_NR_capset:
5cd4393b 5295 goto unimplemented;
31e31b8a 5296 case TARGET_NR_sigaltstack:
198a74de
TS
5297#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5298 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
579a97f7 5299 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
a04e134a
TS
5300 break;
5301#else
5cd4393b 5302 goto unimplemented;
a04e134a 5303#endif
31e31b8a 5304 case TARGET_NR_sendfile:
5cd4393b 5305 goto unimplemented;
ebc05488 5306#ifdef TARGET_NR_getpmsg
31e31b8a 5307 case TARGET_NR_getpmsg:
5cd4393b 5308 goto unimplemented;
ebc05488
FB
5309#endif
5310#ifdef TARGET_NR_putpmsg
31e31b8a 5311 case TARGET_NR_putpmsg:
5cd4393b 5312 goto unimplemented;
ebc05488 5313#endif
048f6b4d 5314#ifdef TARGET_NR_vfork
31e31b8a 5315 case TARGET_NR_vfork:
d865bab5
PB
5316 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5317 0, 0, 0, 0));
31e31b8a 5318 break;
048f6b4d 5319#endif
ebc05488 5320#ifdef TARGET_NR_ugetrlimit
31e31b8a 5321 case TARGET_NR_ugetrlimit:
728584be
FB
5322 {
5323 struct rlimit rlim;
5324 ret = get_errno(getrlimit(arg1, &rlim));
5325 if (!is_error(ret)) {
53a5960a 5326 struct target_rlimit *target_rlim;
579a97f7
FB
5327 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5328 goto efault;
728584be
FB
5329 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5330 target_rlim->rlim_max = tswapl(rlim.rlim_max);
53a5960a 5331 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
5332 }
5333 break;
5334 }
ebc05488 5335#endif
a315a145 5336#ifdef TARGET_NR_truncate64
31e31b8a 5337 case TARGET_NR_truncate64:
579a97f7
FB
5338 if (!(p = lock_user_string(arg1)))
5339 goto efault;
53a5960a
PB
5340 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5341 unlock_user(p, arg1, 0);
667f38b1 5342 break;
a315a145
FB
5343#endif
5344#ifdef TARGET_NR_ftruncate64
31e31b8a 5345 case TARGET_NR_ftruncate64:
ce4defa0 5346 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 5347 break;
a315a145
FB
5348#endif
5349#ifdef TARGET_NR_stat64
31e31b8a 5350 case TARGET_NR_stat64:
579a97f7
FB
5351 if (!(p = lock_user_string(arg1)))
5352 goto efault;
53a5960a
PB
5353 ret = get_errno(stat(path(p), &st));
5354 unlock_user(p, arg1, 0);
6a24a778
AZ
5355 if (!is_error(ret))
5356 ret = host_to_target_stat64(cpu_env, arg2, &st);
5357 break;
a315a145
FB
5358#endif
5359#ifdef TARGET_NR_lstat64
31e31b8a 5360 case TARGET_NR_lstat64:
579a97f7
FB
5361 if (!(p = lock_user_string(arg1)))
5362 goto efault;
53a5960a
PB
5363 ret = get_errno(lstat(path(p), &st));
5364 unlock_user(p, arg1, 0);
6a24a778
AZ
5365 if (!is_error(ret))
5366 ret = host_to_target_stat64(cpu_env, arg2, &st);
5367 break;
a315a145
FB
5368#endif
5369#ifdef TARGET_NR_fstat64
31e31b8a 5370 case TARGET_NR_fstat64:
6a24a778
AZ
5371 ret = get_errno(fstat(arg1, &st));
5372 if (!is_error(ret))
5373 ret = host_to_target_stat64(cpu_env, arg2, &st);
5374 break;
ce4defa0 5375#endif
6a24a778
AZ
5376#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5377 case TARGET_NR_fstatat64:
5378 if (!(p = lock_user_string(arg2)))
5379 goto efault;
5380 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5381 if (!is_error(ret))
5382 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 5383 break;
a315a145 5384#endif
67867308
FB
5385#ifdef USE_UID16
5386 case TARGET_NR_lchown:
579a97f7
FB
5387 if (!(p = lock_user_string(arg1)))
5388 goto efault;
53a5960a
PB
5389 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5390 unlock_user(p, arg1, 0);
67867308
FB
5391 break;
5392 case TARGET_NR_getuid:
5393 ret = get_errno(high2lowuid(getuid()));
5394 break;
5395 case TARGET_NR_getgid:
5396 ret = get_errno(high2lowgid(getgid()));
5397 break;
5398 case TARGET_NR_geteuid:
5399 ret = get_errno(high2lowuid(geteuid()));
5400 break;
5401 case TARGET_NR_getegid:
5402 ret = get_errno(high2lowgid(getegid()));
5403 break;
5404 case TARGET_NR_setreuid:
5405 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5406 break;
5407 case TARGET_NR_setregid:
5408 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5409 break;
5410 case TARGET_NR_getgroups:
5411 {
5412 int gidsetsize = arg1;
53a5960a 5413 uint16_t *target_grouplist;
67867308
FB
5414 gid_t *grouplist;
5415 int i;
5416
5417 grouplist = alloca(gidsetsize * sizeof(gid_t));
5418 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
5419 if (gidsetsize == 0)
5420 break;
67867308 5421 if (!is_error(ret)) {
579a97f7
FB
5422 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5423 if (!target_grouplist)
5424 goto efault;
a2155fcc 5425 for(i = 0;i < ret; i++)
67867308 5426 target_grouplist[i] = tswap16(grouplist[i]);
53a5960a 5427 unlock_user(target_grouplist, arg2, gidsetsize * 2);
67867308
FB
5428 }
5429 }
5430 break;
5431 case TARGET_NR_setgroups:
5432 {
5433 int gidsetsize = arg1;
53a5960a 5434 uint16_t *target_grouplist;
67867308
FB
5435 gid_t *grouplist;
5436 int i;
5437
5438 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
5439 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5440 if (!target_grouplist) {
5441 ret = -TARGET_EFAULT;
5442 goto fail;
5443 }
67867308
FB
5444 for(i = 0;i < gidsetsize; i++)
5445 grouplist[i] = tswap16(target_grouplist[i]);
53a5960a 5446 unlock_user(target_grouplist, arg2, 0);
67867308
FB
5447 ret = get_errno(setgroups(gidsetsize, grouplist));
5448 }
5449 break;
5450 case TARGET_NR_fchown:
5451 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5452 break;
ccfa72b7
TS
5453#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5454 case TARGET_NR_fchownat:
579a97f7
FB
5455 if (!(p = lock_user_string(arg2)))
5456 goto efault;
5457 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5458 unlock_user(p, arg2, 0);
ccfa72b7
TS
5459 break;
5460#endif
67867308
FB
5461#ifdef TARGET_NR_setresuid
5462 case TARGET_NR_setresuid:
5fafdf24
TS
5463 ret = get_errno(setresuid(low2highuid(arg1),
5464 low2highuid(arg2),
67867308
FB
5465 low2highuid(arg3)));
5466 break;
5467#endif
5468#ifdef TARGET_NR_getresuid
5469 case TARGET_NR_getresuid:
5470 {
53a5960a 5471 uid_t ruid, euid, suid;
67867308
FB
5472 ret = get_errno(getresuid(&ruid, &euid, &suid));
5473 if (!is_error(ret)) {
2f619698
FB
5474 if (put_user_u16(high2lowuid(ruid), arg1)
5475 || put_user_u16(high2lowuid(euid), arg2)
5476 || put_user_u16(high2lowuid(suid), arg3))
5477 goto efault;
67867308
FB
5478 }
5479 }
5480 break;
5481#endif
5482#ifdef TARGET_NR_getresgid
5483 case TARGET_NR_setresgid:
5fafdf24
TS
5484 ret = get_errno(setresgid(low2highgid(arg1),
5485 low2highgid(arg2),
67867308
FB
5486 low2highgid(arg3)));
5487 break;
5488#endif
5489#ifdef TARGET_NR_getresgid
5490 case TARGET_NR_getresgid:
5491 {
53a5960a 5492 gid_t rgid, egid, sgid;
67867308
FB
5493 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5494 if (!is_error(ret)) {
2f619698
FB
5495 if (put_user_u16(high2lowgid(rgid), arg1)
5496 || put_user_u16(high2lowgid(egid), arg2)
5497 || put_user_u16(high2lowgid(sgid), arg3))
5498 goto efault;
67867308
FB
5499 }
5500 }
5501 break;
5502#endif
5503 case TARGET_NR_chown:
579a97f7
FB
5504 if (!(p = lock_user_string(arg1)))
5505 goto efault;
53a5960a
PB
5506 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5507 unlock_user(p, arg1, 0);
67867308
FB
5508 break;
5509 case TARGET_NR_setuid:
5510 ret = get_errno(setuid(low2highuid(arg1)));
5511 break;
5512 case TARGET_NR_setgid:
5513 ret = get_errno(setgid(low2highgid(arg1)));
5514 break;
5515 case TARGET_NR_setfsuid:
5516 ret = get_errno(setfsuid(arg1));
5517 break;
5518 case TARGET_NR_setfsgid:
5519 ret = get_errno(setfsgid(arg1));
5520 break;
5521#endif /* USE_UID16 */
5522
a315a145 5523#ifdef TARGET_NR_lchown32
31e31b8a 5524 case TARGET_NR_lchown32:
579a97f7
FB
5525 if (!(p = lock_user_string(arg1)))
5526 goto efault;
53a5960a
PB
5527 ret = get_errno(lchown(p, arg2, arg3));
5528 unlock_user(p, arg1, 0);
b03c60f3 5529 break;
a315a145
FB
5530#endif
5531#ifdef TARGET_NR_getuid32
31e31b8a 5532 case TARGET_NR_getuid32:
b03c60f3
FB
5533 ret = get_errno(getuid());
5534 break;
a315a145
FB
5535#endif
5536#ifdef TARGET_NR_getgid32
31e31b8a 5537 case TARGET_NR_getgid32:
b03c60f3
FB
5538 ret = get_errno(getgid());
5539 break;
a315a145
FB
5540#endif
5541#ifdef TARGET_NR_geteuid32
31e31b8a 5542 case TARGET_NR_geteuid32:
b03c60f3
FB
5543 ret = get_errno(geteuid());
5544 break;
a315a145
FB
5545#endif
5546#ifdef TARGET_NR_getegid32
31e31b8a 5547 case TARGET_NR_getegid32:
b03c60f3
FB
5548 ret = get_errno(getegid());
5549 break;
a315a145
FB
5550#endif
5551#ifdef TARGET_NR_setreuid32
31e31b8a 5552 case TARGET_NR_setreuid32:
b03c60f3
FB
5553 ret = get_errno(setreuid(arg1, arg2));
5554 break;
a315a145
FB
5555#endif
5556#ifdef TARGET_NR_setregid32
31e31b8a 5557 case TARGET_NR_setregid32:
b03c60f3
FB
5558 ret = get_errno(setregid(arg1, arg2));
5559 break;
a315a145
FB
5560#endif
5561#ifdef TARGET_NR_getgroups32
31e31b8a 5562 case TARGET_NR_getgroups32:
99c475ab
FB
5563 {
5564 int gidsetsize = arg1;
53a5960a 5565 uint32_t *target_grouplist;
99c475ab
FB
5566 gid_t *grouplist;
5567 int i;
5568
5569 grouplist = alloca(gidsetsize * sizeof(gid_t));
5570 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
5571 if (gidsetsize == 0)
5572 break;
99c475ab 5573 if (!is_error(ret)) {
579a97f7
FB
5574 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5575 if (!target_grouplist) {
5576 ret = -TARGET_EFAULT;
5577 goto fail;
5578 }
a2155fcc 5579 for(i = 0;i < ret; i++)
53a5960a
PB
5580 target_grouplist[i] = tswap32(grouplist[i]);
5581 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
5582 }
5583 }
5584 break;
a315a145
FB
5585#endif
5586#ifdef TARGET_NR_setgroups32
31e31b8a 5587 case TARGET_NR_setgroups32:
99c475ab
FB
5588 {
5589 int gidsetsize = arg1;
53a5960a 5590 uint32_t *target_grouplist;
99c475ab
FB
5591 gid_t *grouplist;
5592 int i;
3b46e624 5593
99c475ab 5594 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
5595 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5596 if (!target_grouplist) {
5597 ret = -TARGET_EFAULT;
5598 goto fail;
5599 }
99c475ab 5600 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
5601 grouplist[i] = tswap32(target_grouplist[i]);
5602 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
5603 ret = get_errno(setgroups(gidsetsize, grouplist));
5604 }
5605 break;
a315a145
FB
5606#endif
5607#ifdef TARGET_NR_fchown32
31e31b8a 5608 case TARGET_NR_fchown32:
b03c60f3
FB
5609 ret = get_errno(fchown(arg1, arg2, arg3));
5610 break;
a315a145
FB
5611#endif
5612#ifdef TARGET_NR_setresuid32
31e31b8a 5613 case TARGET_NR_setresuid32:
b03c60f3
FB
5614 ret = get_errno(setresuid(arg1, arg2, arg3));
5615 break;
a315a145
FB
5616#endif
5617#ifdef TARGET_NR_getresuid32
31e31b8a 5618 case TARGET_NR_getresuid32:
b03c60f3 5619 {
53a5960a 5620 uid_t ruid, euid, suid;
b03c60f3
FB
5621 ret = get_errno(getresuid(&ruid, &euid, &suid));
5622 if (!is_error(ret)) {
2f619698
FB
5623 if (put_user_u32(ruid, arg1)
5624 || put_user_u32(euid, arg2)
5625 || put_user_u32(suid, arg3))
5626 goto efault;
b03c60f3
FB
5627 }
5628 }
5629 break;
a315a145
FB
5630#endif
5631#ifdef TARGET_NR_setresgid32
31e31b8a 5632 case TARGET_NR_setresgid32:
b03c60f3
FB
5633 ret = get_errno(setresgid(arg1, arg2, arg3));
5634 break;
a315a145
FB
5635#endif
5636#ifdef TARGET_NR_getresgid32
31e31b8a 5637 case TARGET_NR_getresgid32:
b03c60f3 5638 {
53a5960a 5639 gid_t rgid, egid, sgid;
b03c60f3
FB
5640 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5641 if (!is_error(ret)) {
2f619698
FB
5642 if (put_user_u32(rgid, arg1)
5643 || put_user_u32(egid, arg2)
5644 || put_user_u32(sgid, arg3))
5645 goto efault;
b03c60f3
FB
5646 }
5647 }
5648 break;
a315a145
FB
5649#endif
5650#ifdef TARGET_NR_chown32
31e31b8a 5651 case TARGET_NR_chown32:
579a97f7
FB
5652 if (!(p = lock_user_string(arg1)))
5653 goto efault;
53a5960a
PB
5654 ret = get_errno(chown(p, arg2, arg3));
5655 unlock_user(p, arg1, 0);
b03c60f3 5656 break;
a315a145
FB
5657#endif
5658#ifdef TARGET_NR_setuid32
31e31b8a 5659 case TARGET_NR_setuid32:
b03c60f3
FB
5660 ret = get_errno(setuid(arg1));
5661 break;
a315a145
FB
5662#endif
5663#ifdef TARGET_NR_setgid32
31e31b8a 5664 case TARGET_NR_setgid32:
b03c60f3
FB
5665 ret = get_errno(setgid(arg1));
5666 break;
a315a145
FB
5667#endif
5668#ifdef TARGET_NR_setfsuid32
31e31b8a 5669 case TARGET_NR_setfsuid32:
b03c60f3
FB
5670 ret = get_errno(setfsuid(arg1));
5671 break;
a315a145
FB
5672#endif
5673#ifdef TARGET_NR_setfsgid32
31e31b8a 5674 case TARGET_NR_setfsgid32:
b03c60f3
FB
5675 ret = get_errno(setfsgid(arg1));
5676 break;
a315a145 5677#endif
67867308 5678
31e31b8a 5679 case TARGET_NR_pivot_root:
b03c60f3 5680 goto unimplemented;
ffa65c3b 5681#ifdef TARGET_NR_mincore
31e31b8a 5682 case TARGET_NR_mincore:
04bb9ace
AJ
5683 {
5684 void *a;
5685 ret = -TARGET_EFAULT;
5686 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
5687 goto efault;
5688 if (!(p = lock_user_string(arg3)))
5689 goto mincore_fail;
5690 ret = get_errno(mincore(a, arg2, p));
5691 unlock_user(p, arg3, ret);
5692 mincore_fail:
5693 unlock_user(a, arg1, 0);
5694 }
5695 break;
ffa65c3b 5696#endif
408321b6
AJ
5697#ifdef TARGET_NR_arm_fadvise64_64
5698 case TARGET_NR_arm_fadvise64_64:
5699 {
5700 /*
5701 * arm_fadvise64_64 looks like fadvise64_64 but
5702 * with different argument order
5703 */
5704 abi_long temp;
5705 temp = arg3;
5706 arg3 = arg4;
5707 arg4 = temp;
5708 }
5709#endif
5710#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
5711#ifdef TARGET_NR_fadvise64_64
5712 case TARGET_NR_fadvise64_64:
5713#endif
5714 /* This is a hint, so ignoring and returning success is ok. */
5715 ret = get_errno(0);
5716 break;
5717#endif
ffa65c3b 5718#ifdef TARGET_NR_madvise
31e31b8a 5719 case TARGET_NR_madvise:
24836689
PB
5720 /* A straight passthrough may not be safe because qemu sometimes
5721 turns private flie-backed mappings into anonymous mappings.
5722 This will break MADV_DONTNEED.
5723 This is a hint, so ignoring and returning success is ok. */
5724 ret = get_errno(0);
5725 break;
ffa65c3b 5726#endif
992f48a0 5727#if TARGET_ABI_BITS == 32
31e31b8a 5728 case TARGET_NR_fcntl64:
77e4672d 5729 {
b1e341eb 5730 int cmd;
77e4672d 5731 struct flock64 fl;
53a5960a 5732 struct target_flock64 *target_fl;
ce4defa0 5733#ifdef TARGET_ARM
53a5960a 5734 struct target_eabi_flock64 *target_efl;
ce4defa0 5735#endif
77e4672d 5736
b1e341eb
TS
5737 switch(arg2){
5738 case TARGET_F_GETLK64:
5739 cmd = F_GETLK64;
a7222580 5740 break;
b1e341eb
TS
5741 case TARGET_F_SETLK64:
5742 cmd = F_SETLK64;
a7222580 5743 break;
b1e341eb
TS
5744 case TARGET_F_SETLKW64:
5745 cmd = F_SETLK64;
a7222580 5746 break;
b1e341eb
TS
5747 default:
5748 cmd = arg2;
a7222580 5749 break;
b1e341eb
TS
5750 }
5751
60cd49d5 5752 switch(arg2) {
b1e341eb 5753 case TARGET_F_GETLK64:
5813427b
TS
5754#ifdef TARGET_ARM
5755 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5756 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5757 goto efault;
5813427b
TS
5758 fl.l_type = tswap16(target_efl->l_type);
5759 fl.l_whence = tswap16(target_efl->l_whence);
5760 fl.l_start = tswap64(target_efl->l_start);
5761 fl.l_len = tswap64(target_efl->l_len);
5762 fl.l_pid = tswapl(target_efl->l_pid);
5763 unlock_user_struct(target_efl, arg3, 0);
5764 } else
5765#endif
5766 {
9ee1fa2c
FB
5767 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5768 goto efault;
5813427b
TS
5769 fl.l_type = tswap16(target_fl->l_type);
5770 fl.l_whence = tswap16(target_fl->l_whence);
5771 fl.l_start = tswap64(target_fl->l_start);
5772 fl.l_len = tswap64(target_fl->l_len);
5773 fl.l_pid = tswapl(target_fl->l_pid);
5774 unlock_user_struct(target_fl, arg3, 0);
5775 }
b1e341eb 5776 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 5777 if (ret == 0) {
ce4defa0
PB
5778#ifdef TARGET_ARM
5779 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5780 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5781 goto efault;
ce4defa0
PB
5782 target_efl->l_type = tswap16(fl.l_type);
5783 target_efl->l_whence = tswap16(fl.l_whence);
5784 target_efl->l_start = tswap64(fl.l_start);
5785 target_efl->l_len = tswap64(fl.l_len);
5786 target_efl->l_pid = tswapl(fl.l_pid);
53a5960a 5787 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
5788 } else
5789#endif
5790 {
9ee1fa2c
FB
5791 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5792 goto efault;
ce4defa0
PB
5793 target_fl->l_type = tswap16(fl.l_type);
5794 target_fl->l_whence = tswap16(fl.l_whence);
5795 target_fl->l_start = tswap64(fl.l_start);
5796 target_fl->l_len = tswap64(fl.l_len);
5797 target_fl->l_pid = tswapl(fl.l_pid);
53a5960a 5798 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 5799 }
77e4672d
FB
5800 }
5801 break;
5802
b1e341eb
TS
5803 case TARGET_F_SETLK64:
5804 case TARGET_F_SETLKW64:
ce4defa0
PB
5805#ifdef TARGET_ARM
5806 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
5807 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5808 goto efault;
ce4defa0
PB
5809 fl.l_type = tswap16(target_efl->l_type);
5810 fl.l_whence = tswap16(target_efl->l_whence);
5811 fl.l_start = tswap64(target_efl->l_start);
5812 fl.l_len = tswap64(target_efl->l_len);
5813 fl.l_pid = tswapl(target_efl->l_pid);
53a5960a 5814 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
5815 } else
5816#endif
5817 {
9ee1fa2c
FB
5818 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5819 goto efault;
ce4defa0
PB
5820 fl.l_type = tswap16(target_fl->l_type);
5821 fl.l_whence = tswap16(target_fl->l_whence);
5822 fl.l_start = tswap64(target_fl->l_start);
5823 fl.l_len = tswap64(target_fl->l_len);
5824 fl.l_pid = tswapl(target_fl->l_pid);
53a5960a 5825 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 5826 }
b1e341eb 5827 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 5828 break;
60cd49d5 5829 default:
9ee1fa2c 5830 ret = do_fcntl(arg1, cmd, arg3);
60cd49d5
FB
5831 break;
5832 }
77e4672d
FB
5833 break;
5834 }
60cd49d5 5835#endif
7d600c80
TS
5836#ifdef TARGET_NR_cacheflush
5837 case TARGET_NR_cacheflush:
5838 /* self-modifying code is handled automatically, so nothing needed */
5839 ret = 0;
5840 break;
5841#endif
ebc05488 5842#ifdef TARGET_NR_security
31e31b8a
FB
5843 case TARGET_NR_security:
5844 goto unimplemented;
c573ff67
FB
5845#endif
5846#ifdef TARGET_NR_getpagesize
5847 case TARGET_NR_getpagesize:
5848 ret = TARGET_PAGE_SIZE;
5849 break;
ebc05488 5850#endif
31e31b8a
FB
5851 case TARGET_NR_gettid:
5852 ret = get_errno(gettid());
5853 break;
e5febef5 5854#ifdef TARGET_NR_readahead
31e31b8a 5855 case TARGET_NR_readahead:
2054ac9b
AJ
5856#if TARGET_ABI_BITS == 32
5857#ifdef TARGET_ARM
5858 if (((CPUARMState *)cpu_env)->eabi)
5859 {
5860 arg2 = arg3;
5861 arg3 = arg4;
5862 arg4 = arg5;
5863 }
5864#endif
5865 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
5866#else
5867 ret = get_errno(readahead(arg1, arg2, arg3));
5868#endif
5869 break;
e5febef5 5870#endif
ebc05488 5871#ifdef TARGET_NR_setxattr
31e31b8a
FB
5872 case TARGET_NR_setxattr:
5873 case TARGET_NR_lsetxattr:
5874 case TARGET_NR_fsetxattr:
5875 case TARGET_NR_getxattr:
5876 case TARGET_NR_lgetxattr:
5877 case TARGET_NR_fgetxattr:
5878 case TARGET_NR_listxattr:
5879 case TARGET_NR_llistxattr:
5880 case TARGET_NR_flistxattr:
5881 case TARGET_NR_removexattr:
5882 case TARGET_NR_lremovexattr:
5883 case TARGET_NR_fremovexattr:
5cd4393b 5884 goto unimplemented_nowarn;
ebc05488
FB
5885#endif
5886#ifdef TARGET_NR_set_thread_area
5cd4393b 5887 case TARGET_NR_set_thread_area:
8d18e893 5888#if defined(TARGET_MIPS)
6f5b89a0
TS
5889 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5890 ret = 0;
5891 break;
8d18e893
FB
5892#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5893 ret = do_set_thread_area(cpu_env, arg1);
5894 break;
6f5b89a0
TS
5895#else
5896 goto unimplemented_nowarn;
5897#endif
5898#endif
5899#ifdef TARGET_NR_get_thread_area
5cd4393b 5900 case TARGET_NR_get_thread_area:
8d18e893
FB
5901#if defined(TARGET_I386) && defined(TARGET_ABI32)
5902 ret = do_get_thread_area(cpu_env, arg1);
5903#else
5cd4393b 5904 goto unimplemented_nowarn;
48dc41eb 5905#endif
8d18e893 5906#endif
48dc41eb
FB
5907#ifdef TARGET_NR_getdomainname
5908 case TARGET_NR_getdomainname:
5909 goto unimplemented_nowarn;
ebc05488 5910#endif
6f5b89a0 5911
b5906f95
TS
5912#ifdef TARGET_NR_clock_gettime
5913 case TARGET_NR_clock_gettime:
5914 {
5915 struct timespec ts;
5916 ret = get_errno(clock_gettime(arg1, &ts));
5917 if (!is_error(ret)) {
5918 host_to_target_timespec(arg2, &ts);
5919 }
5920 break;
5921 }
5922#endif
5923#ifdef TARGET_NR_clock_getres
5924 case TARGET_NR_clock_getres:
5925 {
5926 struct timespec ts;
5927 ret = get_errno(clock_getres(arg1, &ts));
5928 if (!is_error(ret)) {
5929 host_to_target_timespec(arg2, &ts);
5930 }
5931 break;
5932 }
5933#endif
63d7651b
PB
5934#ifdef TARGET_NR_clock_nanosleep
5935 case TARGET_NR_clock_nanosleep:
5936 {
5937 struct timespec ts;
5938 target_to_host_timespec(&ts, arg3);
5939 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5940 if (arg4)
5941 host_to_target_timespec(arg4, &ts);
5942 break;
5943 }
5944#endif
b5906f95 5945
6f5b89a0
TS
5946#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5947 case TARGET_NR_set_tid_address:
579a97f7
FB
5948 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5949 break;
6f5b89a0
TS
5950#endif
5951
3ae43202 5952#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 5953 case TARGET_NR_tkill:
4cb05961 5954 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
5955 break;
5956#endif
5957
3ae43202 5958#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 5959 case TARGET_NR_tgkill:
4cb05961
PB
5960 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5961 target_to_host_signal(arg3)));
71455574
TS
5962 break;
5963#endif
5964
4f2b1fe8
TS
5965#ifdef TARGET_NR_set_robust_list
5966 case TARGET_NR_set_robust_list:
5967 goto unimplemented_nowarn;
5968#endif
5969
9007f0ef
TS
5970#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
5971 case TARGET_NR_utimensat:
5972 {
5973 struct timespec ts[2];
5974 target_to_host_timespec(ts, arg3);
5975 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
5976 if (!arg2)
5977 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
5978 else {
579a97f7 5979 if (!(p = lock_user_string(arg2))) {
0da46a6e 5980 ret = -TARGET_EFAULT;
579a97f7
FB
5981 goto fail;
5982 }
5983 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
5984 unlock_user(p, arg2, 0);
9007f0ef
TS
5985 }
5986 }
5987 break;
5988#endif
bd0c5661
PB
5989#if defined(USE_NPTL)
5990 case TARGET_NR_futex:
5991 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
5992 break;
5993#endif
39b59763
AJ
5994#ifdef TARGET_NR_inotify_init
5995 case TARGET_NR_inotify_init:
5996 ret = get_errno(sys_inotify_init());
5997 break;
5998#endif
5999#ifdef TARGET_NR_inotify_add_watch
6000 case TARGET_NR_inotify_add_watch:
6001 p = lock_user_string(arg2);
6002 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6003 unlock_user(p, arg2, 0);
6004 break;
6005#endif
6006#ifdef TARGET_NR_inotify_rm_watch
6007 case TARGET_NR_inotify_rm_watch:
6008 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6009 break;
6010#endif
9007f0ef 6011
31e31b8a
FB
6012 default:
6013 unimplemented:
5cd4393b 6014 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 6015#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 6016 unimplemented_nowarn:
80a9d035 6017#endif
0da46a6e 6018 ret = -TARGET_ENOSYS;
31e31b8a
FB
6019 break;
6020 }
579a97f7 6021fail:
c573ff67
FB
6022#ifdef DEBUG
6023 gemu_log(" = %ld\n", ret);
6024#endif
b92c47c1
TS
6025 if(do_strace)
6026 print_syscall_ret(num, ret);
31e31b8a 6027 return ret;
579a97f7
FB
6028efault:
6029 ret = -TARGET_EFAULT;
6030 goto fail;
31e31b8a 6031}