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