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