]> Git Repo - qemu.git/blame - linux-user/syscall.c
Merge remote-tracking branch 'remotes/cohuck/tags/s390x-20140627' into staging
[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
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d5b3a9b6 19#define _ATFILE_SOURCE
31e31b8a
FB
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>
c56dc774 31#include <grp.h>
31e31b8a 32#include <sys/types.h>
d08d3bb8
TS
33#include <sys/ipc.h>
34#include <sys/msg.h>
31e31b8a
FB
35#include <sys/wait.h>
36#include <sys/time.h>
37#include <sys/stat.h>
38#include <sys/mount.h>
586b0bef
JS
39#include <sys/file.h>
40#include <sys/fsuid.h>
41#include <sys/personality.h>
39b9aae1 42#include <sys/prctl.h>
31e31b8a
FB
43#include <sys/resource.h>
44#include <sys/mman.h>
45#include <sys/swap.h>
e0eb210e 46#include <linux/capability.h>
31e31b8a
FB
47#include <signal.h>
48#include <sched.h>
60e99246
AJ
49#ifdef __ia64__
50int __clone2(int (*fn)(void *), void *child_stack_base,
51 size_t stack_size, int flags, void *arg, ...);
52#endif
31e31b8a 53#include <sys/socket.h>
607175e0 54#include <sys/un.h>
31e31b8a 55#include <sys/uio.h>
9de5e440 56#include <sys/poll.h>
32f36bce 57#include <sys/times.h>
8853f86e 58#include <sys/shm.h>
fa294816 59#include <sys/sem.h>
56c8f68f 60#include <sys/statfs.h>
ebc05488 61#include <utime.h>
a5448a7d 62#include <sys/sysinfo.h>
72f03900 63//#include <sys/user.h>
8853f86e 64#include <netinet/ip.h>
7854b056 65#include <netinet/tcp.h>
86fcd946 66#include <linux/wireless.h>
920394db 67#include <linux/icmp.h>
5a61cb60 68#include "qemu-common.h"
9788c9ca 69#ifdef TARGET_GPROF
6d946cda
AJ
70#include <sys/gmon.h>
71#endif
c2882b96
RV
72#ifdef CONFIG_EVENTFD
73#include <sys/eventfd.h>
74#endif
3b6edd16
PM
75#ifdef CONFIG_EPOLL
76#include <sys/epoll.h>
77#endif
a790ae38 78#ifdef CONFIG_ATTR
1de7afc9 79#include "qemu/xattr.h"
a790ae38 80#endif
a8fd1aba
PM
81#ifdef CONFIG_SENDFILE
82#include <sys/sendfile.h>
83#endif
31e31b8a
FB
84
85#define termios host_termios
86#define winsize host_winsize
87#define termio host_termio
04369ff2
FB
88#define sgttyb host_sgttyb /* same as target */
89#define tchars host_tchars /* same as target */
90#define ltchars host_ltchars /* same as target */
31e31b8a
FB
91
92#include <linux/termios.h>
93#include <linux/unistd.h>
31e31b8a
FB
94#include <linux/cdrom.h>
95#include <linux/hdreg.h>
96#include <linux/soundcard.h>
19b84f3c 97#include <linux/kd.h>
8fbd6b52 98#include <linux/mtio.h>
350d1779 99#include <linux/fs.h>
dace20dc 100#if defined(CONFIG_FIEMAP)
285da2b9 101#include <linux/fiemap.h>
dace20dc 102#endif
f7680a55
UH
103#include <linux/fb.h>
104#include <linux/vt.h>
56e904ec 105#include <linux/dm-ioctl.h>
c07ecc68 106#include <linux/reboot.h>
7ff7b666 107#include <linux/route.h>
f57d4192 108#include <linux/filter.h>
fff8c539 109#include <linux/blkpg.h>
d7e4036e 110#include "linux_loop.h"
18cb0088 111#include "uname.h"
31e31b8a 112
3ef693a0 113#include "qemu.h"
31e31b8a 114
d865bab5
PB
115#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
116 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
30813cea 117
72f03900 118//#define DEBUG
31e31b8a 119
1a9353d2 120//#include <linux/msdos_fs.h>
6556a833
AJ
121#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
122#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
1a9353d2 123
70a194b9 124
70a194b9
FB
125#undef _syscall0
126#undef _syscall1
127#undef _syscall2
128#undef _syscall3
129#undef _syscall4
130#undef _syscall5
83fcb515 131#undef _syscall6
70a194b9 132
83fcb515 133#define _syscall0(type,name) \
8fcd3692 134static type name (void) \
83fcb515
FB
135{ \
136 return syscall(__NR_##name); \
137}
70a194b9 138
83fcb515 139#define _syscall1(type,name,type1,arg1) \
8fcd3692 140static type name (type1 arg1) \
83fcb515
FB
141{ \
142 return syscall(__NR_##name, arg1); \
70a194b9
FB
143}
144
83fcb515 145#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 146static type name (type1 arg1,type2 arg2) \
83fcb515
FB
147{ \
148 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
149}
150
83fcb515 151#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 152static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
153{ \
154 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
155}
156
83fcb515 157#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 158static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
159{ \
160 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
161}
162
83fcb515
FB
163#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
164 type5,arg5) \
8fcd3692 165static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
166{ \
167 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
168}
169
83fcb515
FB
170
171#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
172 type5,arg5,type6,arg6) \
8fcd3692
BS
173static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
174 type6 arg6) \
83fcb515
FB
175{ \
176 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 177}
83fcb515 178
70a194b9 179
31e31b8a 180#define __NR_sys_uname __NR_uname
72f03900 181#define __NR_sys_getcwd1 __NR_getcwd
72f03900 182#define __NR_sys_getdents __NR_getdents
dab2ed99 183#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 184#define __NR_sys_getpriority __NR_getpriority
66fb9763 185#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
7494b0f9 186#define __NR_sys_syslog __NR_syslog
71455574 187#define __NR_sys_tgkill __NR_tgkill
4cae1d16 188#define __NR_sys_tkill __NR_tkill
bd0c5661 189#define __NR_sys_futex __NR_futex
39b59763
AJ
190#define __NR_sys_inotify_init __NR_inotify_init
191#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
192#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
31e31b8a 193
42a39fbe
AG
194#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
195 defined(__s390x__)
9af9eaaa
FB
196#define __NR__llseek __NR_lseek
197#endif
198
a29e5ba2
JH
199/* Newer kernel ports have llseek() instead of _llseek() */
200#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
201#define TARGET_NR__llseek TARGET_NR_llseek
202#endif
203
72f03900 204#ifdef __NR_gettid
31e31b8a 205_syscall0(int, gettid)
72f03900 206#else
0da46a6e
TS
207/* This is a replacement for the host gettid() and must return a host
208 errno. */
72f03900
FB
209static int gettid(void) {
210 return -ENOSYS;
211}
212#endif
3307e236 213#ifdef __NR_getdents
3b3f24ad 214_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3307e236
PM
215#endif
216#if !defined(__NR_getdents) || \
217 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
3b3f24ad
AJ
218_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
219#endif
d35b261c 220#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
221_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
222 loff_t *, res, uint, wh);
223#endif
224_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
225_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
226#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
227_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
228#endif
229#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
230_syscall2(int,sys_tkill,int,tid,int,sig)
231#endif
232#ifdef __NR_exit_group
233_syscall1(int,exit_group,int,error_code)
234#endif
235#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
236_syscall1(int,set_tid_address,int *,tidptr)
237#endif
3b3f24ad
AJ
238#if defined(TARGET_NR_futex) && defined(__NR_futex)
239_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
240 const struct timespec *,timeout,int *,uaddr2,int,val3)
241#endif
737de1d1
MF
242#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
243_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
244 unsigned long *, user_mask_ptr);
245#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
246_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
247 unsigned long *, user_mask_ptr);
0f6b4d21
AG
248_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
249 void *, arg);
e0eb210e
PM
250_syscall2(int, capget, struct __user_cap_header_struct *, header,
251 struct __user_cap_data_struct *, data);
252_syscall2(int, capset, struct __user_cap_header_struct *, header,
253 struct __user_cap_data_struct *, data);
3b3f24ad
AJ
254
255static bitmask_transtbl fcntl_flags_tbl[] = {
256 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
257 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
258 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
259 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
260 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
261 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
262 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
263 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
afc8763f 264 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
3b3f24ad
AJ
265 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
266 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
267 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
268 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
3b3f24ad
AJ
269#if defined(O_DIRECT)
270 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
afc8763f
RH
271#endif
272#if defined(O_NOATIME)
273 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
274#endif
275#if defined(O_CLOEXEC)
276 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
277#endif
278#if defined(O_PATH)
279 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
280#endif
281 /* Don't terminate the list prematurely on 64-bit host+guest. */
282#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
283 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
3b3f24ad
AJ
284#endif
285 { 0, 0, 0, 0 }
286};
287
3b3f24ad
AJ
288static int sys_getcwd1(char *buf, size_t size)
289{
290 if (getcwd(buf, size) == NULL) {
291 /* getcwd() sets errno */
292 return (-1);
293 }
aaf4ad39 294 return strlen(buf)+1;
3b3f24ad
AJ
295}
296
3b3f24ad 297#ifdef TARGET_NR_openat
f4c69010 298static int sys_openat(int dirfd, const char *pathname, int flags, mode_t mode)
3b3f24ad
AJ
299{
300 /*
301 * open(2) has extra parameter 'mode' when called with
302 * flag O_CREAT.
303 */
304 if ((flags & O_CREAT) != 0) {
3b3f24ad
AJ
305 return (openat(dirfd, pathname, flags, mode));
306 }
307 return (openat(dirfd, pathname, flags));
308}
309#endif
ebc996f3 310
1acae9f2 311#ifdef TARGET_NR_utimensat
ebc996f3
RV
312#ifdef CONFIG_UTIMENSAT
313static int sys_utimensat(int dirfd, const char *pathname,
314 const struct timespec times[2], int flags)
315{
316 if (pathname == NULL)
317 return futimens(dirfd, times);
318 else
319 return utimensat(dirfd, pathname, times, flags);
320}
1acae9f2
PM
321#elif defined(__NR_utimensat)
322#define __NR_sys_utimensat __NR_utimensat
9007f0ef
TS
323_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
324 const struct timespec *,tsp,int,flags)
1acae9f2
PM
325#else
326static int sys_utimensat(int dirfd, const char *pathname,
327 const struct timespec times[2], int flags)
328{
329 errno = ENOSYS;
330 return -1;
331}
9007f0ef 332#endif
1acae9f2 333#endif /* TARGET_NR_utimensat */
3b3f24ad
AJ
334
335#ifdef CONFIG_INOTIFY
8690e420 336#include <sys/inotify.h>
3b3f24ad 337
39b59763 338#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
3b3f24ad
AJ
339static int sys_inotify_init(void)
340{
341 return (inotify_init());
342}
39b59763
AJ
343#endif
344#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
3b3f24ad
AJ
345static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
346{
347 return (inotify_add_watch(fd, pathname, mask));
348}
39b59763
AJ
349#endif
350#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
3b3f24ad
AJ
351static int sys_inotify_rm_watch(int fd, int32_t wd)
352{
8690e420 353 return (inotify_rm_watch(fd, wd));
3b3f24ad 354}
bd0c5661 355#endif
c05c7a73
RV
356#ifdef CONFIG_INOTIFY1
357#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
358static int sys_inotify_init1(int flags)
359{
360 return (inotify_init1(flags));
361}
362#endif
363#endif
3b3f24ad
AJ
364#else
365/* Userspace can usually survive runtime without inotify */
366#undef TARGET_NR_inotify_init
c05c7a73 367#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
368#undef TARGET_NR_inotify_add_watch
369#undef TARGET_NR_inotify_rm_watch
370#endif /* CONFIG_INOTIFY */
371
d8035d4c
MF
372#if defined(TARGET_NR_ppoll)
373#ifndef __NR_ppoll
374# define __NR_ppoll -1
375#endif
376#define __NR_sys_ppoll __NR_ppoll
377_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
34d60862 378 struct timespec *, timeout, const sigset_t *, sigmask,
d8035d4c
MF
379 size_t, sigsetsize)
380#endif
66fb9763 381
055e0906
MF
382#if defined(TARGET_NR_pselect6)
383#ifndef __NR_pselect6
384# define __NR_pselect6 -1
385#endif
386#define __NR_sys_pselect6 __NR_pselect6
387_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
388 fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
389#endif
390
163a05a8
PM
391#if defined(TARGET_NR_prlimit64)
392#ifndef __NR_prlimit64
393# define __NR_prlimit64 -1
394#endif
395#define __NR_sys_prlimit64 __NR_prlimit64
396/* The glibc rlimit structure may not be that used by the underlying syscall */
397struct host_rlimit64 {
398 uint64_t rlim_cur;
399 uint64_t rlim_max;
400};
401_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
402 const struct host_rlimit64 *, new_limit,
403 struct host_rlimit64 *, old_limit)
404#endif
405
f4f1e10a
ECL
406
407#if defined(TARGET_NR_timer_create)
408/* Maxiumum of 32 active POSIX timers allowed at any one time. */
409static timer_t g_posix_timers[32] = { 0, } ;
410
411static inline int next_free_host_timer(void)
412{
413 int k ;
414 /* FIXME: Does finding the next free slot require a lock? */
415 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
416 if (g_posix_timers[k] == 0) {
417 g_posix_timers[k] = (timer_t) 1;
418 return k;
419 }
420 }
421 return -1;
422}
423#endif
424
48e515d4 425/* ARM EABI and MIPS expect 64bit types aligned even on pairs or registers */
4a1def4e 426#ifdef TARGET_ARM
48e515d4
RV
427static inline int regpairs_aligned(void *cpu_env) {
428 return ((((CPUARMState *)cpu_env)->eabi) == 1) ;
429}
430#elif defined(TARGET_MIPS)
431static inline int regpairs_aligned(void *cpu_env) { return 1; }
4a1def4e
AG
432#elif defined(TARGET_PPC) && !defined(TARGET_PPC64)
433/* SysV AVI for PPC32 expects 64bit parameters to be passed on odd/even pairs
434 * of registers which translates to the same as ARM/MIPS, because we start with
435 * r3 as arg1 */
436static inline int regpairs_aligned(void *cpu_env) { return 1; }
48e515d4
RV
437#else
438static inline int regpairs_aligned(void *cpu_env) { return 0; }
439#endif
440
b92c47c1
TS
441#define ERRNO_TABLE_SIZE 1200
442
443/* target_to_host_errno_table[] is initialized from
444 * host_to_target_errno_table[] in syscall_init(). */
445static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
446};
447
637947f1 448/*
fe8f096b 449 * This list is the union of errno values overridden in asm-<arch>/errno.h
637947f1
TS
450 * minus the errnos that are not actually generic to all archs.
451 */
b92c47c1 452static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
637947f1
TS
453 [EIDRM] = TARGET_EIDRM,
454 [ECHRNG] = TARGET_ECHRNG,
455 [EL2NSYNC] = TARGET_EL2NSYNC,
456 [EL3HLT] = TARGET_EL3HLT,
457 [EL3RST] = TARGET_EL3RST,
458 [ELNRNG] = TARGET_ELNRNG,
459 [EUNATCH] = TARGET_EUNATCH,
460 [ENOCSI] = TARGET_ENOCSI,
461 [EL2HLT] = TARGET_EL2HLT,
462 [EDEADLK] = TARGET_EDEADLK,
463 [ENOLCK] = TARGET_ENOLCK,
464 [EBADE] = TARGET_EBADE,
465 [EBADR] = TARGET_EBADR,
466 [EXFULL] = TARGET_EXFULL,
467 [ENOANO] = TARGET_ENOANO,
468 [EBADRQC] = TARGET_EBADRQC,
469 [EBADSLT] = TARGET_EBADSLT,
470 [EBFONT] = TARGET_EBFONT,
471 [ENOSTR] = TARGET_ENOSTR,
472 [ENODATA] = TARGET_ENODATA,
473 [ETIME] = TARGET_ETIME,
474 [ENOSR] = TARGET_ENOSR,
475 [ENONET] = TARGET_ENONET,
476 [ENOPKG] = TARGET_ENOPKG,
477 [EREMOTE] = TARGET_EREMOTE,
478 [ENOLINK] = TARGET_ENOLINK,
479 [EADV] = TARGET_EADV,
480 [ESRMNT] = TARGET_ESRMNT,
481 [ECOMM] = TARGET_ECOMM,
482 [EPROTO] = TARGET_EPROTO,
483 [EDOTDOT] = TARGET_EDOTDOT,
484 [EMULTIHOP] = TARGET_EMULTIHOP,
485 [EBADMSG] = TARGET_EBADMSG,
486 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
487 [EOVERFLOW] = TARGET_EOVERFLOW,
488 [ENOTUNIQ] = TARGET_ENOTUNIQ,
489 [EBADFD] = TARGET_EBADFD,
490 [EREMCHG] = TARGET_EREMCHG,
491 [ELIBACC] = TARGET_ELIBACC,
492 [ELIBBAD] = TARGET_ELIBBAD,
493 [ELIBSCN] = TARGET_ELIBSCN,
494 [ELIBMAX] = TARGET_ELIBMAX,
495 [ELIBEXEC] = TARGET_ELIBEXEC,
496 [EILSEQ] = TARGET_EILSEQ,
497 [ENOSYS] = TARGET_ENOSYS,
498 [ELOOP] = TARGET_ELOOP,
499 [ERESTART] = TARGET_ERESTART,
500 [ESTRPIPE] = TARGET_ESTRPIPE,
501 [ENOTEMPTY] = TARGET_ENOTEMPTY,
502 [EUSERS] = TARGET_EUSERS,
503 [ENOTSOCK] = TARGET_ENOTSOCK,
504 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
505 [EMSGSIZE] = TARGET_EMSGSIZE,
506 [EPROTOTYPE] = TARGET_EPROTOTYPE,
507 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
508 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
509 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
510 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
511 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
512 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
513 [EADDRINUSE] = TARGET_EADDRINUSE,
514 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
515 [ENETDOWN] = TARGET_ENETDOWN,
516 [ENETUNREACH] = TARGET_ENETUNREACH,
517 [ENETRESET] = TARGET_ENETRESET,
518 [ECONNABORTED] = TARGET_ECONNABORTED,
519 [ECONNRESET] = TARGET_ECONNRESET,
520 [ENOBUFS] = TARGET_ENOBUFS,
521 [EISCONN] = TARGET_EISCONN,
522 [ENOTCONN] = TARGET_ENOTCONN,
523 [EUCLEAN] = TARGET_EUCLEAN,
524 [ENOTNAM] = TARGET_ENOTNAM,
525 [ENAVAIL] = TARGET_ENAVAIL,
526 [EISNAM] = TARGET_EISNAM,
527 [EREMOTEIO] = TARGET_EREMOTEIO,
528 [ESHUTDOWN] = TARGET_ESHUTDOWN,
529 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
530 [ETIMEDOUT] = TARGET_ETIMEDOUT,
531 [ECONNREFUSED] = TARGET_ECONNREFUSED,
532 [EHOSTDOWN] = TARGET_EHOSTDOWN,
533 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
534 [EALREADY] = TARGET_EALREADY,
535 [EINPROGRESS] = TARGET_EINPROGRESS,
536 [ESTALE] = TARGET_ESTALE,
537 [ECANCELED] = TARGET_ECANCELED,
538 [ENOMEDIUM] = TARGET_ENOMEDIUM,
539 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
b7fe5db7 540#ifdef ENOKEY
637947f1 541 [ENOKEY] = TARGET_ENOKEY,
b7fe5db7
TS
542#endif
543#ifdef EKEYEXPIRED
637947f1 544 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
b7fe5db7
TS
545#endif
546#ifdef EKEYREVOKED
637947f1 547 [EKEYREVOKED] = TARGET_EKEYREVOKED,
b7fe5db7
TS
548#endif
549#ifdef EKEYREJECTED
637947f1 550 [EKEYREJECTED] = TARGET_EKEYREJECTED,
b7fe5db7
TS
551#endif
552#ifdef EOWNERDEAD
637947f1 553 [EOWNERDEAD] = TARGET_EOWNERDEAD,
b7fe5db7
TS
554#endif
555#ifdef ENOTRECOVERABLE
637947f1 556 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
b7fe5db7 557#endif
b92c47c1 558};
637947f1
TS
559
560static inline int host_to_target_errno(int err)
561{
562 if(host_to_target_errno_table[err])
563 return host_to_target_errno_table[err];
564 return err;
565}
566
b92c47c1
TS
567static inline int target_to_host_errno(int err)
568{
569 if (target_to_host_errno_table[err])
570 return target_to_host_errno_table[err];
571 return err;
572}
573
992f48a0 574static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
575{
576 if (ret == -1)
637947f1 577 return -host_to_target_errno(errno);
31e31b8a
FB
578 else
579 return ret;
580}
581
992f48a0 582static inline int is_error(abi_long ret)
31e31b8a 583{
992f48a0 584 return (abi_ulong)ret >= (abi_ulong)(-4096);
31e31b8a
FB
585}
586
b92c47c1
TS
587char *target_strerror(int err)
588{
962b289e
AG
589 if ((err >= ERRNO_TABLE_SIZE) || (err < 0)) {
590 return NULL;
591 }
b92c47c1
TS
592 return strerror(target_to_host_errno(err));
593}
594
992f48a0
BS
595static abi_ulong target_brk;
596static abi_ulong target_original_brk;
4d1de87c 597static abi_ulong brk_page;
31e31b8a 598
992f48a0 599void target_set_brk(abi_ulong new_brk)
31e31b8a 600{
4c1de73d 601 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
4d1de87c 602 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
603}
604
4d1de87c
CV
605//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
606#define DEBUGF_BRK(message, args...)
607
0da46a6e 608/* do_brk() must return target values and target errnos. */
992f48a0 609abi_long do_brk(abi_ulong new_brk)
31e31b8a 610{
992f48a0 611 abi_long mapped_addr;
31e31b8a
FB
612 int new_alloc_size;
613
3a0c6c4a 614 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
4d1de87c
CV
615
616 if (!new_brk) {
3a0c6c4a 617 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
53a5960a 618 return target_brk;
4d1de87c
CV
619 }
620 if (new_brk < target_original_brk) {
3a0c6c4a
PB
621 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
622 target_brk);
7ab240ad 623 return target_brk;
4d1de87c 624 }
3b46e624 625
4d1de87c
CV
626 /* If the new brk is less than the highest page reserved to the
627 * target heap allocation, set it and we're almost done... */
628 if (new_brk <= brk_page) {
629 /* Heap contents are initialized to zero, as for anonymous
630 * mapped pages. */
631 if (new_brk > target_brk) {
632 memset(g2h(target_brk), 0, new_brk - target_brk);
633 }
31e31b8a 634 target_brk = new_brk;
3a0c6c4a 635 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
53a5960a 636 return target_brk;
31e31b8a
FB
637 }
638
00faf08c
PM
639 /* We need to allocate more memory after the brk... Note that
640 * we don't use MAP_FIXED because that will map over the top of
641 * any existing mapping (like the one with the host libc or qemu
642 * itself); instead we treat "mapped but at wrong address" as
643 * a failure and unmap again.
644 */
4d1de87c 645 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
5fafdf24 646 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 647 PROT_READ|PROT_WRITE,
00faf08c
PM
648 MAP_ANON|MAP_PRIVATE, 0, 0));
649
650 if (mapped_addr == brk_page) {
70afc343
CV
651 /* Heap contents are initialized to zero, as for anonymous
652 * mapped pages. Technically the new pages are already
653 * initialized to zero since they *are* anonymous mapped
654 * pages, however we have to take care with the contents that
655 * come from the remaining part of the previous page: it may
656 * contains garbage data due to a previous heap usage (grown
657 * then shrunken). */
658 memset(g2h(target_brk), 0, brk_page - target_brk);
659
00faf08c 660 target_brk = new_brk;
4d1de87c 661 brk_page = HOST_PAGE_ALIGN(target_brk);
3a0c6c4a
PB
662 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
663 target_brk);
00faf08c
PM
664 return target_brk;
665 } else if (mapped_addr != -1) {
666 /* Mapped but at wrong address, meaning there wasn't actually
667 * enough space for this brk.
668 */
669 target_munmap(mapped_addr, new_alloc_size);
670 mapped_addr = -1;
3a0c6c4a 671 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
4d1de87c
CV
672 }
673 else {
3a0c6c4a 674 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
00faf08c 675 }
7ab240ad 676
7dd46c02
RH
677#if defined(TARGET_ALPHA)
678 /* We (partially) emulate OSF/1 on Alpha, which requires we
679 return a proper errno, not an unchanged brk value. */
00faf08c 680 return -TARGET_ENOMEM;
7dd46c02 681#endif
00faf08c 682 /* For everything else, return the previous break. */
7ab240ad 683 return target_brk;
31e31b8a
FB
684}
685
26edcf41
TS
686static inline abi_long copy_from_user_fdset(fd_set *fds,
687 abi_ulong target_fds_addr,
688 int n)
31e31b8a 689{
26edcf41
TS
690 int i, nw, j, k;
691 abi_ulong b, *target_fds;
692
693 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
694 if (!(target_fds = lock_user(VERIFY_READ,
695 target_fds_addr,
696 sizeof(abi_ulong) * nw,
697 1)))
698 return -TARGET_EFAULT;
699
700 FD_ZERO(fds);
701 k = 0;
702 for (i = 0; i < nw; i++) {
703 /* grab the abi_ulong */
704 __get_user(b, &target_fds[i]);
705 for (j = 0; j < TARGET_ABI_BITS; j++) {
706 /* check the bit inside the abi_ulong */
707 if ((b >> j) & 1)
708 FD_SET(k, fds);
709 k++;
31e31b8a 710 }
31e31b8a 711 }
26edcf41
TS
712
713 unlock_user(target_fds, target_fds_addr, 0);
714
715 return 0;
31e31b8a
FB
716}
717
055e0906
MF
718static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
719 abi_ulong target_fds_addr,
720 int n)
721{
722 if (target_fds_addr) {
723 if (copy_from_user_fdset(fds, target_fds_addr, n))
724 return -TARGET_EFAULT;
725 *fds_ptr = fds;
726 } else {
727 *fds_ptr = NULL;
728 }
729 return 0;
730}
731
26edcf41
TS
732static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
733 const fd_set *fds,
734 int n)
31e31b8a 735{
31e31b8a 736 int i, nw, j, k;
992f48a0 737 abi_long v;
26edcf41 738 abi_ulong *target_fds;
31e31b8a 739
26edcf41
TS
740 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
741 if (!(target_fds = lock_user(VERIFY_WRITE,
742 target_fds_addr,
743 sizeof(abi_ulong) * nw,
744 0)))
745 return -TARGET_EFAULT;
746
747 k = 0;
748 for (i = 0; i < nw; i++) {
749 v = 0;
750 for (j = 0; j < TARGET_ABI_BITS; j++) {
9ab709be 751 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
26edcf41 752 k++;
31e31b8a 753 }
26edcf41 754 __put_user(v, &target_fds[i]);
31e31b8a 755 }
26edcf41
TS
756
757 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
758
759 return 0;
31e31b8a
FB
760}
761
c596ed17
FB
762#if defined(__alpha__)
763#define HOST_HZ 1024
764#else
765#define HOST_HZ 100
766#endif
767
992f48a0 768static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
769{
770#if HOST_HZ == TARGET_HZ
771 return ticks;
772#else
773 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
774#endif
775}
776
579a97f7
FB
777static inline abi_long host_to_target_rusage(abi_ulong target_addr,
778 const struct rusage *rusage)
b409186b 779{
53a5960a
PB
780 struct target_rusage *target_rusage;
781
579a97f7
FB
782 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
783 return -TARGET_EFAULT;
cbb21eed
MB
784 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
785 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
786 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
787 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
788 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
789 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
790 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
791 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
792 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
793 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
794 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
795 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
796 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
797 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
798 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
799 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
800 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
801 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
53a5960a 802 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
803
804 return 0;
b409186b
FB
805}
806
cbb21eed 807static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
81bbe906 808{
cbb21eed 809 abi_ulong target_rlim_swap;
95b33b2f
WT
810 rlim_t result;
811
cbb21eed
MB
812 target_rlim_swap = tswapal(target_rlim);
813 if (target_rlim_swap == TARGET_RLIM_INFINITY)
814 return RLIM_INFINITY;
815
816 result = target_rlim_swap;
817 if (target_rlim_swap != (rlim_t)result)
818 return RLIM_INFINITY;
95b33b2f
WT
819
820 return result;
81bbe906
TY
821}
822
cbb21eed 823static inline abi_ulong host_to_target_rlim(rlim_t rlim)
81bbe906 824{
cbb21eed
MB
825 abi_ulong target_rlim_swap;
826 abi_ulong result;
95b33b2f 827
cbb21eed 828 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
95b33b2f 829 target_rlim_swap = TARGET_RLIM_INFINITY;
81bbe906 830 else
95b33b2f 831 target_rlim_swap = rlim;
cbb21eed 832 result = tswapal(target_rlim_swap);
95b33b2f
WT
833
834 return result;
81bbe906
TY
835}
836
e22b7015
WT
837static inline int target_to_host_resource(int code)
838{
839 switch (code) {
840 case TARGET_RLIMIT_AS:
841 return RLIMIT_AS;
842 case TARGET_RLIMIT_CORE:
843 return RLIMIT_CORE;
844 case TARGET_RLIMIT_CPU:
845 return RLIMIT_CPU;
846 case TARGET_RLIMIT_DATA:
847 return RLIMIT_DATA;
848 case TARGET_RLIMIT_FSIZE:
849 return RLIMIT_FSIZE;
850 case TARGET_RLIMIT_LOCKS:
851 return RLIMIT_LOCKS;
852 case TARGET_RLIMIT_MEMLOCK:
853 return RLIMIT_MEMLOCK;
854 case TARGET_RLIMIT_MSGQUEUE:
855 return RLIMIT_MSGQUEUE;
856 case TARGET_RLIMIT_NICE:
857 return RLIMIT_NICE;
858 case TARGET_RLIMIT_NOFILE:
859 return RLIMIT_NOFILE;
860 case TARGET_RLIMIT_NPROC:
861 return RLIMIT_NPROC;
862 case TARGET_RLIMIT_RSS:
863 return RLIMIT_RSS;
864 case TARGET_RLIMIT_RTPRIO:
865 return RLIMIT_RTPRIO;
866 case TARGET_RLIMIT_SIGPENDING:
867 return RLIMIT_SIGPENDING;
868 case TARGET_RLIMIT_STACK:
869 return RLIMIT_STACK;
870 default:
871 return code;
872 }
873}
874
788f5ec4
TS
875static inline abi_long copy_from_user_timeval(struct timeval *tv,
876 abi_ulong target_tv_addr)
31e31b8a 877{
53a5960a
PB
878 struct target_timeval *target_tv;
879
788f5ec4 880 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
579a97f7 881 return -TARGET_EFAULT;
788f5ec4
TS
882
883 __get_user(tv->tv_sec, &target_tv->tv_sec);
884 __get_user(tv->tv_usec, &target_tv->tv_usec);
885
886 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
887
888 return 0;
31e31b8a
FB
889}
890
788f5ec4
TS
891static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
892 const struct timeval *tv)
31e31b8a 893{
53a5960a
PB
894 struct target_timeval *target_tv;
895
788f5ec4 896 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
579a97f7 897 return -TARGET_EFAULT;
788f5ec4
TS
898
899 __put_user(tv->tv_sec, &target_tv->tv_sec);
900 __put_user(tv->tv_usec, &target_tv->tv_usec);
901
902 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
903
904 return 0;
31e31b8a
FB
905}
906
8ec9cf89
NF
907#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
908#include <mqueue.h>
909
24e1003a
AJ
910static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
911 abi_ulong target_mq_attr_addr)
912{
913 struct target_mq_attr *target_mq_attr;
914
915 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
916 target_mq_attr_addr, 1))
917 return -TARGET_EFAULT;
918
919 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
920 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
921 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
922 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
923
924 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
925
926 return 0;
927}
928
929static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
930 const struct mq_attr *attr)
931{
932 struct target_mq_attr *target_mq_attr;
933
934 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
935 target_mq_attr_addr, 0))
936 return -TARGET_EFAULT;
937
938 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
939 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
940 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
941 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
942
943 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
944
945 return 0;
946}
8ec9cf89 947#endif
31e31b8a 948
055e0906 949#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 950/* do_select() must return target values and target errnos. */
992f48a0 951static abi_long do_select(int n,
26edcf41
TS
952 abi_ulong rfd_addr, abi_ulong wfd_addr,
953 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
954{
955 fd_set rfds, wfds, efds;
956 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
957 struct timeval tv, *tv_ptr;
992f48a0 958 abi_long ret;
31e31b8a 959
055e0906
MF
960 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
961 if (ret) {
962 return ret;
53a5960a 963 }
055e0906
MF
964 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
965 if (ret) {
966 return ret;
53a5960a 967 }
055e0906
MF
968 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
969 if (ret) {
970 return ret;
53a5960a 971 }
3b46e624 972
26edcf41 973 if (target_tv_addr) {
788f5ec4
TS
974 if (copy_from_user_timeval(&tv, target_tv_addr))
975 return -TARGET_EFAULT;
31e31b8a
FB
976 tv_ptr = &tv;
977 } else {
978 tv_ptr = NULL;
979 }
26edcf41 980
31e31b8a 981 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
53a5960a 982
26edcf41
TS
983 if (!is_error(ret)) {
984 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
985 return -TARGET_EFAULT;
986 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
987 return -TARGET_EFAULT;
988 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
989 return -TARGET_EFAULT;
31e31b8a 990
788f5ec4
TS
991 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
992 return -TARGET_EFAULT;
31e31b8a 993 }
579a97f7 994
31e31b8a
FB
995 return ret;
996}
055e0906 997#endif
31e31b8a 998
099d6b0f
RV
999static abi_long do_pipe2(int host_pipe[], int flags)
1000{
1001#ifdef CONFIG_PIPE2
1002 return pipe2(host_pipe, flags);
1003#else
1004 return -ENOSYS;
1005#endif
1006}
1007
fb41a66e
RH
1008static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1009 int flags, int is_pipe2)
099d6b0f
RV
1010{
1011 int host_pipe[2];
1012 abi_long ret;
1013 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1014
1015 if (is_error(ret))
1016 return get_errno(ret);
fb41a66e
RH
1017
1018 /* Several targets have special calling conventions for the original
1019 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1020 if (!is_pipe2) {
1021#if defined(TARGET_ALPHA)
1022 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1023 return host_pipe[0];
1024#elif defined(TARGET_MIPS)
1025 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1026 return host_pipe[0];
1027#elif defined(TARGET_SH4)
597c0212 1028 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
fb41a66e 1029 return host_pipe[0];
82f05b69
PM
1030#elif defined(TARGET_SPARC)
1031 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1032 return host_pipe[0];
597c0212 1033#endif
fb41a66e
RH
1034 }
1035
099d6b0f
RV
1036 if (put_user_s32(host_pipe[0], pipedes)
1037 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1038 return -TARGET_EFAULT;
099d6b0f
RV
1039 return get_errno(ret);
1040}
1041
b975b83b
LL
1042static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1043 abi_ulong target_addr,
1044 socklen_t len)
1045{
1046 struct target_ip_mreqn *target_smreqn;
1047
1048 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1049 if (!target_smreqn)
1050 return -TARGET_EFAULT;
1051 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1052 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1053 if (len == sizeof(struct target_ip_mreqn))
cbb21eed 1054 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
b975b83b
LL
1055 unlock_user(target_smreqn, target_addr, 0);
1056
1057 return 0;
1058}
1059
579a97f7
FB
1060static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1061 abi_ulong target_addr,
1062 socklen_t len)
7854b056 1063{
607175e0
AJ
1064 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1065 sa_family_t sa_family;
53a5960a
PB
1066 struct target_sockaddr *target_saddr;
1067
579a97f7
FB
1068 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1069 if (!target_saddr)
1070 return -TARGET_EFAULT;
607175e0
AJ
1071
1072 sa_family = tswap16(target_saddr->sa_family);
1073
1074 /* Oops. The caller might send a incomplete sun_path; sun_path
1075 * must be terminated by \0 (see the manual page), but
1076 * unfortunately it is quite common to specify sockaddr_un
1077 * length as "strlen(x->sun_path)" while it should be
1078 * "strlen(...) + 1". We'll fix that here if needed.
1079 * Linux kernel has a similar feature.
1080 */
1081
1082 if (sa_family == AF_UNIX) {
1083 if (len < unix_maxlen && len > 0) {
1084 char *cp = (char*)target_saddr;
1085
1086 if ( cp[len-1] && !cp[len] )
1087 len++;
1088 }
1089 if (len > unix_maxlen)
1090 len = unix_maxlen;
1091 }
1092
53a5960a 1093 memcpy(addr, target_saddr, len);
607175e0 1094 addr->sa_family = sa_family;
53a5960a 1095 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1096
1097 return 0;
7854b056
FB
1098}
1099
579a97f7
FB
1100static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1101 struct sockaddr *addr,
1102 socklen_t len)
7854b056 1103{
53a5960a
PB
1104 struct target_sockaddr *target_saddr;
1105
579a97f7
FB
1106 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1107 if (!target_saddr)
1108 return -TARGET_EFAULT;
53a5960a
PB
1109 memcpy(target_saddr, addr, len);
1110 target_saddr->sa_family = tswap16(addr->sa_family);
1111 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1112
1113 return 0;
7854b056
FB
1114}
1115
5a4a898d
FB
1116static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1117 struct target_msghdr *target_msgh)
7854b056
FB
1118{
1119 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1120 abi_long msg_controllen;
1121 abi_ulong target_cmsg_addr;
1122 struct target_cmsghdr *target_cmsg;
7854b056 1123 socklen_t space = 0;
5a4a898d 1124
cbb21eed 1125 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1126 if (msg_controllen < sizeof (struct target_cmsghdr))
1127 goto the_end;
cbb21eed 1128 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d
FB
1129 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1130 if (!target_cmsg)
1131 return -TARGET_EFAULT;
7854b056
FB
1132
1133 while (cmsg && target_cmsg) {
1134 void *data = CMSG_DATA(cmsg);
1135 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1136
cbb21eed 1137 int len = tswapal(target_cmsg->cmsg_len)
7854b056
FB
1138 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1139
1140 space += CMSG_SPACE(len);
1141 if (space > msgh->msg_controllen) {
1142 space -= CMSG_SPACE(len);
31febb71 1143 gemu_log("Host cmsg overflow\n");
7854b056
FB
1144 break;
1145 }
1146
dbf4f796
PJ
1147 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1148 cmsg->cmsg_level = SOL_SOCKET;
1149 } else {
1150 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1151 }
7854b056
FB
1152 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1153 cmsg->cmsg_len = CMSG_LEN(len);
1154
dbf4f796 1155 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
7854b056
FB
1156 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1157 memcpy(data, target_data, len);
1158 } else {
1159 int *fd = (int *)data;
1160 int *target_fd = (int *)target_data;
1161 int i, numfds = len / sizeof(int);
1162
1163 for (i = 0; i < numfds; i++)
1164 fd[i] = tswap32(target_fd[i]);
1165 }
1166
1167 cmsg = CMSG_NXTHDR(msgh, cmsg);
1168 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1169 }
5a4a898d
FB
1170 unlock_user(target_cmsg, target_cmsg_addr, 0);
1171 the_end:
7854b056 1172 msgh->msg_controllen = space;
5a4a898d 1173 return 0;
7854b056
FB
1174}
1175
5a4a898d
FB
1176static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1177 struct msghdr *msgh)
7854b056
FB
1178{
1179 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1180 abi_long msg_controllen;
1181 abi_ulong target_cmsg_addr;
1182 struct target_cmsghdr *target_cmsg;
7854b056
FB
1183 socklen_t space = 0;
1184
cbb21eed 1185 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1186 if (msg_controllen < sizeof (struct target_cmsghdr))
1187 goto the_end;
cbb21eed 1188 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d
FB
1189 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1190 if (!target_cmsg)
1191 return -TARGET_EFAULT;
1192
7854b056
FB
1193 while (cmsg && target_cmsg) {
1194 void *data = CMSG_DATA(cmsg);
1195 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1196
1197 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1198
1199 space += TARGET_CMSG_SPACE(len);
5a4a898d 1200 if (space > msg_controllen) {
7854b056 1201 space -= TARGET_CMSG_SPACE(len);
31febb71 1202 gemu_log("Target cmsg overflow\n");
7854b056
FB
1203 break;
1204 }
1205
dbf4f796
PJ
1206 if (cmsg->cmsg_level == SOL_SOCKET) {
1207 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1208 } else {
1209 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1210 }
7854b056 1211 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
cbb21eed 1212 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(len));
7854b056 1213
52b65494
HD
1214 switch (cmsg->cmsg_level) {
1215 case SOL_SOCKET:
1216 switch (cmsg->cmsg_type) {
1217 case SCM_RIGHTS:
1218 {
1219 int *fd = (int *)data;
1220 int *target_fd = (int *)target_data;
1221 int i, numfds = len / sizeof(int);
1222
1223 for (i = 0; i < numfds; i++)
1224 target_fd[i] = tswap32(fd[i]);
1225 break;
1226 }
1227 case SO_TIMESTAMP:
1228 {
1229 struct timeval *tv = (struct timeval *)data;
1230 struct target_timeval *target_tv =
1231 (struct target_timeval *)target_data;
1232
1233 if (len != sizeof(struct timeval))
1234 goto unimplemented;
1235
1236 /* copy struct timeval to target */
1237 target_tv->tv_sec = tswapal(tv->tv_sec);
1238 target_tv->tv_usec = tswapal(tv->tv_usec);
1239 break;
1240 }
4bc29756
HD
1241 case SCM_CREDENTIALS:
1242 {
1243 struct ucred *cred = (struct ucred *)data;
1244 struct target_ucred *target_cred =
1245 (struct target_ucred *)target_data;
1246
1247 __put_user(cred->pid, &target_cred->pid);
1248 __put_user(cred->uid, &target_cred->uid);
1249 __put_user(cred->gid, &target_cred->gid);
1250 break;
1251 }
52b65494
HD
1252 default:
1253 goto unimplemented;
1254 }
1255 break;
7854b056 1256
52b65494
HD
1257 default:
1258 unimplemented:
aebf5bc7
JH
1259 gemu_log("Unsupported ancillary data: %d/%d\n",
1260 cmsg->cmsg_level, cmsg->cmsg_type);
1261 memcpy(target_data, data, len);
7854b056
FB
1262 }
1263
1264 cmsg = CMSG_NXTHDR(msgh, cmsg);
1265 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1266 }
5a4a898d
FB
1267 unlock_user(target_cmsg, target_cmsg_addr, space);
1268 the_end:
cbb21eed 1269 target_msgh->msg_controllen = tswapal(space);
5a4a898d 1270 return 0;
7854b056
FB
1271}
1272
0da46a6e 1273/* do_setsockopt() Must return target values and target errnos. */
992f48a0 1274static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 1275 abi_ulong optval_addr, socklen_t optlen)
7854b056 1276{
992f48a0 1277 abi_long ret;
32407103 1278 int val;
b975b83b 1279 struct ip_mreqn *ip_mreq;
6e3cb58f 1280 struct ip_mreq_source *ip_mreq_source;
3b46e624 1281
8853f86e
FB
1282 switch(level) {
1283 case SOL_TCP:
7854b056 1284 /* TCP options all take an 'int' value. */
7854b056 1285 if (optlen < sizeof(uint32_t))
0da46a6e 1286 return -TARGET_EINVAL;
3b46e624 1287
2f619698
FB
1288 if (get_user_u32(val, optval_addr))
1289 return -TARGET_EFAULT;
8853f86e
FB
1290 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1291 break;
1292 case SOL_IP:
1293 switch(optname) {
2efbe911
FB
1294 case IP_TOS:
1295 case IP_TTL:
8853f86e 1296 case IP_HDRINCL:
2efbe911
FB
1297 case IP_ROUTER_ALERT:
1298 case IP_RECVOPTS:
1299 case IP_RETOPTS:
1300 case IP_PKTINFO:
1301 case IP_MTU_DISCOVER:
1302 case IP_RECVERR:
1303 case IP_RECVTOS:
1304#ifdef IP_FREEBIND
1305 case IP_FREEBIND:
1306#endif
1307 case IP_MULTICAST_TTL:
1308 case IP_MULTICAST_LOOP:
8853f86e
FB
1309 val = 0;
1310 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
1311 if (get_user_u32(val, optval_addr))
1312 return -TARGET_EFAULT;
8853f86e 1313 } else if (optlen >= 1) {
2f619698
FB
1314 if (get_user_u8(val, optval_addr))
1315 return -TARGET_EFAULT;
8853f86e
FB
1316 }
1317 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1318 break;
b975b83b
LL
1319 case IP_ADD_MEMBERSHIP:
1320 case IP_DROP_MEMBERSHIP:
1321 if (optlen < sizeof (struct target_ip_mreq) ||
1322 optlen > sizeof (struct target_ip_mreqn))
1323 return -TARGET_EINVAL;
1324
1325 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1326 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1327 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1328 break;
1329
6e3cb58f
LL
1330 case IP_BLOCK_SOURCE:
1331 case IP_UNBLOCK_SOURCE:
1332 case IP_ADD_SOURCE_MEMBERSHIP:
1333 case IP_DROP_SOURCE_MEMBERSHIP:
1334 if (optlen != sizeof (struct target_ip_mreq_source))
1335 return -TARGET_EINVAL;
1336
1337 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1338 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1339 unlock_user (ip_mreq_source, optval_addr, 0);
1340 break;
1341
920394db
JH
1342 default:
1343 goto unimplemented;
1344 }
1345 break;
0d78b3b5
LV
1346 case SOL_IPV6:
1347 switch (optname) {
1348 case IPV6_MTU_DISCOVER:
1349 case IPV6_MTU:
1350 case IPV6_V6ONLY:
1351 case IPV6_RECVPKTINFO:
1352 val = 0;
1353 if (optlen < sizeof(uint32_t)) {
1354 return -TARGET_EINVAL;
1355 }
1356 if (get_user_u32(val, optval_addr)) {
1357 return -TARGET_EFAULT;
1358 }
1359 ret = get_errno(setsockopt(sockfd, level, optname,
1360 &val, sizeof(val)));
1361 break;
1362 default:
1363 goto unimplemented;
1364 }
1365 break;
920394db
JH
1366 case SOL_RAW:
1367 switch (optname) {
1368 case ICMP_FILTER:
1369 /* struct icmp_filter takes an u32 value */
1370 if (optlen < sizeof(uint32_t)) {
1371 return -TARGET_EINVAL;
1372 }
1373
1374 if (get_user_u32(val, optval_addr)) {
1375 return -TARGET_EFAULT;
1376 }
1377 ret = get_errno(setsockopt(sockfd, level, optname,
1378 &val, sizeof(val)));
1379 break;
1380
8853f86e
FB
1381 default:
1382 goto unimplemented;
1383 }
1384 break;
3532fa74 1385 case TARGET_SOL_SOCKET:
8853f86e 1386 switch (optname) {
1b09aeb9
LV
1387 case TARGET_SO_RCVTIMEO:
1388 {
1389 struct timeval tv;
1390
1391 optname = SO_RCVTIMEO;
1392
1393set_timeout:
1394 if (optlen != sizeof(struct target_timeval)) {
1395 return -TARGET_EINVAL;
1396 }
1397
1398 if (copy_from_user_timeval(&tv, optval_addr)) {
1399 return -TARGET_EFAULT;
1400 }
1401
1402 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
1403 &tv, sizeof(tv)));
1404 return ret;
1405 }
1406 case TARGET_SO_SNDTIMEO:
1407 optname = SO_SNDTIMEO;
1408 goto set_timeout;
f57d4192
LV
1409 case TARGET_SO_ATTACH_FILTER:
1410 {
1411 struct target_sock_fprog *tfprog;
1412 struct target_sock_filter *tfilter;
1413 struct sock_fprog fprog;
1414 struct sock_filter *filter;
1415 int i;
1416
1417 if (optlen != sizeof(*tfprog)) {
1418 return -TARGET_EINVAL;
1419 }
1420 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
1421 return -TARGET_EFAULT;
1422 }
1423 if (!lock_user_struct(VERIFY_READ, tfilter,
1424 tswapal(tfprog->filter), 0)) {
1425 unlock_user_struct(tfprog, optval_addr, 1);
1426 return -TARGET_EFAULT;
1427 }
1428
1429 fprog.len = tswap16(tfprog->len);
1430 filter = malloc(fprog.len * sizeof(*filter));
1431 if (filter == NULL) {
1432 unlock_user_struct(tfilter, tfprog->filter, 1);
1433 unlock_user_struct(tfprog, optval_addr, 1);
1434 return -TARGET_ENOMEM;
1435 }
1436 for (i = 0; i < fprog.len; i++) {
1437 filter[i].code = tswap16(tfilter[i].code);
1438 filter[i].jt = tfilter[i].jt;
1439 filter[i].jf = tfilter[i].jf;
1440 filter[i].k = tswap32(tfilter[i].k);
1441 }
1442 fprog.filter = filter;
1443
1444 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
1445 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
1446 free(filter);
1447
1448 unlock_user_struct(tfilter, tfprog->filter, 1);
1449 unlock_user_struct(tfprog, optval_addr, 1);
1450 return ret;
1451 }
8853f86e 1452 /* Options with 'int' argument. */
3532fa74
FB
1453 case TARGET_SO_DEBUG:
1454 optname = SO_DEBUG;
1455 break;
1456 case TARGET_SO_REUSEADDR:
1457 optname = SO_REUSEADDR;
1458 break;
1459 case TARGET_SO_TYPE:
1460 optname = SO_TYPE;
1461 break;
1462 case TARGET_SO_ERROR:
1463 optname = SO_ERROR;
1464 break;
1465 case TARGET_SO_DONTROUTE:
1466 optname = SO_DONTROUTE;
1467 break;
1468 case TARGET_SO_BROADCAST:
1469 optname = SO_BROADCAST;
1470 break;
1471 case TARGET_SO_SNDBUF:
1472 optname = SO_SNDBUF;
1473 break;
1474 case TARGET_SO_RCVBUF:
1475 optname = SO_RCVBUF;
1476 break;
1477 case TARGET_SO_KEEPALIVE:
1478 optname = SO_KEEPALIVE;
1479 break;
1480 case TARGET_SO_OOBINLINE:
1481 optname = SO_OOBINLINE;
1482 break;
1483 case TARGET_SO_NO_CHECK:
1484 optname = SO_NO_CHECK;
1485 break;
1486 case TARGET_SO_PRIORITY:
1487 optname = SO_PRIORITY;
1488 break;
5e83e8e3 1489#ifdef SO_BSDCOMPAT
3532fa74
FB
1490 case TARGET_SO_BSDCOMPAT:
1491 optname = SO_BSDCOMPAT;
1492 break;
5e83e8e3 1493#endif
3532fa74
FB
1494 case TARGET_SO_PASSCRED:
1495 optname = SO_PASSCRED;
1496 break;
1497 case TARGET_SO_TIMESTAMP:
1498 optname = SO_TIMESTAMP;
1499 break;
1500 case TARGET_SO_RCVLOWAT:
1501 optname = SO_RCVLOWAT;
1502 break;
8853f86e
FB
1503 break;
1504 default:
1505 goto unimplemented;
1506 }
3532fa74 1507 if (optlen < sizeof(uint32_t))
2f619698 1508 return -TARGET_EINVAL;
3532fa74 1509
2f619698
FB
1510 if (get_user_u32(val, optval_addr))
1511 return -TARGET_EFAULT;
3532fa74 1512 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 1513 break;
7854b056 1514 default:
8853f86e 1515 unimplemented:
b2bedb21 1516 gemu_log("Unsupported setsockopt level=%d optname=%d\n", level, optname);
6fa13c17 1517 ret = -TARGET_ENOPROTOOPT;
7854b056 1518 }
8853f86e 1519 return ret;
7854b056
FB
1520}
1521
0da46a6e 1522/* do_getsockopt() Must return target values and target errnos. */
992f48a0 1523static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 1524 abi_ulong optval_addr, abi_ulong optlen)
7854b056 1525{
992f48a0 1526 abi_long ret;
b55266b5
BS
1527 int len, val;
1528 socklen_t lv;
8853f86e
FB
1529
1530 switch(level) {
3532fa74 1531 case TARGET_SOL_SOCKET:
f3b974cd
JL
1532 level = SOL_SOCKET;
1533 switch (optname) {
1534 /* These don't just return a single integer */
1535 case TARGET_SO_LINGER:
1536 case TARGET_SO_RCVTIMEO:
1537 case TARGET_SO_SNDTIMEO:
f3b974cd
JL
1538 case TARGET_SO_PEERNAME:
1539 goto unimplemented;
583359a6
AP
1540 case TARGET_SO_PEERCRED: {
1541 struct ucred cr;
1542 socklen_t crlen;
1543 struct target_ucred *tcr;
1544
1545 if (get_user_u32(len, optlen)) {
1546 return -TARGET_EFAULT;
1547 }
1548 if (len < 0) {
1549 return -TARGET_EINVAL;
1550 }
1551
1552 crlen = sizeof(cr);
1553 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
1554 &cr, &crlen));
1555 if (ret < 0) {
1556 return ret;
1557 }
1558 if (len > crlen) {
1559 len = crlen;
1560 }
1561 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
1562 return -TARGET_EFAULT;
1563 }
1564 __put_user(cr.pid, &tcr->pid);
1565 __put_user(cr.uid, &tcr->uid);
1566 __put_user(cr.gid, &tcr->gid);
1567 unlock_user_struct(tcr, optval_addr, 1);
1568 if (put_user_u32(len, optlen)) {
1569 return -TARGET_EFAULT;
1570 }
1571 break;
1572 }
f3b974cd
JL
1573 /* Options with 'int' argument. */
1574 case TARGET_SO_DEBUG:
1575 optname = SO_DEBUG;
1576 goto int_case;
1577 case TARGET_SO_REUSEADDR:
1578 optname = SO_REUSEADDR;
1579 goto int_case;
1580 case TARGET_SO_TYPE:
1581 optname = SO_TYPE;
1582 goto int_case;
1583 case TARGET_SO_ERROR:
1584 optname = SO_ERROR;
1585 goto int_case;
1586 case TARGET_SO_DONTROUTE:
1587 optname = SO_DONTROUTE;
1588 goto int_case;
1589 case TARGET_SO_BROADCAST:
1590 optname = SO_BROADCAST;
1591 goto int_case;
1592 case TARGET_SO_SNDBUF:
1593 optname = SO_SNDBUF;
1594 goto int_case;
1595 case TARGET_SO_RCVBUF:
1596 optname = SO_RCVBUF;
1597 goto int_case;
1598 case TARGET_SO_KEEPALIVE:
1599 optname = SO_KEEPALIVE;
1600 goto int_case;
1601 case TARGET_SO_OOBINLINE:
1602 optname = SO_OOBINLINE;
1603 goto int_case;
1604 case TARGET_SO_NO_CHECK:
1605 optname = SO_NO_CHECK;
1606 goto int_case;
1607 case TARGET_SO_PRIORITY:
1608 optname = SO_PRIORITY;
1609 goto int_case;
1610#ifdef SO_BSDCOMPAT
1611 case TARGET_SO_BSDCOMPAT:
1612 optname = SO_BSDCOMPAT;
1613 goto int_case;
1614#endif
1615 case TARGET_SO_PASSCRED:
1616 optname = SO_PASSCRED;
1617 goto int_case;
1618 case TARGET_SO_TIMESTAMP:
1619 optname = SO_TIMESTAMP;
1620 goto int_case;
1621 case TARGET_SO_RCVLOWAT:
1622 optname = SO_RCVLOWAT;
1623 goto int_case;
8853f86e 1624 default:
2efbe911
FB
1625 goto int_case;
1626 }
1627 break;
1628 case SOL_TCP:
1629 /* TCP options all take an 'int' value. */
1630 int_case:
2f619698
FB
1631 if (get_user_u32(len, optlen))
1632 return -TARGET_EFAULT;
2efbe911 1633 if (len < 0)
0da46a6e 1634 return -TARGET_EINVAL;
73160d95 1635 lv = sizeof(lv);
2efbe911
FB
1636 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1637 if (ret < 0)
1638 return ret;
2efbe911
FB
1639 if (len > lv)
1640 len = lv;
2f619698
FB
1641 if (len == 4) {
1642 if (put_user_u32(val, optval_addr))
1643 return -TARGET_EFAULT;
1644 } else {
1645 if (put_user_u8(val, optval_addr))
1646 return -TARGET_EFAULT;
f3b974cd 1647 }
2f619698
FB
1648 if (put_user_u32(len, optlen))
1649 return -TARGET_EFAULT;
2efbe911
FB
1650 break;
1651 case SOL_IP:
1652 switch(optname) {
1653 case IP_TOS:
1654 case IP_TTL:
1655 case IP_HDRINCL:
1656 case IP_ROUTER_ALERT:
1657 case IP_RECVOPTS:
1658 case IP_RETOPTS:
1659 case IP_PKTINFO:
1660 case IP_MTU_DISCOVER:
1661 case IP_RECVERR:
1662 case IP_RECVTOS:
1663#ifdef IP_FREEBIND
1664 case IP_FREEBIND:
1665#endif
1666 case IP_MULTICAST_TTL:
1667 case IP_MULTICAST_LOOP:
2f619698
FB
1668 if (get_user_u32(len, optlen))
1669 return -TARGET_EFAULT;
8853f86e 1670 if (len < 0)
0da46a6e 1671 return -TARGET_EINVAL;
73160d95 1672 lv = sizeof(lv);
8853f86e
FB
1673 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1674 if (ret < 0)
1675 return ret;
2efbe911 1676 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 1677 len = 1;
2f619698
FB
1678 if (put_user_u32(len, optlen)
1679 || put_user_u8(val, optval_addr))
1680 return -TARGET_EFAULT;
2efbe911 1681 } else {
2efbe911
FB
1682 if (len > sizeof(int))
1683 len = sizeof(int);
2f619698
FB
1684 if (put_user_u32(len, optlen)
1685 || put_user_u32(val, optval_addr))
1686 return -TARGET_EFAULT;
2efbe911 1687 }
8853f86e 1688 break;
2efbe911 1689 default:
c02f499e
TS
1690 ret = -TARGET_ENOPROTOOPT;
1691 break;
8853f86e
FB
1692 }
1693 break;
1694 default:
1695 unimplemented:
1696 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1697 level, optname);
c02f499e 1698 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
1699 break;
1700 }
1701 return ret;
7854b056
FB
1702}
1703
f287b2c2
RH
1704static struct iovec *lock_iovec(int type, abi_ulong target_addr,
1705 int count, int copy)
53a5960a
PB
1706{
1707 struct target_iovec *target_vec;
f287b2c2
RH
1708 struct iovec *vec;
1709 abi_ulong total_len, max_len;
d732dcb4 1710 int i;
501bb4b0 1711 int err = 0;
53a5960a 1712
f287b2c2
RH
1713 if (count == 0) {
1714 errno = 0;
1715 return NULL;
1716 }
dfae8e00 1717 if (count < 0 || count > IOV_MAX) {
f287b2c2
RH
1718 errno = EINVAL;
1719 return NULL;
1720 }
1721
1722 vec = calloc(count, sizeof(struct iovec));
1723 if (vec == NULL) {
1724 errno = ENOMEM;
1725 return NULL;
1726 }
1727
1728 target_vec = lock_user(VERIFY_READ, target_addr,
1729 count * sizeof(struct target_iovec), 1);
1730 if (target_vec == NULL) {
501bb4b0 1731 err = EFAULT;
f287b2c2
RH
1732 goto fail2;
1733 }
1734
1735 /* ??? If host page size > target page size, this will result in a
1736 value larger than what we can actually support. */
1737 max_len = 0x7fffffff & TARGET_PAGE_MASK;
1738 total_len = 0;
1739
1740 for (i = 0; i < count; i++) {
1741 abi_ulong base = tswapal(target_vec[i].iov_base);
1742 abi_long len = tswapal(target_vec[i].iov_len);
1743
1744 if (len < 0) {
501bb4b0 1745 err = EINVAL;
f287b2c2
RH
1746 goto fail;
1747 } else if (len == 0) {
1748 /* Zero length pointer is ignored. */
1749 vec[i].iov_base = 0;
41df8411 1750 } else {
f287b2c2
RH
1751 vec[i].iov_base = lock_user(type, base, len, copy);
1752 if (!vec[i].iov_base) {
501bb4b0 1753 err = EFAULT;
f287b2c2
RH
1754 goto fail;
1755 }
1756 if (len > max_len - total_len) {
1757 len = max_len - total_len;
1758 }
41df8411 1759 }
f287b2c2
RH
1760 vec[i].iov_len = len;
1761 total_len += len;
579a97f7 1762 }
f287b2c2
RH
1763
1764 unlock_user(target_vec, target_addr, 0);
1765 return vec;
1766
1767 fail:
f287b2c2 1768 unlock_user(target_vec, target_addr, 0);
501bb4b0
PM
1769 fail2:
1770 free(vec);
1771 errno = err;
f287b2c2 1772 return NULL;
53a5960a
PB
1773}
1774
f287b2c2
RH
1775static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1776 int count, int copy)
53a5960a
PB
1777{
1778 struct target_iovec *target_vec;
53a5960a
PB
1779 int i;
1780
f287b2c2
RH
1781 target_vec = lock_user(VERIFY_READ, target_addr,
1782 count * sizeof(struct target_iovec), 1);
1783 if (target_vec) {
1784 for (i = 0; i < count; i++) {
1785 abi_ulong base = tswapal(target_vec[i].iov_base);
1786 abi_long len = tswapal(target_vec[i].iov_base);
1787 if (len < 0) {
1788 break;
1789 }
d732dcb4
AZ
1790 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1791 }
f287b2c2 1792 unlock_user(target_vec, target_addr, 0);
53a5960a 1793 }
579a97f7 1794
f287b2c2 1795 free(vec);
53a5960a
PB
1796}
1797
53d09b76 1798static inline int target_to_host_sock_type(int *type)
3532fa74 1799{
f651e6ae
PJ
1800 int host_type = 0;
1801 int target_type = *type;
1802
1803 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3532fa74 1804 case TARGET_SOCK_DGRAM:
f651e6ae 1805 host_type = SOCK_DGRAM;
3532fa74
FB
1806 break;
1807 case TARGET_SOCK_STREAM:
f651e6ae 1808 host_type = SOCK_STREAM;
3532fa74 1809 break;
f651e6ae
PJ
1810 default:
1811 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3532fa74
FB
1812 break;
1813 }
f651e6ae 1814 if (target_type & TARGET_SOCK_CLOEXEC) {
53d09b76 1815#if defined(SOCK_CLOEXEC)
f651e6ae 1816 host_type |= SOCK_CLOEXEC;
53d09b76
EI
1817#else
1818 return -TARGET_EINVAL;
1819#endif
f651e6ae
PJ
1820 }
1821 if (target_type & TARGET_SOCK_NONBLOCK) {
53d09b76 1822#if defined(SOCK_NONBLOCK)
f651e6ae 1823 host_type |= SOCK_NONBLOCK;
53d09b76
EI
1824#elif !defined(O_NONBLOCK)
1825 return -TARGET_EINVAL;
1826#endif
f651e6ae
PJ
1827 }
1828 *type = host_type;
53d09b76
EI
1829 return 0;
1830}
1831
1832/* Try to emulate socket type flags after socket creation. */
1833static int sock_flags_fixup(int fd, int target_type)
1834{
1835#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
1836 if (target_type & TARGET_SOCK_NONBLOCK) {
1837 int flags = fcntl(fd, F_GETFL);
1838 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
1839 close(fd);
1840 return -TARGET_EINVAL;
1841 }
1842 }
1843#endif
1844 return fd;
f651e6ae
PJ
1845}
1846
1847/* do_socket() Must return target values and target errnos. */
1848static abi_long do_socket(int domain, int type, int protocol)
1849{
53d09b76
EI
1850 int target_type = type;
1851 int ret;
1852
1853 ret = target_to_host_sock_type(&type);
1854 if (ret) {
1855 return ret;
1856 }
f651e6ae 1857
12bc92ab 1858 if (domain == PF_NETLINK)
480eda2e 1859 return -TARGET_EAFNOSUPPORT;
53d09b76
EI
1860 ret = get_errno(socket(domain, type, protocol));
1861 if (ret >= 0) {
1862 ret = sock_flags_fixup(ret, target_type);
1863 }
1864 return ret;
3532fa74
FB
1865}
1866
0da46a6e 1867/* do_bind() Must return target values and target errnos. */
992f48a0
BS
1868static abi_long do_bind(int sockfd, abi_ulong target_addr,
1869 socklen_t addrlen)
3532fa74 1870{
8f7aeaf6 1871 void *addr;
917507b0 1872 abi_long ret;
8f7aeaf6 1873
38724253 1874 if ((int)addrlen < 0) {
8f7aeaf6 1875 return -TARGET_EINVAL;
38724253 1876 }
8f7aeaf6 1877
607175e0 1878 addr = alloca(addrlen+1);
3b46e624 1879
917507b0
AP
1880 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1881 if (ret)
1882 return ret;
1883
3532fa74
FB
1884 return get_errno(bind(sockfd, addr, addrlen));
1885}
1886
0da46a6e 1887/* do_connect() Must return target values and target errnos. */
992f48a0
BS
1888static abi_long do_connect(int sockfd, abi_ulong target_addr,
1889 socklen_t addrlen)
3532fa74 1890{
8f7aeaf6 1891 void *addr;
917507b0 1892 abi_long ret;
8f7aeaf6 1893
38724253 1894 if ((int)addrlen < 0) {
8f7aeaf6 1895 return -TARGET_EINVAL;
38724253 1896 }
8f7aeaf6
AJ
1897
1898 addr = alloca(addrlen);
3b46e624 1899
917507b0
AP
1900 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1901 if (ret)
1902 return ret;
1903
3532fa74
FB
1904 return get_errno(connect(sockfd, addr, addrlen));
1905}
1906
f19e00d7
AG
1907/* do_sendrecvmsg_locked() Must return target values and target errnos. */
1908static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
1909 int flags, int send)
3532fa74 1910{
6de645c7 1911 abi_long ret, len;
3532fa74
FB
1912 struct msghdr msg;
1913 int count;
1914 struct iovec *vec;
992f48a0 1915 abi_ulong target_vec;
3532fa74 1916
3532fa74
FB
1917 if (msgp->msg_name) {
1918 msg.msg_namelen = tswap32(msgp->msg_namelen);
1919 msg.msg_name = alloca(msg.msg_namelen);
cbb21eed 1920 ret = target_to_host_sockaddr(msg.msg_name, tswapal(msgp->msg_name),
3532fa74 1921 msg.msg_namelen);
917507b0 1922 if (ret) {
f287b2c2 1923 goto out2;
917507b0 1924 }
3532fa74
FB
1925 } else {
1926 msg.msg_name = NULL;
1927 msg.msg_namelen = 0;
1928 }
cbb21eed 1929 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
3532fa74
FB
1930 msg.msg_control = alloca(msg.msg_controllen);
1931 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 1932
cbb21eed 1933 count = tswapal(msgp->msg_iovlen);
cbb21eed 1934 target_vec = tswapal(msgp->msg_iov);
f287b2c2
RH
1935 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
1936 target_vec, count, send);
1937 if (vec == NULL) {
1938 ret = -host_to_target_errno(errno);
1939 goto out2;
1940 }
3532fa74
FB
1941 msg.msg_iovlen = count;
1942 msg.msg_iov = vec;
3b46e624 1943
3532fa74 1944 if (send) {
5a4a898d
FB
1945 ret = target_to_host_cmsg(&msg, msgp);
1946 if (ret == 0)
1947 ret = get_errno(sendmsg(fd, &msg, flags));
3532fa74
FB
1948 } else {
1949 ret = get_errno(recvmsg(fd, &msg, flags));
6de645c7
AZ
1950 if (!is_error(ret)) {
1951 len = ret;
5a4a898d 1952 ret = host_to_target_cmsg(msgp, &msg);
ca619067
JH
1953 if (!is_error(ret)) {
1954 msgp->msg_namelen = tswap32(msg.msg_namelen);
1955 if (msg.msg_name != NULL) {
1956 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
1957 msg.msg_name, msg.msg_namelen);
1958 if (ret) {
1959 goto out;
1960 }
1961 }
1962
6de645c7 1963 ret = len;
ca619067 1964 }
6de645c7 1965 }
3532fa74 1966 }
ca619067
JH
1967
1968out:
3532fa74 1969 unlock_iovec(vec, target_vec, count, !send);
f287b2c2 1970out2:
f19e00d7
AG
1971 return ret;
1972}
1973
1974static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1975 int flags, int send)
1976{
1977 abi_long ret;
1978 struct target_msghdr *msgp;
1979
1980 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1981 msgp,
1982 target_msg,
1983 send ? 1 : 0)) {
1984 return -TARGET_EFAULT;
1985 }
1986 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
579a97f7 1987 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
1988 return ret;
1989}
1990
f19e00d7
AG
1991#ifdef TARGET_NR_sendmmsg
1992/* We don't rely on the C library to have sendmmsg/recvmmsg support,
1993 * so it might not have this *mmsg-specific flag either.
1994 */
1995#ifndef MSG_WAITFORONE
1996#define MSG_WAITFORONE 0x10000
1997#endif
1998
1999static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
2000 unsigned int vlen, unsigned int flags,
2001 int send)
2002{
2003 struct target_mmsghdr *mmsgp;
2004 abi_long ret = 0;
2005 int i;
2006
2007 if (vlen > UIO_MAXIOV) {
2008 vlen = UIO_MAXIOV;
2009 }
2010
2011 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
2012 if (!mmsgp) {
2013 return -TARGET_EFAULT;
2014 }
2015
2016 for (i = 0; i < vlen; i++) {
2017 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
2018 if (is_error(ret)) {
2019 break;
2020 }
2021 mmsgp[i].msg_len = tswap32(ret);
2022 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
2023 if (flags & MSG_WAITFORONE) {
2024 flags |= MSG_DONTWAIT;
2025 }
2026 }
2027
2028 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
2029
2030 /* Return number of datagrams sent if we sent any at all;
2031 * otherwise return the error.
2032 */
2033 if (i) {
2034 return i;
2035 }
2036 return ret;
2037}
2038#endif
2039
a94b4987
PM
2040/* If we don't have a system accept4() then just call accept.
2041 * The callsites to do_accept4() will ensure that they don't
2042 * pass a non-zero flags argument in this config.
2043 */
2044#ifndef CONFIG_ACCEPT4
2045static inline int accept4(int sockfd, struct sockaddr *addr,
2046 socklen_t *addrlen, int flags)
2047{
2048 assert(flags == 0);
2049 return accept(sockfd, addr, addrlen);
2050}
2051#endif
2052
2053/* do_accept4() Must return target values and target errnos. */
2054static abi_long do_accept4(int fd, abi_ulong target_addr,
2055 abi_ulong target_addrlen_addr, int flags)
1be9e1dc 2056{
2f619698
FB
2057 socklen_t addrlen;
2058 void *addr;
992f48a0 2059 abi_long ret;
d25295d4
PJ
2060 int host_flags;
2061
2062 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
1be9e1dc 2063
a94b4987 2064 if (target_addr == 0) {
d25295d4 2065 return get_errno(accept4(fd, NULL, NULL, host_flags));
a94b4987 2066 }
917507b0
AP
2067
2068 /* linux returns EINVAL if addrlen pointer is invalid */
2f619698 2069 if (get_user_u32(addrlen, target_addrlen_addr))
917507b0 2070 return -TARGET_EINVAL;
2f619698 2071
38724253 2072 if ((int)addrlen < 0) {
8f7aeaf6 2073 return -TARGET_EINVAL;
38724253 2074 }
8f7aeaf6 2075
917507b0
AP
2076 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2077 return -TARGET_EINVAL;
2078
2f619698
FB
2079 addr = alloca(addrlen);
2080
d25295d4 2081 ret = get_errno(accept4(fd, addr, &addrlen, host_flags));
1be9e1dc
PB
2082 if (!is_error(ret)) {
2083 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2084 if (put_user_u32(addrlen, target_addrlen_addr))
2085 ret = -TARGET_EFAULT;
1be9e1dc
PB
2086 }
2087 return ret;
2088}
2089
0da46a6e 2090/* do_getpeername() Must return target values and target errnos. */
992f48a0 2091static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 2092 abi_ulong target_addrlen_addr)
1be9e1dc 2093{
2f619698
FB
2094 socklen_t addrlen;
2095 void *addr;
992f48a0 2096 abi_long ret;
1be9e1dc 2097
2f619698
FB
2098 if (get_user_u32(addrlen, target_addrlen_addr))
2099 return -TARGET_EFAULT;
2100
38724253 2101 if ((int)addrlen < 0) {
8f7aeaf6 2102 return -TARGET_EINVAL;
38724253 2103 }
8f7aeaf6 2104
917507b0
AP
2105 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2106 return -TARGET_EFAULT;
2107
2f619698
FB
2108 addr = alloca(addrlen);
2109
1be9e1dc
PB
2110 ret = get_errno(getpeername(fd, addr, &addrlen));
2111 if (!is_error(ret)) {
2112 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2113 if (put_user_u32(addrlen, target_addrlen_addr))
2114 ret = -TARGET_EFAULT;
1be9e1dc
PB
2115 }
2116 return ret;
2117}
2118
0da46a6e 2119/* do_getsockname() Must return target values and target errnos. */
992f48a0 2120static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 2121 abi_ulong target_addrlen_addr)
1be9e1dc 2122{
2f619698
FB
2123 socklen_t addrlen;
2124 void *addr;
992f48a0 2125 abi_long ret;
1be9e1dc 2126
2f619698
FB
2127 if (get_user_u32(addrlen, target_addrlen_addr))
2128 return -TARGET_EFAULT;
2129
38724253 2130 if ((int)addrlen < 0) {
8f7aeaf6 2131 return -TARGET_EINVAL;
38724253 2132 }
8f7aeaf6 2133
917507b0
AP
2134 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
2135 return -TARGET_EFAULT;
2136
2f619698
FB
2137 addr = alloca(addrlen);
2138
1be9e1dc
PB
2139 ret = get_errno(getsockname(fd, addr, &addrlen));
2140 if (!is_error(ret)) {
2141 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2142 if (put_user_u32(addrlen, target_addrlen_addr))
2143 ret = -TARGET_EFAULT;
1be9e1dc
PB
2144 }
2145 return ret;
2146}
2147
0da46a6e 2148/* do_socketpair() Must return target values and target errnos. */
992f48a0 2149static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 2150 abi_ulong target_tab_addr)
1be9e1dc
PB
2151{
2152 int tab[2];
992f48a0 2153 abi_long ret;
1be9e1dc 2154
f651e6ae
PJ
2155 target_to_host_sock_type(&type);
2156
1be9e1dc
PB
2157 ret = get_errno(socketpair(domain, type, protocol, tab));
2158 if (!is_error(ret)) {
2f619698
FB
2159 if (put_user_s32(tab[0], target_tab_addr)
2160 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
2161 ret = -TARGET_EFAULT;
1be9e1dc
PB
2162 }
2163 return ret;
2164}
2165
0da46a6e 2166/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
2167static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
2168 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
2169{
2170 void *addr;
2171 void *host_msg;
992f48a0 2172 abi_long ret;
1be9e1dc 2173
38724253 2174 if ((int)addrlen < 0) {
8f7aeaf6 2175 return -TARGET_EINVAL;
38724253 2176 }
8f7aeaf6 2177
579a97f7
FB
2178 host_msg = lock_user(VERIFY_READ, msg, len, 1);
2179 if (!host_msg)
2180 return -TARGET_EFAULT;
1be9e1dc
PB
2181 if (target_addr) {
2182 addr = alloca(addrlen);
917507b0
AP
2183 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
2184 if (ret) {
2185 unlock_user(host_msg, msg, 0);
2186 return ret;
2187 }
1be9e1dc
PB
2188 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
2189 } else {
2190 ret = get_errno(send(fd, host_msg, len, flags));
2191 }
2192 unlock_user(host_msg, msg, 0);
2193 return ret;
2194}
2195
0da46a6e 2196/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
2197static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
2198 abi_ulong target_addr,
2199 abi_ulong target_addrlen)
1be9e1dc
PB
2200{
2201 socklen_t addrlen;
2202 void *addr;
2203 void *host_msg;
992f48a0 2204 abi_long ret;
1be9e1dc 2205
579a97f7
FB
2206 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
2207 if (!host_msg)
2208 return -TARGET_EFAULT;
1be9e1dc 2209 if (target_addr) {
2f619698
FB
2210 if (get_user_u32(addrlen, target_addrlen)) {
2211 ret = -TARGET_EFAULT;
2212 goto fail;
2213 }
38724253 2214 if ((int)addrlen < 0) {
8f7aeaf6
AJ
2215 ret = -TARGET_EINVAL;
2216 goto fail;
2217 }
1be9e1dc
PB
2218 addr = alloca(addrlen);
2219 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
2220 } else {
2221 addr = NULL; /* To keep compiler quiet. */
00aa0040 2222 ret = get_errno(qemu_recv(fd, host_msg, len, flags));
1be9e1dc
PB
2223 }
2224 if (!is_error(ret)) {
2225 if (target_addr) {
2226 host_to_target_sockaddr(target_addr, addr, addrlen);
2f619698
FB
2227 if (put_user_u32(addrlen, target_addrlen)) {
2228 ret = -TARGET_EFAULT;
2229 goto fail;
2230 }
1be9e1dc
PB
2231 }
2232 unlock_user(host_msg, msg, len);
2233 } else {
2f619698 2234fail:
1be9e1dc
PB
2235 unlock_user(host_msg, msg, 0);
2236 }
2237 return ret;
2238}
2239
32407103 2240#ifdef TARGET_NR_socketcall
0da46a6e 2241/* do_socketcall() Must return target values and target errnos. */
992f48a0 2242static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 2243{
62dc90c6
MT
2244 static const unsigned ac[] = { /* number of arguments per call */
2245 [SOCKOP_socket] = 3, /* domain, type, protocol */
2246 [SOCKOP_bind] = 3, /* sockfd, addr, addrlen */
2247 [SOCKOP_connect] = 3, /* sockfd, addr, addrlen */
2248 [SOCKOP_listen] = 2, /* sockfd, backlog */
2249 [SOCKOP_accept] = 3, /* sockfd, addr, addrlen */
2250 [SOCKOP_accept4] = 4, /* sockfd, addr, addrlen, flags */
2251 [SOCKOP_getsockname] = 3, /* sockfd, addr, addrlen */
2252 [SOCKOP_getpeername] = 3, /* sockfd, addr, addrlen */
2253 [SOCKOP_socketpair] = 4, /* domain, type, protocol, tab */
2254 [SOCKOP_send] = 4, /* sockfd, msg, len, flags */
2255 [SOCKOP_recv] = 4, /* sockfd, msg, len, flags */
2256 [SOCKOP_sendto] = 6, /* sockfd, msg, len, flags, addr, addrlen */
2257 [SOCKOP_recvfrom] = 6, /* sockfd, msg, len, flags, addr, addrlen */
2258 [SOCKOP_shutdown] = 2, /* sockfd, how */
2259 [SOCKOP_sendmsg] = 3, /* sockfd, msg, flags */
2260 [SOCKOP_recvmsg] = 3, /* sockfd, msg, flags */
2261 [SOCKOP_setsockopt] = 5, /* sockfd, level, optname, optval, optlen */
2262 [SOCKOP_getsockopt] = 5, /* sockfd, level, optname, optval, optlen */
2263 };
2264 abi_long a[6]; /* max 6 args */
2265
2266 /* first, collect the arguments in a[] according to ac[] */
2267 if (num >= 0 && num < ARRAY_SIZE(ac)) {
2268 unsigned i;
2269 assert(ARRAY_SIZE(a) >= ac[num]); /* ensure we have space for args */
2270 for (i = 0; i < ac[num]; ++i) {
2271 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
b9d36eb2
AH
2272 return -TARGET_EFAULT;
2273 }
31e31b8a 2274 }
62dc90c6 2275 }
7854b056 2276
62dc90c6
MT
2277 /* now when we have the args, actually handle the call */
2278 switch (num) {
2279 case SOCKOP_socket: /* domain, type, protocol */
2280 return do_socket(a[0], a[1], a[2]);
2281 case SOCKOP_bind: /* sockfd, addr, addrlen */
2282 return do_bind(a[0], a[1], a[2]);
2283 case SOCKOP_connect: /* sockfd, addr, addrlen */
2284 return do_connect(a[0], a[1], a[2]);
2285 case SOCKOP_listen: /* sockfd, backlog */
2286 return get_errno(listen(a[0], a[1]));
2287 case SOCKOP_accept: /* sockfd, addr, addrlen */
2288 return do_accept4(a[0], a[1], a[2], 0);
2289 case SOCKOP_accept4: /* sockfd, addr, addrlen, flags */
2290 return do_accept4(a[0], a[1], a[2], a[3]);
2291 case SOCKOP_getsockname: /* sockfd, addr, addrlen */
2292 return do_getsockname(a[0], a[1], a[2]);
2293 case SOCKOP_getpeername: /* sockfd, addr, addrlen */
2294 return do_getpeername(a[0], a[1], a[2]);
2295 case SOCKOP_socketpair: /* domain, type, protocol, tab */
2296 return do_socketpair(a[0], a[1], a[2], a[3]);
2297 case SOCKOP_send: /* sockfd, msg, len, flags */
2298 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
2299 case SOCKOP_recv: /* sockfd, msg, len, flags */
2300 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
2301 case SOCKOP_sendto: /* sockfd, msg, len, flags, addr, addrlen */
2302 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
2303 case SOCKOP_recvfrom: /* sockfd, msg, len, flags, addr, addrlen */
2304 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
2305 case SOCKOP_shutdown: /* sockfd, how */
2306 return get_errno(shutdown(a[0], a[1]));
2307 case SOCKOP_sendmsg: /* sockfd, msg, flags */
2308 return do_sendrecvmsg(a[0], a[1], a[2], 1);
2309 case SOCKOP_recvmsg: /* sockfd, msg, flags */
2310 return do_sendrecvmsg(a[0], a[1], a[2], 0);
2311 case SOCKOP_setsockopt: /* sockfd, level, optname, optval, optlen */
2312 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
2313 case SOCKOP_getsockopt: /* sockfd, level, optname, optval, optlen */
2314 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
31e31b8a
FB
2315 default:
2316 gemu_log("Unsupported socketcall: %d\n", num);
62dc90c6 2317 return -TARGET_ENOSYS;
31e31b8a 2318 }
31e31b8a 2319}
32407103 2320#endif
31e31b8a 2321
8853f86e
FB
2322#define N_SHM_REGIONS 32
2323
2324static struct shm_region {
5a4a898d
FB
2325 abi_ulong start;
2326 abi_ulong size;
8853f86e
FB
2327} shm_regions[N_SHM_REGIONS];
2328
3eb6b044
TS
2329struct target_semid_ds
2330{
2331 struct target_ipc_perm sem_perm;
992f48a0
BS
2332 abi_ulong sem_otime;
2333 abi_ulong __unused1;
2334 abi_ulong sem_ctime;
2335 abi_ulong __unused2;
2336 abi_ulong sem_nsems;
2337 abi_ulong __unused3;
2338 abi_ulong __unused4;
3eb6b044
TS
2339};
2340
579a97f7
FB
2341static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2342 abi_ulong target_addr)
3eb6b044
TS
2343{
2344 struct target_ipc_perm *target_ip;
2345 struct target_semid_ds *target_sd;
2346
579a97f7
FB
2347 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2348 return -TARGET_EFAULT;
e8bbe36c 2349 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2350 host_ip->__key = tswap32(target_ip->__key);
2351 host_ip->uid = tswap32(target_ip->uid);
2352 host_ip->gid = tswap32(target_ip->gid);
2353 host_ip->cuid = tswap32(target_ip->cuid);
2354 host_ip->cgid = tswap32(target_ip->cgid);
2355#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2356 host_ip->mode = tswap32(target_ip->mode);
2357#else
cbb21eed 2358 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
2359#endif
2360#if defined(TARGET_PPC)
2361 host_ip->__seq = tswap32(target_ip->__seq);
2362#else
2363 host_ip->__seq = tswap16(target_ip->__seq);
2364#endif
3eb6b044 2365 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2366 return 0;
3eb6b044
TS
2367}
2368
579a97f7
FB
2369static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2370 struct ipc_perm *host_ip)
3eb6b044
TS
2371{
2372 struct target_ipc_perm *target_ip;
2373 struct target_semid_ds *target_sd;
2374
579a97f7
FB
2375 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2376 return -TARGET_EFAULT;
3eb6b044 2377 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
2378 target_ip->__key = tswap32(host_ip->__key);
2379 target_ip->uid = tswap32(host_ip->uid);
2380 target_ip->gid = tswap32(host_ip->gid);
2381 target_ip->cuid = tswap32(host_ip->cuid);
2382 target_ip->cgid = tswap32(host_ip->cgid);
2383#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
2384 target_ip->mode = tswap32(host_ip->mode);
2385#else
cbb21eed 2386 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
2387#endif
2388#if defined(TARGET_PPC)
2389 target_ip->__seq = tswap32(host_ip->__seq);
2390#else
2391 target_ip->__seq = tswap16(host_ip->__seq);
2392#endif
3eb6b044 2393 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2394 return 0;
3eb6b044
TS
2395}
2396
579a97f7
FB
2397static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2398 abi_ulong target_addr)
3eb6b044
TS
2399{
2400 struct target_semid_ds *target_sd;
2401
579a97f7
FB
2402 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2403 return -TARGET_EFAULT;
e5289087
AJ
2404 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2405 return -TARGET_EFAULT;
cbb21eed
MB
2406 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
2407 host_sd->sem_otime = tswapal(target_sd->sem_otime);
2408 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 2409 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 2410 return 0;
3eb6b044
TS
2411}
2412
579a97f7
FB
2413static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2414 struct semid_ds *host_sd)
3eb6b044
TS
2415{
2416 struct target_semid_ds *target_sd;
2417
579a97f7
FB
2418 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2419 return -TARGET_EFAULT;
e5289087 2420 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 2421 return -TARGET_EFAULT;
cbb21eed
MB
2422 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
2423 target_sd->sem_otime = tswapal(host_sd->sem_otime);
2424 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 2425 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 2426 return 0;
3eb6b044
TS
2427}
2428
e5289087
AJ
2429struct target_seminfo {
2430 int semmap;
2431 int semmni;
2432 int semmns;
2433 int semmnu;
2434 int semmsl;
2435 int semopm;
2436 int semume;
2437 int semusz;
2438 int semvmx;
2439 int semaem;
2440};
2441
2442static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2443 struct seminfo *host_seminfo)
2444{
2445 struct target_seminfo *target_seminfo;
2446 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2447 return -TARGET_EFAULT;
2448 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2449 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2450 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2451 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2452 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2453 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2454 __put_user(host_seminfo->semume, &target_seminfo->semume);
2455 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2456 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2457 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2458 unlock_user_struct(target_seminfo, target_addr, 1);
2459 return 0;
2460}
2461
fa294816
TS
2462union semun {
2463 int val;
3eb6b044 2464 struct semid_ds *buf;
fa294816 2465 unsigned short *array;
e5289087 2466 struct seminfo *__buf;
fa294816
TS
2467};
2468
3eb6b044
TS
2469union target_semun {
2470 int val;
e5289087
AJ
2471 abi_ulong buf;
2472 abi_ulong array;
2473 abi_ulong __buf;
3eb6b044
TS
2474};
2475
e5289087
AJ
2476static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2477 abi_ulong target_addr)
3eb6b044 2478{
e5289087
AJ
2479 int nsems;
2480 unsigned short *array;
2481 union semun semun;
2482 struct semid_ds semid_ds;
2483 int i, ret;
3eb6b044 2484
e5289087
AJ
2485 semun.buf = &semid_ds;
2486
2487 ret = semctl(semid, 0, IPC_STAT, semun);
2488 if (ret == -1)
2489 return get_errno(ret);
2490
2491 nsems = semid_ds.sem_nsems;
2492
2493 *host_array = malloc(nsems*sizeof(unsigned short));
69d4c703
PM
2494 if (!*host_array) {
2495 return -TARGET_ENOMEM;
2496 }
e5289087
AJ
2497 array = lock_user(VERIFY_READ, target_addr,
2498 nsems*sizeof(unsigned short), 1);
69d4c703
PM
2499 if (!array) {
2500 free(*host_array);
e5289087 2501 return -TARGET_EFAULT;
69d4c703 2502 }
e5289087
AJ
2503
2504 for(i=0; i<nsems; i++) {
2505 __get_user((*host_array)[i], &array[i]);
3eb6b044 2506 }
e5289087
AJ
2507 unlock_user(array, target_addr, 0);
2508
579a97f7 2509 return 0;
3eb6b044
TS
2510}
2511
e5289087
AJ
2512static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2513 unsigned short **host_array)
3eb6b044 2514{
e5289087
AJ
2515 int nsems;
2516 unsigned short *array;
2517 union semun semun;
2518 struct semid_ds semid_ds;
2519 int i, ret;
3eb6b044 2520
e5289087
AJ
2521 semun.buf = &semid_ds;
2522
2523 ret = semctl(semid, 0, IPC_STAT, semun);
2524 if (ret == -1)
2525 return get_errno(ret);
2526
2527 nsems = semid_ds.sem_nsems;
2528
2529 array = lock_user(VERIFY_WRITE, target_addr,
2530 nsems*sizeof(unsigned short), 0);
2531 if (!array)
2532 return -TARGET_EFAULT;
2533
2534 for(i=0; i<nsems; i++) {
2535 __put_user((*host_array)[i], &array[i]);
3eb6b044 2536 }
e5289087
AJ
2537 free(*host_array);
2538 unlock_user(array, target_addr, 1);
2539
579a97f7 2540 return 0;
3eb6b044
TS
2541}
2542
e5289087
AJ
2543static inline abi_long do_semctl(int semid, int semnum, int cmd,
2544 union target_semun target_su)
3eb6b044
TS
2545{
2546 union semun arg;
2547 struct semid_ds dsarg;
7b8118e8 2548 unsigned short *array = NULL;
e5289087
AJ
2549 struct seminfo seminfo;
2550 abi_long ret = -TARGET_EINVAL;
2551 abi_long err;
2552 cmd &= 0xff;
3eb6b044
TS
2553
2554 switch( cmd ) {
2555 case GETVAL:
3eb6b044 2556 case SETVAL:
cbb21eed 2557 arg.val = tswap32(target_su.val);
e5289087 2558 ret = get_errno(semctl(semid, semnum, cmd, arg));
cbb21eed 2559 target_su.val = tswap32(arg.val);
3eb6b044
TS
2560 break;
2561 case GETALL:
3eb6b044 2562 case SETALL:
e5289087
AJ
2563 err = target_to_host_semarray(semid, &array, target_su.array);
2564 if (err)
2565 return err;
2566 arg.array = array;
2567 ret = get_errno(semctl(semid, semnum, cmd, arg));
2568 err = host_to_target_semarray(semid, target_su.array, &array);
2569 if (err)
2570 return err;
3eb6b044
TS
2571 break;
2572 case IPC_STAT:
3eb6b044 2573 case IPC_SET:
e5289087
AJ
2574 case SEM_STAT:
2575 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2576 if (err)
2577 return err;
2578 arg.buf = &dsarg;
2579 ret = get_errno(semctl(semid, semnum, cmd, arg));
2580 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2581 if (err)
2582 return err;
2583 break;
2584 case IPC_INFO:
2585 case SEM_INFO:
2586 arg.__buf = &seminfo;
2587 ret = get_errno(semctl(semid, semnum, cmd, arg));
2588 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2589 if (err)
2590 return err;
2591 break;
2592 case IPC_RMID:
2593 case GETPID:
2594 case GETNCNT:
2595 case GETZCNT:
2596 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 2597 break;
3eb6b044
TS
2598 }
2599
2600 return ret;
2601}
2602
e5289087
AJ
2603struct target_sembuf {
2604 unsigned short sem_num;
2605 short sem_op;
2606 short sem_flg;
2607};
2608
2609static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2610 abi_ulong target_addr,
2611 unsigned nsops)
2612{
2613 struct target_sembuf *target_sembuf;
2614 int i;
2615
2616 target_sembuf = lock_user(VERIFY_READ, target_addr,
2617 nsops*sizeof(struct target_sembuf), 1);
2618 if (!target_sembuf)
2619 return -TARGET_EFAULT;
2620
2621 for(i=0; i<nsops; i++) {
2622 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2623 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2624 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2625 }
2626
2627 unlock_user(target_sembuf, target_addr, 0);
2628
2629 return 0;
2630}
2631
2632static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2633{
2634 struct sembuf sops[nsops];
2635
2636 if (target_to_host_sembuf(sops, ptr, nsops))
2637 return -TARGET_EFAULT;
2638
c7128c9f 2639 return get_errno(semop(semid, sops, nsops));
e5289087
AJ
2640}
2641
1bc012f6
TS
2642struct target_msqid_ds
2643{
1c54ff97
AJ
2644 struct target_ipc_perm msg_perm;
2645 abi_ulong msg_stime;
2646#if TARGET_ABI_BITS == 32
2647 abi_ulong __unused1;
2648#endif
2649 abi_ulong msg_rtime;
2650#if TARGET_ABI_BITS == 32
2651 abi_ulong __unused2;
2652#endif
2653 abi_ulong msg_ctime;
2654#if TARGET_ABI_BITS == 32
2655 abi_ulong __unused3;
2656#endif
2657 abi_ulong __msg_cbytes;
2658 abi_ulong msg_qnum;
2659 abi_ulong msg_qbytes;
2660 abi_ulong msg_lspid;
2661 abi_ulong msg_lrpid;
2662 abi_ulong __unused4;
2663 abi_ulong __unused5;
1bc012f6
TS
2664};
2665
579a97f7
FB
2666static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2667 abi_ulong target_addr)
1bc012f6
TS
2668{
2669 struct target_msqid_ds *target_md;
2670
579a97f7
FB
2671 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2672 return -TARGET_EFAULT;
1c54ff97
AJ
2673 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2674 return -TARGET_EFAULT;
cbb21eed
MB
2675 host_md->msg_stime = tswapal(target_md->msg_stime);
2676 host_md->msg_rtime = tswapal(target_md->msg_rtime);
2677 host_md->msg_ctime = tswapal(target_md->msg_ctime);
2678 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
2679 host_md->msg_qnum = tswapal(target_md->msg_qnum);
2680 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
2681 host_md->msg_lspid = tswapal(target_md->msg_lspid);
2682 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 2683 unlock_user_struct(target_md, target_addr, 0);
579a97f7 2684 return 0;
1bc012f6
TS
2685}
2686
579a97f7
FB
2687static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2688 struct msqid_ds *host_md)
1bc012f6
TS
2689{
2690 struct target_msqid_ds *target_md;
2691
579a97f7
FB
2692 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2693 return -TARGET_EFAULT;
1c54ff97
AJ
2694 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2695 return -TARGET_EFAULT;
cbb21eed
MB
2696 target_md->msg_stime = tswapal(host_md->msg_stime);
2697 target_md->msg_rtime = tswapal(host_md->msg_rtime);
2698 target_md->msg_ctime = tswapal(host_md->msg_ctime);
2699 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
2700 target_md->msg_qnum = tswapal(host_md->msg_qnum);
2701 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
2702 target_md->msg_lspid = tswapal(host_md->msg_lspid);
2703 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 2704 unlock_user_struct(target_md, target_addr, 1);
579a97f7 2705 return 0;
1bc012f6
TS
2706}
2707
1c54ff97
AJ
2708struct target_msginfo {
2709 int msgpool;
2710 int msgmap;
2711 int msgmax;
2712 int msgmnb;
2713 int msgmni;
2714 int msgssz;
2715 int msgtql;
2716 unsigned short int msgseg;
2717};
2718
2719static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2720 struct msginfo *host_msginfo)
2721{
2722 struct target_msginfo *target_msginfo;
2723 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2724 return -TARGET_EFAULT;
2725 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2726 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2727 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2728 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2729 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2730 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2731 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2732 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2733 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 2734 return 0;
1c54ff97
AJ
2735}
2736
2737static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
2738{
2739 struct msqid_ds dsarg;
1c54ff97
AJ
2740 struct msginfo msginfo;
2741 abi_long ret = -TARGET_EINVAL;
2742
2743 cmd &= 0xff;
2744
2745 switch (cmd) {
1bc012f6
TS
2746 case IPC_STAT:
2747 case IPC_SET:
1c54ff97
AJ
2748 case MSG_STAT:
2749 if (target_to_host_msqid_ds(&dsarg,ptr))
2750 return -TARGET_EFAULT;
2751 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2752 if (host_to_target_msqid_ds(ptr,&dsarg))
2753 return -TARGET_EFAULT;
2754 break;
2755 case IPC_RMID:
2756 ret = get_errno(msgctl(msgid, cmd, NULL));
2757 break;
2758 case IPC_INFO:
2759 case MSG_INFO:
2760 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2761 if (host_to_target_msginfo(ptr, &msginfo))
2762 return -TARGET_EFAULT;
2763 break;
1bc012f6 2764 }
1c54ff97 2765
1bc012f6
TS
2766 return ret;
2767}
2768
2769struct target_msgbuf {
1c54ff97
AJ
2770 abi_long mtype;
2771 char mtext[1];
1bc012f6
TS
2772};
2773
992f48a0
BS
2774static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2775 unsigned int msgsz, int msgflg)
1bc012f6
TS
2776{
2777 struct target_msgbuf *target_mb;
2778 struct msgbuf *host_mb;
992f48a0 2779 abi_long ret = 0;
1bc012f6 2780
579a97f7
FB
2781 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2782 return -TARGET_EFAULT;
1bc012f6 2783 host_mb = malloc(msgsz+sizeof(long));
cbb21eed 2784 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 2785 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
1bc012f6
TS
2786 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2787 free(host_mb);
2788 unlock_user_struct(target_mb, msgp, 0);
2789
2790 return ret;
2791}
2792
992f48a0 2793static inline abi_long do_msgrcv(int msqid, abi_long msgp,
1c54ff97 2794 unsigned int msgsz, abi_long msgtyp,
992f48a0 2795 int msgflg)
1bc012f6
TS
2796{
2797 struct target_msgbuf *target_mb;
579a97f7 2798 char *target_mtext;
1bc012f6 2799 struct msgbuf *host_mb;
992f48a0 2800 abi_long ret = 0;
1bc012f6 2801
579a97f7
FB
2802 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2803 return -TARGET_EFAULT;
1c54ff97 2804
0d07fe47 2805 host_mb = g_malloc(msgsz+sizeof(long));
79dd77de 2806 ret = get_errno(msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
1c54ff97 2807
579a97f7
FB
2808 if (ret > 0) {
2809 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2810 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2811 if (!target_mtext) {
2812 ret = -TARGET_EFAULT;
2813 goto end;
2814 }
1c54ff97 2815 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
2816 unlock_user(target_mtext, target_mtext_addr, ret);
2817 }
1c54ff97 2818
cbb21eed 2819 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 2820
579a97f7
FB
2821end:
2822 if (target_mb)
2823 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 2824 g_free(host_mb);
1bc012f6
TS
2825 return ret;
2826}
2827
88a8c984
RV
2828static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2829 abi_ulong target_addr)
2830{
2831 struct target_shmid_ds *target_sd;
2832
2833 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2834 return -TARGET_EFAULT;
2835 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2836 return -TARGET_EFAULT;
2837 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2838 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2839 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2840 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2841 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2842 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2843 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2844 unlock_user_struct(target_sd, target_addr, 0);
2845 return 0;
2846}
2847
2848static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2849 struct shmid_ds *host_sd)
2850{
2851 struct target_shmid_ds *target_sd;
2852
2853 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2854 return -TARGET_EFAULT;
2855 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2856 return -TARGET_EFAULT;
2857 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2858 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2859 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2860 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2861 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2862 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2863 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2864 unlock_user_struct(target_sd, target_addr, 1);
2865 return 0;
2866}
2867
2868struct target_shminfo {
2869 abi_ulong shmmax;
2870 abi_ulong shmmin;
2871 abi_ulong shmmni;
2872 abi_ulong shmseg;
2873 abi_ulong shmall;
2874};
2875
2876static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2877 struct shminfo *host_shminfo)
2878{
2879 struct target_shminfo *target_shminfo;
2880 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2881 return -TARGET_EFAULT;
2882 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2883 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2884 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2885 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2886 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2887 unlock_user_struct(target_shminfo, target_addr, 1);
2888 return 0;
2889}
2890
2891struct target_shm_info {
2892 int used_ids;
2893 abi_ulong shm_tot;
2894 abi_ulong shm_rss;
2895 abi_ulong shm_swp;
2896 abi_ulong swap_attempts;
2897 abi_ulong swap_successes;
2898};
2899
2900static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2901 struct shm_info *host_shm_info)
2902{
2903 struct target_shm_info *target_shm_info;
2904 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2905 return -TARGET_EFAULT;
2906 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2907 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2908 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2909 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2910 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2911 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2912 unlock_user_struct(target_shm_info, target_addr, 1);
2913 return 0;
2914}
2915
2916static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2917{
2918 struct shmid_ds dsarg;
2919 struct shminfo shminfo;
2920 struct shm_info shm_info;
2921 abi_long ret = -TARGET_EINVAL;
2922
2923 cmd &= 0xff;
2924
2925 switch(cmd) {
2926 case IPC_STAT:
2927 case IPC_SET:
2928 case SHM_STAT:
2929 if (target_to_host_shmid_ds(&dsarg, buf))
2930 return -TARGET_EFAULT;
2931 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2932 if (host_to_target_shmid_ds(buf, &dsarg))
2933 return -TARGET_EFAULT;
2934 break;
2935 case IPC_INFO:
2936 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2937 if (host_to_target_shminfo(buf, &shminfo))
2938 return -TARGET_EFAULT;
2939 break;
2940 case SHM_INFO:
2941 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2942 if (host_to_target_shm_info(buf, &shm_info))
2943 return -TARGET_EFAULT;
2944 break;
2945 case IPC_RMID:
2946 case SHM_LOCK:
2947 case SHM_UNLOCK:
2948 ret = get_errno(shmctl(shmid, cmd, NULL));
2949 break;
2950 }
2951
2952 return ret;
2953}
2954
2955static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2956{
2957 abi_long raddr;
2958 void *host_raddr;
2959 struct shmid_ds shm_info;
2960 int i,ret;
2961
2962 /* find out the length of the shared memory segment */
2963 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2964 if (is_error(ret)) {
2965 /* can't get length, bail out */
2966 return ret;
2967 }
2968
2969 mmap_lock();
2970
2971 if (shmaddr)
2972 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2973 else {
2974 abi_ulong mmap_start;
2975
2976 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2977
2978 if (mmap_start == -1) {
2979 errno = ENOMEM;
2980 host_raddr = (void *)-1;
2981 } else
2982 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2983 }
2984
2985 if (host_raddr == (void *)-1) {
2986 mmap_unlock();
2987 return get_errno((long)host_raddr);
2988 }
2989 raddr=h2g((unsigned long)host_raddr);
2990
2991 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2992 PAGE_VALID | PAGE_READ |
2993 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2994
2995 for (i = 0; i < N_SHM_REGIONS; i++) {
2996 if (shm_regions[i].start == 0) {
2997 shm_regions[i].start = raddr;
2998 shm_regions[i].size = shm_info.shm_segsz;
2999 break;
3000 }
3001 }
3002
3003 mmap_unlock();
3004 return raddr;
3005
3006}
3007
3008static inline abi_long do_shmdt(abi_ulong shmaddr)
3009{
3010 int i;
3011
3012 for (i = 0; i < N_SHM_REGIONS; ++i) {
3013 if (shm_regions[i].start == shmaddr) {
3014 shm_regions[i].start = 0;
e00ac249 3015 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
3016 break;
3017 }
3018 }
3019
3020 return get_errno(shmdt(g2h(shmaddr)));
3021}
3022
1c54ff97 3023#ifdef TARGET_NR_ipc
53a5960a 3024/* ??? This only works with linear mappings. */
0da46a6e 3025/* do_ipc() must return target values and target errnos. */
992f48a0
BS
3026static abi_long do_ipc(unsigned int call, int first,
3027 int second, int third,
3028 abi_long ptr, abi_long fifth)
8853f86e
FB
3029{
3030 int version;
992f48a0 3031 abi_long ret = 0;
8853f86e
FB
3032
3033 version = call >> 16;
3034 call &= 0xffff;
3035
3036 switch (call) {
fa294816 3037 case IPCOP_semop:
e5289087 3038 ret = do_semop(first, ptr, second);
fa294816
TS
3039 break;
3040
3041 case IPCOP_semget:
3042 ret = get_errno(semget(first, second, third));
3043 break;
3044
3045 case IPCOP_semctl:
e5289087 3046 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
fa294816 3047 break;
d96372ef 3048
1c54ff97
AJ
3049 case IPCOP_msgget:
3050 ret = get_errno(msgget(first, second));
3051 break;
d96372ef 3052
1c54ff97
AJ
3053 case IPCOP_msgsnd:
3054 ret = do_msgsnd(first, ptr, second, third);
3055 break;
d96372ef 3056
1c54ff97
AJ
3057 case IPCOP_msgctl:
3058 ret = do_msgctl(first, second, ptr);
3059 break;
d96372ef 3060
1c54ff97
AJ
3061 case IPCOP_msgrcv:
3062 switch (version) {
3063 case 0:
3064 {
3065 struct target_ipc_kludge {
3066 abi_long msgp;
3067 abi_long msgtyp;
3068 } *tmp;
3069
3070 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
3071 ret = -TARGET_EFAULT;
3072 break;
3073 }
d96372ef 3074
79dd77de 3075 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 3076
1c54ff97
AJ
3077 unlock_user_struct(tmp, ptr, 0);
3078 break;
3079 }
3080 default:
3081 ret = do_msgrcv(first, ptr, second, fifth, third);
3082 }
3083 break;
d96372ef 3084
8853f86e 3085 case IPCOP_shmat:
88a8c984
RV
3086 switch (version) {
3087 default:
5a4a898d
FB
3088 {
3089 abi_ulong raddr;
88a8c984
RV
3090 raddr = do_shmat(first, ptr, second);
3091 if (is_error(raddr))
3092 return get_errno(raddr);
2f619698 3093 if (put_user_ual(raddr, third))
5a4a898d 3094 return -TARGET_EFAULT;
88a8c984
RV
3095 break;
3096 }
3097 case 1:
3098 ret = -TARGET_EINVAL;
3099 break;
5a4a898d 3100 }
8853f86e
FB
3101 break;
3102 case IPCOP_shmdt:
88a8c984 3103 ret = do_shmdt(ptr);
8853f86e
FB
3104 break;
3105
3106 case IPCOP_shmget:
3107 /* IPC_* flag values are the same on all linux platforms */
3108 ret = get_errno(shmget(first, second, third));
3109 break;
3110
3111 /* IPC_* and SHM_* command values are the same on all linux platforms */
3112 case IPCOP_shmctl:
a2926784 3113 ret = do_shmctl(first, second, ptr);
8853f86e
FB
3114 break;
3115 default:
32407103 3116 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
0da46a6e 3117 ret = -TARGET_ENOSYS;
8853f86e
FB
3118 break;
3119 }
3120 return ret;
3121}
32407103 3122#endif
8853f86e 3123
31e31b8a 3124/* kernel structure types definitions */
31e31b8a 3125
001faf32 3126#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
3127#define STRUCT_SPECIAL(name) STRUCT_ ## name,
3128enum {
3129#include "syscall_types.h"
3130};
3131#undef STRUCT
3132#undef STRUCT_SPECIAL
3133
001faf32 3134#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
3135#define STRUCT_SPECIAL(name)
3136#include "syscall_types.h"
3137#undef STRUCT
3138#undef STRUCT_SPECIAL
3139
d2ef05bb
PM
3140typedef struct IOCTLEntry IOCTLEntry;
3141
3142typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
3143 int fd, abi_long cmd, abi_long arg);
3144
3145struct IOCTLEntry {
2ab83ea7
FB
3146 unsigned int target_cmd;
3147 unsigned int host_cmd;
31e31b8a
FB
3148 const char *name;
3149 int access;
d2ef05bb 3150 do_ioctl_fn *do_ioctl;
1a9353d2 3151 const argtype arg_type[5];
d2ef05bb 3152};
31e31b8a
FB
3153
3154#define IOC_R 0x0001
3155#define IOC_W 0x0002
3156#define IOC_RW (IOC_R | IOC_W)
3157
3158#define MAX_STRUCT_SIZE 4096
3159
dace20dc 3160#ifdef CONFIG_FIEMAP
285da2b9
PM
3161/* So fiemap access checks don't overflow on 32 bit systems.
3162 * This is very slightly smaller than the limit imposed by
3163 * the underlying kernel.
3164 */
3165#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3166 / sizeof(struct fiemap_extent))
3167
3168static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
3169 int fd, abi_long cmd, abi_long arg)
3170{
3171 /* The parameter for this ioctl is a struct fiemap followed
3172 * by an array of struct fiemap_extent whose size is set
3173 * in fiemap->fm_extent_count. The array is filled in by the
3174 * ioctl.
3175 */
3176 int target_size_in, target_size_out;
3177 struct fiemap *fm;
3178 const argtype *arg_type = ie->arg_type;
3179 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3180 void *argptr, *p;
3181 abi_long ret;
3182 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3183 uint32_t outbufsz;
3184 int free_fm = 0;
3185
3186 assert(arg_type[0] == TYPE_PTR);
3187 assert(ie->access == IOC_RW);
3188 arg_type++;
3189 target_size_in = thunk_type_size(arg_type, 0);
3190 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3191 if (!argptr) {
3192 return -TARGET_EFAULT;
3193 }
3194 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3195 unlock_user(argptr, arg, 0);
3196 fm = (struct fiemap *)buf_temp;
3197 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3198 return -TARGET_EINVAL;
3199 }
3200
3201 outbufsz = sizeof (*fm) +
3202 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3203
3204 if (outbufsz > MAX_STRUCT_SIZE) {
3205 /* We can't fit all the extents into the fixed size buffer.
3206 * Allocate one that is large enough and use it instead.
3207 */
3208 fm = malloc(outbufsz);
3209 if (!fm) {
3210 return -TARGET_ENOMEM;
3211 }
3212 memcpy(fm, buf_temp, sizeof(struct fiemap));
3213 free_fm = 1;
3214 }
3215 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3216 if (!is_error(ret)) {
3217 target_size_out = target_size_in;
3218 /* An extent_count of 0 means we were only counting the extents
3219 * so there are no structs to copy
3220 */
3221 if (fm->fm_extent_count != 0) {
3222 target_size_out += fm->fm_mapped_extents * extent_size;
3223 }
3224 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3225 if (!argptr) {
3226 ret = -TARGET_EFAULT;
3227 } else {
3228 /* Convert the struct fiemap */
3229 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3230 if (fm->fm_extent_count != 0) {
3231 p = argptr + target_size_in;
3232 /* ...and then all the struct fiemap_extents */
3233 for (i = 0; i < fm->fm_mapped_extents; i++) {
3234 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3235 THUNK_TARGET);
3236 p += extent_size;
3237 }
3238 }
3239 unlock_user(argptr, arg, target_size_out);
3240 }
3241 }
3242 if (free_fm) {
3243 free(fm);
3244 }
3245 return ret;
3246}
dace20dc 3247#endif
285da2b9 3248
059c2f2c
LV
3249static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
3250 int fd, abi_long cmd, abi_long arg)
3251{
3252 const argtype *arg_type = ie->arg_type;
3253 int target_size;
3254 void *argptr;
3255 int ret;
3256 struct ifconf *host_ifconf;
3257 uint32_t outbufsz;
3258 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
3259 int target_ifreq_size;
3260 int nb_ifreq;
3261 int free_buf = 0;
3262 int i;
3263 int target_ifc_len;
3264 abi_long target_ifc_buf;
3265 int host_ifc_len;
3266 char *host_ifc_buf;
3267
3268 assert(arg_type[0] == TYPE_PTR);
3269 assert(ie->access == IOC_RW);
3270
3271 arg_type++;
3272 target_size = thunk_type_size(arg_type, 0);
3273
3274 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3275 if (!argptr)
3276 return -TARGET_EFAULT;
3277 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3278 unlock_user(argptr, arg, 0);
3279
3280 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
3281 target_ifc_len = host_ifconf->ifc_len;
3282 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
3283
3284 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
3285 nb_ifreq = target_ifc_len / target_ifreq_size;
3286 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
3287
3288 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
3289 if (outbufsz > MAX_STRUCT_SIZE) {
3290 /* We can't fit all the extents into the fixed size buffer.
3291 * Allocate one that is large enough and use it instead.
3292 */
3293 host_ifconf = malloc(outbufsz);
3294 if (!host_ifconf) {
3295 return -TARGET_ENOMEM;
3296 }
3297 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
3298 free_buf = 1;
3299 }
3300 host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
3301
3302 host_ifconf->ifc_len = host_ifc_len;
3303 host_ifconf->ifc_buf = host_ifc_buf;
3304
3305 ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
3306 if (!is_error(ret)) {
3307 /* convert host ifc_len to target ifc_len */
3308
3309 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
3310 target_ifc_len = nb_ifreq * target_ifreq_size;
3311 host_ifconf->ifc_len = target_ifc_len;
3312
3313 /* restore target ifc_buf */
3314
3315 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
3316
3317 /* copy struct ifconf to target user */
3318
3319 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3320 if (!argptr)
3321 return -TARGET_EFAULT;
3322 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
3323 unlock_user(argptr, arg, target_size);
3324
3325 /* copy ifreq[] to target user */
3326
3327 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
3328 for (i = 0; i < nb_ifreq ; i++) {
3329 thunk_convert(argptr + i * target_ifreq_size,
3330 host_ifc_buf + i * sizeof(struct ifreq),
3331 ifreq_arg_type, THUNK_TARGET);
3332 }
3333 unlock_user(argptr, target_ifc_buf, target_ifc_len);
3334 }
3335
3336 if (free_buf) {
3337 free(host_ifconf);
3338 }
3339
3340 return ret;
3341}
3342
56e904ec
AG
3343static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
3344 abi_long cmd, abi_long arg)
3345{
3346 void *argptr;
3347 struct dm_ioctl *host_dm;
3348 abi_long guest_data;
3349 uint32_t guest_data_size;
3350 int target_size;
3351 const argtype *arg_type = ie->arg_type;
3352 abi_long ret;
3353 void *big_buf = NULL;
3354 char *host_data;
3355
3356 arg_type++;
3357 target_size = thunk_type_size(arg_type, 0);
3358 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3359 if (!argptr) {
3360 ret = -TARGET_EFAULT;
3361 goto out;
3362 }
3363 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3364 unlock_user(argptr, arg, 0);
3365
3366 /* buf_temp is too small, so fetch things into a bigger buffer */
3367 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
3368 memcpy(big_buf, buf_temp, target_size);
3369 buf_temp = big_buf;
3370 host_dm = big_buf;
3371
3372 guest_data = arg + host_dm->data_start;
3373 if ((guest_data - arg) < 0) {
3374 ret = -EINVAL;
3375 goto out;
3376 }
3377 guest_data_size = host_dm->data_size - host_dm->data_start;
3378 host_data = (char*)host_dm + host_dm->data_start;
3379
3380 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3381 switch (ie->host_cmd) {
3382 case DM_REMOVE_ALL:
3383 case DM_LIST_DEVICES:
3384 case DM_DEV_CREATE:
3385 case DM_DEV_REMOVE:
3386 case DM_DEV_SUSPEND:
3387 case DM_DEV_STATUS:
3388 case DM_DEV_WAIT:
3389 case DM_TABLE_STATUS:
3390 case DM_TABLE_CLEAR:
3391 case DM_TABLE_DEPS:
3392 case DM_LIST_VERSIONS:
3393 /* no input data */
3394 break;
3395 case DM_DEV_RENAME:
3396 case DM_DEV_SET_GEOMETRY:
3397 /* data contains only strings */
3398 memcpy(host_data, argptr, guest_data_size);
3399 break;
3400 case DM_TARGET_MSG:
3401 memcpy(host_data, argptr, guest_data_size);
3402 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
3403 break;
3404 case DM_TABLE_LOAD:
3405 {
3406 void *gspec = argptr;
3407 void *cur_data = host_data;
3408 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3409 int spec_size = thunk_type_size(arg_type, 0);
3410 int i;
3411
3412 for (i = 0; i < host_dm->target_count; i++) {
3413 struct dm_target_spec *spec = cur_data;
3414 uint32_t next;
3415 int slen;
3416
3417 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
3418 slen = strlen((char*)gspec + spec_size) + 1;
3419 next = spec->next;
3420 spec->next = sizeof(*spec) + slen;
3421 strcpy((char*)&spec[1], gspec + spec_size);
3422 gspec += next;
3423 cur_data += spec->next;
3424 }
3425 break;
3426 }
3427 default:
3428 ret = -TARGET_EINVAL;
3429 goto out;
3430 }
3431 unlock_user(argptr, guest_data, 0);
3432
3433 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3434 if (!is_error(ret)) {
3435 guest_data = arg + host_dm->data_start;
3436 guest_data_size = host_dm->data_size - host_dm->data_start;
3437 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
3438 switch (ie->host_cmd) {
3439 case DM_REMOVE_ALL:
3440 case DM_DEV_CREATE:
3441 case DM_DEV_REMOVE:
3442 case DM_DEV_RENAME:
3443 case DM_DEV_SUSPEND:
3444 case DM_DEV_STATUS:
3445 case DM_TABLE_LOAD:
3446 case DM_TABLE_CLEAR:
3447 case DM_TARGET_MSG:
3448 case DM_DEV_SET_GEOMETRY:
3449 /* no return data */
3450 break;
3451 case DM_LIST_DEVICES:
3452 {
3453 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
3454 uint32_t remaining_data = guest_data_size;
3455 void *cur_data = argptr;
3456 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
3457 int nl_size = 12; /* can't use thunk_size due to alignment */
3458
3459 while (1) {
3460 uint32_t next = nl->next;
3461 if (next) {
3462 nl->next = nl_size + (strlen(nl->name) + 1);
3463 }
3464 if (remaining_data < nl->next) {
3465 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3466 break;
3467 }
3468 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
3469 strcpy(cur_data + nl_size, nl->name);
3470 cur_data += nl->next;
3471 remaining_data -= nl->next;
3472 if (!next) {
3473 break;
3474 }
3475 nl = (void*)nl + next;
3476 }
3477 break;
3478 }
3479 case DM_DEV_WAIT:
3480 case DM_TABLE_STATUS:
3481 {
3482 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
3483 void *cur_data = argptr;
3484 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
3485 int spec_size = thunk_type_size(arg_type, 0);
3486 int i;
3487
3488 for (i = 0; i < host_dm->target_count; i++) {
3489 uint32_t next = spec->next;
3490 int slen = strlen((char*)&spec[1]) + 1;
3491 spec->next = (cur_data - argptr) + spec_size + slen;
3492 if (guest_data_size < spec->next) {
3493 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3494 break;
3495 }
3496 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
3497 strcpy(cur_data + spec_size, (char*)&spec[1]);
3498 cur_data = argptr + spec->next;
3499 spec = (void*)host_dm + host_dm->data_start + next;
3500 }
3501 break;
3502 }
3503 case DM_TABLE_DEPS:
3504 {
3505 void *hdata = (void*)host_dm + host_dm->data_start;
3506 int count = *(uint32_t*)hdata;
3507 uint64_t *hdev = hdata + 8;
3508 uint64_t *gdev = argptr + 8;
3509 int i;
3510
3511 *(uint32_t*)argptr = tswap32(count);
3512 for (i = 0; i < count; i++) {
3513 *gdev = tswap64(*hdev);
3514 gdev++;
3515 hdev++;
3516 }
3517 break;
3518 }
3519 case DM_LIST_VERSIONS:
3520 {
3521 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
3522 uint32_t remaining_data = guest_data_size;
3523 void *cur_data = argptr;
3524 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
3525 int vers_size = thunk_type_size(arg_type, 0);
3526
3527 while (1) {
3528 uint32_t next = vers->next;
3529 if (next) {
3530 vers->next = vers_size + (strlen(vers->name) + 1);
3531 }
3532 if (remaining_data < vers->next) {
3533 host_dm->flags |= DM_BUFFER_FULL_FLAG;
3534 break;
3535 }
3536 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
3537 strcpy(cur_data + vers_size, vers->name);
3538 cur_data += vers->next;
3539 remaining_data -= vers->next;
3540 if (!next) {
3541 break;
3542 }
3543 vers = (void*)vers + next;
3544 }
3545 break;
3546 }
3547 default:
3548 ret = -TARGET_EINVAL;
3549 goto out;
3550 }
3551 unlock_user(argptr, guest_data, guest_data_size);
3552
3553 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3554 if (!argptr) {
3555 ret = -TARGET_EFAULT;
3556 goto out;
3557 }
3558 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3559 unlock_user(argptr, arg, target_size);
3560 }
3561out:
ad11ad77 3562 g_free(big_buf);
56e904ec
AG
3563 return ret;
3564}
3565
7ff7b666
LV
3566static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
3567 int fd, abi_long cmd, abi_long arg)
3568{
3569 const argtype *arg_type = ie->arg_type;
3570 const StructEntry *se;
3571 const argtype *field_types;
3572 const int *dst_offsets, *src_offsets;
3573 int target_size;
3574 void *argptr;
3575 abi_ulong *target_rt_dev_ptr;
3576 unsigned long *host_rt_dev_ptr;
3577 abi_long ret;
3578 int i;
3579
3580 assert(ie->access == IOC_W);
3581 assert(*arg_type == TYPE_PTR);
3582 arg_type++;
3583 assert(*arg_type == TYPE_STRUCT);
3584 target_size = thunk_type_size(arg_type, 0);
3585 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3586 if (!argptr) {
3587 return -TARGET_EFAULT;
3588 }
3589 arg_type++;
3590 assert(*arg_type == (int)STRUCT_rtentry);
3591 se = struct_entries + *arg_type++;
3592 assert(se->convert[0] == NULL);
3593 /* convert struct here to be able to catch rt_dev string */
3594 field_types = se->field_types;
3595 dst_offsets = se->field_offsets[THUNK_HOST];
3596 src_offsets = se->field_offsets[THUNK_TARGET];
3597 for (i = 0; i < se->nb_fields; i++) {
3598 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
3599 assert(*field_types == TYPE_PTRVOID);
3600 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
3601 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
3602 if (*target_rt_dev_ptr != 0) {
3603 *host_rt_dev_ptr = (unsigned long)lock_user_string(
3604 tswapal(*target_rt_dev_ptr));
3605 if (!*host_rt_dev_ptr) {
3606 unlock_user(argptr, arg, 0);
3607 return -TARGET_EFAULT;
3608 }
3609 } else {
3610 *host_rt_dev_ptr = 0;
3611 }
3612 field_types++;
3613 continue;
3614 }
3615 field_types = thunk_convert(buf_temp + dst_offsets[i],
3616 argptr + src_offsets[i],
3617 field_types, THUNK_HOST);
3618 }
3619 unlock_user(argptr, arg, 0);
3620
3621 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3622 if (*host_rt_dev_ptr != 0) {
3623 unlock_user((void *)*host_rt_dev_ptr,
3624 *target_rt_dev_ptr, 0);
3625 }
3626 return ret;
3627}
3628
9f106a75 3629static IOCTLEntry ioctl_entries[] = {
001faf32 3630#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
3631 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
3632#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
3633 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
31e31b8a
FB
3634#include "ioctls.h"
3635 { 0, 0, },
3636};
3637
53a5960a 3638/* ??? Implement proper locking for ioctls. */
0da46a6e 3639/* do_ioctl() Must return target values and target errnos. */
992f48a0 3640static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
31e31b8a
FB
3641{
3642 const IOCTLEntry *ie;
3643 const argtype *arg_type;
992f48a0 3644 abi_long ret;
31e31b8a 3645 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
3646 int target_size;
3647 void *argptr;
31e31b8a
FB
3648
3649 ie = ioctl_entries;
3650 for(;;) {
3651 if (ie->target_cmd == 0) {
32407103 3652 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 3653 return -TARGET_ENOSYS;
31e31b8a
FB
3654 }
3655 if (ie->target_cmd == cmd)
3656 break;
3657 ie++;
3658 }
3659 arg_type = ie->arg_type;
9de5e440 3660#if defined(DEBUG)
32407103 3661 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
72f03900 3662#endif
d2ef05bb
PM
3663 if (ie->do_ioctl) {
3664 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
3665 }
3666
31e31b8a
FB
3667 switch(arg_type[0]) {
3668 case TYPE_NULL:
3669 /* no argument */
3670 ret = get_errno(ioctl(fd, ie->host_cmd));
3671 break;
3672 case TYPE_PTRVOID:
3673 case TYPE_INT:
3674 /* int argment */
3675 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
3676 break;
3677 case TYPE_PTR:
3678 arg_type++;
53a5960a 3679 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
3680 switch(ie->access) {
3681 case IOC_R:
3682 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3683 if (!is_error(ret)) {
579a97f7
FB
3684 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3685 if (!argptr)
3686 return -TARGET_EFAULT;
53a5960a
PB
3687 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3688 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3689 }
3690 break;
3691 case IOC_W:
579a97f7
FB
3692 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3693 if (!argptr)
3694 return -TARGET_EFAULT;
53a5960a
PB
3695 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3696 unlock_user(argptr, arg, 0);
31e31b8a
FB
3697 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3698 break;
3699 default:
3700 case IOC_RW:
579a97f7
FB
3701 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3702 if (!argptr)
3703 return -TARGET_EFAULT;
53a5960a
PB
3704 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3705 unlock_user(argptr, arg, 0);
31e31b8a
FB
3706 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3707 if (!is_error(ret)) {
579a97f7
FB
3708 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3709 if (!argptr)
3710 return -TARGET_EFAULT;
53a5960a
PB
3711 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3712 unlock_user(argptr, arg, target_size);
31e31b8a
FB
3713 }
3714 break;
3715 }
3716 break;
3717 default:
32407103
JM
3718 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
3719 (long)cmd, arg_type[0]);
0da46a6e 3720 ret = -TARGET_ENOSYS;
31e31b8a
FB
3721 break;
3722 }
3723 return ret;
3724}
3725
b39bc503 3726static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
3727 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
3728 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
3729 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
3730 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
3731 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
3732 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
3733 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
3734 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
3735 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
3736 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
3737 { TARGET_IXON, TARGET_IXON, IXON, IXON },
3738 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
3739 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
3740 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
3741 { 0, 0, 0, 0 }
3742};
3743
b39bc503 3744static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
3745 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
3746 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
3747 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
3748 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
3749 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
3750 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
3751 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
3752 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
3753 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
3754 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
3755 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
3756 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
3757 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
3758 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
3759 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
3760 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
3761 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
3762 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3763 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3764 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3765 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3766 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3767 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3768 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3769 { 0, 0, 0, 0 }
3770};
3771
b39bc503 3772static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
3773 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3774 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3775 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3776 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3777 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3778 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3779 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3780 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3781 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3782 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3783 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3784 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3785 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3786 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3787 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3788 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3789 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3790 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3791 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3792 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3793 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3794 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3795 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3796 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3797 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3798 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3799 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3800 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3801 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3802 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3803 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3804 { 0, 0, 0, 0 }
3805};
3806
b39bc503 3807static const bitmask_transtbl lflag_tbl[] = {
31e31b8a
FB
3808 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3809 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3810 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3811 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3812 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3813 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3814 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3815 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3816 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3817 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3818 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3819 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3820 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3821 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3822 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3823 { 0, 0, 0, 0 }
3824};
3825
3826static void target_to_host_termios (void *dst, const void *src)
3827{
3828 struct host_termios *host = dst;
3829 const struct target_termios *target = src;
3b46e624 3830
5fafdf24 3831 host->c_iflag =
31e31b8a 3832 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 3833 host->c_oflag =
31e31b8a 3834 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 3835 host->c_cflag =
31e31b8a 3836 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 3837 host->c_lflag =
31e31b8a
FB
3838 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3839 host->c_line = target->c_line;
3b46e624 3840
44607123 3841 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
3842 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3843 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 3844 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 3845 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 3846 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 3847 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 3848 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 3849 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 3850 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
3851 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3852 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
3853 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3854 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3855 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3856 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3857 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 3858 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 3859}
3b46e624 3860
31e31b8a
FB
3861static void host_to_target_termios (void *dst, const void *src)
3862{
3863 struct target_termios *target = dst;
3864 const struct host_termios *host = src;
3865
5fafdf24 3866 target->c_iflag =
31e31b8a 3867 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 3868 target->c_oflag =
31e31b8a 3869 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 3870 target->c_cflag =
31e31b8a 3871 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 3872 target->c_lflag =
31e31b8a
FB
3873 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3874 target->c_line = host->c_line;
3b46e624 3875
44607123 3876 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
3877 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3878 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3879 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3880 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3881 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3882 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3883 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3884 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3885 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3886 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3887 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3888 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3889 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3890 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3891 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3892 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3893 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3894}
3895
8e853dc7 3896static const StructEntry struct_termios_def = {
31e31b8a
FB
3897 .convert = { host_to_target_termios, target_to_host_termios },
3898 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3899 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3900};
3901
5286db75
FB
3902static bitmask_transtbl mmap_flags_tbl[] = {
3903 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3904 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3905 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3906 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3907 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3908 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3909 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3910 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3911 { 0, 0, 0, 0 }
3912};
3913
2ab83ea7 3914#if defined(TARGET_I386)
6dbad63e
FB
3915
3916/* NOTE: there is really one LDT for all the threads */
b1d8e52e 3917static uint8_t *ldt_table;
6dbad63e 3918
03acab66 3919static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
3920{
3921 int size;
53a5960a 3922 void *p;
6dbad63e
FB
3923
3924 if (!ldt_table)
3925 return 0;
3926 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3927 if (size > bytecount)
3928 size = bytecount;
579a97f7
FB
3929 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3930 if (!p)
03acab66 3931 return -TARGET_EFAULT;
579a97f7 3932 /* ??? Should this by byteswapped? */
53a5960a
PB
3933 memcpy(p, ldt_table, size);
3934 unlock_user(p, ptr, size);
6dbad63e
FB
3935 return size;
3936}
3937
3938/* XXX: add locking support */
03acab66
FB
3939static abi_long write_ldt(CPUX86State *env,
3940 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
3941{
3942 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 3943 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 3944 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 3945 int seg_not_present, useable, lm;
6dbad63e
FB
3946 uint32_t *lp, entry_1, entry_2;
3947
3948 if (bytecount != sizeof(ldt_info))
03acab66 3949 return -TARGET_EINVAL;
579a97f7 3950 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 3951 return -TARGET_EFAULT;
53a5960a 3952 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 3953 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
3954 ldt_info.limit = tswap32(target_ldt_info->limit);
3955 ldt_info.flags = tswap32(target_ldt_info->flags);
3956 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 3957
6dbad63e 3958 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 3959 return -TARGET_EINVAL;
6dbad63e
FB
3960 seg_32bit = ldt_info.flags & 1;
3961 contents = (ldt_info.flags >> 1) & 3;
3962 read_exec_only = (ldt_info.flags >> 3) & 1;
3963 limit_in_pages = (ldt_info.flags >> 4) & 1;
3964 seg_not_present = (ldt_info.flags >> 5) & 1;
3965 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
3966#ifdef TARGET_ABI32
3967 lm = 0;
3968#else
3969 lm = (ldt_info.flags >> 7) & 1;
3970#endif
6dbad63e
FB
3971 if (contents == 3) {
3972 if (oldmode)
03acab66 3973 return -TARGET_EINVAL;
6dbad63e 3974 if (seg_not_present == 0)
03acab66 3975 return -TARGET_EINVAL;
6dbad63e
FB
3976 }
3977 /* allocate the LDT */
3978 if (!ldt_table) {
e441570f
AZ
3979 env->ldt.base = target_mmap(0,
3980 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3981 PROT_READ|PROT_WRITE,
3982 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3983 if (env->ldt.base == -1)
03acab66 3984 return -TARGET_ENOMEM;
e441570f
AZ
3985 memset(g2h(env->ldt.base), 0,
3986 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 3987 env->ldt.limit = 0xffff;
e441570f 3988 ldt_table = g2h(env->ldt.base);
6dbad63e
FB
3989 }
3990
3991 /* NOTE: same code as Linux kernel */
3992 /* Allow LDTs to be cleared by the user. */
3993 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3994 if (oldmode ||
3995 (contents == 0 &&
3996 read_exec_only == 1 &&
3997 seg_32bit == 0 &&
3998 limit_in_pages == 0 &&
3999 seg_not_present == 1 &&
4000 useable == 0 )) {
4001 entry_1 = 0;
4002 entry_2 = 0;
4003 goto install;
4004 }
4005 }
3b46e624 4006
6dbad63e
FB
4007 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4008 (ldt_info.limit & 0x0ffff);
4009 entry_2 = (ldt_info.base_addr & 0xff000000) |
4010 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4011 (ldt_info.limit & 0xf0000) |
4012 ((read_exec_only ^ 1) << 9) |
4013 (contents << 10) |
4014 ((seg_not_present ^ 1) << 15) |
4015 (seg_32bit << 22) |
4016 (limit_in_pages << 23) |
8d18e893 4017 (lm << 21) |
6dbad63e
FB
4018 0x7000;
4019 if (!oldmode)
4020 entry_2 |= (useable << 20);
14ae3ba7 4021
6dbad63e
FB
4022 /* Install the new entry ... */
4023install:
4024 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
4025 lp[0] = tswap32(entry_1);
4026 lp[1] = tswap32(entry_2);
4027 return 0;
4028}
4029
4030/* specific and weird i386 syscalls */
8fcd3692
BS
4031static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
4032 unsigned long bytecount)
6dbad63e 4033{
03acab66 4034 abi_long ret;
3b46e624 4035
6dbad63e
FB
4036 switch (func) {
4037 case 0:
4038 ret = read_ldt(ptr, bytecount);
4039 break;
4040 case 1:
4041 ret = write_ldt(env, ptr, bytecount, 1);
4042 break;
4043 case 0x11:
4044 ret = write_ldt(env, ptr, bytecount, 0);
4045 break;
03acab66
FB
4046 default:
4047 ret = -TARGET_ENOSYS;
4048 break;
6dbad63e
FB
4049 }
4050 return ret;
4051}
1b6b029e 4052
4583f589 4053#if defined(TARGET_I386) && defined(TARGET_ABI32)
bc22eb44 4054abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4055{
4056 uint64_t *gdt_table = g2h(env->gdt.base);
4057 struct target_modify_ldt_ldt_s ldt_info;
4058 struct target_modify_ldt_ldt_s *target_ldt_info;
4059 int seg_32bit, contents, read_exec_only, limit_in_pages;
4060 int seg_not_present, useable, lm;
4061 uint32_t *lp, entry_1, entry_2;
4062 int i;
4063
4064 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4065 if (!target_ldt_info)
4066 return -TARGET_EFAULT;
4067 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 4068 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
4069 ldt_info.limit = tswap32(target_ldt_info->limit);
4070 ldt_info.flags = tswap32(target_ldt_info->flags);
4071 if (ldt_info.entry_number == -1) {
4072 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
4073 if (gdt_table[i] == 0) {
4074 ldt_info.entry_number = i;
4075 target_ldt_info->entry_number = tswap32(i);
4076 break;
4077 }
4078 }
4079 }
4080 unlock_user_struct(target_ldt_info, ptr, 1);
4081
4082 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
4083 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
4084 return -TARGET_EINVAL;
4085 seg_32bit = ldt_info.flags & 1;
4086 contents = (ldt_info.flags >> 1) & 3;
4087 read_exec_only = (ldt_info.flags >> 3) & 1;
4088 limit_in_pages = (ldt_info.flags >> 4) & 1;
4089 seg_not_present = (ldt_info.flags >> 5) & 1;
4090 useable = (ldt_info.flags >> 6) & 1;
4091#ifdef TARGET_ABI32
4092 lm = 0;
4093#else
4094 lm = (ldt_info.flags >> 7) & 1;
4095#endif
4096
4097 if (contents == 3) {
4098 if (seg_not_present == 0)
4099 return -TARGET_EINVAL;
4100 }
4101
4102 /* NOTE: same code as Linux kernel */
4103 /* Allow LDTs to be cleared by the user. */
4104 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
4105 if ((contents == 0 &&
4106 read_exec_only == 1 &&
4107 seg_32bit == 0 &&
4108 limit_in_pages == 0 &&
4109 seg_not_present == 1 &&
4110 useable == 0 )) {
4111 entry_1 = 0;
4112 entry_2 = 0;
4113 goto install;
4114 }
4115 }
4116
4117 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
4118 (ldt_info.limit & 0x0ffff);
4119 entry_2 = (ldt_info.base_addr & 0xff000000) |
4120 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
4121 (ldt_info.limit & 0xf0000) |
4122 ((read_exec_only ^ 1) << 9) |
4123 (contents << 10) |
4124 ((seg_not_present ^ 1) << 15) |
4125 (seg_32bit << 22) |
4126 (limit_in_pages << 23) |
4127 (useable << 20) |
4128 (lm << 21) |
4129 0x7000;
4130
4131 /* Install the new entry ... */
4132install:
4133 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
4134 lp[0] = tswap32(entry_1);
4135 lp[1] = tswap32(entry_2);
4136 return 0;
4137}
4138
8fcd3692 4139static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
4140{
4141 struct target_modify_ldt_ldt_s *target_ldt_info;
4142 uint64_t *gdt_table = g2h(env->gdt.base);
4143 uint32_t base_addr, limit, flags;
4144 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
4145 int seg_not_present, useable, lm;
4146 uint32_t *lp, entry_1, entry_2;
4147
4148 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
4149 if (!target_ldt_info)
4150 return -TARGET_EFAULT;
4151 idx = tswap32(target_ldt_info->entry_number);
4152 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
4153 idx > TARGET_GDT_ENTRY_TLS_MAX) {
4154 unlock_user_struct(target_ldt_info, ptr, 1);
4155 return -TARGET_EINVAL;
4156 }
4157 lp = (uint32_t *)(gdt_table + idx);
4158 entry_1 = tswap32(lp[0]);
4159 entry_2 = tswap32(lp[1]);
4160
4161 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
4162 contents = (entry_2 >> 10) & 3;
4163 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
4164 seg_32bit = (entry_2 >> 22) & 1;
4165 limit_in_pages = (entry_2 >> 23) & 1;
4166 useable = (entry_2 >> 20) & 1;
4167#ifdef TARGET_ABI32
4168 lm = 0;
4169#else
4170 lm = (entry_2 >> 21) & 1;
4171#endif
4172 flags = (seg_32bit << 0) | (contents << 1) |
4173 (read_exec_only << 3) | (limit_in_pages << 4) |
4174 (seg_not_present << 5) | (useable << 6) | (lm << 7);
4175 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
4176 base_addr = (entry_1 >> 16) |
4177 (entry_2 & 0xff000000) |
4178 ((entry_2 & 0xff) << 16);
cbb21eed 4179 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
4180 target_ldt_info->limit = tswap32(limit);
4181 target_ldt_info->flags = tswap32(flags);
4182 unlock_user_struct(target_ldt_info, ptr, 1);
4183 return 0;
4184}
4583f589 4185#endif /* TARGET_I386 && TARGET_ABI32 */
8d18e893 4186
d2fd1af7 4187#ifndef TARGET_ABI32
2667e71c 4188abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 4189{
1add8698 4190 abi_long ret = 0;
d2fd1af7
FB
4191 abi_ulong val;
4192 int idx;
1add8698 4193
d2fd1af7
FB
4194 switch(code) {
4195 case TARGET_ARCH_SET_GS:
4196 case TARGET_ARCH_SET_FS:
4197 if (code == TARGET_ARCH_SET_GS)
4198 idx = R_GS;
4199 else
4200 idx = R_FS;
4201 cpu_x86_load_seg(env, idx, 0);
4202 env->segs[idx].base = addr;
4203 break;
4204 case TARGET_ARCH_GET_GS:
4205 case TARGET_ARCH_GET_FS:
4206 if (code == TARGET_ARCH_GET_GS)
4207 idx = R_GS;
4208 else
4209 idx = R_FS;
4210 val = env->segs[idx].base;
4211 if (put_user(val, addr, abi_ulong))
1add8698 4212 ret = -TARGET_EFAULT;
d2fd1af7
FB
4213 break;
4214 default:
4215 ret = -TARGET_EINVAL;
4216 break;
4217 }
1add8698 4218 return ret;
d2fd1af7
FB
4219}
4220#endif
4221
2ab83ea7
FB
4222#endif /* defined(TARGET_I386) */
4223
05098a93 4224#define NEW_STACK_SIZE 0x40000
d865bab5 4225
d865bab5
PB
4226
4227static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
4228typedef struct {
9349b4f9 4229 CPUArchState *env;
d865bab5
PB
4230 pthread_mutex_t mutex;
4231 pthread_cond_t cond;
4232 pthread_t thread;
4233 uint32_t tid;
4234 abi_ulong child_tidptr;
4235 abi_ulong parent_tidptr;
4236 sigset_t sigmask;
4237} new_thread_info;
4238
4239static void *clone_func(void *arg)
4240{
4241 new_thread_info *info = arg;
9349b4f9 4242 CPUArchState *env;
0d34282f 4243 CPUState *cpu;
edf8e2af 4244 TaskState *ts;
d865bab5
PB
4245
4246 env = info->env;
0d34282f 4247 cpu = ENV_GET_CPU(env);
a2247f8e 4248 thread_cpu = cpu;
0429a971 4249 ts = (TaskState *)cpu->opaque;
d865bab5 4250 info->tid = gettid();
0d34282f 4251 cpu->host_tid = info->tid;
edf8e2af 4252 task_settid(ts);
d865bab5
PB
4253 if (info->child_tidptr)
4254 put_user_u32(info->tid, info->child_tidptr);
4255 if (info->parent_tidptr)
4256 put_user_u32(info->tid, info->parent_tidptr);
4257 /* Enable signals. */
4258 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
4259 /* Signal to the parent that we're ready. */
4260 pthread_mutex_lock(&info->mutex);
4261 pthread_cond_broadcast(&info->cond);
4262 pthread_mutex_unlock(&info->mutex);
4263 /* Wait until the parent has finshed initializing the tls state. */
4264 pthread_mutex_lock(&clone_lock);
4265 pthread_mutex_unlock(&clone_lock);
4266 cpu_loop(env);
4267 /* never exits */
4268 return NULL;
4269}
1b6b029e 4270
0da46a6e
TS
4271/* do_fork() Must return host values and target errnos (unlike most
4272 do_*() functions). */
9349b4f9 4273static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
4274 abi_ulong parent_tidptr, target_ulong newtls,
4275 abi_ulong child_tidptr)
1b6b029e 4276{
0429a971 4277 CPUState *cpu = ENV_GET_CPU(env);
1b6b029e 4278 int ret;
5cd4393b 4279 TaskState *ts;
0429a971 4280 CPUState *new_cpu;
9349b4f9 4281 CPUArchState *new_env;
d865bab5
PB
4282 unsigned int nptl_flags;
4283 sigset_t sigmask;
3b46e624 4284
436d124b
AZ
4285 /* Emulate vfork() with fork() */
4286 if (flags & CLONE_VFORK)
4287 flags &= ~(CLONE_VFORK | CLONE_VM);
4288
1b6b029e 4289 if (flags & CLONE_VM) {
0429a971 4290 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
4291 new_thread_info info;
4292 pthread_attr_t attr;
24cb36a6 4293
7267c094 4294 ts = g_malloc0(sizeof(TaskState));
624f7979 4295 init_task_state(ts);
1b6b029e 4296 /* we create a new CPU instance. */
c5be9f08 4297 new_env = cpu_copy(env);
6e68e076
PB
4298 /* Init regs that differ from the parent. */
4299 cpu_clone_regs(new_env, newsp);
0429a971
AF
4300 new_cpu = ENV_GET_CPU(new_env);
4301 new_cpu->opaque = ts;
edf8e2af
MW
4302 ts->bprm = parent_ts->bprm;
4303 ts->info = parent_ts->info;
d865bab5
PB
4304 nptl_flags = flags;
4305 flags &= ~CLONE_NPTL_FLAGS2;
4306
c2764719
PB
4307 if (nptl_flags & CLONE_CHILD_CLEARTID) {
4308 ts->child_tidptr = child_tidptr;
4309 }
4310
d865bab5
PB
4311 if (nptl_flags & CLONE_SETTLS)
4312 cpu_set_tls (new_env, newtls);
4313
4314 /* Grab a mutex so that thread setup appears atomic. */
4315 pthread_mutex_lock(&clone_lock);
4316
4317 memset(&info, 0, sizeof(info));
4318 pthread_mutex_init(&info.mutex, NULL);
4319 pthread_mutex_lock(&info.mutex);
4320 pthread_cond_init(&info.cond, NULL);
4321 info.env = new_env;
4322 if (nptl_flags & CLONE_CHILD_SETTID)
4323 info.child_tidptr = child_tidptr;
4324 if (nptl_flags & CLONE_PARENT_SETTID)
4325 info.parent_tidptr = parent_tidptr;
4326
4327 ret = pthread_attr_init(&attr);
48e15fc2
NF
4328 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
4329 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
4330 /* It is not safe to deliver signals until the child has finished
4331 initializing, so temporarily block all signals. */
4332 sigfillset(&sigmask);
4333 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
4334
4335 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 4336 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
4337
4338 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
4339 pthread_attr_destroy(&attr);
4340 if (ret == 0) {
4341 /* Wait for the child to initialize. */
4342 pthread_cond_wait(&info.cond, &info.mutex);
4343 ret = info.tid;
4344 if (flags & CLONE_PARENT_SETTID)
4345 put_user_u32(ret, parent_tidptr);
4346 } else {
4347 ret = -1;
4348 }
4349 pthread_mutex_unlock(&info.mutex);
4350 pthread_cond_destroy(&info.cond);
4351 pthread_mutex_destroy(&info.mutex);
4352 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
4353 } else {
4354 /* if no CLONE_VM, we consider it is a fork */
d865bab5 4355 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
1b6b029e 4356 return -EINVAL;
d865bab5 4357 fork_start();
1b6b029e 4358 ret = fork();
d865bab5 4359 if (ret == 0) {
2b1319c8 4360 /* Child Process. */
d865bab5
PB
4361 cpu_clone_regs(env, newsp);
4362 fork_end(1);
2b1319c8
AJ
4363 /* There is a race condition here. The parent process could
4364 theoretically read the TID in the child process before the child
4365 tid is set. This would require using either ptrace
4366 (not implemented) or having *_tidptr to point at a shared memory
4367 mapping. We can't repeat the spinlock hack used above because
4368 the child process gets its own copy of the lock. */
d865bab5
PB
4369 if (flags & CLONE_CHILD_SETTID)
4370 put_user_u32(gettid(), child_tidptr);
4371 if (flags & CLONE_PARENT_SETTID)
4372 put_user_u32(gettid(), parent_tidptr);
0429a971 4373 ts = (TaskState *)cpu->opaque;
d865bab5
PB
4374 if (flags & CLONE_SETTLS)
4375 cpu_set_tls (env, newtls);
c2764719
PB
4376 if (flags & CLONE_CHILD_CLEARTID)
4377 ts->child_tidptr = child_tidptr;
d865bab5
PB
4378 } else {
4379 fork_end(0);
4380 }
1b6b029e
FB
4381 }
4382 return ret;
4383}
4384
5f106811
APR
4385/* warning : doesn't handle linux specific flags... */
4386static int target_to_host_fcntl_cmd(int cmd)
4387{
4388 switch(cmd) {
4389 case TARGET_F_DUPFD:
4390 case TARGET_F_GETFD:
4391 case TARGET_F_SETFD:
4392 case TARGET_F_GETFL:
4393 case TARGET_F_SETFL:
4394 return cmd;
4395 case TARGET_F_GETLK:
4396 return F_GETLK;
4397 case TARGET_F_SETLK:
4398 return F_SETLK;
4399 case TARGET_F_SETLKW:
4400 return F_SETLKW;
4401 case TARGET_F_GETOWN:
4402 return F_GETOWN;
4403 case TARGET_F_SETOWN:
4404 return F_SETOWN;
4405 case TARGET_F_GETSIG:
4406 return F_GETSIG;
4407 case TARGET_F_SETSIG:
4408 return F_SETSIG;
4409#if TARGET_ABI_BITS == 32
4410 case TARGET_F_GETLK64:
4411 return F_GETLK64;
4412 case TARGET_F_SETLK64:
4413 return F_SETLK64;
4414 case TARGET_F_SETLKW64:
4415 return F_SETLKW64;
4416#endif
7e22e546
UH
4417 case TARGET_F_SETLEASE:
4418 return F_SETLEASE;
4419 case TARGET_F_GETLEASE:
4420 return F_GETLEASE;
fbd5de9b 4421#ifdef F_DUPFD_CLOEXEC
7e22e546
UH
4422 case TARGET_F_DUPFD_CLOEXEC:
4423 return F_DUPFD_CLOEXEC;
fbd5de9b 4424#endif
7e22e546
UH
4425 case TARGET_F_NOTIFY:
4426 return F_NOTIFY;
8d5d3004
AS
4427#ifdef F_GETOWN_EX
4428 case TARGET_F_GETOWN_EX:
4429 return F_GETOWN_EX;
4430#endif
4431#ifdef F_SETOWN_EX
4432 case TARGET_F_SETOWN_EX:
4433 return F_SETOWN_EX;
4434#endif
5f106811
APR
4435 default:
4436 return -TARGET_EINVAL;
4437 }
4438 return -TARGET_EINVAL;
4439}
4440
2ba7f730
LV
4441#define TRANSTBL_CONVERT(a) { -1, TARGET_##a, -1, a }
4442static const bitmask_transtbl flock_tbl[] = {
4443 TRANSTBL_CONVERT(F_RDLCK),
4444 TRANSTBL_CONVERT(F_WRLCK),
4445 TRANSTBL_CONVERT(F_UNLCK),
4446 TRANSTBL_CONVERT(F_EXLCK),
4447 TRANSTBL_CONVERT(F_SHLCK),
4448 { 0, 0, 0, 0 }
4449};
4450
992f48a0 4451static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7775e9ec
FB
4452{
4453 struct flock fl;
53a5960a 4454 struct target_flock *target_fl;
43f238d7
TS
4455 struct flock64 fl64;
4456 struct target_flock64 *target_fl64;
8d5d3004
AS
4457#ifdef F_GETOWN_EX
4458 struct f_owner_ex fox;
4459 struct target_f_owner_ex *target_fox;
4460#endif
992f48a0 4461 abi_long ret;
5f106811
APR
4462 int host_cmd = target_to_host_fcntl_cmd(cmd);
4463
4464 if (host_cmd == -TARGET_EINVAL)
4465 return host_cmd;
53a5960a 4466
7775e9ec
FB
4467 switch(cmd) {
4468 case TARGET_F_GETLK:
579a97f7
FB
4469 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4470 return -TARGET_EFAULT;
2ba7f730
LV
4471 fl.l_type =
4472 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
5813427b 4473 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4474 fl.l_start = tswapal(target_fl->l_start);
4475 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4476 fl.l_pid = tswap32(target_fl->l_pid);
5813427b 4477 unlock_user_struct(target_fl, arg, 0);
5f106811 4478 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4479 if (ret == 0) {
579a97f7
FB
4480 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
4481 return -TARGET_EFAULT;
2ba7f730
LV
4482 target_fl->l_type =
4483 host_to_target_bitmask(tswap16(fl.l_type), flock_tbl);
7775e9ec 4484 target_fl->l_whence = tswap16(fl.l_whence);
cbb21eed
MB
4485 target_fl->l_start = tswapal(fl.l_start);
4486 target_fl->l_len = tswapal(fl.l_len);
7e22e546 4487 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 4488 unlock_user_struct(target_fl, arg, 1);
7775e9ec
FB
4489 }
4490 break;
3b46e624 4491
7775e9ec
FB
4492 case TARGET_F_SETLK:
4493 case TARGET_F_SETLKW:
579a97f7
FB
4494 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4495 return -TARGET_EFAULT;
2ba7f730
LV
4496 fl.l_type =
4497 target_to_host_bitmask(tswap16(target_fl->l_type), flock_tbl);
7775e9ec 4498 fl.l_whence = tswap16(target_fl->l_whence);
cbb21eed
MB
4499 fl.l_start = tswapal(target_fl->l_start);
4500 fl.l_len = tswapal(target_fl->l_len);
7e22e546 4501 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 4502 unlock_user_struct(target_fl, arg, 0);
5f106811 4503 ret = get_errno(fcntl(fd, host_cmd, &fl));
7775e9ec 4504 break;
3b46e624 4505
7775e9ec 4506 case TARGET_F_GETLK64:
579a97f7
FB
4507 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4508 return -TARGET_EFAULT;
2ba7f730
LV
4509 fl64.l_type =
4510 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
5813427b 4511 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4512 fl64.l_start = tswap64(target_fl64->l_start);
4513 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4514 fl64.l_pid = tswap32(target_fl64->l_pid);
5813427b 4515 unlock_user_struct(target_fl64, arg, 0);
5f106811 4516 ret = get_errno(fcntl(fd, host_cmd, &fl64));
43f238d7 4517 if (ret == 0) {
579a97f7
FB
4518 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
4519 return -TARGET_EFAULT;
2ba7f730
LV
4520 target_fl64->l_type =
4521 host_to_target_bitmask(tswap16(fl64.l_type), flock_tbl) >> 1;
43f238d7 4522 target_fl64->l_whence = tswap16(fl64.l_whence);
cbb21eed
MB
4523 target_fl64->l_start = tswap64(fl64.l_start);
4524 target_fl64->l_len = tswap64(fl64.l_len);
7e22e546 4525 target_fl64->l_pid = tswap32(fl64.l_pid);
43f238d7
TS
4526 unlock_user_struct(target_fl64, arg, 1);
4527 }
9ee1fa2c 4528 break;
7775e9ec
FB
4529 case TARGET_F_SETLK64:
4530 case TARGET_F_SETLKW64:
579a97f7
FB
4531 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4532 return -TARGET_EFAULT;
2ba7f730
LV
4533 fl64.l_type =
4534 target_to_host_bitmask(tswap16(target_fl64->l_type), flock_tbl) >> 1;
43f238d7 4535 fl64.l_whence = tswap16(target_fl64->l_whence);
cbb21eed
MB
4536 fl64.l_start = tswap64(target_fl64->l_start);
4537 fl64.l_len = tswap64(target_fl64->l_len);
7e22e546 4538 fl64.l_pid = tswap32(target_fl64->l_pid);
43f238d7 4539 unlock_user_struct(target_fl64, arg, 0);
5f106811 4540 ret = get_errno(fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
4541 break;
4542
5f106811
APR
4543 case TARGET_F_GETFL:
4544 ret = get_errno(fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
4545 if (ret >= 0) {
4546 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4547 }
ffa65c3b
FB
4548 break;
4549
5f106811
APR
4550 case TARGET_F_SETFL:
4551 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4552 break;
4553
8d5d3004
AS
4554#ifdef F_GETOWN_EX
4555 case TARGET_F_GETOWN_EX:
4556 ret = get_errno(fcntl(fd, host_cmd, &fox));
4557 if (ret >= 0) {
4558 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
4559 return -TARGET_EFAULT;
4560 target_fox->type = tswap32(fox.type);
4561 target_fox->pid = tswap32(fox.pid);
4562 unlock_user_struct(target_fox, arg, 1);
4563 }
4564 break;
4565#endif
4566
4567#ifdef F_SETOWN_EX
4568 case TARGET_F_SETOWN_EX:
4569 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
4570 return -TARGET_EFAULT;
4571 fox.type = tswap32(target_fox->type);
4572 fox.pid = tswap32(target_fox->pid);
4573 unlock_user_struct(target_fox, arg, 0);
4574 ret = get_errno(fcntl(fd, host_cmd, &fox));
4575 break;
4576#endif
4577
5f106811
APR
4578 case TARGET_F_SETOWN:
4579 case TARGET_F_GETOWN:
4580 case TARGET_F_SETSIG:
4581 case TARGET_F_GETSIG:
7e22e546
UH
4582 case TARGET_F_SETLEASE:
4583 case TARGET_F_GETLEASE:
5f106811 4584 ret = get_errno(fcntl(fd, host_cmd, arg));
ffa65c3b
FB
4585 break;
4586
7775e9ec 4587 default:
9ee1fa2c 4588 ret = get_errno(fcntl(fd, cmd, arg));
7775e9ec
FB
4589 break;
4590 }
4591 return ret;
4592}
4593
67867308 4594#ifdef USE_UID16
7775e9ec 4595
67867308
FB
4596static inline int high2lowuid(int uid)
4597{
4598 if (uid > 65535)
4599 return 65534;
4600 else
4601 return uid;
4602}
4603
4604static inline int high2lowgid(int gid)
4605{
4606 if (gid > 65535)
4607 return 65534;
4608 else
4609 return gid;
4610}
4611
4612static inline int low2highuid(int uid)
4613{
4614 if ((int16_t)uid == -1)
4615 return -1;
4616 else
4617 return uid;
4618}
4619
4620static inline int low2highgid(int gid)
4621{
4622 if ((int16_t)gid == -1)
4623 return -1;
4624 else
4625 return gid;
4626}
0c866a7e
RV
4627static inline int tswapid(int id)
4628{
4629 return tswap16(id);
4630}
76ca310a
PM
4631
4632#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
4633
0c866a7e
RV
4634#else /* !USE_UID16 */
4635static inline int high2lowuid(int uid)
4636{
4637 return uid;
4638}
4639static inline int high2lowgid(int gid)
4640{
4641 return gid;
4642}
4643static inline int low2highuid(int uid)
4644{
4645 return uid;
4646}
4647static inline int low2highgid(int gid)
4648{
4649 return gid;
4650}
4651static inline int tswapid(int id)
4652{
4653 return tswap32(id);
4654}
76ca310a
PM
4655
4656#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
4657
67867308 4658#endif /* USE_UID16 */
1b6b029e 4659
31e31b8a
FB
4660void syscall_init(void)
4661{
2ab83ea7
FB
4662 IOCTLEntry *ie;
4663 const argtype *arg_type;
4664 int size;
b92c47c1 4665 int i;
2ab83ea7 4666
001faf32 4667#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 4668#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
4669#include "syscall_types.h"
4670#undef STRUCT
4671#undef STRUCT_SPECIAL
2ab83ea7 4672
dd6e957a
PM
4673 /* Build target_to_host_errno_table[] table from
4674 * host_to_target_errno_table[]. */
4675 for (i = 0; i < ERRNO_TABLE_SIZE; i++) {
4676 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
4677 }
4678
2ab83ea7
FB
4679 /* we patch the ioctl size if necessary. We rely on the fact that
4680 no ioctl has all the bits at '1' in the size field */
4681 ie = ioctl_entries;
4682 while (ie->target_cmd != 0) {
4683 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
4684 TARGET_IOC_SIZEMASK) {
4685 arg_type = ie->arg_type;
4686 if (arg_type[0] != TYPE_PTR) {
5fafdf24 4687 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
4688 ie->target_cmd);
4689 exit(1);
4690 }
4691 arg_type++;
4692 size = thunk_type_size(arg_type, 0);
5fafdf24 4693 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
4694 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
4695 (size << TARGET_IOC_SIZESHIFT);
4696 }
b92c47c1 4697
2ab83ea7 4698 /* automatic consistency check if same arch */
872ea0c0
AZ
4699#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
4700 (defined(__x86_64__) && defined(TARGET_X86_64))
4701 if (unlikely(ie->target_cmd != ie->host_cmd)) {
4702 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
4703 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
4704 }
4705#endif
4706 ie++;
4707 }
31e31b8a 4708}
c573ff67 4709
992f48a0 4710#if TARGET_ABI_BITS == 32
ce4defa0
PB
4711static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
4712{
af325d36 4713#ifdef TARGET_WORDS_BIGENDIAN
ce4defa0
PB
4714 return ((uint64_t)word0 << 32) | word1;
4715#else
4716 return ((uint64_t)word1 << 32) | word0;
4717#endif
4718}
992f48a0 4719#else /* TARGET_ABI_BITS == 32 */
32407103
JM
4720static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
4721{
4722 return word0;
4723}
992f48a0 4724#endif /* TARGET_ABI_BITS != 32 */
ce4defa0
PB
4725
4726#ifdef TARGET_NR_truncate64
992f48a0
BS
4727static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
4728 abi_long arg2,
4729 abi_long arg3,
4730 abi_long arg4)
ce4defa0 4731{
48e515d4 4732 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
4733 arg2 = arg3;
4734 arg3 = arg4;
48e515d4 4735 }
ce4defa0
PB
4736 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
4737}
4738#endif
4739
4740#ifdef TARGET_NR_ftruncate64
992f48a0
BS
4741static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
4742 abi_long arg2,
4743 abi_long arg3,
4744 abi_long arg4)
ce4defa0 4745{
48e515d4 4746 if (regpairs_aligned(cpu_env)) {
ce4defa0
PB
4747 arg2 = arg3;
4748 arg3 = arg4;
48e515d4 4749 }
ce4defa0
PB
4750 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
4751}
4752#endif
4753
579a97f7
FB
4754static inline abi_long target_to_host_timespec(struct timespec *host_ts,
4755 abi_ulong target_addr)
53a5960a
PB
4756{
4757 struct target_timespec *target_ts;
4758
579a97f7
FB
4759 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
4760 return -TARGET_EFAULT;
cbb21eed
MB
4761 host_ts->tv_sec = tswapal(target_ts->tv_sec);
4762 host_ts->tv_nsec = tswapal(target_ts->tv_nsec);
53a5960a 4763 unlock_user_struct(target_ts, target_addr, 0);
b255bfa8 4764 return 0;
53a5960a
PB
4765}
4766
579a97f7
FB
4767static inline abi_long host_to_target_timespec(abi_ulong target_addr,
4768 struct timespec *host_ts)
53a5960a
PB
4769{
4770 struct target_timespec *target_ts;
4771
579a97f7
FB
4772 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
4773 return -TARGET_EFAULT;
cbb21eed
MB
4774 target_ts->tv_sec = tswapal(host_ts->tv_sec);
4775 target_ts->tv_nsec = tswapal(host_ts->tv_nsec);
53a5960a 4776 unlock_user_struct(target_ts, target_addr, 1);
b255bfa8 4777 return 0;
53a5960a
PB
4778}
4779
f4f1e10a
ECL
4780static inline abi_long target_to_host_itimerspec(struct itimerspec *host_itspec,
4781 abi_ulong target_addr)
4782{
4783 struct target_itimerspec *target_itspec;
4784
4785 if (!lock_user_struct(VERIFY_READ, target_itspec, target_addr, 1)) {
4786 return -TARGET_EFAULT;
4787 }
4788
4789 host_itspec->it_interval.tv_sec =
4790 tswapal(target_itspec->it_interval.tv_sec);
4791 host_itspec->it_interval.tv_nsec =
4792 tswapal(target_itspec->it_interval.tv_nsec);
4793 host_itspec->it_value.tv_sec = tswapal(target_itspec->it_value.tv_sec);
4794 host_itspec->it_value.tv_nsec = tswapal(target_itspec->it_value.tv_nsec);
4795
4796 unlock_user_struct(target_itspec, target_addr, 1);
4797 return 0;
4798}
4799
4800static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
4801 struct itimerspec *host_its)
4802{
4803 struct target_itimerspec *target_itspec;
4804
4805 if (!lock_user_struct(VERIFY_WRITE, target_itspec, target_addr, 0)) {
4806 return -TARGET_EFAULT;
4807 }
4808
4809 target_itspec->it_interval.tv_sec = tswapal(host_its->it_interval.tv_sec);
4810 target_itspec->it_interval.tv_nsec = tswapal(host_its->it_interval.tv_nsec);
4811
4812 target_itspec->it_value.tv_sec = tswapal(host_its->it_value.tv_sec);
4813 target_itspec->it_value.tv_nsec = tswapal(host_its->it_value.tv_nsec);
4814
4815 unlock_user_struct(target_itspec, target_addr, 0);
4816 return 0;
4817}
4818
9d33b76b 4819#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
6a24a778
AZ
4820static inline abi_long host_to_target_stat64(void *cpu_env,
4821 abi_ulong target_addr,
4822 struct stat *host_st)
4823{
09701199 4824#if defined(TARGET_ARM) && defined(TARGET_ABI32)
6a24a778
AZ
4825 if (((CPUARMState *)cpu_env)->eabi) {
4826 struct target_eabi_stat64 *target_st;
4827
4828 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4829 return -TARGET_EFAULT;
4830 memset(target_st, 0, sizeof(struct target_eabi_stat64));
4831 __put_user(host_st->st_dev, &target_st->st_dev);
4832 __put_user(host_st->st_ino, &target_st->st_ino);
4833#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4834 __put_user(host_st->st_ino, &target_st->__st_ino);
4835#endif
4836 __put_user(host_st->st_mode, &target_st->st_mode);
4837 __put_user(host_st->st_nlink, &target_st->st_nlink);
4838 __put_user(host_st->st_uid, &target_st->st_uid);
4839 __put_user(host_st->st_gid, &target_st->st_gid);
4840 __put_user(host_st->st_rdev, &target_st->st_rdev);
4841 __put_user(host_st->st_size, &target_st->st_size);
4842 __put_user(host_st->st_blksize, &target_st->st_blksize);
4843 __put_user(host_st->st_blocks, &target_st->st_blocks);
4844 __put_user(host_st->st_atime, &target_st->target_st_atime);
4845 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4846 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4847 unlock_user_struct(target_st, target_addr, 1);
4848 } else
4849#endif
4850 {
20d155bc 4851#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 4852 struct target_stat64 *target_st;
20d155bc
SW
4853#else
4854 struct target_stat *target_st;
9d33b76b 4855#endif
6a24a778
AZ
4856
4857 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4858 return -TARGET_EFAULT;
9d33b76b 4859 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
4860 __put_user(host_st->st_dev, &target_st->st_dev);
4861 __put_user(host_st->st_ino, &target_st->st_ino);
4862#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4863 __put_user(host_st->st_ino, &target_st->__st_ino);
4864#endif
4865 __put_user(host_st->st_mode, &target_st->st_mode);
4866 __put_user(host_st->st_nlink, &target_st->st_nlink);
4867 __put_user(host_st->st_uid, &target_st->st_uid);
4868 __put_user(host_st->st_gid, &target_st->st_gid);
4869 __put_user(host_st->st_rdev, &target_st->st_rdev);
4870 /* XXX: better use of kernel struct */
4871 __put_user(host_st->st_size, &target_st->st_size);
4872 __put_user(host_st->st_blksize, &target_st->st_blksize);
4873 __put_user(host_st->st_blocks, &target_st->st_blocks);
4874 __put_user(host_st->st_atime, &target_st->target_st_atime);
4875 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4876 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4877 unlock_user_struct(target_st, target_addr, 1);
4878 }
4879
4880 return 0;
4881}
4882#endif
4883
bd0c5661
PB
4884/* ??? Using host futex calls even when target atomic operations
4885 are not really atomic probably breaks things. However implementing
4886 futexes locally would make futexes shared between multiple processes
4887 tricky. However they're probably useless because guest atomic
4888 operations won't work either. */
8fcd3692
BS
4889static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
4890 target_ulong uaddr2, int val3)
bd0c5661
PB
4891{
4892 struct timespec ts, *pts;
a16aae0c 4893 int base_op;
bd0c5661
PB
4894
4895 /* ??? We assume FUTEX_* constants are the same on both host
4896 and target. */
a29ccd63 4897#ifdef FUTEX_CMD_MASK
a16aae0c 4898 base_op = op & FUTEX_CMD_MASK;
a29ccd63 4899#else
a16aae0c 4900 base_op = op;
a29ccd63 4901#endif
a16aae0c 4902 switch (base_op) {
bd0c5661 4903 case FUTEX_WAIT:
cce246e0 4904 case FUTEX_WAIT_BITSET:
bd0c5661
PB
4905 if (timeout) {
4906 pts = &ts;
4907 target_to_host_timespec(pts, timeout);
4908 } else {
4909 pts = NULL;
4910 }
a29ccd63 4911 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
cce246e0 4912 pts, NULL, val3));
bd0c5661 4913 case FUTEX_WAKE:
a29ccd63 4914 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 4915 case FUTEX_FD:
a29ccd63 4916 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
bd0c5661 4917 case FUTEX_REQUEUE:
bd0c5661 4918 case FUTEX_CMP_REQUEUE:
a16aae0c
NF
4919 case FUTEX_WAKE_OP:
4920 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
4921 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
4922 But the prototype takes a `struct timespec *'; insert casts
4923 to satisfy the compiler. We do not need to tswap TIMEOUT
4924 since it's not compared to guest memory. */
4925 pts = (struct timespec *)(uintptr_t) timeout;
4926 return get_errno(sys_futex(g2h(uaddr), op, val, pts,
4927 g2h(uaddr2),
4928 (base_op == FUTEX_CMP_REQUEUE
4929 ? tswap32(val3)
4930 : val3)));
bd0c5661
PB
4931 default:
4932 return -TARGET_ENOSYS;
4933 }
4934}
bd0c5661 4935
1d9d8b55
PB
4936/* Map host to target signal numbers for the wait family of syscalls.
4937 Assume all other status bits are the same. */
a05c6409 4938int host_to_target_waitstatus(int status)
1d9d8b55
PB
4939{
4940 if (WIFSIGNALED(status)) {
4941 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
4942 }
4943 if (WIFSTOPPED(status)) {
4944 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4945 | (status & 0xff);
4946 }
4947 return status;
4948}
4949
36c08d49
AG
4950static int open_self_maps(void *cpu_env, int fd)
4951{
1a49ef2a 4952#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
0429a971
AF
4953 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
4954 TaskState *ts = cpu->opaque;
1a49ef2a
AG
4955#endif
4956 FILE *fp;
4957 char *line = NULL;
4958 size_t len = 0;
4959 ssize_t read;
4960
4961 fp = fopen("/proc/self/maps", "r");
4962 if (fp == NULL) {
4963 return -EACCES;
4964 }
36c08d49 4965
1a49ef2a
AG
4966 while ((read = getline(&line, &len, fp)) != -1) {
4967 int fields, dev_maj, dev_min, inode;
4968 uint64_t min, max, offset;
4969 char flag_r, flag_w, flag_x, flag_p;
4970 char path[512] = "";
4971 fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
4972 " %512s", &min, &max, &flag_r, &flag_w, &flag_x,
4973 &flag_p, &offset, &dev_maj, &dev_min, &inode, path);
4974
4975 if ((fields < 10) || (fields > 11)) {
4976 continue;
4977 }
4978 if (!strncmp(path, "[stack]", 7)) {
4979 continue;
4980 }
4981 if (h2g_valid(min) && h2g_valid(max)) {
4982 dprintf(fd, TARGET_ABI_FMT_lx "-" TARGET_ABI_FMT_lx
e24fed4e 4983 " %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
1a49ef2a
AG
4984 h2g(min), h2g(max), flag_r, flag_w,
4985 flag_x, flag_p, offset, dev_maj, dev_min, inode,
e24fed4e 4986 path[0] ? " " : "", path);
1a49ef2a
AG
4987 }
4988 }
4989
4990 free(line);
4991 fclose(fp);
4992
4993#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_UNICORE32)
36c08d49
AG
4994 dprintf(fd, "%08llx-%08llx rw-p %08llx 00:00 0 [stack]\n",
4995 (unsigned long long)ts->info->stack_limit,
1bdd7c7e
AG
4996 (unsigned long long)(ts->info->start_stack +
4997 (TARGET_PAGE_SIZE - 1)) & TARGET_PAGE_MASK,
1a49ef2a
AG
4998 (unsigned long long)0);
4999#endif
36c08d49
AG
5000
5001 return 0;
5002}
5003
480b8e7d
AG
5004static int open_self_stat(void *cpu_env, int fd)
5005{
0429a971
AF
5006 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
5007 TaskState *ts = cpu->opaque;
480b8e7d
AG
5008 abi_ulong start_stack = ts->info->start_stack;
5009 int i;
5010
5011 for (i = 0; i < 44; i++) {
5012 char buf[128];
5013 int len;
5014 uint64_t val = 0;
5015
e0e65bee
FE
5016 if (i == 0) {
5017 /* pid */
5018 val = getpid();
5019 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
5020 } else if (i == 1) {
5021 /* app name */
5022 snprintf(buf, sizeof(buf), "(%s) ", ts->bprm->argv[0]);
5023 } else if (i == 27) {
5024 /* stack bottom */
5025 val = start_stack;
5026 snprintf(buf, sizeof(buf), "%"PRId64 " ", val);
5027 } else {
5028 /* for the rest, there is MasterCard */
5029 snprintf(buf, sizeof(buf), "0%c", i == 43 ? '\n' : ' ');
480b8e7d 5030 }
e0e65bee 5031
480b8e7d
AG
5032 len = strlen(buf);
5033 if (write(fd, buf, len) != len) {
5034 return -1;
5035 }
5036 }
5037
5038 return 0;
5039}
5040
257450ee
AG
5041static int open_self_auxv(void *cpu_env, int fd)
5042{
0429a971
AF
5043 CPUState *cpu = ENV_GET_CPU((CPUArchState *)cpu_env);
5044 TaskState *ts = cpu->opaque;
257450ee
AG
5045 abi_ulong auxv = ts->info->saved_auxv;
5046 abi_ulong len = ts->info->auxv_len;
5047 char *ptr;
5048
5049 /*
5050 * Auxiliary vector is stored in target process stack.
5051 * read in whole auxv vector and copy it to file
5052 */
5053 ptr = lock_user(VERIFY_READ, auxv, len, 0);
5054 if (ptr != NULL) {
5055 while (len > 0) {
5056 ssize_t r;
5057 r = write(fd, ptr, len);
5058 if (r <= 0) {
5059 break;
5060 }
5061 len -= r;
5062 ptr += r;
5063 }
5064 lseek(fd, 0, SEEK_SET);
5065 unlock_user(ptr, auxv, len);
5066 }
5067
5068 return 0;
5069}
5070
463d8e73
AS
5071static int is_proc_myself(const char *filename, const char *entry)
5072{
5073 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
5074 filename += strlen("/proc/");
5075 if (!strncmp(filename, "self/", strlen("self/"))) {
5076 filename += strlen("self/");
5077 } else if (*filename >= '1' && *filename <= '9') {
5078 char myself[80];
5079 snprintf(myself, sizeof(myself), "%d/", getpid());
5080 if (!strncmp(filename, myself, strlen(myself))) {
5081 filename += strlen(myself);
5082 } else {
5083 return 0;
5084 }
5085 } else {
5086 return 0;
5087 }
5088 if (!strcmp(filename, entry)) {
5089 return 1;
5090 }
5091 }
5092 return 0;
5093}
5094
de6b9933
LV
5095#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
5096static int is_proc(const char *filename, const char *entry)
5097{
5098 return strcmp(filename, entry) == 0;
5099}
5100
5101static int open_net_route(void *cpu_env, int fd)
5102{
5103 FILE *fp;
5104 char *line = NULL;
5105 size_t len = 0;
5106 ssize_t read;
5107
5108 fp = fopen("/proc/net/route", "r");
5109 if (fp == NULL) {
5110 return -EACCES;
5111 }
5112
5113 /* read header */
5114
5115 read = getline(&line, &len, fp);
5116 dprintf(fd, "%s", line);
5117
5118 /* read routes */
5119
5120 while ((read = getline(&line, &len, fp)) != -1) {
5121 char iface[16];
5122 uint32_t dest, gw, mask;
5123 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
5124 sscanf(line, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
5125 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
5126 &mask, &mtu, &window, &irtt);
5127 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
5128 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
5129 metric, tswap32(mask), mtu, window, irtt);
5130 }
5131
5132 free(line);
5133 fclose(fp);
5134
5135 return 0;
5136}
5137#endif
5138
3be14d05
AG
5139static int do_open(void *cpu_env, const char *pathname, int flags, mode_t mode)
5140{
5141 struct fake_open {
5142 const char *filename;
5143 int (*fill)(void *cpu_env, int fd);
de6b9933 5144 int (*cmp)(const char *s1, const char *s2);
3be14d05
AG
5145 };
5146 const struct fake_open *fake_open;
5147 static const struct fake_open fakes[] = {
de6b9933
LV
5148 { "maps", open_self_maps, is_proc_myself },
5149 { "stat", open_self_stat, is_proc_myself },
5150 { "auxv", open_self_auxv, is_proc_myself },
5151#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
5152 { "/proc/net/route", open_net_route, is_proc },
5153#endif
5154 { NULL, NULL, NULL }
3be14d05
AG
5155 };
5156
aa07f5ec
MO
5157 if (is_proc_myself(pathname, "exe")) {
5158 int execfd = qemu_getauxval(AT_EXECFD);
5159 return execfd ? execfd : get_errno(open(exec_path, flags, mode));
5160 }
5161
3be14d05 5162 for (fake_open = fakes; fake_open->filename; fake_open++) {
de6b9933 5163 if (fake_open->cmp(pathname, fake_open->filename)) {
3be14d05
AG
5164 break;
5165 }
5166 }
5167
5168 if (fake_open->filename) {
5169 const char *tmpdir;
5170 char filename[PATH_MAX];
5171 int fd, r;
5172
5173 /* create temporary file to map stat to */
5174 tmpdir = getenv("TMPDIR");
5175 if (!tmpdir)
5176 tmpdir = "/tmp";
5177 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
5178 fd = mkstemp(filename);
5179 if (fd < 0) {
5180 return fd;
5181 }
5182 unlink(filename);
5183
5184 if ((r = fake_open->fill(cpu_env, fd))) {
5185 close(fd);
5186 return r;
5187 }
5188 lseek(fd, 0, SEEK_SET);
5189
5190 return fd;
5191 }
5192
5193 return get_errno(open(path(pathname), flags, mode));
5194}
5195
0da46a6e
TS
5196/* do_syscall() should always have a single exit point at the end so
5197 that actions, such as logging of syscall results, can be performed.
5198 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
992f48a0
BS
5199abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
5200 abi_long arg2, abi_long arg3, abi_long arg4,
5945cfcb
PM
5201 abi_long arg5, abi_long arg6, abi_long arg7,
5202 abi_long arg8)
31e31b8a 5203{
182735ef 5204 CPUState *cpu = ENV_GET_CPU(cpu_env);
992f48a0 5205 abi_long ret;
31e31b8a 5206 struct stat st;
56c8f68f 5207 struct statfs stfs;
53a5960a 5208 void *p;
3b46e624 5209
72f03900 5210#ifdef DEBUG
c573ff67 5211 gemu_log("syscall %d", num);
72f03900 5212#endif
b92c47c1
TS
5213 if(do_strace)
5214 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
5215
31e31b8a
FB
5216 switch(num) {
5217 case TARGET_NR_exit:
9b056fcc
AF
5218 /* In old applications this may be used to implement _exit(2).
5219 However in threaded applictions it is used for thread termination,
5220 and _exit_group is used for application termination.
5221 Do thread termination if we have more then one thread. */
5222 /* FIXME: This probably breaks if a signal arrives. We should probably
5223 be disabling signals. */
bdc44640 5224 if (CPU_NEXT(first_cpu)) {
9b056fcc 5225 TaskState *ts;
9b056fcc
AF
5226
5227 cpu_list_lock();
9b056fcc 5228 /* Remove the CPU from the list. */
bdc44640 5229 QTAILQ_REMOVE(&cpus, cpu, node);
9b056fcc 5230 cpu_list_unlock();
0429a971 5231 ts = cpu->opaque;
9b056fcc
AF
5232 if (ts->child_tidptr) {
5233 put_user_u32(0, ts->child_tidptr);
5234 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
5235 NULL, NULL, 0);
5236 }
a2247f8e 5237 thread_cpu = NULL;
0429a971 5238 object_unref(OBJECT(cpu));
9b056fcc
AF
5239 g_free(ts);
5240 pthread_exit(NULL);
5241 }
9788c9ca 5242#ifdef TARGET_GPROF
7d13299d
FB
5243 _mcleanup();
5244#endif
e9009676 5245 gdb_exit(cpu_env, arg1);
c2764719 5246 _exit(arg1);
31e31b8a
FB
5247 ret = 0; /* avoid warning */
5248 break;
5249 case TARGET_NR_read:
38d840e6
AJ
5250 if (arg3 == 0)
5251 ret = 0;
5252 else {
5253 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5254 goto efault;
5255 ret = get_errno(read(arg1, p, arg3));
5256 unlock_user(p, arg2, ret);
5257 }
31e31b8a
FB
5258 break;
5259 case TARGET_NR_write:
579a97f7
FB
5260 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5261 goto efault;
53a5960a
PB
5262 ret = get_errno(write(arg1, p, arg3));
5263 unlock_user(p, arg2, 0);
31e31b8a
FB
5264 break;
5265 case TARGET_NR_open:
2f619698
FB
5266 if (!(p = lock_user_string(arg1)))
5267 goto efault;
3be14d05
AG
5268 ret = get_errno(do_open(cpu_env, p,
5269 target_to_host_bitmask(arg2, fcntl_flags_tbl),
5270 arg3));
53a5960a 5271 unlock_user(p, arg1, 0);
31e31b8a 5272 break;
82424832
TS
5273#if defined(TARGET_NR_openat) && defined(__NR_openat)
5274 case TARGET_NR_openat:
579a97f7
FB
5275 if (!(p = lock_user_string(arg2)))
5276 goto efault;
5277 ret = get_errno(sys_openat(arg1,
5278 path(p),
5279 target_to_host_bitmask(arg3, fcntl_flags_tbl),
5280 arg4));
5281 unlock_user(p, arg2, 0);
82424832
TS
5282 break;
5283#endif
31e31b8a
FB
5284 case TARGET_NR_close:
5285 ret = get_errno(close(arg1));
5286 break;
5287 case TARGET_NR_brk:
53a5960a 5288 ret = do_brk(arg1);
31e31b8a
FB
5289 break;
5290 case TARGET_NR_fork:
d865bab5 5291 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
31e31b8a 5292 break;
e5febef5 5293#ifdef TARGET_NR_waitpid
31e31b8a
FB
5294 case TARGET_NR_waitpid:
5295 {
53a5960a
PB
5296 int status;
5297 ret = get_errno(waitpid(arg1, &status, arg3));
5379557b 5298 if (!is_error(ret) && arg2 && ret
1d9d8b55 5299 && put_user_s32(host_to_target_waitstatus(status), arg2))
2f619698 5300 goto efault;
31e31b8a
FB
5301 }
5302 break;
e5febef5 5303#endif
f0cbb613
PB
5304#ifdef TARGET_NR_waitid
5305 case TARGET_NR_waitid:
5306 {
5307 siginfo_t info;
5308 info.si_pid = 0;
5309 ret = get_errno(waitid(arg1, arg2, &info, arg4));
5310 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 5311 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
f0cbb613
PB
5312 goto efault;
5313 host_to_target_siginfo(p, &info);
c227f099 5314 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
5315 }
5316 }
5317 break;
5318#endif
7a3148a9 5319#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 5320 case TARGET_NR_creat:
579a97f7
FB
5321 if (!(p = lock_user_string(arg1)))
5322 goto efault;
53a5960a
PB
5323 ret = get_errno(creat(p, arg2));
5324 unlock_user(p, arg1, 0);
31e31b8a 5325 break;
7a3148a9 5326#endif
31e31b8a 5327 case TARGET_NR_link:
53a5960a
PB
5328 {
5329 void * p2;
5330 p = lock_user_string(arg1);
5331 p2 = lock_user_string(arg2);
579a97f7
FB
5332 if (!p || !p2)
5333 ret = -TARGET_EFAULT;
5334 else
5335 ret = get_errno(link(p, p2));
53a5960a
PB
5336 unlock_user(p2, arg2, 0);
5337 unlock_user(p, arg1, 0);
5338 }
31e31b8a 5339 break;
c0d472b1 5340#if defined(TARGET_NR_linkat)
64f0ce4c 5341 case TARGET_NR_linkat:
64f0ce4c
TS
5342 {
5343 void * p2 = NULL;
579a97f7
FB
5344 if (!arg2 || !arg4)
5345 goto efault;
64f0ce4c
TS
5346 p = lock_user_string(arg2);
5347 p2 = lock_user_string(arg4);
579a97f7 5348 if (!p || !p2)
0da46a6e 5349 ret = -TARGET_EFAULT;
64f0ce4c 5350 else
c0d472b1 5351 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
5352 unlock_user(p, arg2, 0);
5353 unlock_user(p2, arg4, 0);
64f0ce4c
TS
5354 }
5355 break;
5356#endif
31e31b8a 5357 case TARGET_NR_unlink:
579a97f7
FB
5358 if (!(p = lock_user_string(arg1)))
5359 goto efault;
53a5960a
PB
5360 ret = get_errno(unlink(p));
5361 unlock_user(p, arg1, 0);
31e31b8a 5362 break;
c0d472b1 5363#if defined(TARGET_NR_unlinkat)
8170f56b 5364 case TARGET_NR_unlinkat:
579a97f7
FB
5365 if (!(p = lock_user_string(arg2)))
5366 goto efault;
c0d472b1 5367 ret = get_errno(unlinkat(arg1, p, arg3));
579a97f7 5368 unlock_user(p, arg2, 0);
ed494d87 5369 break;
b7d35e65 5370#endif
31e31b8a 5371 case TARGET_NR_execve:
7854b056
FB
5372 {
5373 char **argp, **envp;
f7341ff4 5374 int argc, envc;
992f48a0
BS
5375 abi_ulong gp;
5376 abi_ulong guest_argp;
5377 abi_ulong guest_envp;
5378 abi_ulong addr;
7854b056 5379 char **q;
a6f79cc9 5380 int total_size = 0;
7854b056 5381
f7341ff4 5382 argc = 0;
53a5960a 5383 guest_argp = arg2;
da94d263 5384 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 5385 if (get_user_ual(addr, gp))
2f619698 5386 goto efault;
03aa1976 5387 if (!addr)
2f619698 5388 break;
7854b056 5389 argc++;
2f619698 5390 }
f7341ff4 5391 envc = 0;
53a5960a 5392 guest_envp = arg3;
da94d263 5393 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 5394 if (get_user_ual(addr, gp))
2f619698 5395 goto efault;
03aa1976 5396 if (!addr)
2f619698 5397 break;
7854b056 5398 envc++;
2f619698 5399 }
7854b056 5400
f7341ff4
FB
5401 argp = alloca((argc + 1) * sizeof(void *));
5402 envp = alloca((envc + 1) * sizeof(void *));
7854b056 5403
da94d263 5404 for (gp = guest_argp, q = argp; gp;
992f48a0 5405 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5406 if (get_user_ual(addr, gp))
5407 goto execve_efault;
53a5960a
PB
5408 if (!addr)
5409 break;
2f619698
FB
5410 if (!(*q = lock_user_string(addr)))
5411 goto execve_efault;
a6f79cc9 5412 total_size += strlen(*q) + 1;
53a5960a 5413 }
f7341ff4
FB
5414 *q = NULL;
5415
da94d263 5416 for (gp = guest_envp, q = envp; gp;
992f48a0 5417 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5418 if (get_user_ual(addr, gp))
5419 goto execve_efault;
53a5960a
PB
5420 if (!addr)
5421 break;
2f619698
FB
5422 if (!(*q = lock_user_string(addr)))
5423 goto execve_efault;
a6f79cc9 5424 total_size += strlen(*q) + 1;
53a5960a 5425 }
f7341ff4 5426 *q = NULL;
7854b056 5427
a6f79cc9
UH
5428 /* This case will not be caught by the host's execve() if its
5429 page size is bigger than the target's. */
5430 if (total_size > MAX_ARG_PAGES * TARGET_PAGE_SIZE) {
5431 ret = -TARGET_E2BIG;
5432 goto execve_end;
5433 }
2f619698
FB
5434 if (!(p = lock_user_string(arg1)))
5435 goto execve_efault;
53a5960a
PB
5436 ret = get_errno(execve(p, argp, envp));
5437 unlock_user(p, arg1, 0);
5438
2f619698
FB
5439 goto execve_end;
5440
5441 execve_efault:
5442 ret = -TARGET_EFAULT;
5443
5444 execve_end:
53a5960a 5445 for (gp = guest_argp, q = argp; *q;
992f48a0 5446 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5447 if (get_user_ual(addr, gp)
5448 || !addr)
5449 break;
53a5960a
PB
5450 unlock_user(*q, addr, 0);
5451 }
5452 for (gp = guest_envp, q = envp; *q;
992f48a0 5453 gp += sizeof(abi_ulong), q++) {
2f619698
FB
5454 if (get_user_ual(addr, gp)
5455 || !addr)
5456 break;
53a5960a
PB
5457 unlock_user(*q, addr, 0);
5458 }
7854b056 5459 }
31e31b8a
FB
5460 break;
5461 case TARGET_NR_chdir:
579a97f7
FB
5462 if (!(p = lock_user_string(arg1)))
5463 goto efault;
53a5960a
PB
5464 ret = get_errno(chdir(p));
5465 unlock_user(p, arg1, 0);
31e31b8a 5466 break;
a315a145 5467#ifdef TARGET_NR_time
31e31b8a
FB
5468 case TARGET_NR_time:
5469 {
53a5960a
PB
5470 time_t host_time;
5471 ret = get_errno(time(&host_time));
2f619698
FB
5472 if (!is_error(ret)
5473 && arg1
5474 && put_user_sal(host_time, arg1))
5475 goto efault;
31e31b8a
FB
5476 }
5477 break;
a315a145 5478#endif
31e31b8a 5479 case TARGET_NR_mknod:
579a97f7
FB
5480 if (!(p = lock_user_string(arg1)))
5481 goto efault;
53a5960a
PB
5482 ret = get_errno(mknod(p, arg2, arg3));
5483 unlock_user(p, arg1, 0);
31e31b8a 5484 break;
c0d472b1 5485#if defined(TARGET_NR_mknodat)
75ac37a0 5486 case TARGET_NR_mknodat:
579a97f7
FB
5487 if (!(p = lock_user_string(arg2)))
5488 goto efault;
c0d472b1 5489 ret = get_errno(mknodat(arg1, p, arg3, arg4));
579a97f7 5490 unlock_user(p, arg2, 0);
75ac37a0
TS
5491 break;
5492#endif
31e31b8a 5493 case TARGET_NR_chmod:
579a97f7
FB
5494 if (!(p = lock_user_string(arg1)))
5495 goto efault;
53a5960a
PB
5496 ret = get_errno(chmod(p, arg2));
5497 unlock_user(p, arg1, 0);
31e31b8a 5498 break;
ebc05488 5499#ifdef TARGET_NR_break
31e31b8a
FB
5500 case TARGET_NR_break:
5501 goto unimplemented;
ebc05488
FB
5502#endif
5503#ifdef TARGET_NR_oldstat
31e31b8a
FB
5504 case TARGET_NR_oldstat:
5505 goto unimplemented;
ebc05488 5506#endif
31e31b8a
FB
5507 case TARGET_NR_lseek:
5508 ret = get_errno(lseek(arg1, arg2, arg3));
5509 break;
9231733a
RH
5510#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
5511 /* Alpha specific */
7a3148a9 5512 case TARGET_NR_getxpid:
9231733a
RH
5513 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
5514 ret = get_errno(getpid());
5515 break;
7a3148a9 5516#endif
9231733a
RH
5517#ifdef TARGET_NR_getpid
5518 case TARGET_NR_getpid:
31e31b8a
FB
5519 ret = get_errno(getpid());
5520 break;
9231733a 5521#endif
31e31b8a 5522 case TARGET_NR_mount:
80265918
TS
5523 {
5524 /* need to look at the data field */
5525 void *p2, *p3;
5526 p = lock_user_string(arg1);
5527 p2 = lock_user_string(arg2);
5528 p3 = lock_user_string(arg3);
579a97f7
FB
5529 if (!p || !p2 || !p3)
5530 ret = -TARGET_EFAULT;
dab46405 5531 else {
579a97f7
FB
5532 /* FIXME - arg5 should be locked, but it isn't clear how to
5533 * do that since it's not guaranteed to be a NULL-terminated
5534 * string.
5535 */
dab46405
JSM
5536 if ( ! arg5 )
5537 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL));
5538 else
5539 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
5540 }
579a97f7
FB
5541 unlock_user(p, arg1, 0);
5542 unlock_user(p2, arg2, 0);
5543 unlock_user(p3, arg3, 0);
80265918
TS
5544 break;
5545 }
e5febef5 5546#ifdef TARGET_NR_umount
31e31b8a 5547 case TARGET_NR_umount:
579a97f7
FB
5548 if (!(p = lock_user_string(arg1)))
5549 goto efault;
53a5960a
PB
5550 ret = get_errno(umount(p));
5551 unlock_user(p, arg1, 0);
31e31b8a 5552 break;
e5febef5 5553#endif
7a3148a9 5554#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
5555 case TARGET_NR_stime:
5556 {
53a5960a 5557 time_t host_time;
2f619698
FB
5558 if (get_user_sal(host_time, arg1))
5559 goto efault;
53a5960a 5560 ret = get_errno(stime(&host_time));
31e31b8a
FB
5561 }
5562 break;
7a3148a9 5563#endif
31e31b8a
FB
5564 case TARGET_NR_ptrace:
5565 goto unimplemented;
7a3148a9 5566#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a
FB
5567 case TARGET_NR_alarm:
5568 ret = alarm(arg1);
5569 break;
7a3148a9 5570#endif
ebc05488 5571#ifdef TARGET_NR_oldfstat
31e31b8a
FB
5572 case TARGET_NR_oldfstat:
5573 goto unimplemented;
ebc05488 5574#endif
7a3148a9 5575#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a
FB
5576 case TARGET_NR_pause:
5577 ret = get_errno(pause());
5578 break;
7a3148a9 5579#endif
e5febef5 5580#ifdef TARGET_NR_utime
31e31b8a 5581 case TARGET_NR_utime:
ebc05488 5582 {
53a5960a
PB
5583 struct utimbuf tbuf, *host_tbuf;
5584 struct target_utimbuf *target_tbuf;
5585 if (arg2) {
579a97f7
FB
5586 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
5587 goto efault;
cbb21eed
MB
5588 tbuf.actime = tswapal(target_tbuf->actime);
5589 tbuf.modtime = tswapal(target_tbuf->modtime);
53a5960a
PB
5590 unlock_user_struct(target_tbuf, arg2, 0);
5591 host_tbuf = &tbuf;
f72e8ff4 5592 } else {
53a5960a 5593 host_tbuf = NULL;
f72e8ff4 5594 }
579a97f7
FB
5595 if (!(p = lock_user_string(arg1)))
5596 goto efault;
53a5960a
PB
5597 ret = get_errno(utime(p, host_tbuf));
5598 unlock_user(p, arg1, 0);
ebc05488
FB
5599 }
5600 break;
e5febef5 5601#endif
978a66ff
FB
5602 case TARGET_NR_utimes:
5603 {
978a66ff 5604 struct timeval *tvp, tv[2];
53a5960a 5605 if (arg2) {
788f5ec4
TS
5606 if (copy_from_user_timeval(&tv[0], arg2)
5607 || copy_from_user_timeval(&tv[1],
5608 arg2 + sizeof(struct target_timeval)))
5609 goto efault;
978a66ff
FB
5610 tvp = tv;
5611 } else {
5612 tvp = NULL;
5613 }
579a97f7
FB
5614 if (!(p = lock_user_string(arg1)))
5615 goto efault;
53a5960a
PB
5616 ret = get_errno(utimes(p, tvp));
5617 unlock_user(p, arg1, 0);
978a66ff
FB
5618 }
5619 break;
c0d472b1 5620#if defined(TARGET_NR_futimesat)
ac8a6556
AZ
5621 case TARGET_NR_futimesat:
5622 {
5623 struct timeval *tvp, tv[2];
5624 if (arg3) {
5625 if (copy_from_user_timeval(&tv[0], arg3)
5626 || copy_from_user_timeval(&tv[1],
5627 arg3 + sizeof(struct target_timeval)))
5628 goto efault;
5629 tvp = tv;
5630 } else {
5631 tvp = NULL;
5632 }
5633 if (!(p = lock_user_string(arg2)))
5634 goto efault;
c0d472b1 5635 ret = get_errno(futimesat(arg1, path(p), tvp));
ac8a6556
AZ
5636 unlock_user(p, arg2, 0);
5637 }
5638 break;
5639#endif
ebc05488 5640#ifdef TARGET_NR_stty
31e31b8a
FB
5641 case TARGET_NR_stty:
5642 goto unimplemented;
ebc05488
FB
5643#endif
5644#ifdef TARGET_NR_gtty
31e31b8a
FB
5645 case TARGET_NR_gtty:
5646 goto unimplemented;
ebc05488 5647#endif
31e31b8a 5648 case TARGET_NR_access:
579a97f7
FB
5649 if (!(p = lock_user_string(arg1)))
5650 goto efault;
719f908e 5651 ret = get_errno(access(path(p), arg2));
53a5960a 5652 unlock_user(p, arg1, 0);
31e31b8a 5653 break;
92a34c10
TS
5654#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
5655 case TARGET_NR_faccessat:
579a97f7
FB
5656 if (!(p = lock_user_string(arg2)))
5657 goto efault;
c0d472b1 5658 ret = get_errno(faccessat(arg1, p, arg3, 0));
579a97f7 5659 unlock_user(p, arg2, 0);
92a34c10
TS
5660 break;
5661#endif
7a3148a9 5662#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a
FB
5663 case TARGET_NR_nice:
5664 ret = get_errno(nice(arg1));
5665 break;
7a3148a9 5666#endif
ebc05488 5667#ifdef TARGET_NR_ftime
31e31b8a
FB
5668 case TARGET_NR_ftime:
5669 goto unimplemented;
ebc05488 5670#endif
31e31b8a 5671 case TARGET_NR_sync:
04369ff2
FB
5672 sync();
5673 ret = 0;
31e31b8a
FB
5674 break;
5675 case TARGET_NR_kill:
4cb05961 5676 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
31e31b8a
FB
5677 break;
5678 case TARGET_NR_rename:
53a5960a
PB
5679 {
5680 void *p2;
5681 p = lock_user_string(arg1);
5682 p2 = lock_user_string(arg2);
579a97f7
FB
5683 if (!p || !p2)
5684 ret = -TARGET_EFAULT;
5685 else
5686 ret = get_errno(rename(p, p2));
53a5960a
PB
5687 unlock_user(p2, arg2, 0);
5688 unlock_user(p, arg1, 0);
5689 }
31e31b8a 5690 break;
c0d472b1 5691#if defined(TARGET_NR_renameat)
722183f6 5692 case TARGET_NR_renameat:
722183f6 5693 {
579a97f7 5694 void *p2;
722183f6
TS
5695 p = lock_user_string(arg2);
5696 p2 = lock_user_string(arg4);
579a97f7 5697 if (!p || !p2)
0da46a6e 5698 ret = -TARGET_EFAULT;
722183f6 5699 else
c0d472b1 5700 ret = get_errno(renameat(arg1, p, arg3, p2));
579a97f7
FB
5701 unlock_user(p2, arg4, 0);
5702 unlock_user(p, arg2, 0);
722183f6
TS
5703 }
5704 break;
5705#endif
31e31b8a 5706 case TARGET_NR_mkdir:
579a97f7
FB
5707 if (!(p = lock_user_string(arg1)))
5708 goto efault;
53a5960a
PB
5709 ret = get_errno(mkdir(p, arg2));
5710 unlock_user(p, arg1, 0);
31e31b8a 5711 break;
c0d472b1 5712#if defined(TARGET_NR_mkdirat)
4472ad0d 5713 case TARGET_NR_mkdirat:
579a97f7
FB
5714 if (!(p = lock_user_string(arg2)))
5715 goto efault;
c0d472b1 5716 ret = get_errno(mkdirat(arg1, p, arg3));
579a97f7 5717 unlock_user(p, arg2, 0);
4472ad0d
TS
5718 break;
5719#endif
31e31b8a 5720 case TARGET_NR_rmdir:
579a97f7
FB
5721 if (!(p = lock_user_string(arg1)))
5722 goto efault;
53a5960a
PB
5723 ret = get_errno(rmdir(p));
5724 unlock_user(p, arg1, 0);
31e31b8a
FB
5725 break;
5726 case TARGET_NR_dup:
5727 ret = get_errno(dup(arg1));
5728 break;
5729 case TARGET_NR_pipe:
fb41a66e 5730 ret = do_pipe(cpu_env, arg1, 0, 0);
099d6b0f
RV
5731 break;
5732#ifdef TARGET_NR_pipe2
5733 case TARGET_NR_pipe2:
e7ea6cbe
RH
5734 ret = do_pipe(cpu_env, arg1,
5735 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
31e31b8a 5736 break;
099d6b0f 5737#endif
31e31b8a 5738 case TARGET_NR_times:
32f36bce 5739 {
53a5960a 5740 struct target_tms *tmsp;
32f36bce
FB
5741 struct tms tms;
5742 ret = get_errno(times(&tms));
53a5960a 5743 if (arg1) {
579a97f7
FB
5744 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
5745 if (!tmsp)
5746 goto efault;
cbb21eed
MB
5747 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
5748 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
5749 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
5750 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
32f36bce 5751 }
c596ed17
FB
5752 if (!is_error(ret))
5753 ret = host_to_target_clock_t(ret);
32f36bce
FB
5754 }
5755 break;
ebc05488 5756#ifdef TARGET_NR_prof
31e31b8a
FB
5757 case TARGET_NR_prof:
5758 goto unimplemented;
ebc05488 5759#endif
e5febef5 5760#ifdef TARGET_NR_signal
31e31b8a
FB
5761 case TARGET_NR_signal:
5762 goto unimplemented;
e5febef5 5763#endif
31e31b8a 5764 case TARGET_NR_acct:
38d840e6
AJ
5765 if (arg1 == 0) {
5766 ret = get_errno(acct(NULL));
5767 } else {
5768 if (!(p = lock_user_string(arg1)))
5769 goto efault;
5770 ret = get_errno(acct(path(p)));
5771 unlock_user(p, arg1, 0);
5772 }
24836689 5773 break;
8070e7be 5774#ifdef TARGET_NR_umount2
31e31b8a 5775 case TARGET_NR_umount2:
579a97f7
FB
5776 if (!(p = lock_user_string(arg1)))
5777 goto efault;
53a5960a
PB
5778 ret = get_errno(umount2(p, arg2));
5779 unlock_user(p, arg1, 0);
31e31b8a 5780 break;
7a3148a9 5781#endif
ebc05488 5782#ifdef TARGET_NR_lock
31e31b8a
FB
5783 case TARGET_NR_lock:
5784 goto unimplemented;
ebc05488 5785#endif
31e31b8a
FB
5786 case TARGET_NR_ioctl:
5787 ret = do_ioctl(arg1, arg2, arg3);
5788 break;
5789 case TARGET_NR_fcntl:
9ee1fa2c 5790 ret = do_fcntl(arg1, arg2, arg3);
31e31b8a 5791 break;
ebc05488 5792#ifdef TARGET_NR_mpx
31e31b8a
FB
5793 case TARGET_NR_mpx:
5794 goto unimplemented;
ebc05488 5795#endif
31e31b8a
FB
5796 case TARGET_NR_setpgid:
5797 ret = get_errno(setpgid(arg1, arg2));
5798 break;
ebc05488 5799#ifdef TARGET_NR_ulimit
31e31b8a
FB
5800 case TARGET_NR_ulimit:
5801 goto unimplemented;
ebc05488
FB
5802#endif
5803#ifdef TARGET_NR_oldolduname
31e31b8a
FB
5804 case TARGET_NR_oldolduname:
5805 goto unimplemented;
ebc05488 5806#endif
31e31b8a
FB
5807 case TARGET_NR_umask:
5808 ret = get_errno(umask(arg1));
5809 break;
5810 case TARGET_NR_chroot:
579a97f7
FB
5811 if (!(p = lock_user_string(arg1)))
5812 goto efault;
53a5960a
PB
5813 ret = get_errno(chroot(p));
5814 unlock_user(p, arg1, 0);
31e31b8a
FB
5815 break;
5816 case TARGET_NR_ustat:
5817 goto unimplemented;
5818 case TARGET_NR_dup2:
5819 ret = get_errno(dup2(arg1, arg2));
5820 break;
d0927938
UH
5821#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
5822 case TARGET_NR_dup3:
5823 ret = get_errno(dup3(arg1, arg2, arg3));
5824 break;
5825#endif
7a3148a9 5826#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a
FB
5827 case TARGET_NR_getppid:
5828 ret = get_errno(getppid());
5829 break;
7a3148a9 5830#endif
31e31b8a
FB
5831 case TARGET_NR_getpgrp:
5832 ret = get_errno(getpgrp());
5833 break;
5834 case TARGET_NR_setsid:
5835 ret = get_errno(setsid());
5836 break;
e5febef5 5837#ifdef TARGET_NR_sigaction
31e31b8a 5838 case TARGET_NR_sigaction:
31e31b8a 5839 {
6049f4f8
RH
5840#if defined(TARGET_ALPHA)
5841 struct target_sigaction act, oact, *pact = 0;
53a5960a 5842 struct target_old_sigaction *old_act;
53a5960a 5843 if (arg2) {
579a97f7
FB
5844 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5845 goto efault;
66fb9763
FB
5846 act._sa_handler = old_act->_sa_handler;
5847 target_siginitset(&act.sa_mask, old_act->sa_mask);
5848 act.sa_flags = old_act->sa_flags;
6049f4f8 5849 act.sa_restorer = 0;
53a5960a 5850 unlock_user_struct(old_act, arg2, 0);
66fb9763 5851 pact = &act;
66fb9763
FB
5852 }
5853 ret = get_errno(do_sigaction(arg1, pact, &oact));
53a5960a 5854 if (!is_error(ret) && arg3) {
579a97f7
FB
5855 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5856 goto efault;
53a5960a
PB
5857 old_act->_sa_handler = oact._sa_handler;
5858 old_act->sa_mask = oact.sa_mask.sig[0];
5859 old_act->sa_flags = oact.sa_flags;
53a5960a 5860 unlock_user_struct(old_act, arg3, 1);
66fb9763 5861 }
6049f4f8 5862#elif defined(TARGET_MIPS)
106ec879
FB
5863 struct target_sigaction act, oact, *pact, *old_act;
5864
5865 if (arg2) {
579a97f7
FB
5866 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5867 goto efault;
106ec879
FB
5868 act._sa_handler = old_act->_sa_handler;
5869 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
5870 act.sa_flags = old_act->sa_flags;
5871 unlock_user_struct(old_act, arg2, 0);
5872 pact = &act;
5873 } else {
5874 pact = NULL;
5875 }
5876
5877 ret = get_errno(do_sigaction(arg1, pact, &oact));
5878
5879 if (!is_error(ret) && arg3) {
579a97f7
FB
5880 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5881 goto efault;
106ec879
FB
5882 old_act->_sa_handler = oact._sa_handler;
5883 old_act->sa_flags = oact.sa_flags;
5884 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
5885 old_act->sa_mask.sig[1] = 0;
5886 old_act->sa_mask.sig[2] = 0;
5887 old_act->sa_mask.sig[3] = 0;
5888 unlock_user_struct(old_act, arg3, 1);
5889 }
6049f4f8
RH
5890#else
5891 struct target_old_sigaction *old_act;
5892 struct target_sigaction act, oact, *pact;
5893 if (arg2) {
5894 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5895 goto efault;
5896 act._sa_handler = old_act->_sa_handler;
5897 target_siginitset(&act.sa_mask, old_act->sa_mask);
5898 act.sa_flags = old_act->sa_flags;
5899 act.sa_restorer = old_act->sa_restorer;
5900 unlock_user_struct(old_act, arg2, 0);
5901 pact = &act;
5902 } else {
5903 pact = NULL;
5904 }
5905 ret = get_errno(do_sigaction(arg1, pact, &oact));
5906 if (!is_error(ret) && arg3) {
5907 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5908 goto efault;
5909 old_act->_sa_handler = oact._sa_handler;
5910 old_act->sa_mask = oact.sa_mask.sig[0];
5911 old_act->sa_flags = oact.sa_flags;
5912 old_act->sa_restorer = oact.sa_restorer;
5913 unlock_user_struct(old_act, arg3, 1);
5914 }
388bb21a 5915#endif
31e31b8a
FB
5916 }
5917 break;
e5febef5 5918#endif
66fb9763 5919 case TARGET_NR_rt_sigaction:
53a5960a 5920 {
6049f4f8
RH
5921#if defined(TARGET_ALPHA)
5922 struct target_sigaction act, oact, *pact = 0;
5923 struct target_rt_sigaction *rt_act;
5924 /* ??? arg4 == sizeof(sigset_t). */
5925 if (arg2) {
5926 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
5927 goto efault;
5928 act._sa_handler = rt_act->_sa_handler;
5929 act.sa_mask = rt_act->sa_mask;
5930 act.sa_flags = rt_act->sa_flags;
5931 act.sa_restorer = arg5;
5932 unlock_user_struct(rt_act, arg2, 0);
5933 pact = &act;
5934 }
5935 ret = get_errno(do_sigaction(arg1, pact, &oact));
5936 if (!is_error(ret) && arg3) {
5937 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
5938 goto efault;
5939 rt_act->_sa_handler = oact._sa_handler;
5940 rt_act->sa_mask = oact.sa_mask;
5941 rt_act->sa_flags = oact.sa_flags;
5942 unlock_user_struct(rt_act, arg3, 1);
5943 }
5944#else
53a5960a
PB
5945 struct target_sigaction *act;
5946 struct target_sigaction *oact;
5947
579a97f7
FB
5948 if (arg2) {
5949 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
5950 goto efault;
5951 } else
53a5960a 5952 act = NULL;
579a97f7
FB
5953 if (arg3) {
5954 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
5955 ret = -TARGET_EFAULT;
5956 goto rt_sigaction_fail;
5957 }
5958 } else
53a5960a
PB
5959 oact = NULL;
5960 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
5961 rt_sigaction_fail:
5962 if (act)
53a5960a 5963 unlock_user_struct(act, arg2, 0);
579a97f7 5964 if (oact)
53a5960a 5965 unlock_user_struct(oact, arg3, 1);
6049f4f8 5966#endif
53a5960a 5967 }
66fb9763 5968 break;
7a3148a9 5969#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 5970 case TARGET_NR_sgetmask:
66fb9763
FB
5971 {
5972 sigset_t cur_set;
992f48a0 5973 abi_ulong target_set;
1c275925 5974 do_sigprocmask(0, NULL, &cur_set);
66fb9763
FB
5975 host_to_target_old_sigset(&target_set, &cur_set);
5976 ret = target_set;
5977 }
5978 break;
7a3148a9
JM
5979#endif
5980#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 5981 case TARGET_NR_ssetmask:
66fb9763
FB
5982 {
5983 sigset_t set, oset, cur_set;
992f48a0 5984 abi_ulong target_set = arg1;
1c275925 5985 do_sigprocmask(0, NULL, &cur_set);
66fb9763
FB
5986 target_to_host_old_sigset(&set, &target_set);
5987 sigorset(&set, &set, &cur_set);
1c275925 5988 do_sigprocmask(SIG_SETMASK, &set, &oset);
66fb9763
FB
5989 host_to_target_old_sigset(&target_set, &oset);
5990 ret = target_set;
5991 }
5992 break;
7a3148a9 5993#endif
e5febef5 5994#ifdef TARGET_NR_sigprocmask
66fb9763
FB
5995 case TARGET_NR_sigprocmask:
5996 {
a5b3b13b
RH
5997#if defined(TARGET_ALPHA)
5998 sigset_t set, oldset;
5999 abi_ulong mask;
6000 int how;
6001
6002 switch (arg1) {
6003 case TARGET_SIG_BLOCK:
6004 how = SIG_BLOCK;
6005 break;
6006 case TARGET_SIG_UNBLOCK:
6007 how = SIG_UNBLOCK;
6008 break;
6009 case TARGET_SIG_SETMASK:
6010 how = SIG_SETMASK;
6011 break;
6012 default:
6013 ret = -TARGET_EINVAL;
6014 goto fail;
6015 }
6016 mask = arg2;
6017 target_to_host_old_sigset(&set, &mask);
6018
1c275925 6019 ret = get_errno(do_sigprocmask(how, &set, &oldset));
a5b3b13b
RH
6020 if (!is_error(ret)) {
6021 host_to_target_old_sigset(&mask, &oldset);
6022 ret = mask;
0229f5a3 6023 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
6024 }
6025#else
66fb9763 6026 sigset_t set, oldset, *set_ptr;
a5b3b13b 6027 int how;
3b46e624 6028
53a5960a 6029 if (arg2) {
a5b3b13b 6030 switch (arg1) {
66fb9763
FB
6031 case TARGET_SIG_BLOCK:
6032 how = SIG_BLOCK;
6033 break;
6034 case TARGET_SIG_UNBLOCK:
6035 how = SIG_UNBLOCK;
6036 break;
6037 case TARGET_SIG_SETMASK:
6038 how = SIG_SETMASK;
6039 break;
6040 default:
0da46a6e 6041 ret = -TARGET_EINVAL;
66fb9763
FB
6042 goto fail;
6043 }
c227f099 6044 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 6045 goto efault;
53a5960a
PB
6046 target_to_host_old_sigset(&set, p);
6047 unlock_user(p, arg2, 0);
66fb9763
FB
6048 set_ptr = &set;
6049 } else {
6050 how = 0;
6051 set_ptr = NULL;
6052 }
1c275925 6053 ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
53a5960a 6054 if (!is_error(ret) && arg3) {
c227f099 6055 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 6056 goto efault;
53a5960a 6057 host_to_target_old_sigset(p, &oldset);
c227f099 6058 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 6059 }
a5b3b13b 6060#endif
66fb9763
FB
6061 }
6062 break;
e5febef5 6063#endif
66fb9763
FB
6064 case TARGET_NR_rt_sigprocmask:
6065 {
6066 int how = arg1;
6067 sigset_t set, oldset, *set_ptr;
3b46e624 6068
53a5960a 6069 if (arg2) {
66fb9763
FB
6070 switch(how) {
6071 case TARGET_SIG_BLOCK:
6072 how = SIG_BLOCK;
6073 break;
6074 case TARGET_SIG_UNBLOCK:
6075 how = SIG_UNBLOCK;
6076 break;
6077 case TARGET_SIG_SETMASK:
6078 how = SIG_SETMASK;
6079 break;
6080 default:
0da46a6e 6081 ret = -TARGET_EINVAL;
66fb9763
FB
6082 goto fail;
6083 }
c227f099 6084 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 6085 goto efault;
53a5960a
PB
6086 target_to_host_sigset(&set, p);
6087 unlock_user(p, arg2, 0);
66fb9763
FB
6088 set_ptr = &set;
6089 } else {
6090 how = 0;
6091 set_ptr = NULL;
6092 }
1c275925 6093 ret = get_errno(do_sigprocmask(how, set_ptr, &oldset));
53a5960a 6094 if (!is_error(ret) && arg3) {
c227f099 6095 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 6096 goto efault;
53a5960a 6097 host_to_target_sigset(p, &oldset);
c227f099 6098 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
6099 }
6100 }
6101 break;
e5febef5 6102#ifdef TARGET_NR_sigpending
66fb9763
FB
6103 case TARGET_NR_sigpending:
6104 {
6105 sigset_t set;
6106 ret = get_errno(sigpending(&set));
6107 if (!is_error(ret)) {
c227f099 6108 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 6109 goto efault;
53a5960a 6110 host_to_target_old_sigset(p, &set);
c227f099 6111 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
6112 }
6113 }
6114 break;
e5febef5 6115#endif
66fb9763
FB
6116 case TARGET_NR_rt_sigpending:
6117 {
6118 sigset_t set;
6119 ret = get_errno(sigpending(&set));
6120 if (!is_error(ret)) {
c227f099 6121 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 6122 goto efault;
53a5960a 6123 host_to_target_sigset(p, &set);
c227f099 6124 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
6125 }
6126 }
6127 break;
e5febef5 6128#ifdef TARGET_NR_sigsuspend
66fb9763
FB
6129 case TARGET_NR_sigsuspend:
6130 {
6131 sigset_t set;
f43ce12b
RH
6132#if defined(TARGET_ALPHA)
6133 abi_ulong mask = arg1;
6134 target_to_host_old_sigset(&set, &mask);
6135#else
c227f099 6136 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6137 goto efault;
53a5960a
PB
6138 target_to_host_old_sigset(&set, p);
6139 unlock_user(p, arg1, 0);
f43ce12b 6140#endif
66fb9763
FB
6141 ret = get_errno(sigsuspend(&set));
6142 }
6143 break;
e5febef5 6144#endif
66fb9763
FB
6145 case TARGET_NR_rt_sigsuspend:
6146 {
6147 sigset_t set;
c227f099 6148 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6149 goto efault;
53a5960a
PB
6150 target_to_host_sigset(&set, p);
6151 unlock_user(p, arg1, 0);
66fb9763
FB
6152 ret = get_errno(sigsuspend(&set));
6153 }
6154 break;
6155 case TARGET_NR_rt_sigtimedwait:
6156 {
66fb9763
FB
6157 sigset_t set;
6158 struct timespec uts, *puts;
6159 siginfo_t uinfo;
3b46e624 6160
c227f099 6161 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 6162 goto efault;
53a5960a
PB
6163 target_to_host_sigset(&set, p);
6164 unlock_user(p, arg1, 0);
6165 if (arg3) {
66fb9763 6166 puts = &uts;
53a5960a 6167 target_to_host_timespec(puts, arg3);
66fb9763
FB
6168 } else {
6169 puts = NULL;
6170 }
6171 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
974a196d
PJ
6172 if (!is_error(ret)) {
6173 if (arg2) {
6174 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
6175 0);
6176 if (!p) {
6177 goto efault;
6178 }
6179 host_to_target_siginfo(p, &uinfo);
6180 unlock_user(p, arg2, sizeof(target_siginfo_t));
6181 }
6182 ret = host_to_target_signal(ret);
66fb9763
FB
6183 }
6184 }
6185 break;
6186 case TARGET_NR_rt_sigqueueinfo:
6187 {
6188 siginfo_t uinfo;
c227f099 6189 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
579a97f7 6190 goto efault;
53a5960a
PB
6191 target_to_host_siginfo(&uinfo, p);
6192 unlock_user(p, arg1, 0);
66fb9763
FB
6193 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
6194 }
6195 break;
e5febef5 6196#ifdef TARGET_NR_sigreturn
66fb9763
FB
6197 case TARGET_NR_sigreturn:
6198 /* NOTE: ret is eax, so not transcoding must be done */
6199 ret = do_sigreturn(cpu_env);
6200 break;
e5febef5 6201#endif
66fb9763
FB
6202 case TARGET_NR_rt_sigreturn:
6203 /* NOTE: ret is eax, so not transcoding must be done */
6204 ret = do_rt_sigreturn(cpu_env);
6205 break;
31e31b8a 6206 case TARGET_NR_sethostname:
579a97f7
FB
6207 if (!(p = lock_user_string(arg1)))
6208 goto efault;
53a5960a
PB
6209 ret = get_errno(sethostname(p, arg2));
6210 unlock_user(p, arg1, 0);
31e31b8a
FB
6211 break;
6212 case TARGET_NR_setrlimit:
9de5e440 6213 {
e22b7015 6214 int resource = target_to_host_resource(arg1);
53a5960a 6215 struct target_rlimit *target_rlim;
9de5e440 6216 struct rlimit rlim;
579a97f7
FB
6217 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
6218 goto efault;
81bbe906
TY
6219 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
6220 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 6221 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
6222 ret = get_errno(setrlimit(resource, &rlim));
6223 }
6224 break;
31e31b8a 6225 case TARGET_NR_getrlimit:
9de5e440 6226 {
e22b7015 6227 int resource = target_to_host_resource(arg1);
53a5960a 6228 struct target_rlimit *target_rlim;
9de5e440 6229 struct rlimit rlim;
3b46e624 6230
9de5e440
FB
6231 ret = get_errno(getrlimit(resource, &rlim));
6232 if (!is_error(ret)) {
579a97f7
FB
6233 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6234 goto efault;
81bbe906
TY
6235 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
6236 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 6237 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
6238 }
6239 }
6240 break;
31e31b8a 6241 case TARGET_NR_getrusage:
b409186b
FB
6242 {
6243 struct rusage rusage;
b409186b
FB
6244 ret = get_errno(getrusage(arg1, &rusage));
6245 if (!is_error(ret)) {
a39fb273 6246 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
6247 }
6248 }
6249 break;
31e31b8a
FB
6250 case TARGET_NR_gettimeofday:
6251 {
31e31b8a
FB
6252 struct timeval tv;
6253 ret = get_errno(gettimeofday(&tv, NULL));
6254 if (!is_error(ret)) {
788f5ec4
TS
6255 if (copy_to_user_timeval(arg1, &tv))
6256 goto efault;
31e31b8a
FB
6257 }
6258 }
6259 break;
6260 case TARGET_NR_settimeofday:
6261 {
31e31b8a 6262 struct timeval tv;
788f5ec4
TS
6263 if (copy_from_user_timeval(&tv, arg1))
6264 goto efault;
31e31b8a
FB
6265 ret = get_errno(settimeofday(&tv, NULL));
6266 }
6267 break;
9468a5d4 6268#if defined(TARGET_NR_select)
31e31b8a 6269 case TARGET_NR_select:
9468a5d4
LV
6270#if defined(TARGET_S390X) || defined(TARGET_ALPHA)
6271 ret = do_select(arg1, arg2, arg3, arg4, arg5);
6272#else
f2674e31 6273 {
53a5960a 6274 struct target_sel_arg_struct *sel;
992f48a0 6275 abi_ulong inp, outp, exp, tvp;
53a5960a
PB
6276 long nsel;
6277
579a97f7
FB
6278 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
6279 goto efault;
cbb21eed
MB
6280 nsel = tswapal(sel->n);
6281 inp = tswapal(sel->inp);
6282 outp = tswapal(sel->outp);
6283 exp = tswapal(sel->exp);
6284 tvp = tswapal(sel->tvp);
53a5960a
PB
6285 unlock_user_struct(sel, arg1, 0);
6286 ret = do_select(nsel, inp, outp, exp, tvp);
f2674e31 6287 }
9468a5d4 6288#endif
f2674e31 6289 break;
9e42382f
RV
6290#endif
6291#ifdef TARGET_NR_pselect6
6292 case TARGET_NR_pselect6:
055e0906
MF
6293 {
6294 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
6295 fd_set rfds, wfds, efds;
6296 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
6297 struct timespec ts, *ts_ptr;
6298
6299 /*
6300 * The 6th arg is actually two args smashed together,
6301 * so we cannot use the C library.
6302 */
6303 sigset_t set;
6304 struct {
6305 sigset_t *set;
6306 size_t size;
6307 } sig, *sig_ptr;
6308
6309 abi_ulong arg_sigset, arg_sigsize, *arg7;
6310 target_sigset_t *target_sigset;
6311
6312 n = arg1;
6313 rfd_addr = arg2;
6314 wfd_addr = arg3;
6315 efd_addr = arg4;
6316 ts_addr = arg5;
6317
6318 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
6319 if (ret) {
6320 goto fail;
6321 }
6322 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
6323 if (ret) {
6324 goto fail;
6325 }
6326 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
6327 if (ret) {
6328 goto fail;
6329 }
6330
6331 /*
6332 * This takes a timespec, and not a timeval, so we cannot
6333 * use the do_select() helper ...
6334 */
6335 if (ts_addr) {
6336 if (target_to_host_timespec(&ts, ts_addr)) {
6337 goto efault;
6338 }
6339 ts_ptr = &ts;
6340 } else {
6341 ts_ptr = NULL;
6342 }
6343
6344 /* Extract the two packed args for the sigset */
6345 if (arg6) {
6346 sig_ptr = &sig;
6347 sig.size = _NSIG / 8;
6348
6349 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
6350 if (!arg7) {
6351 goto efault;
6352 }
cbb21eed
MB
6353 arg_sigset = tswapal(arg7[0]);
6354 arg_sigsize = tswapal(arg7[1]);
055e0906
MF
6355 unlock_user(arg7, arg6, 0);
6356
6357 if (arg_sigset) {
6358 sig.set = &set;
8f04eeb3
PM
6359 if (arg_sigsize != sizeof(*target_sigset)) {
6360 /* Like the kernel, we enforce correct size sigsets */
6361 ret = -TARGET_EINVAL;
6362 goto fail;
6363 }
055e0906
MF
6364 target_sigset = lock_user(VERIFY_READ, arg_sigset,
6365 sizeof(*target_sigset), 1);
6366 if (!target_sigset) {
6367 goto efault;
6368 }
6369 target_to_host_sigset(&set, target_sigset);
6370 unlock_user(target_sigset, arg_sigset, 0);
6371 } else {
6372 sig.set = NULL;
6373 }
6374 } else {
6375 sig_ptr = NULL;
6376 }
6377
6378 ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
6379 ts_ptr, sig_ptr));
6380
6381 if (!is_error(ret)) {
6382 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
6383 goto efault;
6384 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
6385 goto efault;
6386 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
6387 goto efault;
6388
6389 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
6390 goto efault;
6391 }
6392 }
6393 break;
048f6b4d 6394#endif
31e31b8a 6395 case TARGET_NR_symlink:
53a5960a
PB
6396 {
6397 void *p2;
6398 p = lock_user_string(arg1);
6399 p2 = lock_user_string(arg2);
579a97f7
FB
6400 if (!p || !p2)
6401 ret = -TARGET_EFAULT;
6402 else
6403 ret = get_errno(symlink(p, p2));
53a5960a
PB
6404 unlock_user(p2, arg2, 0);
6405 unlock_user(p, arg1, 0);
6406 }
31e31b8a 6407 break;
c0d472b1 6408#if defined(TARGET_NR_symlinkat)
f0b6243d 6409 case TARGET_NR_symlinkat:
f0b6243d 6410 {
579a97f7 6411 void *p2;
f0b6243d
TS
6412 p = lock_user_string(arg1);
6413 p2 = lock_user_string(arg3);
579a97f7 6414 if (!p || !p2)
0da46a6e 6415 ret = -TARGET_EFAULT;
f0b6243d 6416 else
c0d472b1 6417 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
6418 unlock_user(p2, arg3, 0);
6419 unlock_user(p, arg1, 0);
f0b6243d
TS
6420 }
6421 break;
6422#endif
ebc05488 6423#ifdef TARGET_NR_oldlstat
31e31b8a
FB
6424 case TARGET_NR_oldlstat:
6425 goto unimplemented;
ebc05488 6426#endif
31e31b8a 6427 case TARGET_NR_readlink:
53a5960a 6428 {
463d8e73 6429 void *p2;
53a5960a 6430 p = lock_user_string(arg1);
579a97f7 6431 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 6432 if (!p || !p2) {
579a97f7 6433 ret = -TARGET_EFAULT;
463d8e73
AS
6434 } else if (is_proc_myself((const char *)p, "exe")) {
6435 char real[PATH_MAX], *temp;
6436 temp = realpath(exec_path, real);
6437 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
6438 snprintf((char *)p2, arg3, "%s", real);
6439 } else {
6440 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 6441 }
53a5960a
PB
6442 unlock_user(p2, arg2, ret);
6443 unlock_user(p, arg1, 0);
6444 }
31e31b8a 6445 break;
c0d472b1 6446#if defined(TARGET_NR_readlinkat)
5e0ccb18 6447 case TARGET_NR_readlinkat:
5e0ccb18 6448 {
579a97f7 6449 void *p2;
5e0ccb18 6450 p = lock_user_string(arg2);
579a97f7 6451 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
6452 if (!p || !p2) {
6453 ret = -TARGET_EFAULT;
6454 } else if (is_proc_myself((const char *)p, "exe")) {
6455 char real[PATH_MAX], *temp;
6456 temp = realpath(exec_path, real);
6457 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
6458 snprintf((char *)p2, arg4, "%s", real);
6459 } else {
c0d472b1 6460 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 6461 }
579a97f7
FB
6462 unlock_user(p2, arg3, ret);
6463 unlock_user(p, arg2, 0);
5e0ccb18
TS
6464 }
6465 break;
6466#endif
e5febef5 6467#ifdef TARGET_NR_uselib
31e31b8a
FB
6468 case TARGET_NR_uselib:
6469 goto unimplemented;
e5febef5
TS
6470#endif
6471#ifdef TARGET_NR_swapon
31e31b8a 6472 case TARGET_NR_swapon:
579a97f7
FB
6473 if (!(p = lock_user_string(arg1)))
6474 goto efault;
53a5960a
PB
6475 ret = get_errno(swapon(p, arg2));
6476 unlock_user(p, arg1, 0);
31e31b8a 6477 break;
e5febef5 6478#endif
31e31b8a 6479 case TARGET_NR_reboot:
c07ecc68
LV
6480 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
6481 /* arg4 must be ignored in all other cases */
6482 p = lock_user_string(arg4);
6483 if (!p) {
6484 goto efault;
6485 }
6486 ret = get_errno(reboot(arg1, arg2, arg3, p));
6487 unlock_user(p, arg4, 0);
6488 } else {
6489 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
6490 }
0f6b4d21 6491 break;
e5febef5 6492#ifdef TARGET_NR_readdir
31e31b8a
FB
6493 case TARGET_NR_readdir:
6494 goto unimplemented;
e5febef5
TS
6495#endif
6496#ifdef TARGET_NR_mmap
31e31b8a 6497 case TARGET_NR_mmap:
09701199
AG
6498#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
6499 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
6500 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
6501 || defined(TARGET_S390X)
31e31b8a 6502 {
992f48a0
BS
6503 abi_ulong *v;
6504 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
6505 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
6506 goto efault;
cbb21eed
MB
6507 v1 = tswapal(v[0]);
6508 v2 = tswapal(v[1]);
6509 v3 = tswapal(v[2]);
6510 v4 = tswapal(v[3]);
6511 v5 = tswapal(v[4]);
6512 v6 = tswapal(v[5]);
53a5960a 6513 unlock_user(v, arg1, 0);
5fafdf24 6514 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
6515 target_to_host_bitmask(v4, mmap_flags_tbl),
6516 v5, v6));
31e31b8a 6517 }
31e31b8a 6518#else
5fafdf24
TS
6519 ret = get_errno(target_mmap(arg1, arg2, arg3,
6520 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
6521 arg5,
6522 arg6));
31e31b8a 6523#endif
6fb883e8 6524 break;
e5febef5 6525#endif
a315a145 6526#ifdef TARGET_NR_mmap2
6fb883e8 6527 case TARGET_NR_mmap2:
bb7ec043 6528#ifndef MMAP_SHIFT
c573ff67 6529#define MMAP_SHIFT 12
c573ff67 6530#endif
5fafdf24
TS
6531 ret = get_errno(target_mmap(arg1, arg2, arg3,
6532 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 6533 arg5,
c573ff67 6534 arg6 << MMAP_SHIFT));
31e31b8a 6535 break;
a315a145 6536#endif
31e31b8a 6537 case TARGET_NR_munmap:
54936004 6538 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 6539 break;
9de5e440 6540 case TARGET_NR_mprotect:
97374d38 6541 {
0429a971 6542 TaskState *ts = cpu->opaque;
97374d38
PB
6543 /* Special hack to detect libc making the stack executable. */
6544 if ((arg3 & PROT_GROWSDOWN)
6545 && arg1 >= ts->info->stack_limit
6546 && arg1 <= ts->info->start_stack) {
6547 arg3 &= ~PROT_GROWSDOWN;
6548 arg2 = arg2 + arg1 - ts->info->stack_limit;
6549 arg1 = ts->info->stack_limit;
6550 }
6551 }
54936004 6552 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 6553 break;
e5febef5 6554#ifdef TARGET_NR_mremap
9de5e440 6555 case TARGET_NR_mremap:
54936004 6556 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 6557 break;
e5febef5 6558#endif
53a5960a 6559 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 6560#ifdef TARGET_NR_msync
9de5e440 6561 case TARGET_NR_msync:
53a5960a 6562 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 6563 break;
e5febef5
TS
6564#endif
6565#ifdef TARGET_NR_mlock
9de5e440 6566 case TARGET_NR_mlock:
53a5960a 6567 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 6568 break;
e5febef5
TS
6569#endif
6570#ifdef TARGET_NR_munlock
9de5e440 6571 case TARGET_NR_munlock:
53a5960a 6572 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 6573 break;
e5febef5
TS
6574#endif
6575#ifdef TARGET_NR_mlockall
9de5e440
FB
6576 case TARGET_NR_mlockall:
6577 ret = get_errno(mlockall(arg1));
6578 break;
e5febef5
TS
6579#endif
6580#ifdef TARGET_NR_munlockall
9de5e440
FB
6581 case TARGET_NR_munlockall:
6582 ret = get_errno(munlockall());
6583 break;
e5febef5 6584#endif
31e31b8a 6585 case TARGET_NR_truncate:
579a97f7
FB
6586 if (!(p = lock_user_string(arg1)))
6587 goto efault;
53a5960a
PB
6588 ret = get_errno(truncate(p, arg2));
6589 unlock_user(p, arg1, 0);
31e31b8a
FB
6590 break;
6591 case TARGET_NR_ftruncate:
6592 ret = get_errno(ftruncate(arg1, arg2));
6593 break;
6594 case TARGET_NR_fchmod:
6595 ret = get_errno(fchmod(arg1, arg2));
6596 break;
c0d472b1 6597#if defined(TARGET_NR_fchmodat)
814d7977 6598 case TARGET_NR_fchmodat:
579a97f7
FB
6599 if (!(p = lock_user_string(arg2)))
6600 goto efault;
c0d472b1 6601 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 6602 unlock_user(p, arg2, 0);
814d7977
TS
6603 break;
6604#endif
31e31b8a 6605 case TARGET_NR_getpriority:
95c09828
RH
6606 /* Note that negative values are valid for getpriority, so we must
6607 differentiate based on errno settings. */
6608 errno = 0;
6609 ret = getpriority(arg1, arg2);
6610 if (ret == -1 && errno != 0) {
6611 ret = -host_to_target_errno(errno);
6612 break;
6613 }
6614#ifdef TARGET_ALPHA
6615 /* Return value is the unbiased priority. Signal no error. */
6616 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
6617#else
6618 /* Return value is a biased priority to avoid negative numbers. */
6619 ret = 20 - ret;
6620#endif
31e31b8a
FB
6621 break;
6622 case TARGET_NR_setpriority:
6623 ret = get_errno(setpriority(arg1, arg2, arg3));
6624 break;
ebc05488 6625#ifdef TARGET_NR_profil
31e31b8a
FB
6626 case TARGET_NR_profil:
6627 goto unimplemented;
ebc05488 6628#endif
31e31b8a 6629 case TARGET_NR_statfs:
579a97f7
FB
6630 if (!(p = lock_user_string(arg1)))
6631 goto efault;
53a5960a
PB
6632 ret = get_errno(statfs(path(p), &stfs));
6633 unlock_user(p, arg1, 0);
31e31b8a
FB
6634 convert_statfs:
6635 if (!is_error(ret)) {
53a5960a 6636 struct target_statfs *target_stfs;
3b46e624 6637
579a97f7
FB
6638 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
6639 goto efault;
6640 __put_user(stfs.f_type, &target_stfs->f_type);
6641 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
6642 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
6643 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
6644 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
6645 __put_user(stfs.f_files, &target_stfs->f_files);
6646 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
6647 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
6648 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
6649 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
6650 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
6651 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 6652 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
6653 }
6654 break;
6655 case TARGET_NR_fstatfs:
56c8f68f 6656 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 6657 goto convert_statfs;
56c8f68f
FB
6658#ifdef TARGET_NR_statfs64
6659 case TARGET_NR_statfs64:
579a97f7
FB
6660 if (!(p = lock_user_string(arg1)))
6661 goto efault;
53a5960a
PB
6662 ret = get_errno(statfs(path(p), &stfs));
6663 unlock_user(p, arg1, 0);
56c8f68f
FB
6664 convert_statfs64:
6665 if (!is_error(ret)) {
53a5960a 6666 struct target_statfs64 *target_stfs;
3b46e624 6667
579a97f7
FB
6668 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
6669 goto efault;
6670 __put_user(stfs.f_type, &target_stfs->f_type);
6671 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
6672 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
6673 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
6674 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
6675 __put_user(stfs.f_files, &target_stfs->f_files);
6676 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
6677 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
6678 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
6679 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
6680 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
6681 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 6682 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
6683 }
6684 break;
6685 case TARGET_NR_fstatfs64:
6686 ret = get_errno(fstatfs(arg1, &stfs));
6687 goto convert_statfs64;
6688#endif
ebc05488 6689#ifdef TARGET_NR_ioperm
31e31b8a
FB
6690 case TARGET_NR_ioperm:
6691 goto unimplemented;
ebc05488 6692#endif
e5febef5 6693#ifdef TARGET_NR_socketcall
31e31b8a 6694 case TARGET_NR_socketcall:
53a5960a 6695 ret = do_socketcall(arg1, arg2);
31e31b8a 6696 break;
e5febef5 6697#endif
3532fa74
FB
6698#ifdef TARGET_NR_accept
6699 case TARGET_NR_accept:
a94b4987
PM
6700 ret = do_accept4(arg1, arg2, arg3, 0);
6701 break;
6702#endif
6703#ifdef TARGET_NR_accept4
6704 case TARGET_NR_accept4:
6705#ifdef CONFIG_ACCEPT4
6706 ret = do_accept4(arg1, arg2, arg3, arg4);
6707#else
6708 goto unimplemented;
6709#endif
3532fa74
FB
6710 break;
6711#endif
6712#ifdef TARGET_NR_bind
6713 case TARGET_NR_bind:
6714 ret = do_bind(arg1, arg2, arg3);
6715 break;
6716#endif
6717#ifdef TARGET_NR_connect
6718 case TARGET_NR_connect:
6719 ret = do_connect(arg1, arg2, arg3);
6720 break;
6721#endif
6722#ifdef TARGET_NR_getpeername
6723 case TARGET_NR_getpeername:
1be9e1dc 6724 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
6725 break;
6726#endif
6727#ifdef TARGET_NR_getsockname
6728 case TARGET_NR_getsockname:
1be9e1dc 6729 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
6730 break;
6731#endif
6732#ifdef TARGET_NR_getsockopt
6733 case TARGET_NR_getsockopt:
6734 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
6735 break;
6736#endif
6737#ifdef TARGET_NR_listen
6738 case TARGET_NR_listen:
1be9e1dc 6739 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
6740 break;
6741#endif
6742#ifdef TARGET_NR_recv
6743 case TARGET_NR_recv:
214201bd 6744 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
6745 break;
6746#endif
6747#ifdef TARGET_NR_recvfrom
6748 case TARGET_NR_recvfrom:
214201bd 6749 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
6750 break;
6751#endif
6752#ifdef TARGET_NR_recvmsg
6753 case TARGET_NR_recvmsg:
6754 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
6755 break;
6756#endif
6757#ifdef TARGET_NR_send
6758 case TARGET_NR_send:
1be9e1dc 6759 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
6760 break;
6761#endif
6762#ifdef TARGET_NR_sendmsg
6763 case TARGET_NR_sendmsg:
6764 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
6765 break;
6766#endif
f19e00d7
AG
6767#ifdef TARGET_NR_sendmmsg
6768 case TARGET_NR_sendmmsg:
6769 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
6770 break;
6771 case TARGET_NR_recvmmsg:
6772 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
6773 break;
6774#endif
3532fa74
FB
6775#ifdef TARGET_NR_sendto
6776 case TARGET_NR_sendto:
1be9e1dc 6777 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
6778 break;
6779#endif
6780#ifdef TARGET_NR_shutdown
6781 case TARGET_NR_shutdown:
1be9e1dc 6782 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
6783 break;
6784#endif
6785#ifdef TARGET_NR_socket
6786 case TARGET_NR_socket:
6787 ret = do_socket(arg1, arg2, arg3);
6788 break;
6789#endif
6790#ifdef TARGET_NR_socketpair
6791 case TARGET_NR_socketpair:
1be9e1dc 6792 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
6793 break;
6794#endif
6795#ifdef TARGET_NR_setsockopt
6796 case TARGET_NR_setsockopt:
6797 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
6798 break;
6799#endif
7494b0f9 6800
31e31b8a 6801 case TARGET_NR_syslog:
579a97f7
FB
6802 if (!(p = lock_user_string(arg2)))
6803 goto efault;
e5574487
TS
6804 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
6805 unlock_user(p, arg2, 0);
7494b0f9
TS
6806 break;
6807
31e31b8a 6808 case TARGET_NR_setitimer:
66fb9763 6809 {
66fb9763
FB
6810 struct itimerval value, ovalue, *pvalue;
6811
53a5960a 6812 if (arg2) {
66fb9763 6813 pvalue = &value;
788f5ec4
TS
6814 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
6815 || copy_from_user_timeval(&pvalue->it_value,
6816 arg2 + sizeof(struct target_timeval)))
6817 goto efault;
66fb9763
FB
6818 } else {
6819 pvalue = NULL;
6820 }
6821 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 6822 if (!is_error(ret) && arg3) {
788f5ec4
TS
6823 if (copy_to_user_timeval(arg3,
6824 &ovalue.it_interval)
6825 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
6826 &ovalue.it_value))
6827 goto efault;
66fb9763
FB
6828 }
6829 }
6830 break;
31e31b8a 6831 case TARGET_NR_getitimer:
66fb9763 6832 {
66fb9763 6833 struct itimerval value;
3b46e624 6834
66fb9763 6835 ret = get_errno(getitimer(arg1, &value));
53a5960a 6836 if (!is_error(ret) && arg2) {
788f5ec4
TS
6837 if (copy_to_user_timeval(arg2,
6838 &value.it_interval)
6839 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
6840 &value.it_value))
6841 goto efault;
66fb9763
FB
6842 }
6843 }
6844 break;
31e31b8a 6845 case TARGET_NR_stat:
579a97f7
FB
6846 if (!(p = lock_user_string(arg1)))
6847 goto efault;
53a5960a
PB
6848 ret = get_errno(stat(path(p), &st));
6849 unlock_user(p, arg1, 0);
31e31b8a
FB
6850 goto do_stat;
6851 case TARGET_NR_lstat:
579a97f7
FB
6852 if (!(p = lock_user_string(arg1)))
6853 goto efault;
53a5960a
PB
6854 ret = get_errno(lstat(path(p), &st));
6855 unlock_user(p, arg1, 0);
31e31b8a
FB
6856 goto do_stat;
6857 case TARGET_NR_fstat:
6858 {
6859 ret = get_errno(fstat(arg1, &st));
6860 do_stat:
6861 if (!is_error(ret)) {
53a5960a 6862 struct target_stat *target_st;
e3584658 6863
579a97f7
FB
6864 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
6865 goto efault;
12727917 6866 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
6867 __put_user(st.st_dev, &target_st->st_dev);
6868 __put_user(st.st_ino, &target_st->st_ino);
6869 __put_user(st.st_mode, &target_st->st_mode);
6870 __put_user(st.st_uid, &target_st->st_uid);
6871 __put_user(st.st_gid, &target_st->st_gid);
6872 __put_user(st.st_nlink, &target_st->st_nlink);
6873 __put_user(st.st_rdev, &target_st->st_rdev);
6874 __put_user(st.st_size, &target_st->st_size);
6875 __put_user(st.st_blksize, &target_st->st_blksize);
6876 __put_user(st.st_blocks, &target_st->st_blocks);
6877 __put_user(st.st_atime, &target_st->target_st_atime);
6878 __put_user(st.st_mtime, &target_st->target_st_mtime);
6879 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 6880 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
6881 }
6882 }
6883 break;
ebc05488 6884#ifdef TARGET_NR_olduname
31e31b8a
FB
6885 case TARGET_NR_olduname:
6886 goto unimplemented;
ebc05488
FB
6887#endif
6888#ifdef TARGET_NR_iopl
31e31b8a
FB
6889 case TARGET_NR_iopl:
6890 goto unimplemented;
ebc05488 6891#endif
31e31b8a
FB
6892 case TARGET_NR_vhangup:
6893 ret = get_errno(vhangup());
6894 break;
ebc05488 6895#ifdef TARGET_NR_idle
31e31b8a
FB
6896 case TARGET_NR_idle:
6897 goto unimplemented;
42ad6ae9
FB
6898#endif
6899#ifdef TARGET_NR_syscall
6900 case TARGET_NR_syscall:
5945cfcb
PM
6901 ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
6902 arg6, arg7, arg8, 0);
6903 break;
ebc05488 6904#endif
31e31b8a
FB
6905 case TARGET_NR_wait4:
6906 {
6907 int status;
992f48a0 6908 abi_long status_ptr = arg2;
31e31b8a 6909 struct rusage rusage, *rusage_ptr;
992f48a0 6910 abi_ulong target_rusage = arg4;
a39fb273 6911 abi_long rusage_err;
31e31b8a
FB
6912 if (target_rusage)
6913 rusage_ptr = &rusage;
6914 else
6915 rusage_ptr = NULL;
6916 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
6917 if (!is_error(ret)) {
5379557b 6918 if (status_ptr && ret) {
1d9d8b55 6919 status = host_to_target_waitstatus(status);
2f619698
FB
6920 if (put_user_s32(status, status_ptr))
6921 goto efault;
31e31b8a 6922 }
a39fb273
PJ
6923 if (target_rusage) {
6924 rusage_err = host_to_target_rusage(target_rusage, &rusage);
6925 if (rusage_err) {
6926 ret = rusage_err;
6927 }
6928 }
31e31b8a
FB
6929 }
6930 }
6931 break;
e5febef5 6932#ifdef TARGET_NR_swapoff
31e31b8a 6933 case TARGET_NR_swapoff:
579a97f7
FB
6934 if (!(p = lock_user_string(arg1)))
6935 goto efault;
53a5960a
PB
6936 ret = get_errno(swapoff(p));
6937 unlock_user(p, arg1, 0);
31e31b8a 6938 break;
e5febef5 6939#endif
31e31b8a 6940 case TARGET_NR_sysinfo:
a5448a7d 6941 {
53a5960a 6942 struct target_sysinfo *target_value;
a5448a7d
FB
6943 struct sysinfo value;
6944 ret = get_errno(sysinfo(&value));
53a5960a 6945 if (!is_error(ret) && arg1)
a5448a7d 6946 {
579a97f7
FB
6947 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
6948 goto efault;
a5448a7d
FB
6949 __put_user(value.uptime, &target_value->uptime);
6950 __put_user(value.loads[0], &target_value->loads[0]);
6951 __put_user(value.loads[1], &target_value->loads[1]);
6952 __put_user(value.loads[2], &target_value->loads[2]);
6953 __put_user(value.totalram, &target_value->totalram);
6954 __put_user(value.freeram, &target_value->freeram);
6955 __put_user(value.sharedram, &target_value->sharedram);
6956 __put_user(value.bufferram, &target_value->bufferram);
6957 __put_user(value.totalswap, &target_value->totalswap);
6958 __put_user(value.freeswap, &target_value->freeswap);
6959 __put_user(value.procs, &target_value->procs);
6960 __put_user(value.totalhigh, &target_value->totalhigh);
6961 __put_user(value.freehigh, &target_value->freehigh);
6962 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 6963 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
6964 }
6965 }
6966 break;
e5febef5 6967#ifdef TARGET_NR_ipc
31e31b8a 6968 case TARGET_NR_ipc:
8853f86e
FB
6969 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
6970 break;
e5febef5 6971#endif
e5289087
AJ
6972#ifdef TARGET_NR_semget
6973 case TARGET_NR_semget:
6974 ret = get_errno(semget(arg1, arg2, arg3));
6975 break;
6976#endif
6977#ifdef TARGET_NR_semop
6978 case TARGET_NR_semop:
c7128c9f 6979 ret = do_semop(arg1, arg2, arg3);
e5289087
AJ
6980 break;
6981#endif
6982#ifdef TARGET_NR_semctl
6983 case TARGET_NR_semctl:
6984 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
6985 break;
6986#endif
eeb438c1
AJ
6987#ifdef TARGET_NR_msgctl
6988 case TARGET_NR_msgctl:
6989 ret = do_msgctl(arg1, arg2, arg3);
6990 break;
6991#endif
6992#ifdef TARGET_NR_msgget
6993 case TARGET_NR_msgget:
6994 ret = get_errno(msgget(arg1, arg2));
6995 break;
6996#endif
6997#ifdef TARGET_NR_msgrcv
6998 case TARGET_NR_msgrcv:
6999 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
7000 break;
7001#endif
7002#ifdef TARGET_NR_msgsnd
7003 case TARGET_NR_msgsnd:
7004 ret = do_msgsnd(arg1, arg2, arg3, arg4);
7005 break;
88a8c984
RV
7006#endif
7007#ifdef TARGET_NR_shmget
7008 case TARGET_NR_shmget:
7009 ret = get_errno(shmget(arg1, arg2, arg3));
7010 break;
7011#endif
7012#ifdef TARGET_NR_shmctl
7013 case TARGET_NR_shmctl:
7014 ret = do_shmctl(arg1, arg2, arg3);
7015 break;
7016#endif
7017#ifdef TARGET_NR_shmat
7018 case TARGET_NR_shmat:
7019 ret = do_shmat(arg1, arg2, arg3);
7020 break;
7021#endif
7022#ifdef TARGET_NR_shmdt
7023 case TARGET_NR_shmdt:
7024 ret = do_shmdt(arg1);
7025 break;
eeb438c1 7026#endif
31e31b8a
FB
7027 case TARGET_NR_fsync:
7028 ret = get_errno(fsync(arg1));
7029 break;
31e31b8a 7030 case TARGET_NR_clone:
4ce6243d
PM
7031 /* Linux manages to have three different orderings for its
7032 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
7033 * match the kernel's CONFIG_CLONE_* settings.
7034 * Microblaze is further special in that it uses a sixth
7035 * implicit argument to clone for the TLS pointer.
7036 */
7037#if defined(TARGET_MICROBLAZE)
a5b3bdcb 7038 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
7039#elif defined(TARGET_CLONE_BACKWARDS)
7040 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
7041#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 7042 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 7043#else
4ce6243d 7044 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 7045#endif
1b6b029e 7046 break;
ec86b0fb
FB
7047#ifdef __NR_exit_group
7048 /* new thread calls */
7049 case TARGET_NR_exit_group:
9788c9ca 7050#ifdef TARGET_GPROF
6d946cda
AJ
7051 _mcleanup();
7052#endif
e9009676 7053 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
7054 ret = get_errno(exit_group(arg1));
7055 break;
7056#endif
31e31b8a 7057 case TARGET_NR_setdomainname:
579a97f7
FB
7058 if (!(p = lock_user_string(arg1)))
7059 goto efault;
53a5960a
PB
7060 ret = get_errno(setdomainname(p, arg2));
7061 unlock_user(p, arg1, 0);
31e31b8a
FB
7062 break;
7063 case TARGET_NR_uname:
7064 /* no need to transcode because we use the linux syscall */
29e619b1
FB
7065 {
7066 struct new_utsname * buf;
3b46e624 7067
579a97f7
FB
7068 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
7069 goto efault;
29e619b1
FB
7070 ret = get_errno(sys_uname(buf));
7071 if (!is_error(ret)) {
7072 /* Overrite the native machine name with whatever is being
7073 emulated. */
da79030f 7074 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
c5937220
PB
7075 /* Allow the user to override the reported release. */
7076 if (qemu_uname_release && *qemu_uname_release)
7077 strcpy (buf->release, qemu_uname_release);
29e619b1 7078 }
53a5960a 7079 unlock_user_struct(buf, arg1, 1);
29e619b1 7080 }
31e31b8a 7081 break;
6dbad63e 7082#ifdef TARGET_I386
31e31b8a 7083 case TARGET_NR_modify_ldt:
03acab66 7084 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 7085 break;
84409ddb 7086#if !defined(TARGET_X86_64)
5cd4393b
FB
7087 case TARGET_NR_vm86old:
7088 goto unimplemented;
7089 case TARGET_NR_vm86:
53a5960a 7090 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 7091 break;
84409ddb 7092#endif
6dbad63e 7093#endif
31e31b8a
FB
7094 case TARGET_NR_adjtimex:
7095 goto unimplemented;
e5febef5 7096#ifdef TARGET_NR_create_module
31e31b8a 7097 case TARGET_NR_create_module:
e5febef5 7098#endif
31e31b8a
FB
7099 case TARGET_NR_init_module:
7100 case TARGET_NR_delete_module:
e5febef5 7101#ifdef TARGET_NR_get_kernel_syms
31e31b8a 7102 case TARGET_NR_get_kernel_syms:
e5febef5 7103#endif
31e31b8a
FB
7104 goto unimplemented;
7105 case TARGET_NR_quotactl:
7106 goto unimplemented;
7107 case TARGET_NR_getpgid:
7108 ret = get_errno(getpgid(arg1));
7109 break;
7110 case TARGET_NR_fchdir:
7111 ret = get_errno(fchdir(arg1));
7112 break;
84409ddb 7113#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
7114 case TARGET_NR_bdflush:
7115 goto unimplemented;
84409ddb 7116#endif
e5febef5 7117#ifdef TARGET_NR_sysfs
31e31b8a
FB
7118 case TARGET_NR_sysfs:
7119 goto unimplemented;
e5febef5 7120#endif
31e31b8a 7121 case TARGET_NR_personality:
1b6b029e 7122 ret = get_errno(personality(arg1));
31e31b8a 7123 break;
e5febef5 7124#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
7125 case TARGET_NR_afs_syscall:
7126 goto unimplemented;
e5febef5 7127#endif
7a3148a9 7128#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
7129 case TARGET_NR__llseek:
7130 {
0c1592d9 7131 int64_t res;
d35b261c 7132#if !defined(__NR_llseek)
0c1592d9
PM
7133 res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
7134 if (res == -1) {
7135 ret = get_errno(res);
7136 } else {
7137 ret = 0;
7138 }
4f2ac237 7139#else
31e31b8a 7140 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 7141#endif
0c1592d9
PM
7142 if ((ret == 0) && put_user_s64(res, arg4)) {
7143 goto efault;
7144 }
31e31b8a
FB
7145 }
7146 break;
7a3148a9 7147#endif
31e31b8a 7148 case TARGET_NR_getdents:
3307e236 7149#ifdef __NR_getdents
d83c8733 7150#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 7151 {
53a5960a 7152 struct target_dirent *target_dirp;
6556a833 7153 struct linux_dirent *dirp;
992f48a0 7154 abi_long count = arg3;
4add45b4
FB
7155
7156 dirp = malloc(count);
0da46a6e 7157 if (!dirp) {
579a97f7 7158 ret = -TARGET_ENOMEM;
0da46a6e
TS
7159 goto fail;
7160 }
3b46e624 7161
4add45b4
FB
7162 ret = get_errno(sys_getdents(arg1, dirp, count));
7163 if (!is_error(ret)) {
6556a833 7164 struct linux_dirent *de;
4add45b4
FB
7165 struct target_dirent *tde;
7166 int len = ret;
7167 int reclen, treclen;
7168 int count1, tnamelen;
7169
7170 count1 = 0;
7171 de = dirp;
579a97f7
FB
7172 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7173 goto efault;
4add45b4
FB
7174 tde = target_dirp;
7175 while (len > 0) {
7176 reclen = de->d_reclen;
333858b7
DL
7177 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
7178 assert(tnamelen >= 0);
7179 treclen = tnamelen + offsetof(struct target_dirent, d_name);
7180 assert(count1 + treclen <= count);
4add45b4 7181 tde->d_reclen = tswap16(treclen);
cbb21eed
MB
7182 tde->d_ino = tswapal(de->d_ino);
7183 tde->d_off = tswapal(de->d_off);
333858b7 7184 memcpy(tde->d_name, de->d_name, tnamelen);
6556a833 7185 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 7186 len -= reclen;
1c5bf3bf 7187 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
7188 count1 += treclen;
7189 }
7190 ret = count1;
579a97f7 7191 unlock_user(target_dirp, arg2, ret);
4add45b4
FB
7192 }
7193 free(dirp);
7194 }
7195#else
31e31b8a 7196 {
6556a833 7197 struct linux_dirent *dirp;
992f48a0 7198 abi_long count = arg3;
dab2ed99 7199
579a97f7
FB
7200 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7201 goto efault;
72f03900 7202 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 7203 if (!is_error(ret)) {
6556a833 7204 struct linux_dirent *de;
31e31b8a
FB
7205 int len = ret;
7206 int reclen;
7207 de = dirp;
7208 while (len > 0) {
8083a3e5 7209 reclen = de->d_reclen;
31e31b8a
FB
7210 if (reclen > len)
7211 break;
8083a3e5 7212 de->d_reclen = tswap16(reclen);
31e31b8a
FB
7213 tswapls(&de->d_ino);
7214 tswapls(&de->d_off);
6556a833 7215 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
7216 len -= reclen;
7217 }
7218 }
53a5960a 7219 unlock_user(dirp, arg2, ret);
3307e236
PM
7220 }
7221#endif
7222#else
7223 /* Implement getdents in terms of getdents64 */
7224 {
7225 struct linux_dirent64 *dirp;
7226 abi_long count = arg3;
7227
7228 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
7229 if (!dirp) {
7230 goto efault;
7231 }
7232 ret = get_errno(sys_getdents64(arg1, dirp, count));
7233 if (!is_error(ret)) {
7234 /* Convert the dirent64 structs to target dirent. We do this
7235 * in-place, since we can guarantee that a target_dirent is no
7236 * larger than a dirent64; however this means we have to be
7237 * careful to read everything before writing in the new format.
7238 */
7239 struct linux_dirent64 *de;
7240 struct target_dirent *tde;
7241 int len = ret;
7242 int tlen = 0;
7243
7244 de = dirp;
7245 tde = (struct target_dirent *)dirp;
7246 while (len > 0) {
7247 int namelen, treclen;
7248 int reclen = de->d_reclen;
7249 uint64_t ino = de->d_ino;
7250 int64_t off = de->d_off;
7251 uint8_t type = de->d_type;
7252
7253 namelen = strlen(de->d_name);
7254 treclen = offsetof(struct target_dirent, d_name)
7255 + namelen + 2;
7256 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
7257
7258 memmove(tde->d_name, de->d_name, namelen + 1);
7259 tde->d_ino = tswapal(ino);
7260 tde->d_off = tswapal(off);
7261 tde->d_reclen = tswap16(treclen);
7262 /* The target_dirent type is in what was formerly a padding
7263 * byte at the end of the structure:
7264 */
7265 *(((char *)tde) + treclen - 1) = type;
7266
7267 de = (struct linux_dirent64 *)((char *)de + reclen);
7268 tde = (struct target_dirent *)((char *)tde + treclen);
7269 len -= reclen;
7270 tlen += treclen;
7271 }
7272 ret = tlen;
7273 }
7274 unlock_user(dirp, arg2, ret);
31e31b8a 7275 }
4add45b4 7276#endif
31e31b8a 7277 break;
3ae43202 7278#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
7279 case TARGET_NR_getdents64:
7280 {
6556a833 7281 struct linux_dirent64 *dirp;
992f48a0 7282 abi_long count = arg3;
579a97f7
FB
7283 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
7284 goto efault;
dab2ed99
FB
7285 ret = get_errno(sys_getdents64(arg1, dirp, count));
7286 if (!is_error(ret)) {
6556a833 7287 struct linux_dirent64 *de;
dab2ed99
FB
7288 int len = ret;
7289 int reclen;
7290 de = dirp;
7291 while (len > 0) {
8083a3e5 7292 reclen = de->d_reclen;
dab2ed99
FB
7293 if (reclen > len)
7294 break;
8083a3e5 7295 de->d_reclen = tswap16(reclen);
8582a53a
FB
7296 tswap64s((uint64_t *)&de->d_ino);
7297 tswap64s((uint64_t *)&de->d_off);
6556a833 7298 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
7299 len -= reclen;
7300 }
7301 }
53a5960a 7302 unlock_user(dirp, arg2, ret);
dab2ed99
FB
7303 }
7304 break;
a541f297 7305#endif /* TARGET_NR_getdents64 */
9468a5d4 7306#if defined(TARGET_NR__newselect)
31e31b8a 7307 case TARGET_NR__newselect:
53a5960a 7308 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 7309 break;
e5febef5 7310#endif
d8035d4c
MF
7311#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
7312# ifdef TARGET_NR_poll
9de5e440 7313 case TARGET_NR_poll:
d8035d4c
MF
7314# endif
7315# ifdef TARGET_NR_ppoll
7316 case TARGET_NR_ppoll:
7317# endif
9de5e440 7318 {
53a5960a 7319 struct target_pollfd *target_pfd;
9de5e440
FB
7320 unsigned int nfds = arg2;
7321 int timeout = arg3;
7322 struct pollfd *pfd;
7854b056 7323 unsigned int i;
9de5e440 7324
579a97f7
FB
7325 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
7326 if (!target_pfd)
7327 goto efault;
d8035d4c 7328
9de5e440
FB
7329 pfd = alloca(sizeof(struct pollfd) * nfds);
7330 for(i = 0; i < nfds; i++) {
5cd4393b
FB
7331 pfd[i].fd = tswap32(target_pfd[i].fd);
7332 pfd[i].events = tswap16(target_pfd[i].events);
9de5e440 7333 }
d8035d4c
MF
7334
7335# ifdef TARGET_NR_ppoll
7336 if (num == TARGET_NR_ppoll) {
7337 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
7338 target_sigset_t *target_set;
7339 sigset_t _set, *set = &_set;
7340
7341 if (arg3) {
7342 if (target_to_host_timespec(timeout_ts, arg3)) {
7343 unlock_user(target_pfd, arg1, 0);
7344 goto efault;
7345 }
7346 } else {
7347 timeout_ts = NULL;
7348 }
7349
7350 if (arg4) {
7351 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
7352 if (!target_set) {
7353 unlock_user(target_pfd, arg1, 0);
7354 goto efault;
7355 }
7356 target_to_host_sigset(set, target_set);
7357 } else {
7358 set = NULL;
7359 }
7360
7361 ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
7362
7363 if (!is_error(ret) && arg3) {
7364 host_to_target_timespec(arg3, timeout_ts);
7365 }
7366 if (arg4) {
7367 unlock_user(target_set, arg4, 0);
7368 }
7369 } else
7370# endif
7371 ret = get_errno(poll(pfd, nfds, timeout));
7372
9de5e440
FB
7373 if (!is_error(ret)) {
7374 for(i = 0; i < nfds; i++) {
5cd4393b 7375 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440
FB
7376 }
7377 }
30cb4cde 7378 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
9de5e440
FB
7379 }
7380 break;
e5febef5 7381#endif
31e31b8a 7382 case TARGET_NR_flock:
9de5e440
FB
7383 /* NOTE: the flock constant seems to be the same for every
7384 Linux platform */
7385 ret = get_errno(flock(arg1, arg2));
31e31b8a
FB
7386 break;
7387 case TARGET_NR_readv:
7388 {
f287b2c2
RH
7389 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
7390 if (vec != NULL) {
7391 ret = get_errno(readv(arg1, vec, arg3));
7392 unlock_iovec(vec, arg2, arg3, 1);
7393 } else {
7394 ret = -host_to_target_errno(errno);
7395 }
31e31b8a
FB
7396 }
7397 break;
7398 case TARGET_NR_writev:
7399 {
f287b2c2
RH
7400 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
7401 if (vec != NULL) {
7402 ret = get_errno(writev(arg1, vec, arg3));
7403 unlock_iovec(vec, arg2, arg3, 0);
7404 } else {
7405 ret = -host_to_target_errno(errno);
7406 }
31e31b8a
FB
7407 }
7408 break;
7409 case TARGET_NR_getsid:
7410 ret = get_errno(getsid(arg1));
7411 break;
7a3148a9 7412#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 7413 case TARGET_NR_fdatasync:
5cd4393b
FB
7414 ret = get_errno(fdatasync(arg1));
7415 break;
7a3148a9 7416#endif
31e31b8a 7417 case TARGET_NR__sysctl:
0da46a6e 7418 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 7419 return value. */
0da46a6e
TS
7420 ret = -TARGET_ENOTDIR;
7421 break;
737de1d1
MF
7422 case TARGET_NR_sched_getaffinity:
7423 {
7424 unsigned int mask_size;
7425 unsigned long *mask;
7426
7427 /*
7428 * sched_getaffinity needs multiples of ulong, so need to take
7429 * care of mismatches between target ulong and host ulong sizes.
7430 */
7431 if (arg2 & (sizeof(abi_ulong) - 1)) {
7432 ret = -TARGET_EINVAL;
7433 break;
7434 }
7435 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
7436
7437 mask = alloca(mask_size);
7438 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
7439
7440 if (!is_error(ret)) {
be3bd286
PM
7441 if (ret > arg2) {
7442 /* More data returned than the caller's buffer will fit.
7443 * This only happens if sizeof(abi_long) < sizeof(long)
7444 * and the caller passed us a buffer holding an odd number
7445 * of abi_longs. If the host kernel is actually using the
7446 * extra 4 bytes then fail EINVAL; otherwise we can just
7447 * ignore them and only copy the interesting part.
7448 */
7449 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
7450 if (numcpus > arg2 * 8) {
7451 ret = -TARGET_EINVAL;
7452 break;
7453 }
7454 ret = arg2;
7455 }
7456
cd18f05e 7457 if (copy_to_user(arg3, mask, ret)) {
737de1d1
MF
7458 goto efault;
7459 }
737de1d1
MF
7460 }
7461 }
7462 break;
7463 case TARGET_NR_sched_setaffinity:
7464 {
7465 unsigned int mask_size;
7466 unsigned long *mask;
7467
7468 /*
7469 * sched_setaffinity needs multiples of ulong, so need to take
7470 * care of mismatches between target ulong and host ulong sizes.
7471 */
7472 if (arg2 & (sizeof(abi_ulong) - 1)) {
7473 ret = -TARGET_EINVAL;
7474 break;
7475 }
7476 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
7477
7478 mask = alloca(mask_size);
7479 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
7480 goto efault;
7481 }
7482 memcpy(mask, p, arg2);
7483 unlock_user_struct(p, arg2, 0);
7484
7485 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
7486 }
7487 break;
31e31b8a 7488 case TARGET_NR_sched_setparam:
5cd4393b 7489 {
53a5960a 7490 struct sched_param *target_schp;
5cd4393b 7491 struct sched_param schp;
53a5960a 7492
579a97f7
FB
7493 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
7494 goto efault;
5cd4393b 7495 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 7496 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
7497 ret = get_errno(sched_setparam(arg1, &schp));
7498 }
7499 break;
31e31b8a 7500 case TARGET_NR_sched_getparam:
5cd4393b 7501 {
53a5960a 7502 struct sched_param *target_schp;
5cd4393b
FB
7503 struct sched_param schp;
7504 ret = get_errno(sched_getparam(arg1, &schp));
7505 if (!is_error(ret)) {
579a97f7
FB
7506 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
7507 goto efault;
5cd4393b 7508 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 7509 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
7510 }
7511 }
7512 break;
31e31b8a 7513 case TARGET_NR_sched_setscheduler:
5cd4393b 7514 {
53a5960a 7515 struct sched_param *target_schp;
5cd4393b 7516 struct sched_param schp;
579a97f7
FB
7517 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
7518 goto efault;
5cd4393b 7519 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 7520 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
7521 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
7522 }
7523 break;
31e31b8a 7524 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
7525 ret = get_errno(sched_getscheduler(arg1));
7526 break;
31e31b8a
FB
7527 case TARGET_NR_sched_yield:
7528 ret = get_errno(sched_yield());
7529 break;
7530 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
7531 ret = get_errno(sched_get_priority_max(arg1));
7532 break;
31e31b8a 7533 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
7534 ret = get_errno(sched_get_priority_min(arg1));
7535 break;
31e31b8a 7536 case TARGET_NR_sched_rr_get_interval:
5cd4393b 7537 {
5cd4393b
FB
7538 struct timespec ts;
7539 ret = get_errno(sched_rr_get_interval(arg1, &ts));
7540 if (!is_error(ret)) {
53a5960a 7541 host_to_target_timespec(arg2, &ts);
5cd4393b
FB
7542 }
7543 }
7544 break;
31e31b8a 7545 case TARGET_NR_nanosleep:
1b6b029e 7546 {
1b6b029e 7547 struct timespec req, rem;
53a5960a 7548 target_to_host_timespec(&req, arg1);
1b6b029e 7549 ret = get_errno(nanosleep(&req, &rem));
53a5960a
PB
7550 if (is_error(ret) && arg2) {
7551 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
7552 }
7553 }
7554 break;
e5febef5 7555#ifdef TARGET_NR_query_module
31e31b8a 7556 case TARGET_NR_query_module:
5cd4393b 7557 goto unimplemented;
e5febef5
TS
7558#endif
7559#ifdef TARGET_NR_nfsservctl
31e31b8a 7560 case TARGET_NR_nfsservctl:
5cd4393b 7561 goto unimplemented;
e5febef5 7562#endif
31e31b8a 7563 case TARGET_NR_prctl:
1e6722f8
PM
7564 switch (arg1) {
7565 case PR_GET_PDEATHSIG:
7566 {
7567 int deathsig;
7568 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
7569 if (!is_error(ret) && arg2
7570 && put_user_ual(deathsig, arg2)) {
7571 goto efault;
e5574487 7572 }
1e6722f8
PM
7573 break;
7574 }
db9526b1
PM
7575#ifdef PR_GET_NAME
7576 case PR_GET_NAME:
7577 {
7578 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
7579 if (!name) {
7580 goto efault;
7581 }
7582 ret = get_errno(prctl(arg1, (unsigned long)name,
7583 arg3, arg4, arg5));
7584 unlock_user(name, arg2, 16);
7585 break;
7586 }
7587 case PR_SET_NAME:
7588 {
7589 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
7590 if (!name) {
7591 goto efault;
7592 }
7593 ret = get_errno(prctl(arg1, (unsigned long)name,
7594 arg3, arg4, arg5));
7595 unlock_user(name, arg2, 0);
7596 break;
7597 }
7598#endif
1e6722f8
PM
7599 default:
7600 /* Most prctl options have no pointer arguments */
7601 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
7602 break;
7603 }
39b9aae1 7604 break;
d2fd1af7
FB
7605#ifdef TARGET_NR_arch_prctl
7606 case TARGET_NR_arch_prctl:
7607#if defined(TARGET_I386) && !defined(TARGET_ABI32)
7608 ret = do_arch_prctl(cpu_env, arg1, arg2);
7609 break;
7610#else
7611 goto unimplemented;
7612#endif
7613#endif
f2c7ba15
AJ
7614#ifdef TARGET_NR_pread64
7615 case TARGET_NR_pread64:
ae017a5b
AG
7616 if (regpairs_aligned(cpu_env)) {
7617 arg4 = arg5;
7618 arg5 = arg6;
7619 }
f2c7ba15
AJ
7620 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
7621 goto efault;
7622 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
7623 unlock_user(p, arg2, ret);
7624 break;
7625 case TARGET_NR_pwrite64:
ae017a5b
AG
7626 if (regpairs_aligned(cpu_env)) {
7627 arg4 = arg5;
7628 arg5 = arg6;
7629 }
f2c7ba15
AJ
7630 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
7631 goto efault;
7632 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
7633 unlock_user(p, arg2, 0);
7634 break;
67867308 7635#endif
31e31b8a 7636 case TARGET_NR_getcwd:
579a97f7
FB
7637 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
7638 goto efault;
53a5960a
PB
7639 ret = get_errno(sys_getcwd1(p, arg2));
7640 unlock_user(p, arg1, ret);
31e31b8a
FB
7641 break;
7642 case TARGET_NR_capget:
7643 case TARGET_NR_capset:
e0eb210e
PM
7644 {
7645 struct target_user_cap_header *target_header;
7646 struct target_user_cap_data *target_data = NULL;
7647 struct __user_cap_header_struct header;
7648 struct __user_cap_data_struct data[2];
7649 struct __user_cap_data_struct *dataptr = NULL;
7650 int i, target_datalen;
7651 int data_items = 1;
7652
7653 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
7654 goto efault;
7655 }
7656 header.version = tswap32(target_header->version);
7657 header.pid = tswap32(target_header->pid);
7658
ec864874 7659 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
7660 /* Version 2 and up takes pointer to two user_data structs */
7661 data_items = 2;
7662 }
7663
7664 target_datalen = sizeof(*target_data) * data_items;
7665
7666 if (arg2) {
7667 if (num == TARGET_NR_capget) {
7668 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
7669 } else {
7670 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
7671 }
7672 if (!target_data) {
7673 unlock_user_struct(target_header, arg1, 0);
7674 goto efault;
7675 }
7676
7677 if (num == TARGET_NR_capset) {
7678 for (i = 0; i < data_items; i++) {
7679 data[i].effective = tswap32(target_data[i].effective);
7680 data[i].permitted = tswap32(target_data[i].permitted);
7681 data[i].inheritable = tswap32(target_data[i].inheritable);
7682 }
7683 }
7684
7685 dataptr = data;
7686 }
7687
7688 if (num == TARGET_NR_capget) {
7689 ret = get_errno(capget(&header, dataptr));
7690 } else {
7691 ret = get_errno(capset(&header, dataptr));
7692 }
7693
7694 /* The kernel always updates version for both capget and capset */
7695 target_header->version = tswap32(header.version);
7696 unlock_user_struct(target_header, arg1, 1);
7697
7698 if (arg2) {
7699 if (num == TARGET_NR_capget) {
7700 for (i = 0; i < data_items; i++) {
7701 target_data[i].effective = tswap32(data[i].effective);
7702 target_data[i].permitted = tswap32(data[i].permitted);
7703 target_data[i].inheritable = tswap32(data[i].inheritable);
7704 }
7705 unlock_user(target_data, arg2, target_datalen);
7706 } else {
7707 unlock_user(target_data, arg2, 0);
7708 }
7709 }
7710 break;
7711 }
31e31b8a 7712 case TARGET_NR_sigaltstack:
198a74de 7713#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
c761c154 7714 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
d962783e 7715 defined(TARGET_M68K) || defined(TARGET_S390X) || defined(TARGET_OPENRISC)
9349b4f9 7716 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
a04e134a
TS
7717 break;
7718#else
5cd4393b 7719 goto unimplemented;
a04e134a 7720#endif
a8fd1aba
PM
7721
7722#ifdef CONFIG_SENDFILE
7723 case TARGET_NR_sendfile:
7724 {
7725 off_t *offp = NULL;
7726 off_t off;
7727 if (arg3) {
7728 ret = get_user_sal(off, arg3);
7729 if (is_error(ret)) {
7730 break;
7731 }
7732 offp = &off;
7733 }
7734 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
7735 if (!is_error(ret) && arg3) {
7736 abi_long ret2 = put_user_sal(off, arg3);
7737 if (is_error(ret2)) {
7738 ret = ret2;
7739 }
7740 }
7741 break;
7742 }
7743#ifdef TARGET_NR_sendfile64
7744 case TARGET_NR_sendfile64:
7745 {
7746 off_t *offp = NULL;
7747 off_t off;
7748 if (arg3) {
7749 ret = get_user_s64(off, arg3);
7750 if (is_error(ret)) {
7751 break;
7752 }
7753 offp = &off;
7754 }
7755 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
7756 if (!is_error(ret) && arg3) {
7757 abi_long ret2 = put_user_s64(off, arg3);
7758 if (is_error(ret2)) {
7759 ret = ret2;
7760 }
7761 }
7762 break;
7763 }
7764#endif
7765#else
31e31b8a 7766 case TARGET_NR_sendfile:
7edd2cf1 7767#ifdef TARGET_NR_sendfile64
a8fd1aba
PM
7768 case TARGET_NR_sendfile64:
7769#endif
5cd4393b 7770 goto unimplemented;
a8fd1aba
PM
7771#endif
7772
ebc05488 7773#ifdef TARGET_NR_getpmsg
31e31b8a 7774 case TARGET_NR_getpmsg:
5cd4393b 7775 goto unimplemented;
ebc05488
FB
7776#endif
7777#ifdef TARGET_NR_putpmsg
31e31b8a 7778 case TARGET_NR_putpmsg:
5cd4393b 7779 goto unimplemented;
ebc05488 7780#endif
048f6b4d 7781#ifdef TARGET_NR_vfork
31e31b8a 7782 case TARGET_NR_vfork:
d865bab5
PB
7783 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
7784 0, 0, 0, 0));
31e31b8a 7785 break;
048f6b4d 7786#endif
ebc05488 7787#ifdef TARGET_NR_ugetrlimit
31e31b8a 7788 case TARGET_NR_ugetrlimit:
728584be
FB
7789 {
7790 struct rlimit rlim;
e22b7015
WT
7791 int resource = target_to_host_resource(arg1);
7792 ret = get_errno(getrlimit(resource, &rlim));
728584be 7793 if (!is_error(ret)) {
53a5960a 7794 struct target_rlimit *target_rlim;
579a97f7
FB
7795 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
7796 goto efault;
81bbe906
TY
7797 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
7798 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 7799 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
7800 }
7801 break;
7802 }
ebc05488 7803#endif
a315a145 7804#ifdef TARGET_NR_truncate64
31e31b8a 7805 case TARGET_NR_truncate64:
579a97f7
FB
7806 if (!(p = lock_user_string(arg1)))
7807 goto efault;
53a5960a
PB
7808 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
7809 unlock_user(p, arg1, 0);
667f38b1 7810 break;
a315a145
FB
7811#endif
7812#ifdef TARGET_NR_ftruncate64
31e31b8a 7813 case TARGET_NR_ftruncate64:
ce4defa0 7814 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 7815 break;
a315a145
FB
7816#endif
7817#ifdef TARGET_NR_stat64
31e31b8a 7818 case TARGET_NR_stat64:
579a97f7
FB
7819 if (!(p = lock_user_string(arg1)))
7820 goto efault;
53a5960a
PB
7821 ret = get_errno(stat(path(p), &st));
7822 unlock_user(p, arg1, 0);
6a24a778
AZ
7823 if (!is_error(ret))
7824 ret = host_to_target_stat64(cpu_env, arg2, &st);
7825 break;
a315a145
FB
7826#endif
7827#ifdef TARGET_NR_lstat64
31e31b8a 7828 case TARGET_NR_lstat64:
579a97f7
FB
7829 if (!(p = lock_user_string(arg1)))
7830 goto efault;
53a5960a
PB
7831 ret = get_errno(lstat(path(p), &st));
7832 unlock_user(p, arg1, 0);
6a24a778
AZ
7833 if (!is_error(ret))
7834 ret = host_to_target_stat64(cpu_env, arg2, &st);
7835 break;
a315a145
FB
7836#endif
7837#ifdef TARGET_NR_fstat64
31e31b8a 7838 case TARGET_NR_fstat64:
6a24a778
AZ
7839 ret = get_errno(fstat(arg1, &st));
7840 if (!is_error(ret))
7841 ret = host_to_target_stat64(cpu_env, arg2, &st);
7842 break;
ce4defa0 7843#endif
c0d472b1 7844#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 7845#ifdef TARGET_NR_fstatat64
6a24a778 7846 case TARGET_NR_fstatat64:
9d33b76b
AJ
7847#endif
7848#ifdef TARGET_NR_newfstatat
7849 case TARGET_NR_newfstatat:
7850#endif
6a24a778
AZ
7851 if (!(p = lock_user_string(arg2)))
7852 goto efault;
c0d472b1 7853 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
6a24a778
AZ
7854 if (!is_error(ret))
7855 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 7856 break;
a315a145 7857#endif
67867308 7858 case TARGET_NR_lchown:
579a97f7
FB
7859 if (!(p = lock_user_string(arg1)))
7860 goto efault;
53a5960a
PB
7861 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
7862 unlock_user(p, arg1, 0);
67867308 7863 break;
0c866a7e 7864#ifdef TARGET_NR_getuid
67867308
FB
7865 case TARGET_NR_getuid:
7866 ret = get_errno(high2lowuid(getuid()));
7867 break;
0c866a7e
RV
7868#endif
7869#ifdef TARGET_NR_getgid
67867308
FB
7870 case TARGET_NR_getgid:
7871 ret = get_errno(high2lowgid(getgid()));
7872 break;
0c866a7e
RV
7873#endif
7874#ifdef TARGET_NR_geteuid
67867308
FB
7875 case TARGET_NR_geteuid:
7876 ret = get_errno(high2lowuid(geteuid()));
7877 break;
0c866a7e
RV
7878#endif
7879#ifdef TARGET_NR_getegid
67867308
FB
7880 case TARGET_NR_getegid:
7881 ret = get_errno(high2lowgid(getegid()));
7882 break;
0c866a7e 7883#endif
67867308
FB
7884 case TARGET_NR_setreuid:
7885 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
7886 break;
7887 case TARGET_NR_setregid:
7888 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
7889 break;
7890 case TARGET_NR_getgroups:
7891 {
7892 int gidsetsize = arg1;
0c866a7e 7893 target_id *target_grouplist;
67867308
FB
7894 gid_t *grouplist;
7895 int i;
7896
7897 grouplist = alloca(gidsetsize * sizeof(gid_t));
7898 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
7899 if (gidsetsize == 0)
7900 break;
67867308 7901 if (!is_error(ret)) {
03903ffc 7902 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7
FB
7903 if (!target_grouplist)
7904 goto efault;
a2155fcc 7905 for(i = 0;i < ret; i++)
0c866a7e 7906 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 7907 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
7908 }
7909 }
7910 break;
7911 case TARGET_NR_setgroups:
7912 {
7913 int gidsetsize = arg1;
0c866a7e 7914 target_id *target_grouplist;
f2b79ce9 7915 gid_t *grouplist = NULL;
67867308 7916 int i;
f2b79ce9
DA
7917 if (gidsetsize) {
7918 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 7919 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9
DA
7920 if (!target_grouplist) {
7921 ret = -TARGET_EFAULT;
7922 goto fail;
7923 }
7924 for (i = 0; i < gidsetsize; i++) {
7925 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
7926 }
7927 unlock_user(target_grouplist, arg2, 0);
579a97f7 7928 }
67867308
FB
7929 ret = get_errno(setgroups(gidsetsize, grouplist));
7930 }
7931 break;
7932 case TARGET_NR_fchown:
7933 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
7934 break;
c0d472b1 7935#if defined(TARGET_NR_fchownat)
ccfa72b7 7936 case TARGET_NR_fchownat:
579a97f7
FB
7937 if (!(p = lock_user_string(arg2)))
7938 goto efault;
c0d472b1
PM
7939 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
7940 low2highgid(arg4), arg5));
579a97f7 7941 unlock_user(p, arg2, 0);
ccfa72b7
TS
7942 break;
7943#endif
67867308
FB
7944#ifdef TARGET_NR_setresuid
7945 case TARGET_NR_setresuid:
5fafdf24
TS
7946 ret = get_errno(setresuid(low2highuid(arg1),
7947 low2highuid(arg2),
67867308
FB
7948 low2highuid(arg3)));
7949 break;
7950#endif
7951#ifdef TARGET_NR_getresuid
7952 case TARGET_NR_getresuid:
7953 {
53a5960a 7954 uid_t ruid, euid, suid;
67867308
FB
7955 ret = get_errno(getresuid(&ruid, &euid, &suid));
7956 if (!is_error(ret)) {
76ca310a
PM
7957 if (put_user_id(high2lowuid(ruid), arg1)
7958 || put_user_id(high2lowuid(euid), arg2)
7959 || put_user_id(high2lowuid(suid), arg3))
2f619698 7960 goto efault;
67867308
FB
7961 }
7962 }
7963 break;
7964#endif
7965#ifdef TARGET_NR_getresgid
7966 case TARGET_NR_setresgid:
5fafdf24
TS
7967 ret = get_errno(setresgid(low2highgid(arg1),
7968 low2highgid(arg2),
67867308
FB
7969 low2highgid(arg3)));
7970 break;
7971#endif
7972#ifdef TARGET_NR_getresgid
7973 case TARGET_NR_getresgid:
7974 {
53a5960a 7975 gid_t rgid, egid, sgid;
67867308
FB
7976 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7977 if (!is_error(ret)) {
76ca310a
PM
7978 if (put_user_id(high2lowgid(rgid), arg1)
7979 || put_user_id(high2lowgid(egid), arg2)
7980 || put_user_id(high2lowgid(sgid), arg3))
2f619698 7981 goto efault;
67867308
FB
7982 }
7983 }
7984 break;
7985#endif
7986 case TARGET_NR_chown:
579a97f7
FB
7987 if (!(p = lock_user_string(arg1)))
7988 goto efault;
53a5960a
PB
7989 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
7990 unlock_user(p, arg1, 0);
67867308
FB
7991 break;
7992 case TARGET_NR_setuid:
7993 ret = get_errno(setuid(low2highuid(arg1)));
7994 break;
7995 case TARGET_NR_setgid:
7996 ret = get_errno(setgid(low2highgid(arg1)));
7997 break;
7998 case TARGET_NR_setfsuid:
7999 ret = get_errno(setfsuid(arg1));
8000 break;
8001 case TARGET_NR_setfsgid:
8002 ret = get_errno(setfsgid(arg1));
8003 break;
67867308 8004
a315a145 8005#ifdef TARGET_NR_lchown32
31e31b8a 8006 case TARGET_NR_lchown32:
579a97f7
FB
8007 if (!(p = lock_user_string(arg1)))
8008 goto efault;
53a5960a
PB
8009 ret = get_errno(lchown(p, arg2, arg3));
8010 unlock_user(p, arg1, 0);
b03c60f3 8011 break;
a315a145
FB
8012#endif
8013#ifdef TARGET_NR_getuid32
31e31b8a 8014 case TARGET_NR_getuid32:
b03c60f3
FB
8015 ret = get_errno(getuid());
8016 break;
a315a145 8017#endif
64b4d28c
AJ
8018
8019#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
8020 /* Alpha specific */
8021 case TARGET_NR_getxuid:
ba0e276d
RH
8022 {
8023 uid_t euid;
8024 euid=geteuid();
8025 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
8026 }
64b4d28c
AJ
8027 ret = get_errno(getuid());
8028 break;
8029#endif
8030#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
8031 /* Alpha specific */
8032 case TARGET_NR_getxgid:
ba0e276d
RH
8033 {
8034 uid_t egid;
8035 egid=getegid();
8036 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
8037 }
64b4d28c
AJ
8038 ret = get_errno(getgid());
8039 break;
8040#endif
ba0e276d
RH
8041#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
8042 /* Alpha specific */
8043 case TARGET_NR_osf_getsysinfo:
8044 ret = -TARGET_EOPNOTSUPP;
8045 switch (arg1) {
8046 case TARGET_GSI_IEEE_FP_CONTROL:
8047 {
8048 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
8049
8050 /* Copied from linux ieee_fpcr_to_swcr. */
8051 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
8052 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
8053 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
8054 | SWCR_TRAP_ENABLE_DZE
8055 | SWCR_TRAP_ENABLE_OVF);
8056 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
8057 | SWCR_TRAP_ENABLE_INE);
8058 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
8059 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
8060
8061 if (put_user_u64 (swcr, arg2))
8062 goto efault;
8063 ret = 0;
8064 }
8065 break;
8066
8067 /* case GSI_IEEE_STATE_AT_SIGNAL:
8068 -- Not implemented in linux kernel.
8069 case GSI_UACPROC:
8070 -- Retrieves current unaligned access state; not much used.
8071 case GSI_PROC_TYPE:
8072 -- Retrieves implver information; surely not used.
8073 case GSI_GET_HWRPB:
8074 -- Grabs a copy of the HWRPB; surely not used.
8075 */
8076 }
8077 break;
8078#endif
8079#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
8080 /* Alpha specific */
8081 case TARGET_NR_osf_setsysinfo:
8082 ret = -TARGET_EOPNOTSUPP;
8083 switch (arg1) {
8084 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d
RH
8085 {
8086 uint64_t swcr, fpcr, orig_fpcr;
8087
6e06d515 8088 if (get_user_u64 (swcr, arg2)) {
ba0e276d 8089 goto efault;
6e06d515
RH
8090 }
8091 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d
RH
8092 fpcr = orig_fpcr & FPCR_DYN_MASK;
8093
8094 /* Copied from linux ieee_swcr_to_fpcr. */
8095 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
8096 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
8097 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
8098 | SWCR_TRAP_ENABLE_DZE
8099 | SWCR_TRAP_ENABLE_OVF)) << 48;
8100 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
8101 | SWCR_TRAP_ENABLE_INE)) << 57;
8102 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
8103 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
8104
6e06d515 8105 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 8106 ret = 0;
6e06d515
RH
8107 }
8108 break;
8109
8110 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
8111 {
8112 uint64_t exc, fpcr, orig_fpcr;
8113 int si_code;
8114
8115 if (get_user_u64(exc, arg2)) {
8116 goto efault;
8117 }
ba0e276d 8118
6e06d515 8119 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 8120
6e06d515
RH
8121 /* We only add to the exception status here. */
8122 fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35);
8123
8124 cpu_alpha_store_fpcr(cpu_env, fpcr);
8125 ret = 0;
8126
8127 /* Old exceptions are not signaled. */
8128 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
8129
8130 /* If any exceptions set by this call,
8131 and are unmasked, send a signal. */
8132 si_code = 0;
8133 if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) {
8134 si_code = TARGET_FPE_FLTRES;
8135 }
8136 if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) {
8137 si_code = TARGET_FPE_FLTUND;
8138 }
8139 if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) {
8140 si_code = TARGET_FPE_FLTOVF;
8141 }
8142 if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) {
8143 si_code = TARGET_FPE_FLTDIV;
8144 }
8145 if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) {
8146 si_code = TARGET_FPE_FLTINV;
8147 }
8148 if (si_code != 0) {
8149 target_siginfo_t info;
8150 info.si_signo = SIGFPE;
8151 info.si_errno = 0;
8152 info.si_code = si_code;
8153 info._sifields._sigfault._addr
8154 = ((CPUArchState *)cpu_env)->pc;
8155 queue_signal((CPUArchState *)cpu_env, info.si_signo, &info);
ba0e276d
RH
8156 }
8157 }
8158 break;
8159
8160 /* case SSI_NVPAIRS:
8161 -- Used with SSIN_UACPROC to enable unaligned accesses.
8162 case SSI_IEEE_STATE_AT_SIGNAL:
8163 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
8164 -- Not implemented in linux kernel
8165 */
8166 }
8167 break;
8168#endif
8169#ifdef TARGET_NR_osf_sigprocmask
8170 /* Alpha specific. */
8171 case TARGET_NR_osf_sigprocmask:
8172 {
8173 abi_ulong mask;
bc088ba1 8174 int how;
ba0e276d
RH
8175 sigset_t set, oldset;
8176
8177 switch(arg1) {
8178 case TARGET_SIG_BLOCK:
8179 how = SIG_BLOCK;
8180 break;
8181 case TARGET_SIG_UNBLOCK:
8182 how = SIG_UNBLOCK;
8183 break;
8184 case TARGET_SIG_SETMASK:
8185 how = SIG_SETMASK;
8186 break;
8187 default:
8188 ret = -TARGET_EINVAL;
8189 goto fail;
8190 }
8191 mask = arg2;
8192 target_to_host_old_sigset(&set, &mask);
1c275925 8193 do_sigprocmask(how, &set, &oldset);
ba0e276d
RH
8194 host_to_target_old_sigset(&mask, &oldset);
8195 ret = mask;
8196 }
8197 break;
8198#endif
64b4d28c 8199
a315a145 8200#ifdef TARGET_NR_getgid32
31e31b8a 8201 case TARGET_NR_getgid32:
b03c60f3
FB
8202 ret = get_errno(getgid());
8203 break;
a315a145
FB
8204#endif
8205#ifdef TARGET_NR_geteuid32
31e31b8a 8206 case TARGET_NR_geteuid32:
b03c60f3
FB
8207 ret = get_errno(geteuid());
8208 break;
a315a145
FB
8209#endif
8210#ifdef TARGET_NR_getegid32
31e31b8a 8211 case TARGET_NR_getegid32:
b03c60f3
FB
8212 ret = get_errno(getegid());
8213 break;
a315a145
FB
8214#endif
8215#ifdef TARGET_NR_setreuid32
31e31b8a 8216 case TARGET_NR_setreuid32:
b03c60f3
FB
8217 ret = get_errno(setreuid(arg1, arg2));
8218 break;
a315a145
FB
8219#endif
8220#ifdef TARGET_NR_setregid32
31e31b8a 8221 case TARGET_NR_setregid32:
b03c60f3
FB
8222 ret = get_errno(setregid(arg1, arg2));
8223 break;
a315a145
FB
8224#endif
8225#ifdef TARGET_NR_getgroups32
31e31b8a 8226 case TARGET_NR_getgroups32:
99c475ab
FB
8227 {
8228 int gidsetsize = arg1;
53a5960a 8229 uint32_t *target_grouplist;
99c475ab
FB
8230 gid_t *grouplist;
8231 int i;
8232
8233 grouplist = alloca(gidsetsize * sizeof(gid_t));
8234 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
8235 if (gidsetsize == 0)
8236 break;
99c475ab 8237 if (!is_error(ret)) {
579a97f7
FB
8238 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
8239 if (!target_grouplist) {
8240 ret = -TARGET_EFAULT;
8241 goto fail;
8242 }
a2155fcc 8243 for(i = 0;i < ret; i++)
53a5960a
PB
8244 target_grouplist[i] = tswap32(grouplist[i]);
8245 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
8246 }
8247 }
8248 break;
a315a145
FB
8249#endif
8250#ifdef TARGET_NR_setgroups32
31e31b8a 8251 case TARGET_NR_setgroups32:
99c475ab
FB
8252 {
8253 int gidsetsize = arg1;
53a5960a 8254 uint32_t *target_grouplist;
99c475ab
FB
8255 gid_t *grouplist;
8256 int i;
3b46e624 8257
99c475ab 8258 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
8259 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
8260 if (!target_grouplist) {
8261 ret = -TARGET_EFAULT;
8262 goto fail;
8263 }
99c475ab 8264 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
8265 grouplist[i] = tswap32(target_grouplist[i]);
8266 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
8267 ret = get_errno(setgroups(gidsetsize, grouplist));
8268 }
8269 break;
a315a145
FB
8270#endif
8271#ifdef TARGET_NR_fchown32
31e31b8a 8272 case TARGET_NR_fchown32:
b03c60f3
FB
8273 ret = get_errno(fchown(arg1, arg2, arg3));
8274 break;
a315a145
FB
8275#endif
8276#ifdef TARGET_NR_setresuid32
31e31b8a 8277 case TARGET_NR_setresuid32:
b03c60f3
FB
8278 ret = get_errno(setresuid(arg1, arg2, arg3));
8279 break;
a315a145
FB
8280#endif
8281#ifdef TARGET_NR_getresuid32
31e31b8a 8282 case TARGET_NR_getresuid32:
b03c60f3 8283 {
53a5960a 8284 uid_t ruid, euid, suid;
b03c60f3
FB
8285 ret = get_errno(getresuid(&ruid, &euid, &suid));
8286 if (!is_error(ret)) {
2f619698
FB
8287 if (put_user_u32(ruid, arg1)
8288 || put_user_u32(euid, arg2)
8289 || put_user_u32(suid, arg3))
8290 goto efault;
b03c60f3
FB
8291 }
8292 }
8293 break;
a315a145
FB
8294#endif
8295#ifdef TARGET_NR_setresgid32
31e31b8a 8296 case TARGET_NR_setresgid32:
b03c60f3
FB
8297 ret = get_errno(setresgid(arg1, arg2, arg3));
8298 break;
a315a145
FB
8299#endif
8300#ifdef TARGET_NR_getresgid32
31e31b8a 8301 case TARGET_NR_getresgid32:
b03c60f3 8302 {
53a5960a 8303 gid_t rgid, egid, sgid;
b03c60f3
FB
8304 ret = get_errno(getresgid(&rgid, &egid, &sgid));
8305 if (!is_error(ret)) {
2f619698
FB
8306 if (put_user_u32(rgid, arg1)
8307 || put_user_u32(egid, arg2)
8308 || put_user_u32(sgid, arg3))
8309 goto efault;
b03c60f3
FB
8310 }
8311 }
8312 break;
a315a145
FB
8313#endif
8314#ifdef TARGET_NR_chown32
31e31b8a 8315 case TARGET_NR_chown32:
579a97f7
FB
8316 if (!(p = lock_user_string(arg1)))
8317 goto efault;
53a5960a
PB
8318 ret = get_errno(chown(p, arg2, arg3));
8319 unlock_user(p, arg1, 0);
b03c60f3 8320 break;
a315a145
FB
8321#endif
8322#ifdef TARGET_NR_setuid32
31e31b8a 8323 case TARGET_NR_setuid32:
b03c60f3
FB
8324 ret = get_errno(setuid(arg1));
8325 break;
a315a145
FB
8326#endif
8327#ifdef TARGET_NR_setgid32
31e31b8a 8328 case TARGET_NR_setgid32:
b03c60f3
FB
8329 ret = get_errno(setgid(arg1));
8330 break;
a315a145
FB
8331#endif
8332#ifdef TARGET_NR_setfsuid32
31e31b8a 8333 case TARGET_NR_setfsuid32:
b03c60f3
FB
8334 ret = get_errno(setfsuid(arg1));
8335 break;
a315a145
FB
8336#endif
8337#ifdef TARGET_NR_setfsgid32
31e31b8a 8338 case TARGET_NR_setfsgid32:
b03c60f3
FB
8339 ret = get_errno(setfsgid(arg1));
8340 break;
a315a145 8341#endif
67867308 8342
31e31b8a 8343 case TARGET_NR_pivot_root:
b03c60f3 8344 goto unimplemented;
ffa65c3b 8345#ifdef TARGET_NR_mincore
31e31b8a 8346 case TARGET_NR_mincore:
04bb9ace
AJ
8347 {
8348 void *a;
8349 ret = -TARGET_EFAULT;
8350 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
8351 goto efault;
8352 if (!(p = lock_user_string(arg3)))
8353 goto mincore_fail;
8354 ret = get_errno(mincore(a, arg2, p));
8355 unlock_user(p, arg3, ret);
8356 mincore_fail:
8357 unlock_user(a, arg1, 0);
8358 }
8359 break;
ffa65c3b 8360#endif
408321b6
AJ
8361#ifdef TARGET_NR_arm_fadvise64_64
8362 case TARGET_NR_arm_fadvise64_64:
8363 {
8364 /*
8365 * arm_fadvise64_64 looks like fadvise64_64 but
8366 * with different argument order
8367 */
8368 abi_long temp;
8369 temp = arg3;
8370 arg3 = arg4;
8371 arg4 = temp;
8372 }
8373#endif
e72d2cc7 8374#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
8375#ifdef TARGET_NR_fadvise64_64
8376 case TARGET_NR_fadvise64_64:
8377#endif
e72d2cc7
UH
8378#ifdef TARGET_NR_fadvise64
8379 case TARGET_NR_fadvise64:
8380#endif
8381#ifdef TARGET_S390X
8382 switch (arg4) {
8383 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
8384 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
8385 case 6: arg4 = POSIX_FADV_DONTNEED; break;
8386 case 7: arg4 = POSIX_FADV_NOREUSE; break;
8387 default: break;
8388 }
8389#endif
8390 ret = -posix_fadvise(arg1, arg2, arg3, arg4);
408321b6
AJ
8391 break;
8392#endif
ffa65c3b 8393#ifdef TARGET_NR_madvise
31e31b8a 8394 case TARGET_NR_madvise:
24836689 8395 /* A straight passthrough may not be safe because qemu sometimes
d2d6b857 8396 turns private file-backed mappings into anonymous mappings.
24836689
PB
8397 This will break MADV_DONTNEED.
8398 This is a hint, so ignoring and returning success is ok. */
8399 ret = get_errno(0);
8400 break;
ffa65c3b 8401#endif
992f48a0 8402#if TARGET_ABI_BITS == 32
31e31b8a 8403 case TARGET_NR_fcntl64:
77e4672d 8404 {
b1e341eb 8405 int cmd;
77e4672d 8406 struct flock64 fl;
53a5960a 8407 struct target_flock64 *target_fl;
ce4defa0 8408#ifdef TARGET_ARM
53a5960a 8409 struct target_eabi_flock64 *target_efl;
ce4defa0 8410#endif
77e4672d 8411
5f106811 8412 cmd = target_to_host_fcntl_cmd(arg2);
31b63193
PM
8413 if (cmd == -TARGET_EINVAL) {
8414 ret = cmd;
8415 break;
8416 }
b1e341eb 8417
60cd49d5 8418 switch(arg2) {
b1e341eb 8419 case TARGET_F_GETLK64:
5813427b
TS
8420#ifdef TARGET_ARM
8421 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8422 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
8423 goto efault;
5813427b
TS
8424 fl.l_type = tswap16(target_efl->l_type);
8425 fl.l_whence = tswap16(target_efl->l_whence);
8426 fl.l_start = tswap64(target_efl->l_start);
8427 fl.l_len = tswap64(target_efl->l_len);
7e22e546 8428 fl.l_pid = tswap32(target_efl->l_pid);
5813427b
TS
8429 unlock_user_struct(target_efl, arg3, 0);
8430 } else
8431#endif
8432 {
9ee1fa2c
FB
8433 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
8434 goto efault;
5813427b
TS
8435 fl.l_type = tswap16(target_fl->l_type);
8436 fl.l_whence = tswap16(target_fl->l_whence);
8437 fl.l_start = tswap64(target_fl->l_start);
8438 fl.l_len = tswap64(target_fl->l_len);
7e22e546 8439 fl.l_pid = tswap32(target_fl->l_pid);
5813427b
TS
8440 unlock_user_struct(target_fl, arg3, 0);
8441 }
b1e341eb 8442 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 8443 if (ret == 0) {
ce4defa0
PB
8444#ifdef TARGET_ARM
8445 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8446 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
8447 goto efault;
ce4defa0
PB
8448 target_efl->l_type = tswap16(fl.l_type);
8449 target_efl->l_whence = tswap16(fl.l_whence);
8450 target_efl->l_start = tswap64(fl.l_start);
8451 target_efl->l_len = tswap64(fl.l_len);
7e22e546 8452 target_efl->l_pid = tswap32(fl.l_pid);
53a5960a 8453 unlock_user_struct(target_efl, arg3, 1);
ce4defa0
PB
8454 } else
8455#endif
8456 {
9ee1fa2c
FB
8457 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
8458 goto efault;
ce4defa0
PB
8459 target_fl->l_type = tswap16(fl.l_type);
8460 target_fl->l_whence = tswap16(fl.l_whence);
8461 target_fl->l_start = tswap64(fl.l_start);
8462 target_fl->l_len = tswap64(fl.l_len);
7e22e546 8463 target_fl->l_pid = tswap32(fl.l_pid);
53a5960a 8464 unlock_user_struct(target_fl, arg3, 1);
ce4defa0 8465 }
77e4672d
FB
8466 }
8467 break;
8468
b1e341eb
TS
8469 case TARGET_F_SETLK64:
8470 case TARGET_F_SETLKW64:
ce4defa0
PB
8471#ifdef TARGET_ARM
8472 if (((CPUARMState *)cpu_env)->eabi) {
9ee1fa2c
FB
8473 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
8474 goto efault;
ce4defa0
PB
8475 fl.l_type = tswap16(target_efl->l_type);
8476 fl.l_whence = tswap16(target_efl->l_whence);
8477 fl.l_start = tswap64(target_efl->l_start);
8478 fl.l_len = tswap64(target_efl->l_len);
7e22e546 8479 fl.l_pid = tswap32(target_efl->l_pid);
53a5960a 8480 unlock_user_struct(target_efl, arg3, 0);
ce4defa0
PB
8481 } else
8482#endif
8483 {
9ee1fa2c
FB
8484 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
8485 goto efault;
ce4defa0
PB
8486 fl.l_type = tswap16(target_fl->l_type);
8487 fl.l_whence = tswap16(target_fl->l_whence);
8488 fl.l_start = tswap64(target_fl->l_start);
8489 fl.l_len = tswap64(target_fl->l_len);
7e22e546 8490 fl.l_pid = tswap32(target_fl->l_pid);
53a5960a 8491 unlock_user_struct(target_fl, arg3, 0);
ce4defa0 8492 }
b1e341eb 8493 ret = get_errno(fcntl(arg1, cmd, &fl));
77e4672d 8494 break;
60cd49d5 8495 default:
5f106811 8496 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
8497 break;
8498 }
77e4672d
FB
8499 break;
8500 }
60cd49d5 8501#endif
7d600c80
TS
8502#ifdef TARGET_NR_cacheflush
8503 case TARGET_NR_cacheflush:
8504 /* self-modifying code is handled automatically, so nothing needed */
8505 ret = 0;
8506 break;
8507#endif
ebc05488 8508#ifdef TARGET_NR_security
31e31b8a
FB
8509 case TARGET_NR_security:
8510 goto unimplemented;
c573ff67
FB
8511#endif
8512#ifdef TARGET_NR_getpagesize
8513 case TARGET_NR_getpagesize:
8514 ret = TARGET_PAGE_SIZE;
8515 break;
ebc05488 8516#endif
31e31b8a
FB
8517 case TARGET_NR_gettid:
8518 ret = get_errno(gettid());
8519 break;
e5febef5 8520#ifdef TARGET_NR_readahead
31e31b8a 8521 case TARGET_NR_readahead:
2054ac9b 8522#if TARGET_ABI_BITS == 32
48e515d4 8523 if (regpairs_aligned(cpu_env)) {
2054ac9b
AJ
8524 arg2 = arg3;
8525 arg3 = arg4;
8526 arg4 = arg5;
8527 }
2054ac9b
AJ
8528 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
8529#else
8530 ret = get_errno(readahead(arg1, arg2, arg3));
8531#endif
8532 break;
e5febef5 8533#endif
a790ae38 8534#ifdef CONFIG_ATTR
ebc05488 8535#ifdef TARGET_NR_setxattr
31e31b8a
FB
8536 case TARGET_NR_listxattr:
8537 case TARGET_NR_llistxattr:
fb5590f7
PM
8538 {
8539 void *p, *b = 0;
8540 if (arg2) {
8541 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
8542 if (!b) {
8543 ret = -TARGET_EFAULT;
8544 break;
8545 }
8546 }
8547 p = lock_user_string(arg1);
8548 if (p) {
8549 if (num == TARGET_NR_listxattr) {
8550 ret = get_errno(listxattr(p, b, arg3));
8551 } else {
8552 ret = get_errno(llistxattr(p, b, arg3));
8553 }
8554 } else {
8555 ret = -TARGET_EFAULT;
8556 }
8557 unlock_user(p, arg1, 0);
8558 unlock_user(b, arg2, arg3);
8559 break;
8560 }
31e31b8a 8561 case TARGET_NR_flistxattr:
fb5590f7
PM
8562 {
8563 void *b = 0;
8564 if (arg2) {
8565 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
8566 if (!b) {
8567 ret = -TARGET_EFAULT;
8568 break;
8569 }
8570 }
8571 ret = get_errno(flistxattr(arg1, b, arg3));
8572 unlock_user(b, arg2, arg3);
6f932f91 8573 break;
fb5590f7 8574 }
a790ae38 8575 case TARGET_NR_setxattr:
30297b55 8576 case TARGET_NR_lsetxattr:
a790ae38 8577 {
e3c33ec6
PM
8578 void *p, *n, *v = 0;
8579 if (arg3) {
8580 v = lock_user(VERIFY_READ, arg3, arg4, 1);
8581 if (!v) {
8582 ret = -TARGET_EFAULT;
8583 break;
8584 }
8585 }
a790ae38
ACH
8586 p = lock_user_string(arg1);
8587 n = lock_user_string(arg2);
e3c33ec6 8588 if (p && n) {
30297b55
PM
8589 if (num == TARGET_NR_setxattr) {
8590 ret = get_errno(setxattr(p, n, v, arg4, arg5));
8591 } else {
8592 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
8593 }
a790ae38
ACH
8594 } else {
8595 ret = -TARGET_EFAULT;
8596 }
8597 unlock_user(p, arg1, 0);
8598 unlock_user(n, arg2, 0);
8599 unlock_user(v, arg3, 0);
8600 }
8601 break;
30297b55
PM
8602 case TARGET_NR_fsetxattr:
8603 {
8604 void *n, *v = 0;
8605 if (arg3) {
8606 v = lock_user(VERIFY_READ, arg3, arg4, 1);
8607 if (!v) {
8608 ret = -TARGET_EFAULT;
8609 break;
8610 }
8611 }
8612 n = lock_user_string(arg2);
8613 if (n) {
8614 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
8615 } else {
8616 ret = -TARGET_EFAULT;
8617 }
8618 unlock_user(n, arg2, 0);
8619 unlock_user(v, arg3, 0);
8620 }
8621 break;
a790ae38 8622 case TARGET_NR_getxattr:
30297b55 8623 case TARGET_NR_lgetxattr:
a790ae38 8624 {
e3c33ec6
PM
8625 void *p, *n, *v = 0;
8626 if (arg3) {
8627 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
8628 if (!v) {
8629 ret = -TARGET_EFAULT;
8630 break;
8631 }
8632 }
a790ae38
ACH
8633 p = lock_user_string(arg1);
8634 n = lock_user_string(arg2);
e3c33ec6 8635 if (p && n) {
30297b55
PM
8636 if (num == TARGET_NR_getxattr) {
8637 ret = get_errno(getxattr(p, n, v, arg4));
8638 } else {
8639 ret = get_errno(lgetxattr(p, n, v, arg4));
8640 }
a790ae38
ACH
8641 } else {
8642 ret = -TARGET_EFAULT;
8643 }
8644 unlock_user(p, arg1, 0);
8645 unlock_user(n, arg2, 0);
8646 unlock_user(v, arg3, arg4);
8647 }
8648 break;
30297b55
PM
8649 case TARGET_NR_fgetxattr:
8650 {
8651 void *n, *v = 0;
8652 if (arg3) {
8653 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
8654 if (!v) {
8655 ret = -TARGET_EFAULT;
8656 break;
8657 }
8658 }
8659 n = lock_user_string(arg2);
8660 if (n) {
8661 ret = get_errno(fgetxattr(arg1, n, v, arg4));
8662 } else {
8663 ret = -TARGET_EFAULT;
8664 }
8665 unlock_user(n, arg2, 0);
8666 unlock_user(v, arg3, arg4);
8667 }
8668 break;
a790ae38 8669 case TARGET_NR_removexattr:
30297b55 8670 case TARGET_NR_lremovexattr:
a790ae38
ACH
8671 {
8672 void *p, *n;
8673 p = lock_user_string(arg1);
8674 n = lock_user_string(arg2);
8675 if (p && n) {
30297b55
PM
8676 if (num == TARGET_NR_removexattr) {
8677 ret = get_errno(removexattr(p, n));
8678 } else {
8679 ret = get_errno(lremovexattr(p, n));
8680 }
a790ae38
ACH
8681 } else {
8682 ret = -TARGET_EFAULT;
8683 }
8684 unlock_user(p, arg1, 0);
8685 unlock_user(n, arg2, 0);
8686 }
8687 break;
30297b55
PM
8688 case TARGET_NR_fremovexattr:
8689 {
8690 void *n;
8691 n = lock_user_string(arg2);
8692 if (n) {
8693 ret = get_errno(fremovexattr(arg1, n));
8694 } else {
8695 ret = -TARGET_EFAULT;
8696 }
8697 unlock_user(n, arg2, 0);
8698 }
8699 break;
ebc05488 8700#endif
a790ae38 8701#endif /* CONFIG_ATTR */
ebc05488 8702#ifdef TARGET_NR_set_thread_area
5cd4393b 8703 case TARGET_NR_set_thread_area:
8d18e893 8704#if defined(TARGET_MIPS)
d279279e 8705 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
6f5b89a0
TS
8706 ret = 0;
8707 break;
ef96779b
EI
8708#elif defined(TARGET_CRIS)
8709 if (arg1 & 0xff)
8710 ret = -TARGET_EINVAL;
8711 else {
8712 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
8713 ret = 0;
8714 }
8715 break;
8d18e893
FB
8716#elif defined(TARGET_I386) && defined(TARGET_ABI32)
8717 ret = do_set_thread_area(cpu_env, arg1);
8718 break;
1ccd9374
PM
8719#elif defined(TARGET_M68K)
8720 {
0429a971 8721 TaskState *ts = cpu->opaque;
1ccd9374 8722 ts->tp_value = arg1;
95c1eb19 8723 ret = 0;
1ccd9374
PM
8724 break;
8725 }
6f5b89a0
TS
8726#else
8727 goto unimplemented_nowarn;
8728#endif
8729#endif
8730#ifdef TARGET_NR_get_thread_area
5cd4393b 8731 case TARGET_NR_get_thread_area:
8d18e893
FB
8732#if defined(TARGET_I386) && defined(TARGET_ABI32)
8733 ret = do_get_thread_area(cpu_env, arg1);
d312bbe1 8734 break;
1ccd9374
PM
8735#elif defined(TARGET_M68K)
8736 {
0429a971 8737 TaskState *ts = cpu->opaque;
1ccd9374
PM
8738 ret = ts->tp_value;
8739 break;
8740 }
8d18e893 8741#else
5cd4393b 8742 goto unimplemented_nowarn;
48dc41eb 8743#endif
8d18e893 8744#endif
48dc41eb
FB
8745#ifdef TARGET_NR_getdomainname
8746 case TARGET_NR_getdomainname:
8747 goto unimplemented_nowarn;
ebc05488 8748#endif
6f5b89a0 8749
b5906f95
TS
8750#ifdef TARGET_NR_clock_gettime
8751 case TARGET_NR_clock_gettime:
8752 {
8753 struct timespec ts;
8754 ret = get_errno(clock_gettime(arg1, &ts));
8755 if (!is_error(ret)) {
8756 host_to_target_timespec(arg2, &ts);
8757 }
8758 break;
8759 }
8760#endif
8761#ifdef TARGET_NR_clock_getres
8762 case TARGET_NR_clock_getres:
8763 {
8764 struct timespec ts;
8765 ret = get_errno(clock_getres(arg1, &ts));
8766 if (!is_error(ret)) {
8767 host_to_target_timespec(arg2, &ts);
8768 }
8769 break;
8770 }
8771#endif
63d7651b
PB
8772#ifdef TARGET_NR_clock_nanosleep
8773 case TARGET_NR_clock_nanosleep:
8774 {
8775 struct timespec ts;
8776 target_to_host_timespec(&ts, arg3);
8777 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
8778 if (arg4)
8779 host_to_target_timespec(arg4, &ts);
8780 break;
8781 }
8782#endif
b5906f95 8783
6f5b89a0
TS
8784#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
8785 case TARGET_NR_set_tid_address:
579a97f7
FB
8786 ret = get_errno(set_tid_address((int *)g2h(arg1)));
8787 break;
6f5b89a0
TS
8788#endif
8789
3ae43202 8790#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
4cae1d16 8791 case TARGET_NR_tkill:
4cb05961 8792 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16
TS
8793 break;
8794#endif
8795
3ae43202 8796#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
71455574 8797 case TARGET_NR_tgkill:
4cb05961
PB
8798 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
8799 target_to_host_signal(arg3)));
71455574
TS
8800 break;
8801#endif
8802
4f2b1fe8
TS
8803#ifdef TARGET_NR_set_robust_list
8804 case TARGET_NR_set_robust_list:
e9a970a8
PM
8805 case TARGET_NR_get_robust_list:
8806 /* The ABI for supporting robust futexes has userspace pass
8807 * the kernel a pointer to a linked list which is updated by
8808 * userspace after the syscall; the list is walked by the kernel
8809 * when the thread exits. Since the linked list in QEMU guest
8810 * memory isn't a valid linked list for the host and we have
8811 * no way to reliably intercept the thread-death event, we can't
8812 * support these. Silently return ENOSYS so that guest userspace
8813 * falls back to a non-robust futex implementation (which should
8814 * be OK except in the corner case of the guest crashing while
8815 * holding a mutex that is shared with another process via
8816 * shared memory).
8817 */
8818 goto unimplemented_nowarn;
4f2b1fe8
TS
8819#endif
8820
1acae9f2 8821#if defined(TARGET_NR_utimensat)
9007f0ef
TS
8822 case TARGET_NR_utimensat:
8823 {
ebc996f3
RV
8824 struct timespec *tsp, ts[2];
8825 if (!arg3) {
8826 tsp = NULL;
8827 } else {
8828 target_to_host_timespec(ts, arg3);
8829 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
8830 tsp = ts;
8831 }
9007f0ef 8832 if (!arg2)
ebc996f3 8833 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 8834 else {
579a97f7 8835 if (!(p = lock_user_string(arg2))) {
0da46a6e 8836 ret = -TARGET_EFAULT;
579a97f7
FB
8837 goto fail;
8838 }
ebc996f3 8839 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 8840 unlock_user(p, arg2, 0);
9007f0ef
TS
8841 }
8842 }
8843 break;
8844#endif
bd0c5661
PB
8845 case TARGET_NR_futex:
8846 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
8847 break;
dbfe4c36 8848#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
39b59763
AJ
8849 case TARGET_NR_inotify_init:
8850 ret = get_errno(sys_inotify_init());
8851 break;
8852#endif
a1606b0b 8853#ifdef CONFIG_INOTIFY1
c05c7a73
RV
8854#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
8855 case TARGET_NR_inotify_init1:
8856 ret = get_errno(sys_inotify_init1(arg1));
8857 break;
8858#endif
a1606b0b 8859#endif
dbfe4c36 8860#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
39b59763
AJ
8861 case TARGET_NR_inotify_add_watch:
8862 p = lock_user_string(arg2);
8863 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
8864 unlock_user(p, arg2, 0);
8865 break;
8866#endif
dbfe4c36 8867#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
39b59763
AJ
8868 case TARGET_NR_inotify_rm_watch:
8869 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
8870 break;
8871#endif
9007f0ef 8872
8ec9cf89 8873#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
8874 case TARGET_NR_mq_open:
8875 {
8876 struct mq_attr posix_mq_attr;
8877
8878 p = lock_user_string(arg1 - 1);
8879 if (arg4 != 0)
8880 copy_from_user_mq_attr (&posix_mq_attr, arg4);
8881 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
8882 unlock_user (p, arg1, 0);
8883 }
8884 break;
8885
8886 case TARGET_NR_mq_unlink:
8887 p = lock_user_string(arg1 - 1);
8888 ret = get_errno(mq_unlink(p));
8889 unlock_user (p, arg1, 0);
8890 break;
8891
8892 case TARGET_NR_mq_timedsend:
8893 {
8894 struct timespec ts;
8895
8896 p = lock_user (VERIFY_READ, arg2, arg3, 1);
8897 if (arg5 != 0) {
8898 target_to_host_timespec(&ts, arg5);
8899 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
8900 host_to_target_timespec(arg5, &ts);
8901 }
8902 else
8903 ret = get_errno(mq_send(arg1, p, arg3, arg4));
8904 unlock_user (p, arg2, arg3);
8905 }
8906 break;
8907
8908 case TARGET_NR_mq_timedreceive:
8909 {
8910 struct timespec ts;
8911 unsigned int prio;
8912
8913 p = lock_user (VERIFY_READ, arg2, arg3, 1);
8914 if (arg5 != 0) {
8915 target_to_host_timespec(&ts, arg5);
8916 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
8917 host_to_target_timespec(arg5, &ts);
8918 }
8919 else
8920 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
8921 unlock_user (p, arg2, arg3);
8922 if (arg4 != 0)
8923 put_user_u32(prio, arg4);
8924 }
8925 break;
8926
8927 /* Not implemented for now... */
8928/* case TARGET_NR_mq_notify: */
8929/* break; */
8930
8931 case TARGET_NR_mq_getsetattr:
8932 {
8933 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
8934 ret = 0;
8935 if (arg3 != 0) {
8936 ret = mq_getattr(arg1, &posix_mq_attr_out);
8937 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
8938 }
8939 if (arg2 != 0) {
8940 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
8941 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
8942 }
8943
8944 }
8945 break;
8946#endif
8947
3ce34dfb
VS
8948#ifdef CONFIG_SPLICE
8949#ifdef TARGET_NR_tee
8950 case TARGET_NR_tee:
8951 {
8952 ret = get_errno(tee(arg1,arg2,arg3,arg4));
8953 }
8954 break;
8955#endif
8956#ifdef TARGET_NR_splice
8957 case TARGET_NR_splice:
8958 {
8959 loff_t loff_in, loff_out;
8960 loff_t *ploff_in = NULL, *ploff_out = NULL;
8961 if(arg2) {
8962 get_user_u64(loff_in, arg2);
8963 ploff_in = &loff_in;
8964 }
8965 if(arg4) {
8966 get_user_u64(loff_out, arg2);
8967 ploff_out = &loff_out;
8968 }
8969 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
8970 }
8971 break;
8972#endif
8973#ifdef TARGET_NR_vmsplice
8974 case TARGET_NR_vmsplice:
8975 {
f287b2c2
RH
8976 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
8977 if (vec != NULL) {
8978 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
8979 unlock_iovec(vec, arg2, arg3, 0);
8980 } else {
8981 ret = -host_to_target_errno(errno);
8982 }
3ce34dfb
VS
8983 }
8984 break;
8985#endif
8986#endif /* CONFIG_SPLICE */
c2882b96
RV
8987#ifdef CONFIG_EVENTFD
8988#if defined(TARGET_NR_eventfd)
8989 case TARGET_NR_eventfd:
8990 ret = get_errno(eventfd(arg1, 0));
8991 break;
8992#endif
8993#if defined(TARGET_NR_eventfd2)
8994 case TARGET_NR_eventfd2:
5947c697
PJ
8995 {
8996 int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC));
8997 if (arg2 & TARGET_O_NONBLOCK) {
8998 host_flags |= O_NONBLOCK;
8999 }
9000 if (arg2 & TARGET_O_CLOEXEC) {
9001 host_flags |= O_CLOEXEC;
9002 }
9003 ret = get_errno(eventfd(arg1, host_flags));
c2882b96 9004 break;
5947c697 9005 }
c2882b96
RV
9006#endif
9007#endif /* CONFIG_EVENTFD */
d0927938
UH
9008#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
9009 case TARGET_NR_fallocate:
20249ae1
AG
9010#if TARGET_ABI_BITS == 32
9011 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
9012 target_offset64(arg5, arg6)));
9013#else
d0927938 9014 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 9015#endif
d0927938 9016 break;
c727f47d
PM
9017#endif
9018#if defined(CONFIG_SYNC_FILE_RANGE)
9019#if defined(TARGET_NR_sync_file_range)
9020 case TARGET_NR_sync_file_range:
9021#if TARGET_ABI_BITS == 32
bfcedc57
RV
9022#if defined(TARGET_MIPS)
9023 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
9024 target_offset64(arg5, arg6), arg7));
9025#else
c727f47d
PM
9026 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
9027 target_offset64(arg4, arg5), arg6));
bfcedc57 9028#endif /* !TARGET_MIPS */
c727f47d
PM
9029#else
9030 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
9031#endif
9032 break;
9033#endif
9034#if defined(TARGET_NR_sync_file_range2)
9035 case TARGET_NR_sync_file_range2:
9036 /* This is like sync_file_range but the arguments are reordered */
9037#if TARGET_ABI_BITS == 32
9038 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
9039 target_offset64(arg5, arg6), arg2));
9040#else
9041 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
9042#endif
9043 break;
9044#endif
3b6edd16
PM
9045#endif
9046#if defined(CONFIG_EPOLL)
9047#if defined(TARGET_NR_epoll_create)
9048 case TARGET_NR_epoll_create:
9049 ret = get_errno(epoll_create(arg1));
9050 break;
9051#endif
9052#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
9053 case TARGET_NR_epoll_create1:
9054 ret = get_errno(epoll_create1(arg1));
9055 break;
9056#endif
9057#if defined(TARGET_NR_epoll_ctl)
9058 case TARGET_NR_epoll_ctl:
9059 {
9060 struct epoll_event ep;
9061 struct epoll_event *epp = 0;
9062 if (arg4) {
9063 struct target_epoll_event *target_ep;
9064 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
9065 goto efault;
9066 }
9067 ep.events = tswap32(target_ep->events);
9068 /* The epoll_data_t union is just opaque data to the kernel,
9069 * so we transfer all 64 bits across and need not worry what
9070 * actual data type it is.
9071 */
9072 ep.data.u64 = tswap64(target_ep->data.u64);
9073 unlock_user_struct(target_ep, arg4, 0);
9074 epp = &ep;
9075 }
9076 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
9077 break;
9078 }
9079#endif
9080
9081#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
9082#define IMPLEMENT_EPOLL_PWAIT
9083#endif
9084#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
9085#if defined(TARGET_NR_epoll_wait)
9086 case TARGET_NR_epoll_wait:
9087#endif
9088#if defined(IMPLEMENT_EPOLL_PWAIT)
9089 case TARGET_NR_epoll_pwait:
9090#endif
9091 {
9092 struct target_epoll_event *target_ep;
9093 struct epoll_event *ep;
9094 int epfd = arg1;
9095 int maxevents = arg3;
9096 int timeout = arg4;
9097
9098 target_ep = lock_user(VERIFY_WRITE, arg2,
9099 maxevents * sizeof(struct target_epoll_event), 1);
9100 if (!target_ep) {
9101 goto efault;
9102 }
9103
9104 ep = alloca(maxevents * sizeof(struct epoll_event));
9105
9106 switch (num) {
9107#if defined(IMPLEMENT_EPOLL_PWAIT)
9108 case TARGET_NR_epoll_pwait:
9109 {
9110 target_sigset_t *target_set;
9111 sigset_t _set, *set = &_set;
9112
9113 if (arg5) {
9114 target_set = lock_user(VERIFY_READ, arg5,
9115 sizeof(target_sigset_t), 1);
9116 if (!target_set) {
9117 unlock_user(target_ep, arg2, 0);
9118 goto efault;
9119 }
9120 target_to_host_sigset(set, target_set);
9121 unlock_user(target_set, arg5, 0);
9122 } else {
9123 set = NULL;
9124 }
9125
9126 ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
9127 break;
9128 }
9129#endif
9130#if defined(TARGET_NR_epoll_wait)
9131 case TARGET_NR_epoll_wait:
9132 ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
9133 break;
9134#endif
9135 default:
9136 ret = -TARGET_ENOSYS;
9137 }
9138 if (!is_error(ret)) {
9139 int i;
9140 for (i = 0; i < ret; i++) {
9141 target_ep[i].events = tswap32(ep[i].events);
9142 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
9143 }
9144 }
9145 unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
9146 break;
9147 }
9148#endif
163a05a8
PM
9149#endif
9150#ifdef TARGET_NR_prlimit64
9151 case TARGET_NR_prlimit64:
9152 {
9153 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
9154 struct target_rlimit64 *target_rnew, *target_rold;
9155 struct host_rlimit64 rnew, rold, *rnewp = 0;
9156 if (arg3) {
9157 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
9158 goto efault;
9159 }
9160 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
9161 rnew.rlim_max = tswap64(target_rnew->rlim_max);
9162 unlock_user_struct(target_rnew, arg3, 0);
9163 rnewp = &rnew;
9164 }
9165
9166 ret = get_errno(sys_prlimit64(arg1, arg2, rnewp, arg4 ? &rold : 0));
9167 if (!is_error(ret) && arg4) {
9168 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
9169 goto efault;
9170 }
9171 target_rold->rlim_cur = tswap64(rold.rlim_cur);
9172 target_rold->rlim_max = tswap64(rold.rlim_max);
9173 unlock_user_struct(target_rold, arg4, 1);
9174 }
9175 break;
9176 }
3d21d29c
RH
9177#endif
9178#ifdef TARGET_NR_gethostname
9179 case TARGET_NR_gethostname:
9180 {
9181 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
9182 if (name) {
9183 ret = get_errno(gethostname(name, arg2));
9184 unlock_user(name, arg1, arg2);
9185 } else {
9186 ret = -TARGET_EFAULT;
9187 }
9188 break;
9189 }
89aaf1a6
RV
9190#endif
9191#ifdef TARGET_NR_atomic_cmpxchg_32
9192 case TARGET_NR_atomic_cmpxchg_32:
9193 {
9194 /* should use start_exclusive from main.c */
9195 abi_ulong mem_value;
9196 if (get_user_u32(mem_value, arg6)) {
9197 target_siginfo_t info;
9198 info.si_signo = SIGSEGV;
9199 info.si_errno = 0;
9200 info.si_code = TARGET_SEGV_MAPERR;
9201 info._sifields._sigfault._addr = arg6;
9202 queue_signal((CPUArchState *)cpu_env, info.si_signo, &info);
9203 ret = 0xdeadbeef;
9204
9205 }
9206 if (mem_value == arg2)
9207 put_user_u32(arg1, arg6);
9208 ret = mem_value;
9209 break;
9210 }
9211#endif
9212#ifdef TARGET_NR_atomic_barrier
9213 case TARGET_NR_atomic_barrier:
9214 {
9215 /* Like the kernel implementation and the qemu arm barrier, no-op this? */
3b899ea7 9216 ret = 0;
89aaf1a6
RV
9217 break;
9218 }
d0927938 9219#endif
f4f1e10a
ECL
9220
9221#ifdef TARGET_NR_timer_create
9222 case TARGET_NR_timer_create:
9223 {
9224 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
9225
9226 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
9227 struct target_sigevent *ptarget_sevp;
9228 struct target_timer_t *ptarget_timer;
9229
9230 int clkid = arg1;
9231 int timer_index = next_free_host_timer();
9232
9233 if (timer_index < 0) {
9234 ret = -TARGET_EAGAIN;
9235 } else {
9236 timer_t *phtimer = g_posix_timers + timer_index;
9237
9238 if (arg2) {
9239 if (!lock_user_struct(VERIFY_READ, ptarget_sevp, arg2, 1)) {
9240 goto efault;
9241 }
9242
9243 host_sevp.sigev_signo = tswap32(ptarget_sevp->sigev_signo);
9244 host_sevp.sigev_notify = tswap32(ptarget_sevp->sigev_notify);
9245
9246 phost_sevp = &host_sevp;
9247 }
9248
9249 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
9250 if (ret) {
9251 phtimer = NULL;
9252 } else {
9253 if (!lock_user_struct(VERIFY_WRITE, ptarget_timer, arg3, 1)) {
9254 goto efault;
9255 }
9256 ptarget_timer->ptr = tswap32(0xcafe0000 | timer_index);
9257 unlock_user_struct(ptarget_timer, arg3, 1);
9258 }
9259 }
9260 break;
9261 }
9262#endif
9263
9264#ifdef TARGET_NR_timer_settime
9265 case TARGET_NR_timer_settime:
9266 {
9267 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
9268 * struct itimerspec * old_value */
9269 arg1 &= 0xffff;
9270 if (arg3 == 0 || arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
9271 ret = -TARGET_EINVAL;
9272 } else {
9273 timer_t htimer = g_posix_timers[arg1];
9274 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
9275
9276 target_to_host_itimerspec(&hspec_new, arg3);
9277 ret = get_errno(
9278 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
9279 host_to_target_itimerspec(arg2, &hspec_old);
9280 }
9281 break;
9282 }
9283#endif
9284
9285#ifdef TARGET_NR_timer_gettime
9286 case TARGET_NR_timer_gettime:
9287 {
9288 /* args: timer_t timerid, struct itimerspec *curr_value */
9289 arg1 &= 0xffff;
9290 if (!arg2) {
9291 return -TARGET_EFAULT;
9292 } else if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
9293 ret = -TARGET_EINVAL;
9294 } else {
9295 timer_t htimer = g_posix_timers[arg1];
9296 struct itimerspec hspec;
9297 ret = get_errno(timer_gettime(htimer, &hspec));
9298
9299 if (host_to_target_itimerspec(arg2, &hspec)) {
9300 ret = -TARGET_EFAULT;
9301 }
9302 }
9303 break;
9304 }
9305#endif
9306
9307#ifdef TARGET_NR_timer_getoverrun
9308 case TARGET_NR_timer_getoverrun:
9309 {
9310 /* args: timer_t timerid */
9311 arg1 &= 0xffff;
9312 if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
9313 ret = -TARGET_EINVAL;
9314 } else {
9315 timer_t htimer = g_posix_timers[arg1];
9316 ret = get_errno(timer_getoverrun(htimer));
9317 }
9318 break;
9319 }
9320#endif
9321
9322#ifdef TARGET_NR_timer_delete
9323 case TARGET_NR_timer_delete:
9324 {
9325 /* args: timer_t timerid */
9326 arg1 &= 0xffff;
9327 if (arg1 < 0 || arg1 >= ARRAY_SIZE(g_posix_timers)) {
9328 ret = -TARGET_EINVAL;
9329 } else {
9330 timer_t htimer = g_posix_timers[arg1];
9331 ret = get_errno(timer_delete(htimer));
9332 g_posix_timers[arg1] = 0;
9333 }
9334 break;
9335 }
9336#endif
9337
31e31b8a
FB
9338 default:
9339 unimplemented:
5cd4393b 9340 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 9341#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 9342 unimplemented_nowarn:
80a9d035 9343#endif
0da46a6e 9344 ret = -TARGET_ENOSYS;
31e31b8a
FB
9345 break;
9346 }
579a97f7 9347fail:
c573ff67 9348#ifdef DEBUG
0bf9e31a 9349 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
c573ff67 9350#endif
b92c47c1
TS
9351 if(do_strace)
9352 print_syscall_ret(num, ret);
31e31b8a 9353 return ret;
579a97f7
FB
9354efault:
9355 ret = -TARGET_EFAULT;
9356 goto fail;
31e31b8a 9357}
This page took 2.229925 seconds and 4 git commands to generate.