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