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