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