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