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