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