]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/syscall.c
tests/vm: custom openbsd partitioning to increase /home space
[mirror_qemu.git] / linux-user / syscall.c
CommitLineData
31e31b8a
FB
1/*
2 * Linux syscalls
5fafdf24 3 *
31e31b8a
FB
4 * Copyright (c) 2003 Fabrice Bellard
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
31e31b8a 18 */
d5b3a9b6 19#define _ATFILE_SOURCE
d39594e9 20#include "qemu/osdep.h"
f348b6d1
VB
21#include "qemu/cutils.h"
22#include "qemu/path.h"
9bdfa4d2 23#include "qemu/memfd.h"
dc5e9ac7 24#include "qemu/queue.h"
720ace24 25#include "qemu/plugin.h"
fe080593 26#include "target_mman.h"
31e31b8a
FB
27#include <elf.h>
28#include <endian.h>
c56dc774 29#include <grp.h>
d08d3bb8
TS
30#include <sys/ipc.h>
31#include <sys/msg.h>
31e31b8a 32#include <sys/wait.h>
31e31b8a 33#include <sys/mount.h>
586b0bef
JS
34#include <sys/file.h>
35#include <sys/fsuid.h>
36#include <sys/personality.h>
39b9aae1 37#include <sys/prctl.h>
31e31b8a 38#include <sys/resource.h>
31e31b8a 39#include <sys/swap.h>
e0eb210e 40#include <linux/capability.h>
31e31b8a 41#include <sched.h>
19f59bce 42#include <sys/timex.h>
31e31b8a 43#include <sys/socket.h>
6d5d5dde 44#include <linux/sockios.h>
607175e0 45#include <sys/un.h>
31e31b8a 46#include <sys/uio.h>
0839f11c 47#include <poll.h>
32f36bce 48#include <sys/times.h>
8853f86e 49#include <sys/shm.h>
fa294816 50#include <sys/sem.h>
56c8f68f 51#include <sys/statfs.h>
ebc05488 52#include <utime.h>
a5448a7d 53#include <sys/sysinfo.h>
e36800c9 54#include <sys/signalfd.h>
72f03900 55//#include <sys/user.h>
22db1213 56#include <netinet/in.h>
8853f86e 57#include <netinet/ip.h>
7854b056 58#include <netinet/tcp.h>
fe51b0a5 59#include <netinet/udp.h>
86fcd946 60#include <linux/wireless.h>
920394db 61#include <linux/icmp.h>
ee1ac3a1 62#include <linux/icmpv6.h>
6addf06a 63#include <linux/if_tun.h>
22db1213 64#include <linux/in6.h>
ee1ac3a1 65#include <linux/errqueue.h>
d6d6d6fe 66#include <linux/random.h>
d80a1905
RV
67#ifdef CONFIG_TIMERFD
68#include <sys/timerfd.h>
69#endif
c2882b96
RV
70#ifdef CONFIG_EVENTFD
71#include <sys/eventfd.h>
72#endif
3b6edd16
PM
73#ifdef CONFIG_EPOLL
74#include <sys/epoll.h>
75#endif
a790ae38 76#ifdef CONFIG_ATTR
1de7afc9 77#include "qemu/xattr.h"
a790ae38 78#endif
a8fd1aba
PM
79#ifdef CONFIG_SENDFILE
80#include <sys/sendfile.h>
81#endif
4a9d5f89 82#ifdef HAVE_SYS_KCOV_H
bd27e675
AM
83#include <sys/kcov.h>
84#endif
31e31b8a
FB
85
86#define termios host_termios
87#define winsize host_winsize
88#define termio host_termio
04369ff2
FB
89#define sgttyb host_sgttyb /* same as target */
90#define tchars host_tchars /* same as target */
91#define ltchars host_ltchars /* same as target */
31e31b8a
FB
92
93#include <linux/termios.h>
94#include <linux/unistd.h>
31e31b8a
FB
95#include <linux/cdrom.h>
96#include <linux/hdreg.h>
97#include <linux/soundcard.h>
19b84f3c 98#include <linux/kd.h>
8fbd6b52 99#include <linux/mtio.h>
350d1779 100#include <linux/fs.h>
ab22b4dd 101#include <linux/fd.h>
dace20dc 102#if defined(CONFIG_FIEMAP)
285da2b9 103#include <linux/fiemap.h>
dace20dc 104#endif
f7680a55 105#include <linux/fb.h>
6c753a63
CT
106#if defined(CONFIG_USBFS)
107#include <linux/usbdevice_fs.h>
a133367e 108#include <linux/usb/ch9.h>
6c753a63 109#endif
f7680a55 110#include <linux/vt.h>
56e904ec 111#include <linux/dm-ioctl.h>
c07ecc68 112#include <linux/reboot.h>
7ff7b666 113#include <linux/route.h>
f57d4192 114#include <linux/filter.h>
fff8c539 115#include <linux/blkpg.h>
a82ea939 116#include <netpacket/packet.h>
6c5b5645 117#include <linux/netlink.h>
f31dddd2 118#include <linux/if_alg.h>
68365f96 119#include <linux/rtc.h>
1c4c6fcd 120#include <sound/asound.h>
48f670ec 121#ifdef HAVE_BTRFS_H
d6092e08
FB
122#include <linux/btrfs.h>
123#endif
e865b97f
CG
124#ifdef HAVE_DRM_H
125#include <libdrm/drm.h>
913b03c2 126#include <libdrm/i915_drm.h>
e865b97f 127#endif
d7e4036e 128#include "linux_loop.h"
18cb0088 129#include "uname.h"
31e31b8a 130
3ef693a0 131#include "qemu.h"
3b249d26 132#include "user-internals.h"
a44d57a3 133#include "strace.h"
2113aed6 134#include "signal-common.h"
3ad0a769 135#include "loader.h"
5423e6d3 136#include "user-mmap.h"
bbf15aaf 137#include "user/safe-syscall.h"
5ebdd774 138#include "qemu/guest-random.h"
01ef6b9e 139#include "qemu/selfmap.h"
c36f7a64 140#include "user/syscall-trace.h"
5da4063f 141#include "special-errno.h"
51977e25 142#include "qapi/error.h"
f7e6a401 143#include "fd-trans.h"
dcb32f1d 144#include "tcg/tcg.h"
bd5ccd61 145#include "cpu_loop-common.h"
31e31b8a 146
5ea2fc84
PM
147#ifndef CLONE_IO
148#define CLONE_IO 0x80000000 /* Clone io context */
149#endif
150
151/* We can't directly call the host clone syscall, because this will
152 * badly confuse libc (breaking mutexes, for example). So we must
153 * divide clone flags into:
154 * * flag combinations that look like pthread_create()
155 * * flag combinations that look like fork()
156 * * flags we can implement within QEMU itself
157 * * flags we can't support and will return an error for
158 */
159/* For thread creation, all these flags must be present; for
160 * fork, none must be present.
161 */
162#define CLONE_THREAD_FLAGS \
163 (CLONE_VM | CLONE_FS | CLONE_FILES | \
164 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
165
166/* These flags are ignored:
167 * CLONE_DETACHED is now ignored by the kernel;
168 * CLONE_IO is just an optimisation hint to the I/O scheduler
169 */
170#define CLONE_IGNORED_FLAGS \
171 (CLONE_DETACHED | CLONE_IO)
172
895ce8bb
HD
173#ifndef CLONE_PIDFD
174# define CLONE_PIDFD 0x00001000
175#endif
176
5ea2fc84
PM
177/* Flags for fork which we can implement within QEMU itself */
178#define CLONE_OPTIONAL_FORK_FLAGS \
895ce8bb 179 (CLONE_SETTLS | CLONE_PARENT_SETTID | CLONE_PIDFD | \
5ea2fc84
PM
180 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
181
182/* Flags for thread creation which we can implement within QEMU itself */
183#define CLONE_OPTIONAL_THREAD_FLAGS \
184 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
185 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
186
187#define CLONE_INVALID_FORK_FLAGS \
188 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
189
190#define CLONE_INVALID_THREAD_FLAGS \
191 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
192 CLONE_IGNORED_FLAGS))
193
194/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
195 * have almost all been allocated. We cannot support any of
196 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
197 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
198 * The checks against the invalid thread masks above will catch these.
199 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
200 */
30813cea 201
71a8f7fe
TB
202/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
203 * once. This exercises the codepaths for restart.
204 */
205//#define DEBUG_ERESTARTSYS
31e31b8a 206
1a9353d2 207//#include <linux/msdos_fs.h>
540a736f
RH
208#define VFAT_IOCTL_READDIR_BOTH \
209 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
210#define VFAT_IOCTL_READDIR_SHORT \
211 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
1a9353d2 212
70a194b9
FB
213#undef _syscall0
214#undef _syscall1
215#undef _syscall2
216#undef _syscall3
217#undef _syscall4
218#undef _syscall5
83fcb515 219#undef _syscall6
70a194b9 220
83fcb515 221#define _syscall0(type,name) \
8fcd3692 222static type name (void) \
83fcb515
FB
223{ \
224 return syscall(__NR_##name); \
225}
70a194b9 226
83fcb515 227#define _syscall1(type,name,type1,arg1) \
8fcd3692 228static type name (type1 arg1) \
83fcb515
FB
229{ \
230 return syscall(__NR_##name, arg1); \
70a194b9
FB
231}
232
83fcb515 233#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 234static type name (type1 arg1,type2 arg2) \
83fcb515
FB
235{ \
236 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
237}
238
83fcb515 239#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 240static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
241{ \
242 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
243}
244
83fcb515 245#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 246static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
247{ \
248 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
249}
250
83fcb515
FB
251#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
252 type5,arg5) \
8fcd3692 253static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
254{ \
255 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
256}
257
83fcb515
FB
258
259#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
260 type5,arg5,type6,arg6) \
8fcd3692
BS
261static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
262 type6 arg6) \
83fcb515
FB
263{ \
264 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 265}
83fcb515 266
70a194b9 267
31e31b8a 268#define __NR_sys_uname __NR_uname
72f03900 269#define __NR_sys_getcwd1 __NR_getcwd
72f03900 270#define __NR_sys_getdents __NR_getdents
dab2ed99 271#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 272#define __NR_sys_getpriority __NR_getpriority
66fb9763 273#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
cf8b8bfc 274#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
7494b0f9 275#define __NR_sys_syslog __NR_syslog
14690296
AF
276#if defined(__NR_futex)
277# define __NR_sys_futex __NR_futex
278#endif
279#if defined(__NR_futex_time64)
280# define __NR_sys_futex_time64 __NR_futex_time64
281#endif
efa92184 282#define __NR_sys_statx __NR_statx
31e31b8a 283
b1cef6d0 284#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
9af9eaaa
FB
285#define __NR__llseek __NR_lseek
286#endif
287
a29e5ba2
JH
288/* Newer kernel ports have llseek() instead of _llseek() */
289#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
290#define TARGET_NR__llseek TARGET_NR_llseek
291#endif
292
78721301
HD
293/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
294#ifndef TARGET_O_NONBLOCK_MASK
295#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
296#endif
297
71ba74f6
DB
298#define __NR_sys_gettid __NR_gettid
299_syscall0(int, sys_gettid)
2b3f64cb
PM
300
301/* For the 64-bit guest on 32-bit host case we must emulate
302 * getdents using getdents64, because otherwise the host
303 * might hand us back more dirent records than we can fit
304 * into the guest buffer after structure format conversion.
305 * Otherwise we emulate getdents with getdents if the host has it.
306 */
307#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
308#define EMULATE_GETDENTS_WITH_GETDENTS
309#endif
310
311#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
3b3f24ad 312_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3307e236 313#endif
2b3f64cb
PM
314#if (defined(TARGET_NR_getdents) && \
315 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
3307e236 316 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
3b3f24ad
AJ
317_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
318#endif
d35b261c 319#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
320_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
321 loff_t *, res, uint, wh);
322#endif
c1a402a7 323_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
cf8b8bfc
MS
324_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
325 siginfo_t *, uinfo)
3b3f24ad 326_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
3b3f24ad
AJ
327#ifdef __NR_exit_group
328_syscall1(int,exit_group,int,error_code)
329#endif
af804f39
HD
330#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
331#define __NR_sys_close_range __NR_close_range
332_syscall3(int,sys_close_range,int,first,int,last,int,flags)
333#ifndef CLOSE_RANGE_CLOEXEC
334#define CLOSE_RANGE_CLOEXEC (1U << 2)
335#endif
336#endif
14690296 337#if defined(__NR_futex)
3b3f24ad
AJ
338_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
339 const struct timespec *,timeout,int *,uaddr2,int,val3)
340#endif
14690296
AF
341#if defined(__NR_futex_time64)
342_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
343 const struct timespec *,timeout,int *,uaddr2,int,val3)
344#endif
cc054c6f
HD
345#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
346_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
347#endif
348#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
349_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
350 unsigned int, flags);
351#endif
352#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
353_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
354#endif
737de1d1
MF
355#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
356_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
357 unsigned long *, user_mask_ptr);
358#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
359_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
360 unsigned long *, user_mask_ptr);
45ad761c
TT
361/* sched_attr is not defined in glibc */
362struct sched_attr {
363 uint32_t size;
364 uint32_t sched_policy;
365 uint64_t sched_flags;
366 int32_t sched_nice;
367 uint32_t sched_priority;
368 uint64_t sched_runtime;
369 uint64_t sched_deadline;
370 uint64_t sched_period;
371 uint32_t sched_util_min;
372 uint32_t sched_util_max;
373};
374#define __NR_sys_sched_getattr __NR_sched_getattr
375_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
376 unsigned int, size, unsigned int, flags);
377#define __NR_sys_sched_setattr __NR_sched_setattr
378_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
379 unsigned int, flags);
407a119b
TT
380#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
381_syscall1(int, sys_sched_getscheduler, pid_t, pid);
382#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
383_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
384 const struct sched_param *, param);
385#define __NR_sys_sched_getparam __NR_sched_getparam
386_syscall2(int, sys_sched_getparam, pid_t, pid,
387 struct sched_param *, param);
388#define __NR_sys_sched_setparam __NR_sched_setparam
389_syscall2(int, sys_sched_setparam, pid_t, pid,
390 const struct sched_param *, param);
b827c3ed
ST
391#define __NR_sys_getcpu __NR_getcpu
392_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
0f6b4d21
AG
393_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
394 void *, arg);
e0eb210e
PM
395_syscall2(int, capget, struct __user_cap_header_struct *, header,
396 struct __user_cap_data_struct *, data);
397_syscall2(int, capset, struct __user_cap_header_struct *, header,
398 struct __user_cap_data_struct *, data);
ab31cda3
PB
399#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
400_syscall2(int, ioprio_get, int, which, int, who)
401#endif
402#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
403_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
404#endif
f894efd1
LV
405#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
406_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
407#endif
3b3f24ad 408
2f14788c
LV
409#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
410_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
411 unsigned long, idx1, unsigned long, idx2)
412#endif
413
efa92184
AR
414/*
415 * It is assumed that struct statx is architecture independent.
416 */
417#if defined(TARGET_NR_statx) && defined(__NR_statx)
418_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
419 unsigned int, mask, struct target_statx *, statxbuf)
420#endif
8500476f
AS
421#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
422_syscall2(int, membarrier, int, cmd, int, flags)
423#endif
efa92184 424
180d4ef3 425static const bitmask_transtbl fcntl_flags_tbl[] = {
3b3f24ad
AJ
426 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
427 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
428 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
429 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
430 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
431 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
432 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
433 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
afc8763f 434 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
3b3f24ad
AJ
435 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
436 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
437 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
438 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
3b3f24ad
AJ
439#if defined(O_DIRECT)
440 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
afc8763f
RH
441#endif
442#if defined(O_NOATIME)
443 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
444#endif
445#if defined(O_CLOEXEC)
446 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
447#endif
448#if defined(O_PATH)
449 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
5f9cee46
RV
450#endif
451#if defined(O_TMPFILE)
452 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
afc8763f
RH
453#endif
454 /* Don't terminate the list prematurely on 64-bit host+guest. */
455#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
456 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
3b3f24ad
AJ
457#endif
458 { 0, 0, 0, 0 }
459};
460
0f6bb195 461_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
3b3f24ad 462
cac46eb0 463#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
700fa58e 464#if defined(__NR_utimensat)
1acae9f2 465#define __NR_sys_utimensat __NR_utimensat
9007f0ef
TS
466_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
467 const struct timespec *,tsp,int,flags)
1acae9f2
PM
468#else
469static int sys_utimensat(int dirfd, const char *pathname,
470 const struct timespec times[2], int flags)
471{
472 errno = ENOSYS;
473 return -1;
474}
9007f0ef 475#endif
1acae9f2 476#endif /* TARGET_NR_utimensat */
3b3f24ad 477
95d0307c
AS
478#ifdef TARGET_NR_renameat2
479#if defined(__NR_renameat2)
480#define __NR_sys_renameat2 __NR_renameat2
481_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
482 const char *, new, unsigned int, flags)
483#else
484static int sys_renameat2(int oldfd, const char *old,
485 int newfd, const char *new, int flags)
486{
487 if (flags == 0) {
488 return renameat(oldfd, old, newfd, new);
489 }
490 errno = ENOSYS;
491 return -1;
492}
493#endif
494#endif /* TARGET_NR_renameat2 */
495
3b3f24ad 496#ifdef CONFIG_INOTIFY
8690e420 497#include <sys/inotify.h>
3b3f24ad
AJ
498#else
499/* Userspace can usually survive runtime without inotify */
500#undef TARGET_NR_inotify_init
c05c7a73 501#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
502#undef TARGET_NR_inotify_add_watch
503#undef TARGET_NR_inotify_rm_watch
504#endif /* CONFIG_INOTIFY */
505
163a05a8
PM
506#if defined(TARGET_NR_prlimit64)
507#ifndef __NR_prlimit64
508# define __NR_prlimit64 -1
509#endif
510#define __NR_sys_prlimit64 __NR_prlimit64
511/* The glibc rlimit structure may not be that used by the underlying syscall */
512struct host_rlimit64 {
513 uint64_t rlim_cur;
514 uint64_t rlim_max;
515};
516_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
517 const struct host_rlimit64 *, new_limit,
518 struct host_rlimit64 *, old_limit)
519#endif
520
f4f1e10a
ECL
521
522#if defined(TARGET_NR_timer_create)
6f9ff551 523/* Maximum of 32 active POSIX timers allowed at any one time. */
9e59899f
PM
524#define GUEST_TIMER_MAX 32
525static timer_t g_posix_timers[GUEST_TIMER_MAX];
526static int g_posix_timer_allocated[GUEST_TIMER_MAX];
f4f1e10a
ECL
527
528static inline int next_free_host_timer(void)
529{
9e59899f
PM
530 int k;
531 for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
532 if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
f4f1e10a
ECL
533 return k;
534 }
535 }
536 return -1;
537}
9e59899f
PM
538
539static inline void free_host_timer_slot(int id)
540{
541 qatomic_store_release(g_posix_timer_allocated + id, 0);
542}
f4f1e10a
ECL
543#endif
544
3ffe3268 545static inline int host_to_target_errno(int host_errno)
637947f1 546{
3ffe3268
PMD
547 switch (host_errno) {
548#define E(X) case X: return TARGET_##X;
549#include "errnos.c.inc"
550#undef E
551 default:
552 return host_errno;
2466119c 553 }
637947f1
TS
554}
555
3ffe3268 556static inline int target_to_host_errno(int target_errno)
b92c47c1 557{
3ffe3268
PMD
558 switch (target_errno) {
559#define E(X) case TARGET_##X: return X;
560#include "errnos.c.inc"
561#undef E
562 default:
563 return target_errno;
2466119c 564 }
b92c47c1
TS
565}
566
892a4f6a 567abi_long get_errno(abi_long ret)
31e31b8a
FB
568{
569 if (ret == -1)
637947f1 570 return -host_to_target_errno(errno);
31e31b8a
FB
571 else
572 return ret;
573}
574
7dcdaeaf 575const char *target_strerror(int err)
b92c47c1 576{
af254a27 577 if (err == QEMU_ERESTARTSYS) {
da2a34f7
PM
578 return "To be restarted";
579 }
57a0c938 580 if (err == QEMU_ESIGRETURN) {
da2a34f7
PM
581 return "Successful exit from sigreturn";
582 }
583
b92c47c1
TS
584 return strerror(target_to_host_errno(err));
585}
586
45ad761c
TT
587static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
588{
589 int i;
590 uint8_t b;
591 if (usize <= ksize) {
592 return 1;
593 }
594 for (i = ksize; i < usize; i++) {
595 if (get_user_u8(b, addr + i)) {
596 return -TARGET_EFAULT;
597 }
598 if (b != 0) {
599 return 0;
600 }
601 }
602 return 1;
603}
604
4d330cee
TB
605#define safe_syscall0(type, name) \
606static type safe_##name(void) \
607{ \
608 return safe_syscall(__NR_##name); \
609}
610
611#define safe_syscall1(type, name, type1, arg1) \
612static type safe_##name(type1 arg1) \
613{ \
614 return safe_syscall(__NR_##name, arg1); \
615}
616
617#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
618static type safe_##name(type1 arg1, type2 arg2) \
619{ \
620 return safe_syscall(__NR_##name, arg1, arg2); \
621}
622
623#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
624static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
625{ \
626 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
627}
628
629#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
630 type4, arg4) \
631static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
632{ \
633 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
634}
635
636#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
637 type4, arg4, type5, arg5) \
638static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
639 type5 arg5) \
640{ \
641 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
642}
643
644#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
645 type4, arg4, type5, arg5, type6, arg6) \
646static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
647 type5 arg5, type6 arg6) \
648{ \
649 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
650}
651
50afd02b
TB
652safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
653safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
c10a0738
TB
654safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
655 int, flags, mode_t, mode)
859e8a89 656#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
4af80a37
TB
657safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
658 struct rusage *, rusage)
859e8a89 659#endif
4af80a37
TB
660safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
661 int, options, struct rusage *, rusage)
55bbe4d5
DD
662safe_syscall5(int, execveat, int, dirfd, const char *, filename,
663 char **, argv, char **, envp, int, flags)
859e8a89 664#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 665 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
6df9d38d
PM
666safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
667 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
859e8a89 668#endif
e5ce9688 669#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
a6130237
PM
670safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
671 struct timespec *, tsp, const sigset_t *, sigmask,
672 size_t, sigsetsize)
859e8a89 673#endif
227f0214
PM
674safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
675 int, maxevents, int, timeout, const sigset_t *, sigmask,
676 size_t, sigsetsize)
14690296 677#if defined(__NR_futex)
d509eeb1
PM
678safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
679 const struct timespec *,timeout,int *,uaddr2,int,val3)
859e8a89 680#endif
14690296
AF
681#if defined(__NR_futex_time64)
682safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
683 const struct timespec *,timeout,int *,uaddr2,int,val3)
684#endif
2fe4fba1 685safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
bef653d9
PM
686safe_syscall2(int, kill, pid_t, pid, int, sig)
687safe_syscall2(int, tkill, int, tid, int, sig)
688safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
918c03ed
PM
689safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
690safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
0f26386c
DJ
691safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
692 unsigned long, pos_l, unsigned long, pos_h)
f8d00fba
DJ
693safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
694 unsigned long, pos_l, unsigned long, pos_h)
2a3c7619
PM
695safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
696 socklen_t, addrlen)
66687530
PM
697safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
698 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
699safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
700 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
701safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
702safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
2a845989 703safe_syscall2(int, flock, int, fd, int, operation)
ddcbde15 704#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
b3f82330
PM
705safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
706 const struct timespec *, uts, size_t, sigsetsize)
859e8a89 707#endif
ff6dc130
PM
708safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
709 int, flags)
859e8a89 710#if defined(TARGET_NR_nanosleep)
9e518226
PM
711safe_syscall2(int, nanosleep, const struct timespec *, req,
712 struct timespec *, rem)
859e8a89 713#endif
6ac03b2c
FB
714#if defined(TARGET_NR_clock_nanosleep) || \
715 defined(TARGET_NR_clock_nanosleep_time64)
9e518226
PM
716safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
717 const struct timespec *, req, struct timespec *, rem)
718#endif
524fa340 719#ifdef __NR_ipc
d8c08b1e
MK
720#ifdef __s390x__
721safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
722 void *, ptr)
723#else
89f9fe44
PM
724safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
725 void *, ptr, long, fifth)
86e63695 726#endif
d8c08b1e 727#endif
86e63695
LV
728#ifdef __NR_msgsnd
729safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
730 int, flags)
86e63695
LV
731#endif
732#ifdef __NR_msgrcv
733safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
734 long, msgtype, int, flags)
86e63695
LV
735#endif
736#ifdef __NR_semtimedop
737safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
738 unsigned, nsops, const struct timespec *, timeout)
89f9fe44 739#endif
d107e375
FB
740#if defined(TARGET_NR_mq_timedsend) || \
741 defined(TARGET_NR_mq_timedsend_time64)
d40ecd66
PM
742safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
743 size_t, len, unsigned, prio, const struct timespec *, timeout)
859e8a89 744#endif
d107e375
FB
745#if defined(TARGET_NR_mq_timedreceive) || \
746 defined(TARGET_NR_mq_timedreceive_time64)
d40ecd66
PM
747safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
748 size_t, len, unsigned *, prio, const struct timespec *, timeout)
749#endif
84946457
AS
750#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
751safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
752 int, outfd, loff_t *, poutoff, size_t, length,
753 unsigned int, flags)
754#endif
755
49ca6f3e
PM
756/* We do ioctl like this rather than via safe_syscall3 to preserve the
757 * "third argument might be integer or pointer or not present" behaviour of
758 * the libc function.
759 */
760#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
435da5e7
PM
761/* Similarly for fcntl. Note that callers must always:
762 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
763 * use the flock64 struct rather than unsuffixed flock
764 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
765 */
766#ifdef __NR_fcntl64
767#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
768#else
769#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
770#endif
50afd02b 771
8289d112
PB
772static inline int host_to_target_sock_type(int host_type)
773{
774 int target_type;
775
776 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
777 case SOCK_DGRAM:
778 target_type = TARGET_SOCK_DGRAM;
779 break;
780 case SOCK_STREAM:
781 target_type = TARGET_SOCK_STREAM;
782 break;
783 default:
784 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
785 break;
786 }
787
788#if defined(SOCK_CLOEXEC)
789 if (host_type & SOCK_CLOEXEC) {
790 target_type |= TARGET_SOCK_CLOEXEC;
791 }
792#endif
793
794#if defined(SOCK_NONBLOCK)
795 if (host_type & SOCK_NONBLOCK) {
796 target_type |= TARGET_SOCK_NONBLOCK;
797 }
798#endif
799
800 return target_type;
801}
802
992f48a0 803static abi_ulong target_brk;
4d1de87c 804static abi_ulong brk_page;
31e31b8a 805
992f48a0 806void target_set_brk(abi_ulong new_brk)
31e31b8a 807{
86f04735 808 target_brk = new_brk;
4d1de87c 809 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
810}
811
0da46a6e 812/* do_brk() must return target values and target errnos. */
86f04735 813abi_long do_brk(abi_ulong brk_val)
31e31b8a 814{
992f48a0 815 abi_long mapped_addr;
ef4330c2 816 abi_ulong new_alloc_size;
86f04735 817 abi_ulong new_brk, new_host_brk_page;
31e31b8a 818
ee1bf83d
RH
819 /* brk pointers are always untagged */
820
86f04735
HD
821 /* return old brk value if brk_val unchanged or zero */
822 if (!brk_val || brk_val == target_brk) {
53a5960a 823 return target_brk;
4d1de87c 824 }
86f04735
HD
825
826 new_brk = TARGET_PAGE_ALIGN(brk_val);
827 new_host_brk_page = HOST_PAGE_ALIGN(brk_val);
828
829 /* brk_val and old target_brk might be on the same page */
830 if (new_brk == TARGET_PAGE_ALIGN(target_brk)) {
831 if (brk_val > target_brk) {
832 /* empty remaining bytes in (possibly larger) host page */
833 memset(g2h_untagged(target_brk), 0, new_host_brk_page - target_brk);
834 }
835 target_brk = brk_val;
7ab240ad 836 return target_brk;
4d1de87c 837 }
3b46e624 838
86f04735
HD
839 /* Release heap if necesary */
840 if (new_brk < target_brk) {
841 /* empty remaining bytes in (possibly larger) host page */
842 memset(g2h_untagged(brk_val), 0, new_host_brk_page - brk_val);
843
844 /* free unused host pages and set new brk_page */
845 target_munmap(new_host_brk_page, brk_page - new_host_brk_page);
846 brk_page = new_host_brk_page;
847
848 target_brk = brk_val;
849 return target_brk;
31e31b8a
FB
850 }
851
00faf08c
PM
852 /* We need to allocate more memory after the brk... Note that
853 * we don't use MAP_FIXED because that will map over the top of
854 * any existing mapping (like the one with the host libc or qemu
855 * itself); instead we treat "mapped but at wrong address" as
856 * a failure and unmap again.
857 */
86f04735
HD
858 new_alloc_size = new_host_brk_page - brk_page;
859 if (new_alloc_size) {
860 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 861 PROT_READ|PROT_WRITE,
00faf08c 862 MAP_ANON|MAP_PRIVATE, 0, 0));
86f04735
HD
863 } else {
864 mapped_addr = brk_page;
865 }
00faf08c
PM
866
867 if (mapped_addr == brk_page) {
70afc343
CV
868 /* Heap contents are initialized to zero, as for anonymous
869 * mapped pages. Technically the new pages are already
870 * initialized to zero since they *are* anonymous mapped
871 * pages, however we have to take care with the contents that
872 * come from the remaining part of the previous page: it may
873 * contains garbage data due to a previous heap usage (grown
874 * then shrunken). */
3e8f1628 875 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
70afc343 876
86f04735
HD
877 target_brk = brk_val;
878 brk_page = new_host_brk_page;
00faf08c
PM
879 return target_brk;
880 } else if (mapped_addr != -1) {
881 /* Mapped but at wrong address, meaning there wasn't actually
882 * enough space for this brk.
883 */
884 target_munmap(mapped_addr, new_alloc_size);
885 mapped_addr = -1;
886 }
7ab240ad 887
7dd46c02
RH
888#if defined(TARGET_ALPHA)
889 /* We (partially) emulate OSF/1 on Alpha, which requires we
890 return a proper errno, not an unchanged brk value. */
00faf08c 891 return -TARGET_ENOMEM;
7dd46c02 892#endif
00faf08c 893 /* For everything else, return the previous break. */
7ab240ad 894 return target_brk;
31e31b8a
FB
895}
896
859e8a89 897#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 898 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
26edcf41
TS
899static inline abi_long copy_from_user_fdset(fd_set *fds,
900 abi_ulong target_fds_addr,
901 int n)
31e31b8a 902{
26edcf41
TS
903 int i, nw, j, k;
904 abi_ulong b, *target_fds;
905
b1b2db29 906 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
907 if (!(target_fds = lock_user(VERIFY_READ,
908 target_fds_addr,
909 sizeof(abi_ulong) * nw,
910 1)))
911 return -TARGET_EFAULT;
912
913 FD_ZERO(fds);
914 k = 0;
915 for (i = 0; i < nw; i++) {
916 /* grab the abi_ulong */
917 __get_user(b, &target_fds[i]);
918 for (j = 0; j < TARGET_ABI_BITS; j++) {
919 /* check the bit inside the abi_ulong */
920 if ((b >> j) & 1)
921 FD_SET(k, fds);
922 k++;
31e31b8a 923 }
31e31b8a 924 }
26edcf41
TS
925
926 unlock_user(target_fds, target_fds_addr, 0);
927
928 return 0;
31e31b8a
FB
929}
930
055e0906
MF
931static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
932 abi_ulong target_fds_addr,
933 int n)
934{
935 if (target_fds_addr) {
936 if (copy_from_user_fdset(fds, target_fds_addr, n))
937 return -TARGET_EFAULT;
938 *fds_ptr = fds;
939 } else {
940 *fds_ptr = NULL;
941 }
942 return 0;
943}
944
26edcf41
TS
945static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
946 const fd_set *fds,
947 int n)
31e31b8a 948{
31e31b8a 949 int i, nw, j, k;
992f48a0 950 abi_long v;
26edcf41 951 abi_ulong *target_fds;
31e31b8a 952
b1b2db29 953 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
954 if (!(target_fds = lock_user(VERIFY_WRITE,
955 target_fds_addr,
956 sizeof(abi_ulong) * nw,
957 0)))
958 return -TARGET_EFAULT;
959
960 k = 0;
961 for (i = 0; i < nw; i++) {
962 v = 0;
963 for (j = 0; j < TARGET_ABI_BITS; j++) {
9ab709be 964 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
26edcf41 965 k++;
31e31b8a 966 }
26edcf41 967 __put_user(v, &target_fds[i]);
31e31b8a 968 }
26edcf41
TS
969
970 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
971
972 return 0;
31e31b8a 973}
859e8a89 974#endif
31e31b8a 975
c596ed17
FB
976#if defined(__alpha__)
977#define HOST_HZ 1024
978#else
979#define HOST_HZ 100
980#endif
981
992f48a0 982static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
983{
984#if HOST_HZ == TARGET_HZ
985 return ticks;
986#else
987 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
988#endif
989}
990
579a97f7
FB
991static inline abi_long host_to_target_rusage(abi_ulong target_addr,
992 const struct rusage *rusage)
b409186b 993{
53a5960a
PB
994 struct target_rusage *target_rusage;
995
579a97f7
FB
996 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
997 return -TARGET_EFAULT;
cbb21eed
MB
998 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
999 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
1000 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
1001 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
1002 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
1003 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
1004 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
1005 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
1006 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1007 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1008 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1009 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1010 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1011 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1012 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1013 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1014 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1015 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
53a5960a 1016 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
1017
1018 return 0;
b409186b
FB
1019}
1020
859e8a89 1021#ifdef TARGET_NR_setrlimit
cbb21eed 1022static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
81bbe906 1023{
cbb21eed 1024 abi_ulong target_rlim_swap;
95b33b2f
WT
1025 rlim_t result;
1026
cbb21eed
MB
1027 target_rlim_swap = tswapal(target_rlim);
1028 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1029 return RLIM_INFINITY;
1030
1031 result = target_rlim_swap;
1032 if (target_rlim_swap != (rlim_t)result)
1033 return RLIM_INFINITY;
95b33b2f
WT
1034
1035 return result;
81bbe906 1036}
859e8a89 1037#endif
81bbe906 1038
859e8a89 1039#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
cbb21eed 1040static inline abi_ulong host_to_target_rlim(rlim_t rlim)
81bbe906 1041{
cbb21eed
MB
1042 abi_ulong target_rlim_swap;
1043 abi_ulong result;
95b33b2f 1044
cbb21eed 1045 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
95b33b2f 1046 target_rlim_swap = TARGET_RLIM_INFINITY;
81bbe906 1047 else
95b33b2f 1048 target_rlim_swap = rlim;
cbb21eed 1049 result = tswapal(target_rlim_swap);
95b33b2f
WT
1050
1051 return result;
81bbe906 1052}
859e8a89 1053#endif
81bbe906 1054
e22b7015
WT
1055static inline int target_to_host_resource(int code)
1056{
1057 switch (code) {
1058 case TARGET_RLIMIT_AS:
1059 return RLIMIT_AS;
1060 case TARGET_RLIMIT_CORE:
1061 return RLIMIT_CORE;
1062 case TARGET_RLIMIT_CPU:
1063 return RLIMIT_CPU;
1064 case TARGET_RLIMIT_DATA:
1065 return RLIMIT_DATA;
1066 case TARGET_RLIMIT_FSIZE:
1067 return RLIMIT_FSIZE;
1068 case TARGET_RLIMIT_LOCKS:
1069 return RLIMIT_LOCKS;
1070 case TARGET_RLIMIT_MEMLOCK:
1071 return RLIMIT_MEMLOCK;
1072 case TARGET_RLIMIT_MSGQUEUE:
1073 return RLIMIT_MSGQUEUE;
1074 case TARGET_RLIMIT_NICE:
1075 return RLIMIT_NICE;
1076 case TARGET_RLIMIT_NOFILE:
1077 return RLIMIT_NOFILE;
1078 case TARGET_RLIMIT_NPROC:
1079 return RLIMIT_NPROC;
1080 case TARGET_RLIMIT_RSS:
1081 return RLIMIT_RSS;
1082 case TARGET_RLIMIT_RTPRIO:
1083 return RLIMIT_RTPRIO;
c3a28d71 1084#ifdef RLIMIT_RTTIME
244fd083
SB
1085 case TARGET_RLIMIT_RTTIME:
1086 return RLIMIT_RTTIME;
c3a28d71 1087#endif
e22b7015
WT
1088 case TARGET_RLIMIT_SIGPENDING:
1089 return RLIMIT_SIGPENDING;
1090 case TARGET_RLIMIT_STACK:
1091 return RLIMIT_STACK;
1092 default:
1093 return code;
1094 }
1095}
1096
788f5ec4
TS
1097static inline abi_long copy_from_user_timeval(struct timeval *tv,
1098 abi_ulong target_tv_addr)
31e31b8a 1099{
53a5960a
PB
1100 struct target_timeval *target_tv;
1101
6d5d5dde 1102 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
579a97f7 1103 return -TARGET_EFAULT;
6d5d5dde 1104 }
788f5ec4
TS
1105
1106 __get_user(tv->tv_sec, &target_tv->tv_sec);
1107 __get_user(tv->tv_usec, &target_tv->tv_usec);
1108
1109 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
1110
1111 return 0;
31e31b8a
FB
1112}
1113
788f5ec4
TS
1114static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1115 const struct timeval *tv)
31e31b8a 1116{
53a5960a
PB
1117 struct target_timeval *target_tv;
1118
6d5d5dde
DB
1119 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1120 return -TARGET_EFAULT;
1121 }
1122
1123 __put_user(tv->tv_sec, &target_tv->tv_sec);
1124 __put_user(tv->tv_usec, &target_tv->tv_usec);
1125
1126 unlock_user_struct(target_tv, target_tv_addr, 1);
1127
1128 return 0;
1129}
1130
6ac03b2c
FB
1131#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1132static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1133 abi_ulong target_tv_addr)
1134{
1135 struct target__kernel_sock_timeval *target_tv;
1136
1137 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1138 return -TARGET_EFAULT;
1139 }
1140
1141 __get_user(tv->tv_sec, &target_tv->tv_sec);
1142 __get_user(tv->tv_usec, &target_tv->tv_usec);
1143
1144 unlock_user_struct(target_tv, target_tv_addr, 0);
1145
1146 return 0;
1147}
1148#endif
1149
6d5d5dde 1150static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
6ac03b2c 1151 const struct timeval *tv)
6d5d5dde
DB
1152{
1153 struct target__kernel_sock_timeval *target_tv;
1154
1155 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
579a97f7 1156 return -TARGET_EFAULT;
6d5d5dde 1157 }
788f5ec4
TS
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);
579a97f7
FB
1163
1164 return 0;
31e31b8a
FB
1165}
1166
859e8a89
AF
1167#if defined(TARGET_NR_futex) || \
1168 defined(TARGET_NR_rt_sigtimedwait) || \
1169 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1170 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1171 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
d8c08b1e 1172 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
2c86c90f
FB
1173 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1174 defined(TARGET_NR_timer_settime) || \
1175 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
6d5d5dde
DB
1176static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1177 abi_ulong target_addr)
1178{
1179 struct target_timespec *target_ts;
1180
1181 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1182 return -TARGET_EFAULT;
1183 }
1184 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1185 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1186 unlock_user_struct(target_ts, target_addr, 0);
1187 return 0;
1188}
859e8a89 1189#endif
6d5d5dde 1190
828cb3a1
FB
1191#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1192 defined(TARGET_NR_timer_settime64) || \
d107e375
FB
1193 defined(TARGET_NR_mq_timedsend_time64) || \
1194 defined(TARGET_NR_mq_timedreceive_time64) || \
6ac03b2c 1195 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
ddcbde15 1196 defined(TARGET_NR_clock_nanosleep_time64) || \
cac46eb0
FB
1197 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1198 defined(TARGET_NR_utimensat) || \
1199 defined(TARGET_NR_utimensat_time64) || \
e5ce9688
FB
1200 defined(TARGET_NR_semtimedop_time64) || \
1201 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
c6c8d102
AF
1202static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1203 abi_ulong target_addr)
1204{
1205 struct target__kernel_timespec *target_ts;
1206
1207 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1208 return -TARGET_EFAULT;
1209 }
1210 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1211 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
00576757
LV
1212 /* in 32bit mode, this drops the padding */
1213 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
c6c8d102
AF
1214 unlock_user_struct(target_ts, target_addr, 0);
1215 return 0;
1216}
1217#endif
1218
6d5d5dde
DB
1219static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1220 struct timespec *host_ts)
1221{
1222 struct target_timespec *target_ts;
1223
1224 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1225 return -TARGET_EFAULT;
1226 }
1227 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1228 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1229 unlock_user_struct(target_ts, target_addr, 1);
1230 return 0;
1231}
1232
1233static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1234 struct timespec *host_ts)
1235{
1236 struct target__kernel_timespec *target_ts;
1237
1238 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1239 return -TARGET_EFAULT;
1240 }
1241 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1242 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1243 unlock_user_struct(target_ts, target_addr, 1);
1244 return 0;
1245}
1246
a52f5f87
RH
1247#if defined(TARGET_NR_gettimeofday)
1248static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1249 struct timezone *tz)
1250{
1251 struct target_timezone *target_tz;
1252
1253 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1254 return -TARGET_EFAULT;
1255 }
1256
1257 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1258 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1259
1260 unlock_user_struct(target_tz, target_tz_addr, 1);
1261
1262 return 0;
1263}
1264#endif
1265
859e8a89 1266#if defined(TARGET_NR_settimeofday)
ef4467e9
PB
1267static inline abi_long copy_from_user_timezone(struct timezone *tz,
1268 abi_ulong target_tz_addr)
1269{
1270 struct target_timezone *target_tz;
1271
1272 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1273 return -TARGET_EFAULT;
1274 }
1275
1276 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1277 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1278
1279 unlock_user_struct(target_tz, target_tz_addr, 0);
1280
1281 return 0;
1282}
859e8a89 1283#endif
ef4467e9 1284
8ec9cf89
NF
1285#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1286#include <mqueue.h>
1287
24e1003a
AJ
1288static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1289 abi_ulong target_mq_attr_addr)
1290{
1291 struct target_mq_attr *target_mq_attr;
1292
1293 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1294 target_mq_attr_addr, 1))
1295 return -TARGET_EFAULT;
1296
1297 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1298 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1299 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1300 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1301
1302 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1303
1304 return 0;
1305}
1306
1307static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1308 const struct mq_attr *attr)
1309{
1310 struct target_mq_attr *target_mq_attr;
1311
1312 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1313 target_mq_attr_addr, 0))
1314 return -TARGET_EFAULT;
1315
1316 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1317 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1318 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1319 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1320
1321 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1322
1323 return 0;
1324}
8ec9cf89 1325#endif
31e31b8a 1326
055e0906 1327#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 1328/* do_select() must return target values and target errnos. */
992f48a0 1329static abi_long do_select(int n,
26edcf41
TS
1330 abi_ulong rfd_addr, abi_ulong wfd_addr,
1331 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
1332{
1333 fd_set rfds, wfds, efds;
1334 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
6df9d38d
PM
1335 struct timeval tv;
1336 struct timespec ts, *ts_ptr;
992f48a0 1337 abi_long ret;
31e31b8a 1338
055e0906
MF
1339 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1340 if (ret) {
1341 return ret;
53a5960a 1342 }
055e0906
MF
1343 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1344 if (ret) {
1345 return ret;
53a5960a 1346 }
055e0906
MF
1347 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1348 if (ret) {
1349 return ret;
53a5960a 1350 }
3b46e624 1351
26edcf41 1352 if (target_tv_addr) {
788f5ec4
TS
1353 if (copy_from_user_timeval(&tv, target_tv_addr))
1354 return -TARGET_EFAULT;
6df9d38d
PM
1355 ts.tv_sec = tv.tv_sec;
1356 ts.tv_nsec = tv.tv_usec * 1000;
1357 ts_ptr = &ts;
31e31b8a 1358 } else {
6df9d38d 1359 ts_ptr = NULL;
31e31b8a 1360 }
26edcf41 1361
6df9d38d
PM
1362 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1363 ts_ptr, NULL));
53a5960a 1364
26edcf41
TS
1365 if (!is_error(ret)) {
1366 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1367 return -TARGET_EFAULT;
1368 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1369 return -TARGET_EFAULT;
1370 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1371 return -TARGET_EFAULT;
31e31b8a 1372
6df9d38d
PM
1373 if (target_tv_addr) {
1374 tv.tv_sec = ts.tv_sec;
1375 tv.tv_usec = ts.tv_nsec / 1000;
1376 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1377 return -TARGET_EFAULT;
1378 }
1379 }
31e31b8a 1380 }
579a97f7 1381
31e31b8a
FB
1382 return ret;
1383}
5457dc9e
LV
1384
1385#if defined(TARGET_WANT_OLD_SYS_SELECT)
1386static abi_long do_old_select(abi_ulong arg1)
1387{
1388 struct target_sel_arg_struct *sel;
1389 abi_ulong inp, outp, exp, tvp;
1390 long nsel;
1391
1392 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1393 return -TARGET_EFAULT;
1394 }
1395
1396 nsel = tswapal(sel->n);
1397 inp = tswapal(sel->inp);
1398 outp = tswapal(sel->outp);
1399 exp = tswapal(sel->exp);
1400 tvp = tswapal(sel->tvp);
1401
1402 unlock_user_struct(sel, arg1, 0);
1403
1404 return do_select(nsel, inp, outp, exp, tvp);
1405}
1406#endif
055e0906 1407#endif
31e31b8a 1408
e5ce9688
FB
1409#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1410static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1411 abi_long arg4, abi_long arg5, abi_long arg6,
1412 bool time64)
1413{
1414 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1415 fd_set rfds, wfds, efds;
1416 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1417 struct timespec ts, *ts_ptr;
1418 abi_long ret;
1419
1420 /*
1421 * The 6th arg is actually two args smashed together,
1422 * so we cannot use the C library.
1423 */
e5ce9688
FB
1424 struct {
1425 sigset_t *set;
1426 size_t size;
1427 } sig, *sig_ptr;
1428
1429 abi_ulong arg_sigset, arg_sigsize, *arg7;
e5ce9688
FB
1430
1431 n = arg1;
1432 rfd_addr = arg2;
1433 wfd_addr = arg3;
1434 efd_addr = arg4;
1435 ts_addr = arg5;
1436
1437 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1438 if (ret) {
1439 return ret;
1440 }
1441 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1442 if (ret) {
1443 return ret;
1444 }
1445 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1446 if (ret) {
1447 return ret;
1448 }
1449
1450 /*
1451 * This takes a timespec, and not a timeval, so we cannot
1452 * use the do_select() helper ...
1453 */
1454 if (ts_addr) {
1455 if (time64) {
1456 if (target_to_host_timespec64(&ts, ts_addr)) {
1457 return -TARGET_EFAULT;
1458 }
1459 } else {
1460 if (target_to_host_timespec(&ts, ts_addr)) {
1461 return -TARGET_EFAULT;
1462 }
1463 }
1464 ts_ptr = &ts;
1465 } else {
1466 ts_ptr = NULL;
1467 }
1468
1469 /* Extract the two packed args for the sigset */
cb226034 1470 sig_ptr = NULL;
e5ce9688 1471 if (arg6) {
e5ce9688
FB
1472 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1473 if (!arg7) {
1474 return -TARGET_EFAULT;
1475 }
1476 arg_sigset = tswapal(arg7[0]);
1477 arg_sigsize = tswapal(arg7[1]);
1478 unlock_user(arg7, arg6, 0);
1479
1480 if (arg_sigset) {
cb226034
RH
1481 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1482 if (ret != 0) {
1483 return ret;
e5ce9688 1484 }
cb226034
RH
1485 sig_ptr = &sig;
1486 sig.size = SIGSET_T_SIZE;
e5ce9688 1487 }
e5ce9688
FB
1488 }
1489
1490 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1491 ts_ptr, sig_ptr));
1492
cb226034
RH
1493 if (sig_ptr) {
1494 finish_sigsuspend_mask(ret);
1495 }
1496
e5ce9688
FB
1497 if (!is_error(ret)) {
1498 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1499 return -TARGET_EFAULT;
1500 }
1501 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1502 return -TARGET_EFAULT;
1503 }
1504 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1505 return -TARGET_EFAULT;
1506 }
1507 if (time64) {
1508 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1509 return -TARGET_EFAULT;
1510 }
1511 } else {
1512 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1513 return -TARGET_EFAULT;
1514 }
1515 }
1516 }
1517 return ret;
1518}
1519#endif
1520
1521#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1522 defined(TARGET_NR_ppoll_time64)
1523static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1524 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1525{
1526 struct target_pollfd *target_pfd;
1527 unsigned int nfds = arg2;
1528 struct pollfd *pfd;
1529 unsigned int i;
1530 abi_long ret;
1531
1532 pfd = NULL;
1533 target_pfd = NULL;
1534 if (nfds) {
1535 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1536 return -TARGET_EINVAL;
1537 }
1538 target_pfd = lock_user(VERIFY_WRITE, arg1,
1539 sizeof(struct target_pollfd) * nfds, 1);
1540 if (!target_pfd) {
1541 return -TARGET_EFAULT;
1542 }
1543
1544 pfd = alloca(sizeof(struct pollfd) * nfds);
1545 for (i = 0; i < nfds; i++) {
1546 pfd[i].fd = tswap32(target_pfd[i].fd);
1547 pfd[i].events = tswap16(target_pfd[i].events);
1548 }
1549 }
1550 if (ppoll) {
1551 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
db36aa7d 1552 sigset_t *set = NULL;
e5ce9688
FB
1553
1554 if (arg3) {
1555 if (time64) {
1556 if (target_to_host_timespec64(timeout_ts, arg3)) {
1557 unlock_user(target_pfd, arg1, 0);
1558 return -TARGET_EFAULT;
1559 }
1560 } else {
1561 if (target_to_host_timespec(timeout_ts, arg3)) {
1562 unlock_user(target_pfd, arg1, 0);
1563 return -TARGET_EFAULT;
1564 }
1565 }
1566 } else {
1567 timeout_ts = NULL;
1568 }
1569
1570 if (arg4) {
db36aa7d
RH
1571 ret = process_sigsuspend_mask(&set, arg4, arg5);
1572 if (ret != 0) {
e5ce9688 1573 unlock_user(target_pfd, arg1, 0);
db36aa7d 1574 return ret;
e5ce9688 1575 }
e5ce9688
FB
1576 }
1577
1578 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1579 set, SIGSET_T_SIZE));
1580
db36aa7d
RH
1581 if (set) {
1582 finish_sigsuspend_mask(ret);
1583 }
e5ce9688
FB
1584 if (!is_error(ret) && arg3) {
1585 if (time64) {
1586 if (host_to_target_timespec64(arg3, timeout_ts)) {
1587 return -TARGET_EFAULT;
1588 }
1589 } else {
1590 if (host_to_target_timespec(arg3, timeout_ts)) {
1591 return -TARGET_EFAULT;
1592 }
1593 }
1594 }
e5ce9688
FB
1595 } else {
1596 struct timespec ts, *pts;
1597
1598 if (arg3 >= 0) {
1599 /* Convert ms to secs, ns */
1600 ts.tv_sec = arg3 / 1000;
1601 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1602 pts = &ts;
1603 } else {
1604 /* -ve poll() timeout means "infinite" */
1605 pts = NULL;
1606 }
1607 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1608 }
1609
1610 if (!is_error(ret)) {
1611 for (i = 0; i < nfds; i++) {
1612 target_pfd[i].revents = tswap16(pfd[i].revents);
1613 }
1614 }
1615 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1616 return ret;
1617}
1618#endif
1619
a0939b89 1620static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
fb41a66e 1621 int flags, int is_pipe2)
099d6b0f
RV
1622{
1623 int host_pipe[2];
1624 abi_long ret;
499d8055 1625 ret = pipe2(host_pipe, flags);
099d6b0f
RV
1626
1627 if (is_error(ret))
1628 return get_errno(ret);
fb41a66e
RH
1629
1630 /* Several targets have special calling conventions for the original
1631 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1632 if (!is_pipe2) {
1633#if defined(TARGET_ALPHA)
0effdc29 1634 cpu_env->ir[IR_A4] = host_pipe[1];
fb41a66e
RH
1635 return host_pipe[0];
1636#elif defined(TARGET_MIPS)
0effdc29 1637 cpu_env->active_tc.gpr[3] = host_pipe[1];
fb41a66e
RH
1638 return host_pipe[0];
1639#elif defined(TARGET_SH4)
0effdc29 1640 cpu_env->gregs[1] = host_pipe[1];
fb41a66e 1641 return host_pipe[0];
82f05b69 1642#elif defined(TARGET_SPARC)
0effdc29 1643 cpu_env->regwptr[1] = host_pipe[1];
82f05b69 1644 return host_pipe[0];
597c0212 1645#endif
fb41a66e
RH
1646 }
1647
099d6b0f 1648 if (put_user_s32(host_pipe[0], pipedes)
6f200f51 1649 || put_user_s32(host_pipe[1], pipedes + sizeof(abi_int)))
099d6b0f 1650 return -TARGET_EFAULT;
099d6b0f
RV
1651 return get_errno(ret);
1652}
1653
b975b83b
LL
1654static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1655 abi_ulong target_addr,
1656 socklen_t len)
1657{
1658 struct target_ip_mreqn *target_smreqn;
1659
1660 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1661 if (!target_smreqn)
1662 return -TARGET_EFAULT;
1663 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1664 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1665 if (len == sizeof(struct target_ip_mreqn))
cbb21eed 1666 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
b975b83b
LL
1667 unlock_user(target_smreqn, target_addr, 0);
1668
1669 return 0;
1670}
1671
7b36f782 1672static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
579a97f7
FB
1673 abi_ulong target_addr,
1674 socklen_t len)
7854b056 1675{
607175e0
AJ
1676 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1677 sa_family_t sa_family;
53a5960a
PB
1678 struct target_sockaddr *target_saddr;
1679
7b36f782
LV
1680 if (fd_trans_target_to_host_addr(fd)) {
1681 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1682 }
1683
579a97f7
FB
1684 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1685 if (!target_saddr)
1686 return -TARGET_EFAULT;
607175e0
AJ
1687
1688 sa_family = tswap16(target_saddr->sa_family);
1689
1690 /* Oops. The caller might send a incomplete sun_path; sun_path
1691 * must be terminated by \0 (see the manual page), but
1692 * unfortunately it is quite common to specify sockaddr_un
1693 * length as "strlen(x->sun_path)" while it should be
1694 * "strlen(...) + 1". We'll fix that here if needed.
1695 * Linux kernel has a similar feature.
1696 */
1697
1698 if (sa_family == AF_UNIX) {
1699 if (len < unix_maxlen && len > 0) {
1700 char *cp = (char*)target_saddr;
1701
1702 if ( cp[len-1] && !cp[len] )
1703 len++;
1704 }
1705 if (len > unix_maxlen)
1706 len = unix_maxlen;
1707 }
1708
53a5960a 1709 memcpy(addr, target_saddr, len);
607175e0 1710 addr->sa_family = sa_family;
6c5b5645
LV
1711 if (sa_family == AF_NETLINK) {
1712 struct sockaddr_nl *nladdr;
1713
1714 nladdr = (struct sockaddr_nl *)addr;
1715 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1716 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1717 } else if (sa_family == AF_PACKET) {
33a29b51
JT
1718 struct target_sockaddr_ll *lladdr;
1719
1720 lladdr = (struct target_sockaddr_ll *)addr;
1721 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1722 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
44cf6731
MM
1723 } else if (sa_family == AF_INET6) {
1724 struct sockaddr_in6 *in6addr;
1725
1726 in6addr = (struct sockaddr_in6 *)addr;
1727 in6addr->sin6_scope_id = tswap32(in6addr->sin6_scope_id);
33a29b51 1728 }
53a5960a 1729 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1730
1731 return 0;
7854b056
FB
1732}
1733
579a97f7
FB
1734static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1735 struct sockaddr *addr,
1736 socklen_t len)
7854b056 1737{
53a5960a
PB
1738 struct target_sockaddr *target_saddr;
1739
a1e22192
PM
1740 if (len == 0) {
1741 return 0;
1742 }
6860710c 1743 assert(addr);
a1e22192 1744
579a97f7
FB
1745 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1746 if (!target_saddr)
1747 return -TARGET_EFAULT;
53a5960a 1748 memcpy(target_saddr, addr, len);
a1e22192
PM
1749 if (len >= offsetof(struct target_sockaddr, sa_family) +
1750 sizeof(target_saddr->sa_family)) {
1751 target_saddr->sa_family = tswap16(addr->sa_family);
1752 }
a47401bc
PMD
1753 if (addr->sa_family == AF_NETLINK &&
1754 len >= sizeof(struct target_sockaddr_nl)) {
1755 struct target_sockaddr_nl *target_nl =
1756 (struct target_sockaddr_nl *)target_saddr;
6c5b5645
LV
1757 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1758 target_nl->nl_groups = tswap32(target_nl->nl_groups);
a82ea939
LV
1759 } else if (addr->sa_family == AF_PACKET) {
1760 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1761 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1762 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
ee1ac3a1
HD
1763 } else if (addr->sa_family == AF_INET6 &&
1764 len >= sizeof(struct target_sockaddr_in6)) {
1765 struct target_sockaddr_in6 *target_in6 =
1766 (struct target_sockaddr_in6 *)target_saddr;
1767 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
6c5b5645 1768 }
53a5960a 1769 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1770
1771 return 0;
7854b056
FB
1772}
1773
5a4a898d
FB
1774static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1775 struct target_msghdr *target_msgh)
7854b056
FB
1776{
1777 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1778 abi_long msg_controllen;
1779 abi_ulong target_cmsg_addr;
ee104587 1780 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056 1781 socklen_t space = 0;
5a4a898d 1782
cbb21eed 1783 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1784 if (msg_controllen < sizeof (struct target_cmsghdr))
1785 goto the_end;
cbb21eed 1786 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1787 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
ee104587 1788 target_cmsg_start = target_cmsg;
5a4a898d
FB
1789 if (!target_cmsg)
1790 return -TARGET_EFAULT;
7854b056
FB
1791
1792 while (cmsg && target_cmsg) {
1793 void *data = CMSG_DATA(cmsg);
1794 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1795
cbb21eed 1796 int len = tswapal(target_cmsg->cmsg_len)
ad762b99 1797 - sizeof(struct target_cmsghdr);
7854b056
FB
1798
1799 space += CMSG_SPACE(len);
1800 if (space > msgh->msg_controllen) {
1801 space -= CMSG_SPACE(len);
c2aeb258
PM
1802 /* This is a QEMU bug, since we allocated the payload
1803 * area ourselves (unlike overflow in host-to-target
1804 * conversion, which is just the guest giving us a buffer
1805 * that's too small). It can't happen for the payload types
1806 * we currently support; if it becomes an issue in future
1807 * we would need to improve our allocation strategy to
1808 * something more intelligent than "twice the size of the
1809 * target buffer we're reading from".
1810 */
39be5350
JK
1811 qemu_log_mask(LOG_UNIMP,
1812 ("Unsupported ancillary data %d/%d: "
1813 "unhandled msg size\n"),
1814 tswap32(target_cmsg->cmsg_level),
1815 tswap32(target_cmsg->cmsg_type));
7854b056
FB
1816 break;
1817 }
1818
dbf4f796
PJ
1819 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1820 cmsg->cmsg_level = SOL_SOCKET;
1821 } else {
1822 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1823 }
7854b056
FB
1824 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1825 cmsg->cmsg_len = CMSG_LEN(len);
1826
30b8b68e 1827 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
7854b056
FB
1828 int *fd = (int *)data;
1829 int *target_fd = (int *)target_data;
1830 int i, numfds = len / sizeof(int);
1831
876e23cb
PM
1832 for (i = 0; i < numfds; i++) {
1833 __get_user(fd[i], target_fd + i);
1834 }
30b8b68e
AS
1835 } else if (cmsg->cmsg_level == SOL_SOCKET
1836 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1837 struct ucred *cred = (struct ucred *)data;
1838 struct target_ucred *target_cred =
1839 (struct target_ucred *)target_data;
1840
876e23cb
PM
1841 __get_user(cred->pid, &target_cred->pid);
1842 __get_user(cred->uid, &target_cred->uid);
1843 __get_user(cred->gid, &target_cred->gid);
27404b6c
HD
1844 } else if (cmsg->cmsg_level == SOL_ALG) {
1845 uint32_t *dst = (uint32_t *)data;
1846
1847 memcpy(dst, target_data, len);
1848 /* fix endianess of first 32-bit word */
1849 if (len >= sizeof(uint32_t)) {
1850 *dst = tswap32(*dst);
1851 }
30b8b68e 1852 } else {
39be5350
JK
1853 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1854 cmsg->cmsg_level, cmsg->cmsg_type);
30b8b68e 1855 memcpy(data, target_data, len);
7854b056
FB
1856 }
1857
1858 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
1859 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1860 target_cmsg_start);
7854b056 1861 }
5a4a898d
FB
1862 unlock_user(target_cmsg, target_cmsg_addr, 0);
1863 the_end:
7854b056 1864 msgh->msg_controllen = space;
5a4a898d 1865 return 0;
7854b056
FB
1866}
1867
5a4a898d
FB
1868static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1869 struct msghdr *msgh)
7854b056
FB
1870{
1871 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1872 abi_long msg_controllen;
1873 abi_ulong target_cmsg_addr;
ee104587 1874 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056
FB
1875 socklen_t space = 0;
1876
cbb21eed 1877 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1878 if (msg_controllen < sizeof (struct target_cmsghdr))
1879 goto the_end;
cbb21eed 1880 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1881 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
ee104587 1882 target_cmsg_start = target_cmsg;
5a4a898d
FB
1883 if (!target_cmsg)
1884 return -TARGET_EFAULT;
1885
7854b056
FB
1886 while (cmsg && target_cmsg) {
1887 void *data = CMSG_DATA(cmsg);
1888 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1889
ad762b99 1890 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
c2aeb258 1891 int tgt_len, tgt_space;
7854b056 1892
c2aeb258
PM
1893 /* We never copy a half-header but may copy half-data;
1894 * this is Linux's behaviour in put_cmsg(). Note that
1895 * truncation here is a guest problem (which we report
1896 * to the guest via the CTRUNC bit), unlike truncation
1897 * in target_to_host_cmsg, which is a QEMU bug.
1898 */
7174970a 1899 if (msg_controllen < sizeof(struct target_cmsghdr)) {
c2aeb258 1900 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7854b056
FB
1901 break;
1902 }
1903
dbf4f796
PJ
1904 if (cmsg->cmsg_level == SOL_SOCKET) {
1905 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1906 } else {
1907 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1908 }
7854b056 1909 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
7854b056 1910
c2aeb258
PM
1911 /* Payload types which need a different size of payload on
1912 * the target must adjust tgt_len here.
1913 */
309786cf 1914 tgt_len = len;
c2aeb258
PM
1915 switch (cmsg->cmsg_level) {
1916 case SOL_SOCKET:
1917 switch (cmsg->cmsg_type) {
1918 case SO_TIMESTAMP:
1919 tgt_len = sizeof(struct target_timeval);
1920 break;
1921 default:
1922 break;
1923 }
309786cf 1924 break;
c2aeb258
PM
1925 default:
1926 break;
1927 }
1928
7174970a 1929 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
c2aeb258 1930 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7174970a 1931 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
c2aeb258
PM
1932 }
1933
1934 /* We must now copy-and-convert len bytes of payload
1935 * into tgt_len bytes of destination space. Bear in mind
1936 * that in both source and destination we may be dealing
1937 * with a truncated value!
1938 */
52b65494
HD
1939 switch (cmsg->cmsg_level) {
1940 case SOL_SOCKET:
1941 switch (cmsg->cmsg_type) {
1942 case SCM_RIGHTS:
1943 {
1944 int *fd = (int *)data;
1945 int *target_fd = (int *)target_data;
c2aeb258 1946 int i, numfds = tgt_len / sizeof(int);
52b65494 1947
876e23cb
PM
1948 for (i = 0; i < numfds; i++) {
1949 __put_user(fd[i], target_fd + i);
1950 }
52b65494
HD
1951 break;
1952 }
1953 case SO_TIMESTAMP:
1954 {
1955 struct timeval *tv = (struct timeval *)data;
1956 struct target_timeval *target_tv =
1957 (struct target_timeval *)target_data;
1958
c2aeb258
PM
1959 if (len != sizeof(struct timeval) ||
1960 tgt_len != sizeof(struct target_timeval)) {
52b65494 1961 goto unimplemented;
c2aeb258 1962 }
52b65494
HD
1963
1964 /* copy struct timeval to target */
876e23cb
PM
1965 __put_user(tv->tv_sec, &target_tv->tv_sec);
1966 __put_user(tv->tv_usec, &target_tv->tv_usec);
52b65494
HD
1967 break;
1968 }
4bc29756
HD
1969 case SCM_CREDENTIALS:
1970 {
1971 struct ucred *cred = (struct ucred *)data;
1972 struct target_ucred *target_cred =
1973 (struct target_ucred *)target_data;
1974
1975 __put_user(cred->pid, &target_cred->pid);
1976 __put_user(cred->uid, &target_cred->uid);
1977 __put_user(cred->gid, &target_cred->gid);
1978 break;
1979 }
52b65494
HD
1980 default:
1981 goto unimplemented;
1982 }
1983 break;
7854b056 1984
ee1ac3a1
HD
1985 case SOL_IP:
1986 switch (cmsg->cmsg_type) {
1987 case IP_TTL:
1988 {
1989 uint32_t *v = (uint32_t *)data;
1990 uint32_t *t_int = (uint32_t *)target_data;
1991
7174970a
PM
1992 if (len != sizeof(uint32_t) ||
1993 tgt_len != sizeof(uint32_t)) {
1994 goto unimplemented;
1995 }
ee1ac3a1
HD
1996 __put_user(*v, t_int);
1997 break;
1998 }
1999 case IP_RECVERR:
2000 {
2001 struct errhdr_t {
2002 struct sock_extended_err ee;
2003 struct sockaddr_in offender;
2004 };
2005 struct errhdr_t *errh = (struct errhdr_t *)data;
2006 struct errhdr_t *target_errh =
2007 (struct errhdr_t *)target_data;
2008
7174970a
PM
2009 if (len != sizeof(struct errhdr_t) ||
2010 tgt_len != sizeof(struct errhdr_t)) {
2011 goto unimplemented;
2012 }
ee1ac3a1
HD
2013 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2014 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2015 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2016 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2017 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2018 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2019 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2020 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2021 (void *) &errh->offender, sizeof(errh->offender));
2022 break;
2023 }
2024 default:
2025 goto unimplemented;
2026 }
2027 break;
2028
2029 case SOL_IPV6:
2030 switch (cmsg->cmsg_type) {
2031 case IPV6_HOPLIMIT:
2032 {
2033 uint32_t *v = (uint32_t *)data;
2034 uint32_t *t_int = (uint32_t *)target_data;
2035
7174970a
PM
2036 if (len != sizeof(uint32_t) ||
2037 tgt_len != sizeof(uint32_t)) {
2038 goto unimplemented;
2039 }
ee1ac3a1
HD
2040 __put_user(*v, t_int);
2041 break;
2042 }
2043 case IPV6_RECVERR:
2044 {
2045 struct errhdr6_t {
2046 struct sock_extended_err ee;
2047 struct sockaddr_in6 offender;
2048 };
2049 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2050 struct errhdr6_t *target_errh =
2051 (struct errhdr6_t *)target_data;
2052
7174970a
PM
2053 if (len != sizeof(struct errhdr6_t) ||
2054 tgt_len != sizeof(struct errhdr6_t)) {
2055 goto unimplemented;
2056 }
ee1ac3a1
HD
2057 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2058 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2059 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2060 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2061 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2062 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2063 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2064 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2065 (void *) &errh->offender, sizeof(errh->offender));
2066 break;
2067 }
2068 default:
2069 goto unimplemented;
2070 }
2071 break;
2072
52b65494
HD
2073 default:
2074 unimplemented:
39be5350
JK
2075 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2076 cmsg->cmsg_level, cmsg->cmsg_type);
c2aeb258
PM
2077 memcpy(target_data, data, MIN(len, tgt_len));
2078 if (tgt_len > len) {
2079 memset(target_data + len, 0, tgt_len - len);
2080 }
7854b056
FB
2081 }
2082
7174970a
PM
2083 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2084 tgt_space = TARGET_CMSG_SPACE(tgt_len);
c2aeb258
PM
2085 if (msg_controllen < tgt_space) {
2086 tgt_space = msg_controllen;
2087 }
2088 msg_controllen -= tgt_space;
2089 space += tgt_space;
7854b056 2090 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
2091 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2092 target_cmsg_start);
7854b056 2093 }
5a4a898d
FB
2094 unlock_user(target_cmsg, target_cmsg_addr, space);
2095 the_end:
cbb21eed 2096 target_msgh->msg_controllen = tswapal(space);
5a4a898d 2097 return 0;
7854b056
FB
2098}
2099
0da46a6e 2100/* do_setsockopt() Must return target values and target errnos. */
992f48a0 2101static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 2102 abi_ulong optval_addr, socklen_t optlen)
7854b056 2103{
992f48a0 2104 abi_long ret;
32407103 2105 int val;
b975b83b 2106 struct ip_mreqn *ip_mreq;
6e3cb58f 2107 struct ip_mreq_source *ip_mreq_source;
3b46e624 2108
8853f86e
FB
2109 switch(level) {
2110 case SOL_TCP:
fe51b0a5
SCW
2111 case SOL_UDP:
2112 /* TCP and UDP options all take an 'int' value. */
7854b056 2113 if (optlen < sizeof(uint32_t))
0da46a6e 2114 return -TARGET_EINVAL;
3b46e624 2115
2f619698
FB
2116 if (get_user_u32(val, optval_addr))
2117 return -TARGET_EFAULT;
8853f86e
FB
2118 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2119 break;
2120 case SOL_IP:
2121 switch(optname) {
2efbe911
FB
2122 case IP_TOS:
2123 case IP_TTL:
8853f86e 2124 case IP_HDRINCL:
2efbe911
FB
2125 case IP_ROUTER_ALERT:
2126 case IP_RECVOPTS:
2127 case IP_RETOPTS:
2128 case IP_PKTINFO:
2129 case IP_MTU_DISCOVER:
2130 case IP_RECVERR:
ee1ac3a1 2131 case IP_RECVTTL:
2efbe911
FB
2132 case IP_RECVTOS:
2133#ifdef IP_FREEBIND
2134 case IP_FREEBIND:
2135#endif
2136 case IP_MULTICAST_TTL:
2137 case IP_MULTICAST_LOOP:
8853f86e
FB
2138 val = 0;
2139 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
2140 if (get_user_u32(val, optval_addr))
2141 return -TARGET_EFAULT;
8853f86e 2142 } else if (optlen >= 1) {
2f619698
FB
2143 if (get_user_u8(val, optval_addr))
2144 return -TARGET_EFAULT;
8853f86e
FB
2145 }
2146 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2147 break;
b975b83b
LL
2148 case IP_ADD_MEMBERSHIP:
2149 case IP_DROP_MEMBERSHIP:
2150 if (optlen < sizeof (struct target_ip_mreq) ||
2151 optlen > sizeof (struct target_ip_mreqn))
2152 return -TARGET_EINVAL;
2153
2154 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2155 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2156 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2157 break;
2158
6e3cb58f
LL
2159 case IP_BLOCK_SOURCE:
2160 case IP_UNBLOCK_SOURCE:
2161 case IP_ADD_SOURCE_MEMBERSHIP:
2162 case IP_DROP_SOURCE_MEMBERSHIP:
2163 if (optlen != sizeof (struct target_ip_mreq_source))
2164 return -TARGET_EINVAL;
2165
2166 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
74e43b04
PM
2167 if (!ip_mreq_source) {
2168 return -TARGET_EFAULT;
2169 }
6e3cb58f
LL
2170 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2171 unlock_user (ip_mreq_source, optval_addr, 0);
2172 break;
2173
920394db
JH
2174 default:
2175 goto unimplemented;
2176 }
2177 break;
0d78b3b5
LV
2178 case SOL_IPV6:
2179 switch (optname) {
2180 case IPV6_MTU_DISCOVER:
2181 case IPV6_MTU:
2182 case IPV6_V6ONLY:
2183 case IPV6_RECVPKTINFO:
ee1ac3a1 2184 case IPV6_UNICAST_HOPS:
21749c4c
LV
2185 case IPV6_MULTICAST_HOPS:
2186 case IPV6_MULTICAST_LOOP:
ee1ac3a1
HD
2187 case IPV6_RECVERR:
2188 case IPV6_RECVHOPLIMIT:
2189 case IPV6_2292HOPLIMIT:
2190 case IPV6_CHECKSUM:
b9cce6d7
HD
2191 case IPV6_ADDRFORM:
2192 case IPV6_2292PKTINFO:
2193 case IPV6_RECVTCLASS:
2194 case IPV6_RECVRTHDR:
2195 case IPV6_2292RTHDR:
2196 case IPV6_RECVHOPOPTS:
2197 case IPV6_2292HOPOPTS:
2198 case IPV6_RECVDSTOPTS:
2199 case IPV6_2292DSTOPTS:
2200 case IPV6_TCLASS:
22db1213 2201 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2202#ifdef IPV6_RECVPATHMTU
2203 case IPV6_RECVPATHMTU:
2204#endif
2205#ifdef IPV6_TRANSPARENT
2206 case IPV6_TRANSPARENT:
2207#endif
2208#ifdef IPV6_FREEBIND
2209 case IPV6_FREEBIND:
2210#endif
2211#ifdef IPV6_RECVORIGDSTADDR
2212 case IPV6_RECVORIGDSTADDR:
2213#endif
0d78b3b5
LV
2214 val = 0;
2215 if (optlen < sizeof(uint32_t)) {
2216 return -TARGET_EINVAL;
2217 }
2218 if (get_user_u32(val, optval_addr)) {
2219 return -TARGET_EFAULT;
2220 }
2221 ret = get_errno(setsockopt(sockfd, level, optname,
2222 &val, sizeof(val)));
2223 break;
ee1ac3a1
HD
2224 case IPV6_PKTINFO:
2225 {
2226 struct in6_pktinfo pki;
2227
2228 if (optlen < sizeof(pki)) {
2229 return -TARGET_EINVAL;
2230 }
2231
2232 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2233 return -TARGET_EFAULT;
2234 }
2235
2236 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2237
2238 ret = get_errno(setsockopt(sockfd, level, optname,
2239 &pki, sizeof(pki)));
2240 break;
2241 }
22bf4ee9
NC
2242 case IPV6_ADD_MEMBERSHIP:
2243 case IPV6_DROP_MEMBERSHIP:
2244 {
2245 struct ipv6_mreq ipv6mreq;
2246
2247 if (optlen < sizeof(ipv6mreq)) {
2248 return -TARGET_EINVAL;
2249 }
2250
2251 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2252 return -TARGET_EFAULT;
2253 }
2254
2255 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2256
2257 ret = get_errno(setsockopt(sockfd, level, optname,
2258 &ipv6mreq, sizeof(ipv6mreq)));
2259 break;
2260 }
ee1ac3a1
HD
2261 default:
2262 goto unimplemented;
2263 }
2264 break;
2265 case SOL_ICMPV6:
2266 switch (optname) {
2267 case ICMPV6_FILTER:
2268 {
2269 struct icmp6_filter icmp6f;
2270
2271 if (optlen > sizeof(icmp6f)) {
2272 optlen = sizeof(icmp6f);
2273 }
2274
2275 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2276 return -TARGET_EFAULT;
2277 }
2278
2279 for (val = 0; val < 8; val++) {
2280 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2281 }
2282
2283 ret = get_errno(setsockopt(sockfd, level, optname,
2284 &icmp6f, optlen));
2285 break;
2286 }
0d78b3b5
LV
2287 default:
2288 goto unimplemented;
2289 }
2290 break;
920394db
JH
2291 case SOL_RAW:
2292 switch (optname) {
2293 case ICMP_FILTER:
ee1ac3a1
HD
2294 case IPV6_CHECKSUM:
2295 /* those take an u32 value */
920394db
JH
2296 if (optlen < sizeof(uint32_t)) {
2297 return -TARGET_EINVAL;
2298 }
2299
2300 if (get_user_u32(val, optval_addr)) {
2301 return -TARGET_EFAULT;
2302 }
2303 ret = get_errno(setsockopt(sockfd, level, optname,
2304 &val, sizeof(val)));
2305 break;
2306
8853f86e
FB
2307 default:
2308 goto unimplemented;
2309 }
2310 break;
f31dddd2
YS
2311#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2312 case SOL_ALG:
2313 switch (optname) {
2314 case ALG_SET_KEY:
2315 {
2316 char *alg_key = g_malloc(optlen);
2317
2318 if (!alg_key) {
2319 return -TARGET_ENOMEM;
2320 }
2321 if (copy_from_user(alg_key, optval_addr, optlen)) {
2322 g_free(alg_key);
2323 return -TARGET_EFAULT;
2324 }
2325 ret = get_errno(setsockopt(sockfd, level, optname,
2326 alg_key, optlen));
2327 g_free(alg_key);
2328 break;
2329 }
2330 case ALG_SET_AEAD_AUTHSIZE:
2331 {
2332 ret = get_errno(setsockopt(sockfd, level, optname,
2333 NULL, optlen));
2334 break;
2335 }
2336 default:
2337 goto unimplemented;
2338 }
2339 break;
2340#endif
3532fa74 2341 case TARGET_SOL_SOCKET:
8853f86e 2342 switch (optname) {
1b09aeb9
LV
2343 case TARGET_SO_RCVTIMEO:
2344 {
2345 struct timeval tv;
2346
2347 optname = SO_RCVTIMEO;
2348
2349set_timeout:
2350 if (optlen != sizeof(struct target_timeval)) {
2351 return -TARGET_EINVAL;
2352 }
2353
2354 if (copy_from_user_timeval(&tv, optval_addr)) {
2355 return -TARGET_EFAULT;
2356 }
2357
2358 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2359 &tv, sizeof(tv)));
2360 return ret;
2361 }
2362 case TARGET_SO_SNDTIMEO:
2363 optname = SO_SNDTIMEO;
2364 goto set_timeout;
f57d4192
LV
2365 case TARGET_SO_ATTACH_FILTER:
2366 {
2367 struct target_sock_fprog *tfprog;
2368 struct target_sock_filter *tfilter;
2369 struct sock_fprog fprog;
2370 struct sock_filter *filter;
2371 int i;
2372
2373 if (optlen != sizeof(*tfprog)) {
2374 return -TARGET_EINVAL;
2375 }
2376 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2377 return -TARGET_EFAULT;
2378 }
2379 if (!lock_user_struct(VERIFY_READ, tfilter,
2380 tswapal(tfprog->filter), 0)) {
2381 unlock_user_struct(tfprog, optval_addr, 1);
2382 return -TARGET_EFAULT;
2383 }
2384
2385 fprog.len = tswap16(tfprog->len);
0e173b24 2386 filter = g_try_new(struct sock_filter, fprog.len);
f57d4192
LV
2387 if (filter == NULL) {
2388 unlock_user_struct(tfilter, tfprog->filter, 1);
2389 unlock_user_struct(tfprog, optval_addr, 1);
2390 return -TARGET_ENOMEM;
2391 }
2392 for (i = 0; i < fprog.len; i++) {
2393 filter[i].code = tswap16(tfilter[i].code);
2394 filter[i].jt = tfilter[i].jt;
2395 filter[i].jf = tfilter[i].jf;
2396 filter[i].k = tswap32(tfilter[i].k);
2397 }
2398 fprog.filter = filter;
2399
2400 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2401 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
0e173b24 2402 g_free(filter);
f57d4192
LV
2403
2404 unlock_user_struct(tfilter, tfprog->filter, 1);
2405 unlock_user_struct(tfprog, optval_addr, 1);
2406 return ret;
2407 }
451aaf68
JT
2408 case TARGET_SO_BINDTODEVICE:
2409 {
2410 char *dev_ifname, *addr_ifname;
2411
2412 if (optlen > IFNAMSIZ - 1) {
2413 optlen = IFNAMSIZ - 1;
2414 }
2415 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2416 if (!dev_ifname) {
2417 return -TARGET_EFAULT;
2418 }
2419 optname = SO_BINDTODEVICE;
2420 addr_ifname = alloca(IFNAMSIZ);
2421 memcpy(addr_ifname, dev_ifname, optlen);
2422 addr_ifname[optlen] = 0;
fad6c58a
CG
2423 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2424 addr_ifname, optlen));
451aaf68
JT
2425 unlock_user (dev_ifname, optval_addr, 0);
2426 return ret;
2427 }
83eb6e50
CMAB
2428 case TARGET_SO_LINGER:
2429 {
2430 struct linger lg;
2431 struct target_linger *tlg;
2432
2433 if (optlen != sizeof(struct target_linger)) {
2434 return -TARGET_EINVAL;
2435 }
2436 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2437 return -TARGET_EFAULT;
2438 }
2439 __get_user(lg.l_onoff, &tlg->l_onoff);
2440 __get_user(lg.l_linger, &tlg->l_linger);
2441 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2442 &lg, sizeof(lg)));
2443 unlock_user_struct(tlg, optval_addr, 0);
2444 return ret;
2445 }
8853f86e 2446 /* Options with 'int' argument. */
3532fa74
FB
2447 case TARGET_SO_DEBUG:
2448 optname = SO_DEBUG;
2449 break;
2450 case TARGET_SO_REUSEADDR:
2451 optname = SO_REUSEADDR;
2452 break;
113a9dd7
YS
2453#ifdef SO_REUSEPORT
2454 case TARGET_SO_REUSEPORT:
2455 optname = SO_REUSEPORT;
2456 break;
2457#endif
3532fa74
FB
2458 case TARGET_SO_TYPE:
2459 optname = SO_TYPE;
2460 break;
2461 case TARGET_SO_ERROR:
2462 optname = SO_ERROR;
2463 break;
2464 case TARGET_SO_DONTROUTE:
2465 optname = SO_DONTROUTE;
2466 break;
2467 case TARGET_SO_BROADCAST:
2468 optname = SO_BROADCAST;
2469 break;
2470 case TARGET_SO_SNDBUF:
2471 optname = SO_SNDBUF;
2472 break;
d79b6cc4
PB
2473 case TARGET_SO_SNDBUFFORCE:
2474 optname = SO_SNDBUFFORCE;
2475 break;
3532fa74
FB
2476 case TARGET_SO_RCVBUF:
2477 optname = SO_RCVBUF;
2478 break;
d79b6cc4
PB
2479 case TARGET_SO_RCVBUFFORCE:
2480 optname = SO_RCVBUFFORCE;
2481 break;
3532fa74
FB
2482 case TARGET_SO_KEEPALIVE:
2483 optname = SO_KEEPALIVE;
2484 break;
2485 case TARGET_SO_OOBINLINE:
2486 optname = SO_OOBINLINE;
2487 break;
2488 case TARGET_SO_NO_CHECK:
2489 optname = SO_NO_CHECK;
2490 break;
2491 case TARGET_SO_PRIORITY:
2492 optname = SO_PRIORITY;
2493 break;
5e83e8e3 2494#ifdef SO_BSDCOMPAT
3532fa74
FB
2495 case TARGET_SO_BSDCOMPAT:
2496 optname = SO_BSDCOMPAT;
2497 break;
5e83e8e3 2498#endif
3532fa74
FB
2499 case TARGET_SO_PASSCRED:
2500 optname = SO_PASSCRED;
2501 break;
82d0fe6b
PB
2502 case TARGET_SO_PASSSEC:
2503 optname = SO_PASSSEC;
2504 break;
3532fa74
FB
2505 case TARGET_SO_TIMESTAMP:
2506 optname = SO_TIMESTAMP;
2507 break;
2508 case TARGET_SO_RCVLOWAT:
2509 optname = SO_RCVLOWAT;
2510 break;
8853f86e
FB
2511 default:
2512 goto unimplemented;
2513 }
3532fa74 2514 if (optlen < sizeof(uint32_t))
2f619698 2515 return -TARGET_EINVAL;
3532fa74 2516
2f619698
FB
2517 if (get_user_u32(val, optval_addr))
2518 return -TARGET_EFAULT;
3532fa74 2519 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 2520 break;
a2d86682
JK
2521#ifdef SOL_NETLINK
2522 case SOL_NETLINK:
2523 switch (optname) {
2524 case NETLINK_PKTINFO:
2525 case NETLINK_ADD_MEMBERSHIP:
2526 case NETLINK_DROP_MEMBERSHIP:
2527 case NETLINK_BROADCAST_ERROR:
2528 case NETLINK_NO_ENOBUFS:
2529#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2530 case NETLINK_LISTEN_ALL_NSID:
2531 case NETLINK_CAP_ACK:
2532#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2533#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2534 case NETLINK_EXT_ACK:
2535#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2536#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2537 case NETLINK_GET_STRICT_CHK:
2538#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2539 break;
2540 default:
2541 goto unimplemented;
2542 }
2543 val = 0;
2544 if (optlen < sizeof(uint32_t)) {
2545 return -TARGET_EINVAL;
2546 }
2547 if (get_user_u32(val, optval_addr)) {
2548 return -TARGET_EFAULT;
2549 }
2550 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2551 sizeof(val)));
2552 break;
2553#endif /* SOL_NETLINK */
7854b056 2554 default:
8853f86e 2555 unimplemented:
39be5350
JK
2556 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2557 level, optname);
6fa13c17 2558 ret = -TARGET_ENOPROTOOPT;
7854b056 2559 }
8853f86e 2560 return ret;
7854b056
FB
2561}
2562
0da46a6e 2563/* do_getsockopt() Must return target values and target errnos. */
992f48a0 2564static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 2565 abi_ulong optval_addr, abi_ulong optlen)
7854b056 2566{
992f48a0 2567 abi_long ret;
b55266b5
BS
2568 int len, val;
2569 socklen_t lv;
8853f86e
FB
2570
2571 switch(level) {
3532fa74 2572 case TARGET_SOL_SOCKET:
f3b974cd
JL
2573 level = SOL_SOCKET;
2574 switch (optname) {
2575 /* These don't just return a single integer */
f3b974cd
JL
2576 case TARGET_SO_PEERNAME:
2577 goto unimplemented;
405dc4cf
AS
2578 case TARGET_SO_RCVTIMEO: {
2579 struct timeval tv;
2580 socklen_t tvlen;
2581
2582 optname = SO_RCVTIMEO;
2583
2584get_timeout:
2585 if (get_user_u32(len, optlen)) {
2586 return -TARGET_EFAULT;
2587 }
2588 if (len < 0) {
2589 return -TARGET_EINVAL;
2590 }
2591
2592 tvlen = sizeof(tv);
2593 ret = get_errno(getsockopt(sockfd, level, optname,
2594 &tv, &tvlen));
2595 if (ret < 0) {
2596 return ret;
2597 }
2598 if (len > sizeof(struct target_timeval)) {
2599 len = sizeof(struct target_timeval);
2600 }
2601 if (copy_to_user_timeval(optval_addr, &tv)) {
2602 return -TARGET_EFAULT;
2603 }
2604 if (put_user_u32(len, optlen)) {
2605 return -TARGET_EFAULT;
2606 }
2607 break;
2608 }
2609 case TARGET_SO_SNDTIMEO:
2610 optname = SO_SNDTIMEO;
2611 goto get_timeout;
583359a6
AP
2612 case TARGET_SO_PEERCRED: {
2613 struct ucred cr;
2614 socklen_t crlen;
2615 struct target_ucred *tcr;
2616
2617 if (get_user_u32(len, optlen)) {
2618 return -TARGET_EFAULT;
2619 }
2620 if (len < 0) {
2621 return -TARGET_EINVAL;
2622 }
2623
2624 crlen = sizeof(cr);
2625 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2626 &cr, &crlen));
2627 if (ret < 0) {
2628 return ret;
2629 }
2630 if (len > crlen) {
2631 len = crlen;
2632 }
2633 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2634 return -TARGET_EFAULT;
2635 }
2636 __put_user(cr.pid, &tcr->pid);
2637 __put_user(cr.uid, &tcr->uid);
2638 __put_user(cr.gid, &tcr->gid);
2639 unlock_user_struct(tcr, optval_addr, 1);
2640 if (put_user_u32(len, optlen)) {
83eb6e50
CMAB
2641 return -TARGET_EFAULT;
2642 }
2643 break;
2644 }
6d485a55
LV
2645 case TARGET_SO_PEERSEC: {
2646 char *name;
2647
2648 if (get_user_u32(len, optlen)) {
2649 return -TARGET_EFAULT;
2650 }
2651 if (len < 0) {
2652 return -TARGET_EINVAL;
2653 }
2654 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2655 if (!name) {
2656 return -TARGET_EFAULT;
2657 }
2658 lv = len;
2659 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2660 name, &lv));
2661 if (put_user_u32(lv, optlen)) {
2662 ret = -TARGET_EFAULT;
2663 }
2664 unlock_user(name, optval_addr, lv);
2665 break;
2666 }
83eb6e50
CMAB
2667 case TARGET_SO_LINGER:
2668 {
2669 struct linger lg;
2670 socklen_t lglen;
2671 struct target_linger *tlg;
2672
2673 if (get_user_u32(len, optlen)) {
2674 return -TARGET_EFAULT;
2675 }
2676 if (len < 0) {
2677 return -TARGET_EINVAL;
2678 }
2679
2680 lglen = sizeof(lg);
2681 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2682 &lg, &lglen));
2683 if (ret < 0) {
2684 return ret;
2685 }
2686 if (len > lglen) {
2687 len = lglen;
2688 }
2689 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2690 return -TARGET_EFAULT;
2691 }
2692 __put_user(lg.l_onoff, &tlg->l_onoff);
2693 __put_user(lg.l_linger, &tlg->l_linger);
2694 unlock_user_struct(tlg, optval_addr, 1);
2695 if (put_user_u32(len, optlen)) {
583359a6
AP
2696 return -TARGET_EFAULT;
2697 }
2698 break;
2699 }
f3b974cd
JL
2700 /* Options with 'int' argument. */
2701 case TARGET_SO_DEBUG:
2702 optname = SO_DEBUG;
2703 goto int_case;
2704 case TARGET_SO_REUSEADDR:
2705 optname = SO_REUSEADDR;
2706 goto int_case;
113a9dd7
YS
2707#ifdef SO_REUSEPORT
2708 case TARGET_SO_REUSEPORT:
2709 optname = SO_REUSEPORT;
2710 goto int_case;
2711#endif
f3b974cd
JL
2712 case TARGET_SO_TYPE:
2713 optname = SO_TYPE;
2714 goto int_case;
2715 case TARGET_SO_ERROR:
2716 optname = SO_ERROR;
2717 goto int_case;
2718 case TARGET_SO_DONTROUTE:
2719 optname = SO_DONTROUTE;
2720 goto int_case;
2721 case TARGET_SO_BROADCAST:
2722 optname = SO_BROADCAST;
2723 goto int_case;
2724 case TARGET_SO_SNDBUF:
2725 optname = SO_SNDBUF;
2726 goto int_case;
2727 case TARGET_SO_RCVBUF:
2728 optname = SO_RCVBUF;
2729 goto int_case;
2730 case TARGET_SO_KEEPALIVE:
2731 optname = SO_KEEPALIVE;
2732 goto int_case;
2733 case TARGET_SO_OOBINLINE:
2734 optname = SO_OOBINLINE;
2735 goto int_case;
2736 case TARGET_SO_NO_CHECK:
2737 optname = SO_NO_CHECK;
2738 goto int_case;
2739 case TARGET_SO_PRIORITY:
2740 optname = SO_PRIORITY;
2741 goto int_case;
2742#ifdef SO_BSDCOMPAT
2743 case TARGET_SO_BSDCOMPAT:
2744 optname = SO_BSDCOMPAT;
2745 goto int_case;
2746#endif
2747 case TARGET_SO_PASSCRED:
2748 optname = SO_PASSCRED;
2749 goto int_case;
2750 case TARGET_SO_TIMESTAMP:
2751 optname = SO_TIMESTAMP;
2752 goto int_case;
2753 case TARGET_SO_RCVLOWAT:
2754 optname = SO_RCVLOWAT;
2755 goto int_case;
aec1ca41
PB
2756 case TARGET_SO_ACCEPTCONN:
2757 optname = SO_ACCEPTCONN;
2758 goto int_case;
ec63e06e
JD
2759 case TARGET_SO_PROTOCOL:
2760 optname = SO_PROTOCOL;
2761 goto int_case;
2762 case TARGET_SO_DOMAIN:
2763 optname = SO_DOMAIN;
2764 goto int_case;
8853f86e 2765 default:
2efbe911
FB
2766 goto int_case;
2767 }
2768 break;
2769 case SOL_TCP:
fe51b0a5
SCW
2770 case SOL_UDP:
2771 /* TCP and UDP options all take an 'int' value. */
2efbe911 2772 int_case:
2f619698
FB
2773 if (get_user_u32(len, optlen))
2774 return -TARGET_EFAULT;
2efbe911 2775 if (len < 0)
0da46a6e 2776 return -TARGET_EINVAL;
73160d95 2777 lv = sizeof(lv);
2efbe911
FB
2778 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2779 if (ret < 0)
2780 return ret;
cb88b7c2
HD
2781 switch (optname) {
2782 case SO_TYPE:
8289d112 2783 val = host_to_target_sock_type(val);
cb88b7c2
HD
2784 break;
2785 case SO_ERROR:
2786 val = host_to_target_errno(val);
2787 break;
8289d112 2788 }
2efbe911
FB
2789 if (len > lv)
2790 len = lv;
2f619698
FB
2791 if (len == 4) {
2792 if (put_user_u32(val, optval_addr))
2793 return -TARGET_EFAULT;
2794 } else {
2795 if (put_user_u8(val, optval_addr))
2796 return -TARGET_EFAULT;
f3b974cd 2797 }
2f619698
FB
2798 if (put_user_u32(len, optlen))
2799 return -TARGET_EFAULT;
2efbe911
FB
2800 break;
2801 case SOL_IP:
2802 switch(optname) {
2803 case IP_TOS:
2804 case IP_TTL:
2805 case IP_HDRINCL:
2806 case IP_ROUTER_ALERT:
2807 case IP_RECVOPTS:
2808 case IP_RETOPTS:
2809 case IP_PKTINFO:
2810 case IP_MTU_DISCOVER:
2811 case IP_RECVERR:
2812 case IP_RECVTOS:
2813#ifdef IP_FREEBIND
2814 case IP_FREEBIND:
2815#endif
2816 case IP_MULTICAST_TTL:
2817 case IP_MULTICAST_LOOP:
2f619698
FB
2818 if (get_user_u32(len, optlen))
2819 return -TARGET_EFAULT;
8853f86e 2820 if (len < 0)
0da46a6e 2821 return -TARGET_EINVAL;
73160d95 2822 lv = sizeof(lv);
8853f86e
FB
2823 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2824 if (ret < 0)
2825 return ret;
2efbe911 2826 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 2827 len = 1;
2f619698
FB
2828 if (put_user_u32(len, optlen)
2829 || put_user_u8(val, optval_addr))
2830 return -TARGET_EFAULT;
2efbe911 2831 } else {
2efbe911
FB
2832 if (len > sizeof(int))
2833 len = sizeof(int);
2f619698
FB
2834 if (put_user_u32(len, optlen)
2835 || put_user_u32(val, optval_addr))
2836 return -TARGET_EFAULT;
2efbe911 2837 }
8853f86e 2838 break;
2efbe911 2839 default:
c02f499e
TS
2840 ret = -TARGET_ENOPROTOOPT;
2841 break;
8853f86e
FB
2842 }
2843 break;
bd8ed485
TD
2844 case SOL_IPV6:
2845 switch (optname) {
2846 case IPV6_MTU_DISCOVER:
2847 case IPV6_MTU:
2848 case IPV6_V6ONLY:
2849 case IPV6_RECVPKTINFO:
2850 case IPV6_UNICAST_HOPS:
2851 case IPV6_MULTICAST_HOPS:
2852 case IPV6_MULTICAST_LOOP:
2853 case IPV6_RECVERR:
2854 case IPV6_RECVHOPLIMIT:
2855 case IPV6_2292HOPLIMIT:
2856 case IPV6_CHECKSUM:
b9cce6d7
HD
2857 case IPV6_ADDRFORM:
2858 case IPV6_2292PKTINFO:
2859 case IPV6_RECVTCLASS:
2860 case IPV6_RECVRTHDR:
2861 case IPV6_2292RTHDR:
2862 case IPV6_RECVHOPOPTS:
2863 case IPV6_2292HOPOPTS:
2864 case IPV6_RECVDSTOPTS:
2865 case IPV6_2292DSTOPTS:
2866 case IPV6_TCLASS:
22db1213 2867 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2868#ifdef IPV6_RECVPATHMTU
2869 case IPV6_RECVPATHMTU:
2870#endif
2871#ifdef IPV6_TRANSPARENT
2872 case IPV6_TRANSPARENT:
2873#endif
2874#ifdef IPV6_FREEBIND
2875 case IPV6_FREEBIND:
2876#endif
2877#ifdef IPV6_RECVORIGDSTADDR
2878 case IPV6_RECVORIGDSTADDR:
2879#endif
bd8ed485
TD
2880 if (get_user_u32(len, optlen))
2881 return -TARGET_EFAULT;
2882 if (len < 0)
2883 return -TARGET_EINVAL;
2884 lv = sizeof(lv);
2885 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2886 if (ret < 0)
2887 return ret;
2888 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2889 len = 1;
2890 if (put_user_u32(len, optlen)
2891 || put_user_u8(val, optval_addr))
2892 return -TARGET_EFAULT;
2893 } else {
2894 if (len > sizeof(int))
2895 len = sizeof(int);
2896 if (put_user_u32(len, optlen)
2897 || put_user_u32(val, optval_addr))
2898 return -TARGET_EFAULT;
2899 }
2900 break;
2901 default:
2902 ret = -TARGET_ENOPROTOOPT;
2903 break;
2904 }
2905 break;
a2d86682
JK
2906#ifdef SOL_NETLINK
2907 case SOL_NETLINK:
2908 switch (optname) {
2909 case NETLINK_PKTINFO:
2910 case NETLINK_BROADCAST_ERROR:
2911 case NETLINK_NO_ENOBUFS:
2912#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2913 case NETLINK_LISTEN_ALL_NSID:
2914 case NETLINK_CAP_ACK:
2915#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2916#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2917 case NETLINK_EXT_ACK:
2918#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2919#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2920 case NETLINK_GET_STRICT_CHK:
2921#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2922 if (get_user_u32(len, optlen)) {
2923 return -TARGET_EFAULT;
2924 }
2925 if (len != sizeof(val)) {
2926 return -TARGET_EINVAL;
2927 }
2928 lv = len;
2929 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2930 if (ret < 0) {
2931 return ret;
2932 }
2933 if (put_user_u32(lv, optlen)
2934 || put_user_u32(val, optval_addr)) {
2935 return -TARGET_EFAULT;
2936 }
2937 break;
2938#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2939 case NETLINK_LIST_MEMBERSHIPS:
2940 {
2941 uint32_t *results;
2942 int i;
2943 if (get_user_u32(len, optlen)) {
2944 return -TARGET_EFAULT;
2945 }
2946 if (len < 0) {
2947 return -TARGET_EINVAL;
2948 }
2949 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
13e340c8 2950 if (!results && len > 0) {
a2d86682
JK
2951 return -TARGET_EFAULT;
2952 }
2953 lv = len;
2954 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2955 if (ret < 0) {
2956 unlock_user(results, optval_addr, 0);
2957 return ret;
2958 }
2959 /* swap host endianess to target endianess. */
2960 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2961 results[i] = tswap32(results[i]);
2962 }
2963 if (put_user_u32(lv, optlen)) {
2964 return -TARGET_EFAULT;
2965 }
2966 unlock_user(results, optval_addr, 0);
2967 break;
2968 }
2969#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2970 default:
2971 goto unimplemented;
2972 }
c0cb8801 2973 break;
a2d86682 2974#endif /* SOL_NETLINK */
8853f86e
FB
2975 default:
2976 unimplemented:
39be5350
JK
2977 qemu_log_mask(LOG_UNIMP,
2978 "getsockopt level=%d optname=%d not yet supported\n",
2979 level, optname);
c02f499e 2980 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
2981 break;
2982 }
2983 return ret;
7854b056
FB
2984}
2985
9ac22517
MF
2986/* Convert target low/high pair representing file offset into the host
2987 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2988 * as the kernel doesn't handle them either.
2989 */
2990static void target_to_host_low_high(abi_ulong tlow,
2991 abi_ulong thigh,
2992 unsigned long *hlow,
2993 unsigned long *hhigh)
2994{
2995 uint64_t off = tlow |
2996 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2997 TARGET_LONG_BITS / 2;
2998
2999 *hlow = off;
3000 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
3001}
3002
f287b2c2 3003static struct iovec *lock_iovec(int type, abi_ulong target_addr,
dab32b32 3004 abi_ulong count, int copy)
53a5960a
PB
3005{
3006 struct target_iovec *target_vec;
f287b2c2
RH
3007 struct iovec *vec;
3008 abi_ulong total_len, max_len;
d732dcb4 3009 int i;
501bb4b0 3010 int err = 0;
29560a6c 3011 bool bad_address = false;
53a5960a 3012
f287b2c2
RH
3013 if (count == 0) {
3014 errno = 0;
3015 return NULL;
3016 }
dab32b32 3017 if (count > IOV_MAX) {
f287b2c2
RH
3018 errno = EINVAL;
3019 return NULL;
3020 }
3021
0e173b24 3022 vec = g_try_new0(struct iovec, count);
f287b2c2
RH
3023 if (vec == NULL) {
3024 errno = ENOMEM;
3025 return NULL;
3026 }
3027
3028 target_vec = lock_user(VERIFY_READ, target_addr,
3029 count * sizeof(struct target_iovec), 1);
3030 if (target_vec == NULL) {
501bb4b0 3031 err = EFAULT;
f287b2c2
RH
3032 goto fail2;
3033 }
3034
3035 /* ??? If host page size > target page size, this will result in a
3036 value larger than what we can actually support. */
3037 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3038 total_len = 0;
3039
3040 for (i = 0; i < count; i++) {
3041 abi_ulong base = tswapal(target_vec[i].iov_base);
3042 abi_long len = tswapal(target_vec[i].iov_len);
3043
3044 if (len < 0) {
501bb4b0 3045 err = EINVAL;
f287b2c2
RH
3046 goto fail;
3047 } else if (len == 0) {
3048 /* Zero length pointer is ignored. */
3049 vec[i].iov_base = 0;
41df8411 3050 } else {
f287b2c2 3051 vec[i].iov_base = lock_user(type, base, len, copy);
29560a6c
TM
3052 /* If the first buffer pointer is bad, this is a fault. But
3053 * subsequent bad buffers will result in a partial write; this
3054 * is realized by filling the vector with null pointers and
3055 * zero lengths. */
f287b2c2 3056 if (!vec[i].iov_base) {
29560a6c
TM
3057 if (i == 0) {
3058 err = EFAULT;
3059 goto fail;
3060 } else {
3061 bad_address = true;
3062 }
3063 }
3064 if (bad_address) {
3065 len = 0;
f287b2c2
RH
3066 }
3067 if (len > max_len - total_len) {
3068 len = max_len - total_len;
3069 }
41df8411 3070 }
f287b2c2
RH
3071 vec[i].iov_len = len;
3072 total_len += len;
579a97f7 3073 }
f287b2c2
RH
3074
3075 unlock_user(target_vec, target_addr, 0);
3076 return vec;
3077
3078 fail:
7eff518b
CG
3079 while (--i >= 0) {
3080 if (tswapal(target_vec[i].iov_len) > 0) {
3081 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3082 }
3083 }
f287b2c2 3084 unlock_user(target_vec, target_addr, 0);
501bb4b0 3085 fail2:
0e173b24 3086 g_free(vec);
501bb4b0 3087 errno = err;
f287b2c2 3088 return NULL;
53a5960a
PB
3089}
3090
f287b2c2 3091static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
dab32b32 3092 abi_ulong count, int copy)
53a5960a
PB
3093{
3094 struct target_iovec *target_vec;
53a5960a
PB
3095 int i;
3096
f287b2c2
RH
3097 target_vec = lock_user(VERIFY_READ, target_addr,
3098 count * sizeof(struct target_iovec), 1);
3099 if (target_vec) {
3100 for (i = 0; i < count; i++) {
3101 abi_ulong base = tswapal(target_vec[i].iov_base);
71ec7cef 3102 abi_long len = tswapal(target_vec[i].iov_len);
f287b2c2
RH
3103 if (len < 0) {
3104 break;
3105 }
d732dcb4
AZ
3106 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3107 }
f287b2c2 3108 unlock_user(target_vec, target_addr, 0);
53a5960a 3109 }
579a97f7 3110
0e173b24 3111 g_free(vec);
53a5960a
PB
3112}
3113
53d09b76 3114static inline int target_to_host_sock_type(int *type)
3532fa74 3115{
f651e6ae
PJ
3116 int host_type = 0;
3117 int target_type = *type;
3118
3119 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3532fa74 3120 case TARGET_SOCK_DGRAM:
f651e6ae 3121 host_type = SOCK_DGRAM;
3532fa74
FB
3122 break;
3123 case TARGET_SOCK_STREAM:
f651e6ae 3124 host_type = SOCK_STREAM;
3532fa74 3125 break;
f651e6ae
PJ
3126 default:
3127 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3532fa74
FB
3128 break;
3129 }
f651e6ae 3130 if (target_type & TARGET_SOCK_CLOEXEC) {
53d09b76 3131#if defined(SOCK_CLOEXEC)
f651e6ae 3132 host_type |= SOCK_CLOEXEC;
53d09b76
EI
3133#else
3134 return -TARGET_EINVAL;
3135#endif
f651e6ae
PJ
3136 }
3137 if (target_type & TARGET_SOCK_NONBLOCK) {
53d09b76 3138#if defined(SOCK_NONBLOCK)
f651e6ae 3139 host_type |= SOCK_NONBLOCK;
53d09b76
EI
3140#elif !defined(O_NONBLOCK)
3141 return -TARGET_EINVAL;
3142#endif
f651e6ae
PJ
3143 }
3144 *type = host_type;
53d09b76
EI
3145 return 0;
3146}
3147
3148/* Try to emulate socket type flags after socket creation. */
3149static int sock_flags_fixup(int fd, int target_type)
3150{
3151#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3152 if (target_type & TARGET_SOCK_NONBLOCK) {
3153 int flags = fcntl(fd, F_GETFL);
3154 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3155 close(fd);
3156 return -TARGET_EINVAL;
3157 }
3158 }
3159#endif
3160 return fd;
f651e6ae
PJ
3161}
3162
3163/* do_socket() Must return target values and target errnos. */
3164static abi_long do_socket(int domain, int type, int protocol)
3165{
53d09b76
EI
3166 int target_type = type;
3167 int ret;
3168
3169 ret = target_to_host_sock_type(&type);
3170 if (ret) {
3171 return ret;
3172 }
f651e6ae 3173
575b22b1
LV
3174 if (domain == PF_NETLINK && !(
3175#ifdef CONFIG_RTNETLINK
3176 protocol == NETLINK_ROUTE ||
3177#endif
3178 protocol == NETLINK_KOBJECT_UEVENT ||
3179 protocol == NETLINK_AUDIT)) {
71e2443e 3180 return -TARGET_EPROTONOSUPPORT;
6c5b5645 3181 }
ff626f2d
LV
3182
3183 if (domain == AF_PACKET ||
3184 (domain == AF_INET && type == SOCK_PACKET)) {
3185 protocol = tswap16(protocol);
3186 }
3187
53d09b76
EI
3188 ret = get_errno(socket(domain, type, protocol));
3189 if (ret >= 0) {
3190 ret = sock_flags_fixup(ret, target_type);
0cf22722
LV
3191 if (type == SOCK_PACKET) {
3192 /* Manage an obsolete case :
3193 * if socket type is SOCK_PACKET, bind by name
3194 */
3195 fd_trans_register(ret, &target_packet_trans);
6c5b5645
LV
3196 } else if (domain == PF_NETLINK) {
3197 switch (protocol) {
575b22b1 3198#ifdef CONFIG_RTNETLINK
6c5b5645
LV
3199 case NETLINK_ROUTE:
3200 fd_trans_register(ret, &target_netlink_route_trans);
3201 break;
575b22b1 3202#endif
b265620b
LV
3203 case NETLINK_KOBJECT_UEVENT:
3204 /* nothing to do: messages are strings */
3205 break;
5ce9bb59
LV
3206 case NETLINK_AUDIT:
3207 fd_trans_register(ret, &target_netlink_audit_trans);
3208 break;
6c5b5645
LV
3209 default:
3210 g_assert_not_reached();
3211 }
0cf22722 3212 }
53d09b76
EI
3213 }
3214 return ret;
3532fa74
FB
3215}
3216
0da46a6e 3217/* do_bind() Must return target values and target errnos. */
992f48a0
BS
3218static abi_long do_bind(int sockfd, abi_ulong target_addr,
3219 socklen_t addrlen)
3532fa74 3220{
8f7aeaf6 3221 void *addr;
917507b0 3222 abi_long ret;
8f7aeaf6 3223
38724253 3224 if ((int)addrlen < 0) {
8f7aeaf6 3225 return -TARGET_EINVAL;
38724253 3226 }
8f7aeaf6 3227
607175e0 3228 addr = alloca(addrlen+1);
3b46e624 3229
7b36f782 3230 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3231 if (ret)
3232 return ret;
3233
3532fa74
FB
3234 return get_errno(bind(sockfd, addr, addrlen));
3235}
3236
0da46a6e 3237/* do_connect() Must return target values and target errnos. */
992f48a0
BS
3238static abi_long do_connect(int sockfd, abi_ulong target_addr,
3239 socklen_t addrlen)
3532fa74 3240{
8f7aeaf6 3241 void *addr;
917507b0 3242 abi_long ret;
8f7aeaf6 3243
38724253 3244 if ((int)addrlen < 0) {
8f7aeaf6 3245 return -TARGET_EINVAL;
38724253 3246 }
8f7aeaf6 3247
2dd08dfd 3248 addr = alloca(addrlen+1);
3b46e624 3249
7b36f782 3250 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3251 if (ret)
3252 return ret;
3253
2a3c7619 3254 return get_errno(safe_connect(sockfd, addr, addrlen));
3532fa74
FB
3255}
3256
f19e00d7
AG
3257/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3258static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3259 int flags, int send)
3532fa74 3260{
6de645c7 3261 abi_long ret, len;
3532fa74 3262 struct msghdr msg;
dab32b32 3263 abi_ulong count;
3532fa74 3264 struct iovec *vec;
992f48a0 3265 abi_ulong target_vec;
3532fa74 3266
3532fa74
FB
3267 if (msgp->msg_name) {
3268 msg.msg_namelen = tswap32(msgp->msg_namelen);
2dd08dfd 3269 msg.msg_name = alloca(msg.msg_namelen+1);
7b36f782
LV
3270 ret = target_to_host_sockaddr(fd, msg.msg_name,
3271 tswapal(msgp->msg_name),
3272 msg.msg_namelen);
26a6fc96
PM
3273 if (ret == -TARGET_EFAULT) {
3274 /* For connected sockets msg_name and msg_namelen must
3275 * be ignored, so returning EFAULT immediately is wrong.
3276 * Instead, pass a bad msg_name to the host kernel, and
3277 * let it decide whether to return EFAULT or not.
3278 */
3279 msg.msg_name = (void *)-1;
3280 } else if (ret) {
f287b2c2 3281 goto out2;
917507b0 3282 }
3532fa74
FB
3283 } else {
3284 msg.msg_name = NULL;
3285 msg.msg_namelen = 0;
3286 }
cbb21eed 3287 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
3532fa74 3288 msg.msg_control = alloca(msg.msg_controllen);
1d3d1b23
JS
3289 memset(msg.msg_control, 0, msg.msg_controllen);
3290
3532fa74 3291 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 3292
cbb21eed 3293 count = tswapal(msgp->msg_iovlen);
cbb21eed 3294 target_vec = tswapal(msgp->msg_iov);
97b07970
PM
3295
3296 if (count > IOV_MAX) {
3297 /* sendrcvmsg returns a different errno for this condition than
3298 * readv/writev, so we must catch it here before lock_iovec() does.
3299 */
3300 ret = -TARGET_EMSGSIZE;
3301 goto out2;
3302 }
3303
f287b2c2
RH
3304 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3305 target_vec, count, send);
3306 if (vec == NULL) {
3307 ret = -host_to_target_errno(errno);
3f0744f9
HD
3308 /* allow sending packet without any iov, e.g. with MSG_MORE flag */
3309 if (!send || ret) {
3310 goto out2;
3311 }
f287b2c2 3312 }
3532fa74
FB
3313 msg.msg_iovlen = count;
3314 msg.msg_iov = vec;
3b46e624 3315
3532fa74 3316 if (send) {
6c5b5645 3317 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3318 void *host_msg;
3319
3320 host_msg = g_malloc(msg.msg_iov->iov_len);
3321 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3322 ret = fd_trans_target_to_host_data(fd)(host_msg,
6c5b5645 3323 msg.msg_iov->iov_len);
7d61d892
LV
3324 if (ret >= 0) {
3325 msg.msg_iov->iov_base = host_msg;
3326 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3327 }
3328 g_free(host_msg);
6c5b5645
LV
3329 } else {
3330 ret = target_to_host_cmsg(&msg, msgp);
7d61d892
LV
3331 if (ret == 0) {
3332 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3333 }
6c5b5645 3334 }
3532fa74 3335 } else {
66687530 3336 ret = get_errno(safe_recvmsg(fd, &msg, flags));
6de645c7
AZ
3337 if (!is_error(ret)) {
3338 len = ret;
6c5b5645
LV
3339 if (fd_trans_host_to_target_data(fd)) {
3340 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
2a03d3e6 3341 MIN(msg.msg_iov->iov_len, len));
16c81dd5
IZ
3342 }
3343 if (!is_error(ret)) {
6c5b5645
LV
3344 ret = host_to_target_cmsg(msgp, &msg);
3345 }
ca619067
JH
3346 if (!is_error(ret)) {
3347 msgp->msg_namelen = tswap32(msg.msg_namelen);
24894f39 3348 msgp->msg_flags = tswap32(msg.msg_flags);
26a6fc96 3349 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ca619067
JH
3350 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3351 msg.msg_name, msg.msg_namelen);
3352 if (ret) {
3353 goto out;
3354 }
3355 }
3356
6de645c7 3357 ret = len;
ca619067 3358 }
6de645c7 3359 }
3532fa74 3360 }
ca619067
JH
3361
3362out:
3f0744f9
HD
3363 if (vec) {
3364 unlock_iovec(vec, target_vec, count, !send);
3365 }
f287b2c2 3366out2:
f19e00d7
AG
3367 return ret;
3368}
3369
3370static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3371 int flags, int send)
3372{
3373 abi_long ret;
3374 struct target_msghdr *msgp;
3375
3376 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3377 msgp,
3378 target_msg,
3379 send ? 1 : 0)) {
3380 return -TARGET_EFAULT;
3381 }
3382 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
579a97f7 3383 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
3384 return ret;
3385}
3386
f19e00d7
AG
3387/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3388 * so it might not have this *mmsg-specific flag either.
3389 */
3390#ifndef MSG_WAITFORONE
3391#define MSG_WAITFORONE 0x10000
3392#endif
3393
3394static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3395 unsigned int vlen, unsigned int flags,
3396 int send)
3397{
3398 struct target_mmsghdr *mmsgp;
3399 abi_long ret = 0;
3400 int i;
3401
3402 if (vlen > UIO_MAXIOV) {
3403 vlen = UIO_MAXIOV;
3404 }
3405
3406 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3407 if (!mmsgp) {
3408 return -TARGET_EFAULT;
3409 }
3410
3411 for (i = 0; i < vlen; i++) {
3412 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3413 if (is_error(ret)) {
3414 break;
3415 }
3416 mmsgp[i].msg_len = tswap32(ret);
3417 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3418 if (flags & MSG_WAITFORONE) {
3419 flags |= MSG_DONTWAIT;
3420 }
3421 }
3422
3423 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3424
3425 /* Return number of datagrams sent if we sent any at all;
3426 * otherwise return the error.
3427 */
3428 if (i) {
3429 return i;
3430 }
3431 return ret;
3432}
f19e00d7 3433
a94b4987
PM
3434/* do_accept4() Must return target values and target errnos. */
3435static abi_long do_accept4(int fd, abi_ulong target_addr,
3436 abi_ulong target_addrlen_addr, int flags)
1be9e1dc 3437{
cd813367 3438 socklen_t addrlen, ret_addrlen;
2f619698 3439 void *addr;
992f48a0 3440 abi_long ret;
d25295d4
PJ
3441 int host_flags;
3442
3443 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
1be9e1dc 3444
a94b4987 3445 if (target_addr == 0) {
ff6dc130 3446 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
a94b4987 3447 }
917507b0 3448
e554eb4b 3449 /* linux returns EFAULT if addrlen pointer is invalid */
2f619698 3450 if (get_user_u32(addrlen, target_addrlen_addr))
e554eb4b 3451 return -TARGET_EFAULT;
2f619698 3452
38724253 3453 if ((int)addrlen < 0) {
8f7aeaf6 3454 return -TARGET_EINVAL;
38724253 3455 }
8f7aeaf6 3456
c7169b02 3457 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
e554eb4b 3458 return -TARGET_EFAULT;
c7169b02 3459 }
917507b0 3460
2f619698
FB
3461 addr = alloca(addrlen);
3462
cd813367
AS
3463 ret_addrlen = addrlen;
3464 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
1be9e1dc 3465 if (!is_error(ret)) {
cd813367
AS
3466 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3467 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3468 ret = -TARGET_EFAULT;
cd813367 3469 }
1be9e1dc
PB
3470 }
3471 return ret;
3472}
3473
0da46a6e 3474/* do_getpeername() Must return target values and target errnos. */
992f48a0 3475static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 3476 abi_ulong target_addrlen_addr)
1be9e1dc 3477{
cd813367 3478 socklen_t addrlen, ret_addrlen;
2f619698 3479 void *addr;
992f48a0 3480 abi_long ret;
1be9e1dc 3481
2f619698
FB
3482 if (get_user_u32(addrlen, target_addrlen_addr))
3483 return -TARGET_EFAULT;
3484
38724253 3485 if ((int)addrlen < 0) {
8f7aeaf6 3486 return -TARGET_EINVAL;
38724253 3487 }
8f7aeaf6 3488
c7169b02 3489 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3490 return -TARGET_EFAULT;
c7169b02 3491 }
917507b0 3492
2f619698
FB
3493 addr = alloca(addrlen);
3494
cd813367
AS
3495 ret_addrlen = addrlen;
3496 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
1be9e1dc 3497 if (!is_error(ret)) {
cd813367
AS
3498 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3499 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3500 ret = -TARGET_EFAULT;
cd813367 3501 }
1be9e1dc
PB
3502 }
3503 return ret;
3504}
3505
0da46a6e 3506/* do_getsockname() Must return target values and target errnos. */
992f48a0 3507static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 3508 abi_ulong target_addrlen_addr)
1be9e1dc 3509{
cd813367 3510 socklen_t addrlen, ret_addrlen;
2f619698 3511 void *addr;
992f48a0 3512 abi_long ret;
1be9e1dc 3513
2f619698
FB
3514 if (get_user_u32(addrlen, target_addrlen_addr))
3515 return -TARGET_EFAULT;
3516
38724253 3517 if ((int)addrlen < 0) {
8f7aeaf6 3518 return -TARGET_EINVAL;
38724253 3519 }
8f7aeaf6 3520
c7169b02 3521 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3522 return -TARGET_EFAULT;
c7169b02 3523 }
917507b0 3524
2f619698
FB
3525 addr = alloca(addrlen);
3526
cd813367
AS
3527 ret_addrlen = addrlen;
3528 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
1be9e1dc 3529 if (!is_error(ret)) {
cd813367
AS
3530 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3531 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3532 ret = -TARGET_EFAULT;
cd813367 3533 }
1be9e1dc
PB
3534 }
3535 return ret;
3536}
3537
0da46a6e 3538/* do_socketpair() Must return target values and target errnos. */
992f48a0 3539static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 3540 abi_ulong target_tab_addr)
1be9e1dc
PB
3541{
3542 int tab[2];
992f48a0 3543 abi_long ret;
1be9e1dc 3544
f651e6ae
PJ
3545 target_to_host_sock_type(&type);
3546
1be9e1dc
PB
3547 ret = get_errno(socketpair(domain, type, protocol, tab));
3548 if (!is_error(ret)) {
2f619698
FB
3549 if (put_user_s32(tab[0], target_tab_addr)
3550 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3551 ret = -TARGET_EFAULT;
1be9e1dc
PB
3552 }
3553 return ret;
3554}
3555
0da46a6e 3556/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
3557static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3558 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
3559{
3560 void *addr;
3561 void *host_msg;
7d61d892 3562 void *copy_msg = NULL;
992f48a0 3563 abi_long ret;
1be9e1dc 3564
38724253 3565 if ((int)addrlen < 0) {
8f7aeaf6 3566 return -TARGET_EINVAL;
38724253 3567 }
8f7aeaf6 3568
579a97f7
FB
3569 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3570 if (!host_msg)
3571 return -TARGET_EFAULT;
6c5b5645 3572 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3573 copy_msg = host_msg;
3574 host_msg = g_malloc(len);
3575 memcpy(host_msg, copy_msg, len);
6c5b5645
LV
3576 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3577 if (ret < 0) {
7d61d892 3578 goto fail;
6c5b5645
LV
3579 }
3580 }
1be9e1dc 3581 if (target_addr) {
2dd08dfd 3582 addr = alloca(addrlen+1);
7b36f782 3583 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
917507b0 3584 if (ret) {
7d61d892 3585 goto fail;
917507b0 3586 }
66687530 3587 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
1be9e1dc 3588 } else {
66687530 3589 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
1be9e1dc 3590 }
7d61d892
LV
3591fail:
3592 if (copy_msg) {
3593 g_free(host_msg);
3594 host_msg = copy_msg;
3595 }
1be9e1dc
PB
3596 unlock_user(host_msg, msg, 0);
3597 return ret;
3598}
3599
0da46a6e 3600/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
3601static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3602 abi_ulong target_addr,
3603 abi_ulong target_addrlen)
1be9e1dc 3604{
cd813367 3605 socklen_t addrlen, ret_addrlen;
1be9e1dc
PB
3606 void *addr;
3607 void *host_msg;
992f48a0 3608 abi_long ret;
1be9e1dc 3609
4a1e6bce
ZR
3610 if (!msg) {
3611 host_msg = NULL;
3612 } else {
3613 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3614 if (!host_msg) {
3615 return -TARGET_EFAULT;
3616 }
3617 }
1be9e1dc 3618 if (target_addr) {
2f619698
FB
3619 if (get_user_u32(addrlen, target_addrlen)) {
3620 ret = -TARGET_EFAULT;
3621 goto fail;
3622 }
38724253 3623 if ((int)addrlen < 0) {
8f7aeaf6
AJ
3624 ret = -TARGET_EINVAL;
3625 goto fail;
3626 }
1be9e1dc 3627 addr = alloca(addrlen);
cd813367 3628 ret_addrlen = addrlen;
66687530 3629 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
cd813367 3630 addr, &ret_addrlen));
1be9e1dc
PB
3631 } else {
3632 addr = NULL; /* To keep compiler quiet. */
cd813367 3633 addrlen = 0; /* To keep compiler quiet. */
66687530 3634 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
1be9e1dc
PB
3635 }
3636 if (!is_error(ret)) {
c35e1f9c 3637 if (fd_trans_host_to_target_data(fd)) {
2a03d3e6
LV
3638 abi_long trans;
3639 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3640 if (is_error(trans)) {
3641 ret = trans;
3642 goto fail;
3643 }
c35e1f9c 3644 }
1be9e1dc 3645 if (target_addr) {
cd813367
AS
3646 host_to_target_sockaddr(target_addr, addr,
3647 MIN(addrlen, ret_addrlen));
3648 if (put_user_u32(ret_addrlen, target_addrlen)) {
2f619698
FB
3649 ret = -TARGET_EFAULT;
3650 goto fail;
3651 }
1be9e1dc
PB
3652 }
3653 unlock_user(host_msg, msg, len);
3654 } else {
2f619698 3655fail:
1be9e1dc
PB
3656 unlock_user(host_msg, msg, 0);
3657 }
3658 return ret;
3659}
3660
32407103 3661#ifdef TARGET_NR_socketcall
ff71a454 3662/* do_socketcall() must return target values and target errnos. */
992f48a0 3663static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 3664{
ff71a454
AM
3665 static const unsigned nargs[] = { /* number of arguments per operation */
3666 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3667 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3668 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3669 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3670 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3671 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3672 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3673 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3674 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3675 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3676 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3677 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3678 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3679 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3680 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3681 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3682 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3683 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3684 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3685 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
62dc90c6
MT
3686 };
3687 abi_long a[6]; /* max 6 args */
ff71a454 3688 unsigned i;
62dc90c6 3689
ff71a454
AM
3690 /* check the range of the first argument num */
3691 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3692 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3693 return -TARGET_EINVAL;
3694 }
3695 /* ensure we have space for args */
3696 if (nargs[num] > ARRAY_SIZE(a)) {
3697 return -TARGET_EINVAL;
3698 }
3699 /* collect the arguments in a[] according to nargs[] */
3700 for (i = 0; i < nargs[num]; ++i) {
3701 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3702 return -TARGET_EFAULT;
31e31b8a 3703 }
62dc90c6 3704 }
ff71a454 3705 /* now when we have the args, invoke the appropriate underlying function */
62dc90c6 3706 switch (num) {
ff71a454 3707 case TARGET_SYS_SOCKET: /* domain, type, protocol */
62dc90c6 3708 return do_socket(a[0], a[1], a[2]);
ff71a454 3709 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
62dc90c6 3710 return do_bind(a[0], a[1], a[2]);
ff71a454 3711 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
62dc90c6 3712 return do_connect(a[0], a[1], a[2]);
ff71a454 3713 case TARGET_SYS_LISTEN: /* sockfd, backlog */
62dc90c6 3714 return get_errno(listen(a[0], a[1]));
ff71a454 3715 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
62dc90c6 3716 return do_accept4(a[0], a[1], a[2], 0);
ff71a454 3717 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
62dc90c6 3718 return do_getsockname(a[0], a[1], a[2]);
ff71a454 3719 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
62dc90c6 3720 return do_getpeername(a[0], a[1], a[2]);
ff71a454 3721 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
62dc90c6 3722 return do_socketpair(a[0], a[1], a[2], a[3]);
ff71a454 3723 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
62dc90c6 3724 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3725 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
62dc90c6 3726 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3727 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3728 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3729 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3730 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3731 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
62dc90c6 3732 return get_errno(shutdown(a[0], a[1]));
ff71a454
AM
3733 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3734 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
3735 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3736 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
3737 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
62dc90c6 3738 return do_sendrecvmsg(a[0], a[1], a[2], 1);
ff71a454 3739 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
62dc90c6 3740 return do_sendrecvmsg(a[0], a[1], a[2], 0);
ff71a454
AM
3741 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3742 return do_accept4(a[0], a[1], a[2], a[3]);
3743 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
5a53dc50 3744 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
ff71a454
AM
3745 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3746 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
31e31b8a 3747 default:
39be5350 3748 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
ff71a454 3749 return -TARGET_EINVAL;
31e31b8a 3750 }
31e31b8a 3751}
32407103 3752#endif
31e31b8a 3753
8853f86e
FB
3754#define N_SHM_REGIONS 32
3755
3756static struct shm_region {
b6e17875
PM
3757 abi_ulong start;
3758 abi_ulong size;
3759 bool in_use;
8853f86e
FB
3760} shm_regions[N_SHM_REGIONS];
3761
005eb2ae
PM
3762#ifndef TARGET_SEMID64_DS
3763/* asm-generic version of this struct */
3764struct target_semid64_ds
3eb6b044
TS
3765{
3766 struct target_ipc_perm sem_perm;
992f48a0 3767 abi_ulong sem_otime;
005eb2ae 3768#if TARGET_ABI_BITS == 32
992f48a0 3769 abi_ulong __unused1;
03527344 3770#endif
992f48a0 3771 abi_ulong sem_ctime;
005eb2ae 3772#if TARGET_ABI_BITS == 32
992f48a0 3773 abi_ulong __unused2;
03527344 3774#endif
992f48a0
BS
3775 abi_ulong sem_nsems;
3776 abi_ulong __unused3;
3777 abi_ulong __unused4;
3eb6b044 3778};
005eb2ae 3779#endif
3eb6b044 3780
579a97f7
FB
3781static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3782 abi_ulong target_addr)
3eb6b044
TS
3783{
3784 struct target_ipc_perm *target_ip;
005eb2ae 3785 struct target_semid64_ds *target_sd;
3eb6b044 3786
579a97f7
FB
3787 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3788 return -TARGET_EFAULT;
e8bbe36c 3789 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3790 host_ip->__key = tswap32(target_ip->__key);
3791 host_ip->uid = tswap32(target_ip->uid);
3792 host_ip->gid = tswap32(target_ip->gid);
3793 host_ip->cuid = tswap32(target_ip->cuid);
3794 host_ip->cgid = tswap32(target_ip->cgid);
3795#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3796 host_ip->mode = tswap32(target_ip->mode);
3797#else
cbb21eed 3798 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
3799#endif
3800#if defined(TARGET_PPC)
3801 host_ip->__seq = tswap32(target_ip->__seq);
3802#else
3803 host_ip->__seq = tswap16(target_ip->__seq);
3804#endif
3eb6b044 3805 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3806 return 0;
3eb6b044
TS
3807}
3808
579a97f7
FB
3809static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3810 struct ipc_perm *host_ip)
3eb6b044
TS
3811{
3812 struct target_ipc_perm *target_ip;
005eb2ae 3813 struct target_semid64_ds *target_sd;
3eb6b044 3814
579a97f7
FB
3815 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3816 return -TARGET_EFAULT;
3eb6b044 3817 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3818 target_ip->__key = tswap32(host_ip->__key);
3819 target_ip->uid = tswap32(host_ip->uid);
3820 target_ip->gid = tswap32(host_ip->gid);
3821 target_ip->cuid = tswap32(host_ip->cuid);
3822 target_ip->cgid = tswap32(host_ip->cgid);
3823#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3824 target_ip->mode = tswap32(host_ip->mode);
3825#else
cbb21eed 3826 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
3827#endif
3828#if defined(TARGET_PPC)
3829 target_ip->__seq = tswap32(host_ip->__seq);
3830#else
3831 target_ip->__seq = tswap16(host_ip->__seq);
3832#endif
3eb6b044 3833 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3834 return 0;
3eb6b044
TS
3835}
3836
579a97f7
FB
3837static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3838 abi_ulong target_addr)
3eb6b044 3839{
005eb2ae 3840 struct target_semid64_ds *target_sd;
3eb6b044 3841
579a97f7
FB
3842 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3843 return -TARGET_EFAULT;
e5289087
AJ
3844 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3845 return -TARGET_EFAULT;
cbb21eed
MB
3846 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3847 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3848 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 3849 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3850 return 0;
3eb6b044
TS
3851}
3852
579a97f7
FB
3853static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3854 struct semid_ds *host_sd)
3eb6b044 3855{
005eb2ae 3856 struct target_semid64_ds *target_sd;
3eb6b044 3857
579a97f7
FB
3858 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3859 return -TARGET_EFAULT;
e5289087 3860 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 3861 return -TARGET_EFAULT;
cbb21eed
MB
3862 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3863 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3864 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 3865 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3866 return 0;
3eb6b044
TS
3867}
3868
e5289087
AJ
3869struct target_seminfo {
3870 int semmap;
3871 int semmni;
3872 int semmns;
3873 int semmnu;
3874 int semmsl;
3875 int semopm;
3876 int semume;
3877 int semusz;
3878 int semvmx;
3879 int semaem;
3880};
3881
3882static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3883 struct seminfo *host_seminfo)
3884{
3885 struct target_seminfo *target_seminfo;
3886 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3887 return -TARGET_EFAULT;
3888 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3889 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3890 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3891 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3892 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3893 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3894 __put_user(host_seminfo->semume, &target_seminfo->semume);
3895 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3896 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3897 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3898 unlock_user_struct(target_seminfo, target_addr, 1);
3899 return 0;
3900}
3901
fa294816
TS
3902union semun {
3903 int val;
3eb6b044 3904 struct semid_ds *buf;
fa294816 3905 unsigned short *array;
e5289087 3906 struct seminfo *__buf;
fa294816
TS
3907};
3908
3eb6b044
TS
3909union target_semun {
3910 int val;
e5289087
AJ
3911 abi_ulong buf;
3912 abi_ulong array;
3913 abi_ulong __buf;
3eb6b044
TS
3914};
3915
e5289087
AJ
3916static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3917 abi_ulong target_addr)
3eb6b044 3918{
e5289087
AJ
3919 int nsems;
3920 unsigned short *array;
3921 union semun semun;
3922 struct semid_ds semid_ds;
3923 int i, ret;
3eb6b044 3924
e5289087
AJ
3925 semun.buf = &semid_ds;
3926
3927 ret = semctl(semid, 0, IPC_STAT, semun);
3928 if (ret == -1)
3929 return get_errno(ret);
3930
3931 nsems = semid_ds.sem_nsems;
3932
0e173b24 3933 *host_array = g_try_new(unsigned short, nsems);
69d4c703
PM
3934 if (!*host_array) {
3935 return -TARGET_ENOMEM;
3936 }
e5289087
AJ
3937 array = lock_user(VERIFY_READ, target_addr,
3938 nsems*sizeof(unsigned short), 1);
69d4c703 3939 if (!array) {
0e173b24 3940 g_free(*host_array);
e5289087 3941 return -TARGET_EFAULT;
69d4c703 3942 }
e5289087
AJ
3943
3944 for(i=0; i<nsems; i++) {
3945 __get_user((*host_array)[i], &array[i]);
3eb6b044 3946 }
e5289087
AJ
3947 unlock_user(array, target_addr, 0);
3948
579a97f7 3949 return 0;
3eb6b044
TS
3950}
3951
e5289087
AJ
3952static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3953 unsigned short **host_array)
3eb6b044 3954{
e5289087
AJ
3955 int nsems;
3956 unsigned short *array;
3957 union semun semun;
3958 struct semid_ds semid_ds;
3959 int i, ret;
3eb6b044 3960
e5289087
AJ
3961 semun.buf = &semid_ds;
3962
3963 ret = semctl(semid, 0, IPC_STAT, semun);
3964 if (ret == -1)
3965 return get_errno(ret);
3966
3967 nsems = semid_ds.sem_nsems;
3968
3969 array = lock_user(VERIFY_WRITE, target_addr,
3970 nsems*sizeof(unsigned short), 0);
3971 if (!array)
3972 return -TARGET_EFAULT;
3973
3974 for(i=0; i<nsems; i++) {
3975 __put_user((*host_array)[i], &array[i]);
3eb6b044 3976 }
0e173b24 3977 g_free(*host_array);
e5289087
AJ
3978 unlock_user(array, target_addr, 1);
3979
579a97f7 3980 return 0;
3eb6b044
TS
3981}
3982
e5289087 3983static inline abi_long do_semctl(int semid, int semnum, int cmd,
d1c002b6 3984 abi_ulong target_arg)
3eb6b044 3985{
d1c002b6 3986 union target_semun target_su = { .buf = target_arg };
3eb6b044
TS
3987 union semun arg;
3988 struct semid_ds dsarg;
7b8118e8 3989 unsigned short *array = NULL;
e5289087
AJ
3990 struct seminfo seminfo;
3991 abi_long ret = -TARGET_EINVAL;
3992 abi_long err;
3993 cmd &= 0xff;
3eb6b044
TS
3994
3995 switch( cmd ) {
3996 case GETVAL:
3eb6b044 3997 case SETVAL:
5464baec
TM
3998 /* In 64 bit cross-endian situations, we will erroneously pick up
3999 * the wrong half of the union for the "val" element. To rectify
4000 * this, the entire 8-byte structure is byteswapped, followed by
4001 * a swap of the 4 byte val field. In other cases, the data is
4002 * already in proper host byte order. */
4003 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
4004 target_su.buf = tswapal(target_su.buf);
4005 arg.val = tswap32(target_su.val);
4006 } else {
4007 arg.val = target_su.val;
4008 }
e5289087 4009 ret = get_errno(semctl(semid, semnum, cmd, arg));
3eb6b044
TS
4010 break;
4011 case GETALL:
3eb6b044 4012 case SETALL:
e5289087
AJ
4013 err = target_to_host_semarray(semid, &array, target_su.array);
4014 if (err)
4015 return err;
4016 arg.array = array;
4017 ret = get_errno(semctl(semid, semnum, cmd, arg));
4018 err = host_to_target_semarray(semid, target_su.array, &array);
4019 if (err)
4020 return err;
3eb6b044
TS
4021 break;
4022 case IPC_STAT:
3eb6b044 4023 case IPC_SET:
e5289087
AJ
4024 case SEM_STAT:
4025 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4026 if (err)
4027 return err;
4028 arg.buf = &dsarg;
4029 ret = get_errno(semctl(semid, semnum, cmd, arg));
4030 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4031 if (err)
4032 return err;
4033 break;
4034 case IPC_INFO:
4035 case SEM_INFO:
4036 arg.__buf = &seminfo;
4037 ret = get_errno(semctl(semid, semnum, cmd, arg));
4038 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4039 if (err)
4040 return err;
4041 break;
4042 case IPC_RMID:
4043 case GETPID:
4044 case GETNCNT:
4045 case GETZCNT:
4046 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 4047 break;
3eb6b044
TS
4048 }
4049
4050 return ret;
4051}
4052
e5289087
AJ
4053struct target_sembuf {
4054 unsigned short sem_num;
4055 short sem_op;
4056 short sem_flg;
4057};
4058
4059static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4060 abi_ulong target_addr,
4061 unsigned nsops)
4062{
4063 struct target_sembuf *target_sembuf;
4064 int i;
4065
4066 target_sembuf = lock_user(VERIFY_READ, target_addr,
4067 nsops*sizeof(struct target_sembuf), 1);
4068 if (!target_sembuf)
4069 return -TARGET_EFAULT;
4070
4071 for(i=0; i<nsops; i++) {
4072 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4073 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4074 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4075 }
4076
4077 unlock_user(target_sembuf, target_addr, 0);
4078
4079 return 0;
4080}
4081
d8c08b1e 4082#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
cac46eb0 4083 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
d8c08b1e
MK
4084
4085/*
4086 * This macro is required to handle the s390 variants, which passes the
4087 * arguments in a different order than default.
4088 */
4089#ifdef __s390x__
4090#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4091 (__nsops), (__timeout), (__sops)
4092#else
4093#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4094 (__nsops), 0, (__sops), (__timeout)
4095#endif
4096
4097static inline abi_long do_semtimedop(int semid,
4098 abi_long ptr,
4099 unsigned nsops,
cac46eb0 4100 abi_long timeout, bool time64)
e5289087 4101{
0a7ec849 4102 struct sembuf *sops;
d8c08b1e 4103 struct timespec ts, *pts = NULL;
524fa340 4104 abi_long ret;
e5289087 4105
d8c08b1e
MK
4106 if (timeout) {
4107 pts = &ts;
cac46eb0
FB
4108 if (time64) {
4109 if (target_to_host_timespec64(pts, timeout)) {
4110 return -TARGET_EFAULT;
4111 }
4112 } else {
4113 if (target_to_host_timespec(pts, timeout)) {
4114 return -TARGET_EFAULT;
4115 }
d8c08b1e
MK
4116 }
4117 }
4118
0a7ec849
FB
4119 if (nsops > TARGET_SEMOPM) {
4120 return -TARGET_E2BIG;
4121 }
4122
4123 sops = g_new(struct sembuf, nsops);
4124
4125 if (target_to_host_sembuf(sops, ptr, nsops)) {
4126 g_free(sops);
e5289087 4127 return -TARGET_EFAULT;
0a7ec849 4128 }
e5289087 4129
524fa340
LV
4130 ret = -TARGET_ENOSYS;
4131#ifdef __NR_semtimedop
d8c08b1e 4132 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
524fa340
LV
4133#endif
4134#ifdef __NR_ipc
4135 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4136 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4137 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
524fa340
LV
4138 }
4139#endif
0a7ec849 4140 g_free(sops);
524fa340 4141 return ret;
e5289087 4142}
d8c08b1e 4143#endif
e5289087 4144
1bc012f6
TS
4145struct target_msqid_ds
4146{
1c54ff97
AJ
4147 struct target_ipc_perm msg_perm;
4148 abi_ulong msg_stime;
4149#if TARGET_ABI_BITS == 32
4150 abi_ulong __unused1;
4151#endif
4152 abi_ulong msg_rtime;
4153#if TARGET_ABI_BITS == 32
4154 abi_ulong __unused2;
4155#endif
4156 abi_ulong msg_ctime;
4157#if TARGET_ABI_BITS == 32
4158 abi_ulong __unused3;
4159#endif
4160 abi_ulong __msg_cbytes;
4161 abi_ulong msg_qnum;
4162 abi_ulong msg_qbytes;
4163 abi_ulong msg_lspid;
4164 abi_ulong msg_lrpid;
4165 abi_ulong __unused4;
4166 abi_ulong __unused5;
1bc012f6
TS
4167};
4168
579a97f7
FB
4169static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4170 abi_ulong target_addr)
1bc012f6
TS
4171{
4172 struct target_msqid_ds *target_md;
4173
579a97f7
FB
4174 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4175 return -TARGET_EFAULT;
1c54ff97
AJ
4176 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4177 return -TARGET_EFAULT;
cbb21eed
MB
4178 host_md->msg_stime = tswapal(target_md->msg_stime);
4179 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4180 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4181 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4182 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4183 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4184 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4185 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 4186 unlock_user_struct(target_md, target_addr, 0);
579a97f7 4187 return 0;
1bc012f6
TS
4188}
4189
579a97f7
FB
4190static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4191 struct msqid_ds *host_md)
1bc012f6
TS
4192{
4193 struct target_msqid_ds *target_md;
4194
579a97f7
FB
4195 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4196 return -TARGET_EFAULT;
1c54ff97
AJ
4197 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4198 return -TARGET_EFAULT;
cbb21eed
MB
4199 target_md->msg_stime = tswapal(host_md->msg_stime);
4200 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4201 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4202 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4203 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4204 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4205 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4206 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 4207 unlock_user_struct(target_md, target_addr, 1);
579a97f7 4208 return 0;
1bc012f6
TS
4209}
4210
1c54ff97
AJ
4211struct target_msginfo {
4212 int msgpool;
4213 int msgmap;
4214 int msgmax;
4215 int msgmnb;
4216 int msgmni;
4217 int msgssz;
4218 int msgtql;
4219 unsigned short int msgseg;
4220};
4221
4222static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4223 struct msginfo *host_msginfo)
4224{
4225 struct target_msginfo *target_msginfo;
4226 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4227 return -TARGET_EFAULT;
4228 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4229 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4230 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4231 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4232 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4233 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4234 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4235 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4236 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 4237 return 0;
1c54ff97
AJ
4238}
4239
4240static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
4241{
4242 struct msqid_ds dsarg;
1c54ff97
AJ
4243 struct msginfo msginfo;
4244 abi_long ret = -TARGET_EINVAL;
4245
4246 cmd &= 0xff;
4247
4248 switch (cmd) {
1bc012f6
TS
4249 case IPC_STAT:
4250 case IPC_SET:
1c54ff97
AJ
4251 case MSG_STAT:
4252 if (target_to_host_msqid_ds(&dsarg,ptr))
4253 return -TARGET_EFAULT;
4254 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4255 if (host_to_target_msqid_ds(ptr,&dsarg))
4256 return -TARGET_EFAULT;
4257 break;
4258 case IPC_RMID:
4259 ret = get_errno(msgctl(msgid, cmd, NULL));
4260 break;
4261 case IPC_INFO:
4262 case MSG_INFO:
4263 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4264 if (host_to_target_msginfo(ptr, &msginfo))
4265 return -TARGET_EFAULT;
4266 break;
1bc012f6 4267 }
1c54ff97 4268
1bc012f6
TS
4269 return ret;
4270}
4271
4272struct target_msgbuf {
1c54ff97
AJ
4273 abi_long mtype;
4274 char mtext[1];
1bc012f6
TS
4275};
4276
992f48a0 4277static inline abi_long do_msgsnd(int msqid, abi_long msgp,
edcc5f9d 4278 ssize_t msgsz, int msgflg)
1bc012f6
TS
4279{
4280 struct target_msgbuf *target_mb;
4281 struct msgbuf *host_mb;
992f48a0 4282 abi_long ret = 0;
1bc012f6 4283
edcc5f9d
TM
4284 if (msgsz < 0) {
4285 return -TARGET_EINVAL;
4286 }
4287
579a97f7
FB
4288 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4289 return -TARGET_EFAULT;
0e173b24 4290 host_mb = g_try_malloc(msgsz + sizeof(long));
29e03fcb
HZ
4291 if (!host_mb) {
4292 unlock_user_struct(target_mb, msgp, 0);
4293 return -TARGET_ENOMEM;
4294 }
cbb21eed 4295 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 4296 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
524fa340
LV
4297 ret = -TARGET_ENOSYS;
4298#ifdef __NR_msgsnd
89f9fe44 4299 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
524fa340
LV
4300#endif
4301#ifdef __NR_ipc
4302 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4303#ifdef __s390x__
4304 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4305 host_mb));
4306#else
524fa340
LV
4307 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4308 host_mb, 0));
d8c08b1e 4309#endif
524fa340
LV
4310 }
4311#endif
0e173b24 4312 g_free(host_mb);
1bc012f6
TS
4313 unlock_user_struct(target_mb, msgp, 0);
4314
4315 return ret;
4316}
4317
d8c08b1e
MK
4318#ifdef __NR_ipc
4319#if defined(__sparc__)
4320/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4321#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4322#elif defined(__s390x__)
4323/* The s390 sys_ipc variant has only five parameters. */
4324#define MSGRCV_ARGS(__msgp, __msgtyp) \
4325 ((long int[]){(long int)__msgp, __msgtyp})
4326#else
4327#define MSGRCV_ARGS(__msgp, __msgtyp) \
4328 ((long int[]){(long int)__msgp, __msgtyp}), 0
4329#endif
4330#endif
4331
992f48a0 4332static inline abi_long do_msgrcv(int msqid, abi_long msgp,
99874f65 4333 ssize_t msgsz, abi_long msgtyp,
992f48a0 4334 int msgflg)
1bc012f6
TS
4335{
4336 struct target_msgbuf *target_mb;
579a97f7 4337 char *target_mtext;
1bc012f6 4338 struct msgbuf *host_mb;
992f48a0 4339 abi_long ret = 0;
1bc012f6 4340
99874f65
PM
4341 if (msgsz < 0) {
4342 return -TARGET_EINVAL;
4343 }
4344
579a97f7
FB
4345 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4346 return -TARGET_EFAULT;
1c54ff97 4347
415d8471
PM
4348 host_mb = g_try_malloc(msgsz + sizeof(long));
4349 if (!host_mb) {
4350 ret = -TARGET_ENOMEM;
4351 goto end;
4352 }
524fa340
LV
4353 ret = -TARGET_ENOSYS;
4354#ifdef __NR_msgrcv
89f9fe44 4355 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
524fa340
LV
4356#endif
4357#ifdef __NR_ipc
4358 if (ret == -TARGET_ENOSYS) {
4359 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
d8c08b1e 4360 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
524fa340
LV
4361 }
4362#endif
1c54ff97 4363
579a97f7
FB
4364 if (ret > 0) {
4365 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4366 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4367 if (!target_mtext) {
4368 ret = -TARGET_EFAULT;
4369 goto end;
4370 }
1c54ff97 4371 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
4372 unlock_user(target_mtext, target_mtext_addr, ret);
4373 }
1c54ff97 4374
cbb21eed 4375 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 4376
579a97f7
FB
4377end:
4378 if (target_mb)
4379 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 4380 g_free(host_mb);
1bc012f6
TS
4381 return ret;
4382}
4383
88a8c984
RV
4384static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4385 abi_ulong target_addr)
4386{
4387 struct target_shmid_ds *target_sd;
4388
4389 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4390 return -TARGET_EFAULT;
4391 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4392 return -TARGET_EFAULT;
4393 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4394 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4395 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4396 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4397 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4398 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4399 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4400 unlock_user_struct(target_sd, target_addr, 0);
4401 return 0;
4402}
4403
4404static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4405 struct shmid_ds *host_sd)
4406{
4407 struct target_shmid_ds *target_sd;
4408
4409 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4410 return -TARGET_EFAULT;
4411 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4412 return -TARGET_EFAULT;
4413 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4414 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4415 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4416 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4417 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4418 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4419 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4420 unlock_user_struct(target_sd, target_addr, 1);
4421 return 0;
4422}
4423
4424struct target_shminfo {
4425 abi_ulong shmmax;
4426 abi_ulong shmmin;
4427 abi_ulong shmmni;
4428 abi_ulong shmseg;
4429 abi_ulong shmall;
4430};
4431
4432static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4433 struct shminfo *host_shminfo)
4434{
4435 struct target_shminfo *target_shminfo;
4436 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4437 return -TARGET_EFAULT;
4438 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4439 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4440 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4441 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4442 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4443 unlock_user_struct(target_shminfo, target_addr, 1);
4444 return 0;
4445}
4446
4447struct target_shm_info {
4448 int used_ids;
4449 abi_ulong shm_tot;
4450 abi_ulong shm_rss;
4451 abi_ulong shm_swp;
4452 abi_ulong swap_attempts;
4453 abi_ulong swap_successes;
4454};
4455
4456static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4457 struct shm_info *host_shm_info)
4458{
4459 struct target_shm_info *target_shm_info;
4460 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4461 return -TARGET_EFAULT;
4462 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4463 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4464 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4465 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4466 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4467 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4468 unlock_user_struct(target_shm_info, target_addr, 1);
4469 return 0;
4470}
4471
4472static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4473{
4474 struct shmid_ds dsarg;
4475 struct shminfo shminfo;
4476 struct shm_info shm_info;
4477 abi_long ret = -TARGET_EINVAL;
4478
4479 cmd &= 0xff;
4480
4481 switch(cmd) {
4482 case IPC_STAT:
4483 case IPC_SET:
4484 case SHM_STAT:
4485 if (target_to_host_shmid_ds(&dsarg, buf))
4486 return -TARGET_EFAULT;
4487 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4488 if (host_to_target_shmid_ds(buf, &dsarg))
4489 return -TARGET_EFAULT;
4490 break;
4491 case IPC_INFO:
4492 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4493 if (host_to_target_shminfo(buf, &shminfo))
4494 return -TARGET_EFAULT;
4495 break;
4496 case SHM_INFO:
4497 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4498 if (host_to_target_shm_info(buf, &shm_info))
4499 return -TARGET_EFAULT;
4500 break;
4501 case IPC_RMID:
4502 case SHM_LOCK:
4503 case SHM_UNLOCK:
4504 ret = get_errno(shmctl(shmid, cmd, NULL));
4505 break;
4506 }
4507
4508 return ret;
4509}
4510
ee8e7614
PM
4511#ifndef TARGET_FORCE_SHMLBA
4512/* For most architectures, SHMLBA is the same as the page size;
4513 * some architectures have larger values, in which case they should
4514 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4515 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4516 * and defining its own value for SHMLBA.
4517 *
4518 * The kernel also permits SHMLBA to be set by the architecture to a
4519 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4520 * this means that addresses are rounded to the large size if
4521 * SHM_RND is set but addresses not aligned to that size are not rejected
4522 * as long as they are at least page-aligned. Since the only architecture
4523 * which uses this is ia64 this code doesn't provide for that oddity.
4524 */
4525static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4526{
4527 return TARGET_PAGE_SIZE;
4528}
4529#endif
4530
4531static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4532 int shmid, abi_ulong shmaddr, int shmflg)
88a8c984 4533{
228168cb 4534 CPUState *cpu = env_cpu(cpu_env);
88a8c984
RV
4535 abi_long raddr;
4536 void *host_raddr;
4537 struct shmid_ds shm_info;
4538 int i,ret;
ee8e7614 4539 abi_ulong shmlba;
88a8c984 4540
ee1bf83d
RH
4541 /* shmat pointers are always untagged */
4542
88a8c984
RV
4543 /* find out the length of the shared memory segment */
4544 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4545 if (is_error(ret)) {
4546 /* can't get length, bail out */
4547 return ret;
4548 }
4549
ee8e7614
PM
4550 shmlba = target_shmlba(cpu_env);
4551
4552 if (shmaddr & (shmlba - 1)) {
4553 if (shmflg & SHM_RND) {
4554 shmaddr &= ~(shmlba - 1);
4555 } else {
4556 return -TARGET_EINVAL;
4557 }
4558 }
46b12f46 4559 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
ebf9a363
MF
4560 return -TARGET_EINVAL;
4561 }
ee8e7614 4562
88a8c984
RV
4563 mmap_lock();
4564
228168cb
RH
4565 /*
4566 * We're mapping shared memory, so ensure we generate code for parallel
4567 * execution and flush old translations. This will work up to the level
4568 * supported by the host -- anything that requires EXCP_ATOMIC will not
4569 * be atomic with respect to an external process.
4570 */
4571 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4572 cpu->tcg_cflags |= CF_PARALLEL;
4573 tb_flush(cpu);
4574 }
4575
88a8c984 4576 if (shmaddr)
3e8f1628 4577 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
88a8c984
RV
4578 else {
4579 abi_ulong mmap_start;
4580
30ab9ef2
RH
4581 /* In order to use the host shmat, we need to honor host SHMLBA. */
4582 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
88a8c984
RV
4583
4584 if (mmap_start == -1) {
4585 errno = ENOMEM;
4586 host_raddr = (void *)-1;
4587 } else
3e8f1628
RH
4588 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4589 shmflg | SHM_REMAP);
88a8c984
RV
4590 }
4591
4592 if (host_raddr == (void *)-1) {
4593 mmap_unlock();
4594 return get_errno((long)host_raddr);
4595 }
4596 raddr=h2g((unsigned long)host_raddr);
4597
4598 page_set_flags(raddr, raddr + shm_info.shm_segsz,
d9c58585
RH
4599 PAGE_VALID | PAGE_RESET | PAGE_READ |
4600 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
88a8c984
RV
4601
4602 for (i = 0; i < N_SHM_REGIONS; i++) {
b6e17875
PM
4603 if (!shm_regions[i].in_use) {
4604 shm_regions[i].in_use = true;
88a8c984
RV
4605 shm_regions[i].start = raddr;
4606 shm_regions[i].size = shm_info.shm_segsz;
4607 break;
4608 }
4609 }
4610
4611 mmap_unlock();
4612 return raddr;
4613
4614}
4615
4616static inline abi_long do_shmdt(abi_ulong shmaddr)
4617{
4618 int i;
3c5f6a5f
MF
4619 abi_long rv;
4620
ee1bf83d
RH
4621 /* shmdt pointers are always untagged */
4622
3c5f6a5f 4623 mmap_lock();
88a8c984
RV
4624
4625 for (i = 0; i < N_SHM_REGIONS; ++i) {
b6e17875
PM
4626 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4627 shm_regions[i].in_use = false;
e00ac249 4628 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
4629 break;
4630 }
4631 }
3e8f1628 4632 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
88a8c984 4633
3c5f6a5f 4634 mmap_unlock();
88a8c984 4635
3c5f6a5f 4636 return rv;
88a8c984
RV
4637}
4638
1c54ff97 4639#ifdef TARGET_NR_ipc
53a5960a 4640/* ??? This only works with linear mappings. */
0da46a6e 4641/* do_ipc() must return target values and target errnos. */
ee8e7614
PM
4642static abi_long do_ipc(CPUArchState *cpu_env,
4643 unsigned int call, abi_long first,
37ed0956 4644 abi_long second, abi_long third,
992f48a0 4645 abi_long ptr, abi_long fifth)
8853f86e
FB
4646{
4647 int version;
992f48a0 4648 abi_long ret = 0;
8853f86e
FB
4649
4650 version = call >> 16;
4651 call &= 0xffff;
4652
4653 switch (call) {
fa294816 4654 case IPCOP_semop:
cac46eb0 4655 ret = do_semtimedop(first, ptr, second, 0, false);
d8c08b1e
MK
4656 break;
4657 case IPCOP_semtimedop:
4658 /*
4659 * The s390 sys_ipc variant has only five parameters instead of six
4660 * (as for default variant) and the only difference is the handling of
4661 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4662 * to a struct timespec where the generic variant uses fifth parameter.
4663 */
4664#if defined(TARGET_S390X)
cac46eb0 4665 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
d8c08b1e 4666#else
cac46eb0 4667 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
d8c08b1e 4668#endif
fa294816
TS
4669 break;
4670
4671 case IPCOP_semget:
4672 ret = get_errno(semget(first, second, third));
4673 break;
4674
5d2fa8eb
TM
4675 case IPCOP_semctl: {
4676 /* The semun argument to semctl is passed by value, so dereference the
4677 * ptr argument. */
4678 abi_ulong atptr;
37ed0956 4679 get_user_ual(atptr, ptr);
d1c002b6 4680 ret = do_semctl(first, second, third, atptr);
fa294816 4681 break;
5d2fa8eb 4682 }
d96372ef 4683
1c54ff97
AJ
4684 case IPCOP_msgget:
4685 ret = get_errno(msgget(first, second));
4686 break;
d96372ef 4687
1c54ff97
AJ
4688 case IPCOP_msgsnd:
4689 ret = do_msgsnd(first, ptr, second, third);
4690 break;
d96372ef 4691
1c54ff97
AJ
4692 case IPCOP_msgctl:
4693 ret = do_msgctl(first, second, ptr);
4694 break;
d96372ef 4695
1c54ff97
AJ
4696 case IPCOP_msgrcv:
4697 switch (version) {
4698 case 0:
4699 {
4700 struct target_ipc_kludge {
4701 abi_long msgp;
4702 abi_long msgtyp;
4703 } *tmp;
4704
4705 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4706 ret = -TARGET_EFAULT;
4707 break;
4708 }
d96372ef 4709
79dd77de 4710 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 4711
1c54ff97
AJ
4712 unlock_user_struct(tmp, ptr, 0);
4713 break;
4714 }
4715 default:
4716 ret = do_msgrcv(first, ptr, second, fifth, third);
4717 }
4718 break;
d96372ef 4719
8853f86e 4720 case IPCOP_shmat:
88a8c984
RV
4721 switch (version) {
4722 default:
5a4a898d
FB
4723 {
4724 abi_ulong raddr;
ee8e7614 4725 raddr = do_shmat(cpu_env, first, ptr, second);
88a8c984
RV
4726 if (is_error(raddr))
4727 return get_errno(raddr);
2f619698 4728 if (put_user_ual(raddr, third))
5a4a898d 4729 return -TARGET_EFAULT;
88a8c984
RV
4730 break;
4731 }
4732 case 1:
4733 ret = -TARGET_EINVAL;
4734 break;
5a4a898d 4735 }
8853f86e
FB
4736 break;
4737 case IPCOP_shmdt:
88a8c984 4738 ret = do_shmdt(ptr);
8853f86e
FB
4739 break;
4740
4741 case IPCOP_shmget:
4742 /* IPC_* flag values are the same on all linux platforms */
4743 ret = get_errno(shmget(first, second, third));
4744 break;
4745
4746 /* IPC_* and SHM_* command values are the same on all linux platforms */
4747 case IPCOP_shmctl:
a2926784 4748 ret = do_shmctl(first, second, ptr);
8853f86e
FB
4749 break;
4750 default:
39be5350
JK
4751 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4752 call, version);
0da46a6e 4753 ret = -TARGET_ENOSYS;
8853f86e
FB
4754 break;
4755 }
4756 return ret;
4757}
32407103 4758#endif
8853f86e 4759
31e31b8a 4760/* kernel structure types definitions */
31e31b8a 4761
001faf32 4762#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
4763#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4764enum {
4765#include "syscall_types.h"
8be656b8 4766STRUCT_MAX
31e31b8a
FB
4767};
4768#undef STRUCT
4769#undef STRUCT_SPECIAL
4770
001faf32 4771#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
4772#define STRUCT_SPECIAL(name)
4773#include "syscall_types.h"
4774#undef STRUCT
4775#undef STRUCT_SPECIAL
4776
31e31b8a
FB
4777#define MAX_STRUCT_SIZE 4096
4778
dace20dc 4779#ifdef CONFIG_FIEMAP
285da2b9
PM
4780/* So fiemap access checks don't overflow on 32 bit systems.
4781 * This is very slightly smaller than the limit imposed by
4782 * the underlying kernel.
4783 */
4784#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4785 / sizeof(struct fiemap_extent))
4786
4787static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4788 int fd, int cmd, abi_long arg)
285da2b9
PM
4789{
4790 /* The parameter for this ioctl is a struct fiemap followed
4791 * by an array of struct fiemap_extent whose size is set
4792 * in fiemap->fm_extent_count. The array is filled in by the
4793 * ioctl.
4794 */
4795 int target_size_in, target_size_out;
4796 struct fiemap *fm;
4797 const argtype *arg_type = ie->arg_type;
4798 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4799 void *argptr, *p;
4800 abi_long ret;
4801 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4802 uint32_t outbufsz;
4803 int free_fm = 0;
4804
4805 assert(arg_type[0] == TYPE_PTR);
4806 assert(ie->access == IOC_RW);
4807 arg_type++;
4808 target_size_in = thunk_type_size(arg_type, 0);
4809 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4810 if (!argptr) {
4811 return -TARGET_EFAULT;
4812 }
4813 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4814 unlock_user(argptr, arg, 0);
4815 fm = (struct fiemap *)buf_temp;
4816 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4817 return -TARGET_EINVAL;
4818 }
4819
4820 outbufsz = sizeof (*fm) +
4821 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4822
4823 if (outbufsz > MAX_STRUCT_SIZE) {
4824 /* We can't fit all the extents into the fixed size buffer.
4825 * Allocate one that is large enough and use it instead.
4826 */
0e173b24 4827 fm = g_try_malloc(outbufsz);
285da2b9
PM
4828 if (!fm) {
4829 return -TARGET_ENOMEM;
4830 }
4831 memcpy(fm, buf_temp, sizeof(struct fiemap));
4832 free_fm = 1;
4833 }
49ca6f3e 4834 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
285da2b9
PM
4835 if (!is_error(ret)) {
4836 target_size_out = target_size_in;
4837 /* An extent_count of 0 means we were only counting the extents
4838 * so there are no structs to copy
4839 */
4840 if (fm->fm_extent_count != 0) {
4841 target_size_out += fm->fm_mapped_extents * extent_size;
4842 }
4843 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4844 if (!argptr) {
4845 ret = -TARGET_EFAULT;
4846 } else {
4847 /* Convert the struct fiemap */
4848 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4849 if (fm->fm_extent_count != 0) {
4850 p = argptr + target_size_in;
4851 /* ...and then all the struct fiemap_extents */
4852 for (i = 0; i < fm->fm_mapped_extents; i++) {
4853 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4854 THUNK_TARGET);
4855 p += extent_size;
4856 }
4857 }
4858 unlock_user(argptr, arg, target_size_out);
4859 }
4860 }
4861 if (free_fm) {
0e173b24 4862 g_free(fm);
285da2b9
PM
4863 }
4864 return ret;
4865}
dace20dc 4866#endif
285da2b9 4867
059c2f2c 4868static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4869 int fd, int cmd, abi_long arg)
059c2f2c
LV
4870{
4871 const argtype *arg_type = ie->arg_type;
4872 int target_size;
4873 void *argptr;
4874 int ret;
4875 struct ifconf *host_ifconf;
4876 uint32_t outbufsz;
4877 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
4df7b7fa 4878 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
059c2f2c
LV
4879 int target_ifreq_size;
4880 int nb_ifreq;
4881 int free_buf = 0;
4882 int i;
4883 int target_ifc_len;
4884 abi_long target_ifc_buf;
4885 int host_ifc_len;
4886 char *host_ifc_buf;
4887
4888 assert(arg_type[0] == TYPE_PTR);
4889 assert(ie->access == IOC_RW);
4890
4891 arg_type++;
4892 target_size = thunk_type_size(arg_type, 0);
4893
4894 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4895 if (!argptr)
4896 return -TARGET_EFAULT;
4897 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4898 unlock_user(argptr, arg, 0);
4899
4900 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
059c2f2c 4901 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
4df7b7fa 4902 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
059c2f2c 4903
22e4a267
KL
4904 if (target_ifc_buf != 0) {
4905 target_ifc_len = host_ifconf->ifc_len;
4906 nb_ifreq = target_ifc_len / target_ifreq_size;
4907 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4908
4909 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4910 if (outbufsz > MAX_STRUCT_SIZE) {
4911 /*
4912 * We can't fit all the extents into the fixed size buffer.
4913 * Allocate one that is large enough and use it instead.
4914 */
7a5626a1 4915 host_ifconf = g_try_malloc(outbufsz);
22e4a267
KL
4916 if (!host_ifconf) {
4917 return -TARGET_ENOMEM;
4918 }
4919 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4920 free_buf = 1;
059c2f2c 4921 }
22e4a267 4922 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
059c2f2c 4923
22e4a267
KL
4924 host_ifconf->ifc_len = host_ifc_len;
4925 } else {
4926 host_ifc_buf = NULL;
4927 }
059c2f2c
LV
4928 host_ifconf->ifc_buf = host_ifc_buf;
4929
49ca6f3e 4930 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
059c2f2c
LV
4931 if (!is_error(ret)) {
4932 /* convert host ifc_len to target ifc_len */
4933
4934 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4935 target_ifc_len = nb_ifreq * target_ifreq_size;
4936 host_ifconf->ifc_len = target_ifc_len;
4937
4938 /* restore target ifc_buf */
4939
4940 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4941
4942 /* copy struct ifconf to target user */
4943
4944 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4945 if (!argptr)
4946 return -TARGET_EFAULT;
4947 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4948 unlock_user(argptr, arg, target_size);
4949
22e4a267
KL
4950 if (target_ifc_buf != 0) {
4951 /* copy ifreq[] to target user */
4952 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4953 for (i = 0; i < nb_ifreq ; i++) {
4954 thunk_convert(argptr + i * target_ifreq_size,
4955 host_ifc_buf + i * sizeof(struct ifreq),
4956 ifreq_arg_type, THUNK_TARGET);
4957 }
4958 unlock_user(argptr, target_ifc_buf, target_ifc_len);
059c2f2c 4959 }
059c2f2c
LV
4960 }
4961
4962 if (free_buf) {
7a5626a1 4963 g_free(host_ifconf);
059c2f2c
LV
4964 }
4965
4966 return ret;
4967}
4968
a133367e
CT
4969#if defined(CONFIG_USBFS)
4970#if HOST_LONG_BITS > 64
4971#error USBDEVFS thunks do not support >64 bit hosts yet.
4972#endif
4973struct live_urb {
4974 uint64_t target_urb_adr;
4975 uint64_t target_buf_adr;
4976 char *target_buf_ptr;
4977 struct usbdevfs_urb host_urb;
4978};
4979
4980static GHashTable *usbdevfs_urb_hashtable(void)
4981{
4982 static GHashTable *urb_hashtable;
4983
4984 if (!urb_hashtable) {
4985 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4986 }
4987 return urb_hashtable;
4988}
4989
4990static void urb_hashtable_insert(struct live_urb *urb)
4991{
4992 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4993 g_hash_table_insert(urb_hashtable, urb, urb);
4994}
4995
4996static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4997{
4998 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4999 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
5000}
5001
5002static void urb_hashtable_remove(struct live_urb *urb)
5003{
5004 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
5005 g_hash_table_remove(urb_hashtable, urb);
5006}
5007
5008static abi_long
5009do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
5010 int fd, int cmd, abi_long arg)
5011{
5012 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5013 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5014 struct live_urb *lurb;
5015 void *argptr;
5016 uint64_t hurb;
5017 int target_size;
5018 uintptr_t target_urb_adr;
5019 abi_long ret;
5020
5021 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5022
5023 memset(buf_temp, 0, sizeof(uint64_t));
5024 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5025 if (is_error(ret)) {
5026 return ret;
5027 }
5028
5029 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5030 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5031 if (!lurb->target_urb_adr) {
5032 return -TARGET_EFAULT;
5033 }
5034 urb_hashtable_remove(lurb);
5035 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5036 lurb->host_urb.buffer_length);
5037 lurb->target_buf_ptr = NULL;
5038
5039 /* restore the guest buffer pointer */
5040 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5041
5042 /* update the guest urb struct */
5043 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5044 if (!argptr) {
5045 g_free(lurb);
5046 return -TARGET_EFAULT;
5047 }
5048 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5049 unlock_user(argptr, lurb->target_urb_adr, target_size);
5050
5051 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5052 /* write back the urb handle */
5053 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5054 if (!argptr) {
5055 g_free(lurb);
5056 return -TARGET_EFAULT;
5057 }
5058
5059 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5060 target_urb_adr = lurb->target_urb_adr;
5061 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5062 unlock_user(argptr, arg, target_size);
5063
5064 g_free(lurb);
5065 return ret;
5066}
5067
5068static abi_long
5069do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5070 uint8_t *buf_temp __attribute__((unused)),
5071 int fd, int cmd, abi_long arg)
5072{
5073 struct live_urb *lurb;
5074
5075 /* map target address back to host URB with metadata. */
5076 lurb = urb_hashtable_lookup(arg);
5077 if (!lurb) {
5078 return -TARGET_EFAULT;
5079 }
5080 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5081}
5082
5083static abi_long
5084do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5085 int fd, int cmd, abi_long arg)
5086{
5087 const argtype *arg_type = ie->arg_type;
5088 int target_size;
5089 abi_long ret;
5090 void *argptr;
5091 int rw_dir;
5092 struct live_urb *lurb;
5093
5094 /*
5095 * each submitted URB needs to map to a unique ID for the
5096 * kernel, and that unique ID needs to be a pointer to
5097 * host memory. hence, we need to malloc for each URB.
5098 * isochronous transfers have a variable length struct.
5099 */
5100 arg_type++;
5101 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5102
5103 /* construct host copy of urb and metadata */
b21e2380 5104 lurb = g_try_new0(struct live_urb, 1);
a133367e
CT
5105 if (!lurb) {
5106 return -TARGET_ENOMEM;
5107 }
5108
5109 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5110 if (!argptr) {
5111 g_free(lurb);
5112 return -TARGET_EFAULT;
5113 }
5114 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5115 unlock_user(argptr, arg, 0);
5116
5117 lurb->target_urb_adr = arg;
5118 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5119
5120 /* buffer space used depends on endpoint type so lock the entire buffer */
5121 /* control type urbs should check the buffer contents for true direction */
5122 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5123 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5124 lurb->host_urb.buffer_length, 1);
5125 if (lurb->target_buf_ptr == NULL) {
5126 g_free(lurb);
5127 return -TARGET_EFAULT;
5128 }
5129
5130 /* update buffer pointer in host copy */
5131 lurb->host_urb.buffer = lurb->target_buf_ptr;
5132
5133 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5134 if (is_error(ret)) {
5135 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5136 g_free(lurb);
5137 } else {
5138 urb_hashtable_insert(lurb);
5139 }
5140
5141 return ret;
5142}
5143#endif /* CONFIG_USBFS */
5144
56e904ec 5145static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5146 int cmd, abi_long arg)
56e904ec
AG
5147{
5148 void *argptr;
5149 struct dm_ioctl *host_dm;
5150 abi_long guest_data;
5151 uint32_t guest_data_size;
5152 int target_size;
5153 const argtype *arg_type = ie->arg_type;
5154 abi_long ret;
5155 void *big_buf = NULL;
5156 char *host_data;
5157
5158 arg_type++;
5159 target_size = thunk_type_size(arg_type, 0);
5160 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5161 if (!argptr) {
5162 ret = -TARGET_EFAULT;
5163 goto out;
5164 }
5165 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5166 unlock_user(argptr, arg, 0);
5167
5168 /* buf_temp is too small, so fetch things into a bigger buffer */
5169 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5170 memcpy(big_buf, buf_temp, target_size);
5171 buf_temp = big_buf;
5172 host_dm = big_buf;
5173
5174 guest_data = arg + host_dm->data_start;
5175 if ((guest_data - arg) < 0) {
f9757b1d 5176 ret = -TARGET_EINVAL;
56e904ec
AG
5177 goto out;
5178 }
5179 guest_data_size = host_dm->data_size - host_dm->data_start;
5180 host_data = (char*)host_dm + host_dm->data_start;
5181
5182 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3211215e
PM
5183 if (!argptr) {
5184 ret = -TARGET_EFAULT;
5185 goto out;
5186 }
5187
56e904ec
AG
5188 switch (ie->host_cmd) {
5189 case DM_REMOVE_ALL:
5190 case DM_LIST_DEVICES:
5191 case DM_DEV_CREATE:
5192 case DM_DEV_REMOVE:
5193 case DM_DEV_SUSPEND:
5194 case DM_DEV_STATUS:
5195 case DM_DEV_WAIT:
5196 case DM_TABLE_STATUS:
5197 case DM_TABLE_CLEAR:
5198 case DM_TABLE_DEPS:
5199 case DM_LIST_VERSIONS:
5200 /* no input data */
5201 break;
5202 case DM_DEV_RENAME:
5203 case DM_DEV_SET_GEOMETRY:
5204 /* data contains only strings */
5205 memcpy(host_data, argptr, guest_data_size);
5206 break;
5207 case DM_TARGET_MSG:
5208 memcpy(host_data, argptr, guest_data_size);
5209 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5210 break;
5211 case DM_TABLE_LOAD:
5212 {
5213 void *gspec = argptr;
5214 void *cur_data = host_data;
5215 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5216 int spec_size = thunk_type_size(arg_type, 0);
5217 int i;
5218
5219 for (i = 0; i < host_dm->target_count; i++) {
5220 struct dm_target_spec *spec = cur_data;
5221 uint32_t next;
5222 int slen;
5223
5224 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5225 slen = strlen((char*)gspec + spec_size) + 1;
5226 next = spec->next;
5227 spec->next = sizeof(*spec) + slen;
5228 strcpy((char*)&spec[1], gspec + spec_size);
5229 gspec += next;
5230 cur_data += spec->next;
5231 }
5232 break;
5233 }
5234 default:
5235 ret = -TARGET_EINVAL;
dec0473d 5236 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5237 goto out;
5238 }
5239 unlock_user(argptr, guest_data, 0);
5240
49ca6f3e 5241 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
56e904ec
AG
5242 if (!is_error(ret)) {
5243 guest_data = arg + host_dm->data_start;
5244 guest_data_size = host_dm->data_size - host_dm->data_start;
5245 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5246 switch (ie->host_cmd) {
5247 case DM_REMOVE_ALL:
5248 case DM_DEV_CREATE:
5249 case DM_DEV_REMOVE:
5250 case DM_DEV_RENAME:
5251 case DM_DEV_SUSPEND:
5252 case DM_DEV_STATUS:
5253 case DM_TABLE_LOAD:
5254 case DM_TABLE_CLEAR:
5255 case DM_TARGET_MSG:
5256 case DM_DEV_SET_GEOMETRY:
5257 /* no return data */
5258 break;
5259 case DM_LIST_DEVICES:
5260 {
5261 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5262 uint32_t remaining_data = guest_data_size;
5263 void *cur_data = argptr;
5264 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5265 int nl_size = 12; /* can't use thunk_size due to alignment */
5266
5267 while (1) {
5268 uint32_t next = nl->next;
5269 if (next) {
5270 nl->next = nl_size + (strlen(nl->name) + 1);
5271 }
5272 if (remaining_data < nl->next) {
5273 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5274 break;
5275 }
5276 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5277 strcpy(cur_data + nl_size, nl->name);
5278 cur_data += nl->next;
5279 remaining_data -= nl->next;
5280 if (!next) {
5281 break;
5282 }
5283 nl = (void*)nl + next;
5284 }
5285 break;
5286 }
5287 case DM_DEV_WAIT:
5288 case DM_TABLE_STATUS:
5289 {
5290 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5291 void *cur_data = argptr;
5292 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5293 int spec_size = thunk_type_size(arg_type, 0);
5294 int i;
5295
5296 for (i = 0; i < host_dm->target_count; i++) {
5297 uint32_t next = spec->next;
5298 int slen = strlen((char*)&spec[1]) + 1;
5299 spec->next = (cur_data - argptr) + spec_size + slen;
5300 if (guest_data_size < spec->next) {
5301 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5302 break;
5303 }
5304 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5305 strcpy(cur_data + spec_size, (char*)&spec[1]);
5306 cur_data = argptr + spec->next;
5307 spec = (void*)host_dm + host_dm->data_start + next;
5308 }
5309 break;
5310 }
5311 case DM_TABLE_DEPS:
5312 {
5313 void *hdata = (void*)host_dm + host_dm->data_start;
5314 int count = *(uint32_t*)hdata;
5315 uint64_t *hdev = hdata + 8;
5316 uint64_t *gdev = argptr + 8;
5317 int i;
5318
5319 *(uint32_t*)argptr = tswap32(count);
5320 for (i = 0; i < count; i++) {
5321 *gdev = tswap64(*hdev);
5322 gdev++;
5323 hdev++;
5324 }
5325 break;
5326 }
5327 case DM_LIST_VERSIONS:
5328 {
5329 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5330 uint32_t remaining_data = guest_data_size;
5331 void *cur_data = argptr;
5332 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5333 int vers_size = thunk_type_size(arg_type, 0);
5334
5335 while (1) {
5336 uint32_t next = vers->next;
5337 if (next) {
5338 vers->next = vers_size + (strlen(vers->name) + 1);
5339 }
5340 if (remaining_data < vers->next) {
5341 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5342 break;
5343 }
5344 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5345 strcpy(cur_data + vers_size, vers->name);
5346 cur_data += vers->next;
5347 remaining_data -= vers->next;
5348 if (!next) {
5349 break;
5350 }
5351 vers = (void*)vers + next;
5352 }
5353 break;
5354 }
5355 default:
dec0473d 5356 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5357 ret = -TARGET_EINVAL;
5358 goto out;
5359 }
5360 unlock_user(argptr, guest_data, guest_data_size);
5361
5362 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5363 if (!argptr) {
5364 ret = -TARGET_EFAULT;
5365 goto out;
5366 }
5367 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5368 unlock_user(argptr, arg, target_size);
5369 }
5370out:
ad11ad77 5371 g_free(big_buf);
56e904ec
AG
5372 return ret;
5373}
5374
a59b5e35 5375static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5376 int cmd, abi_long arg)
a59b5e35
AG
5377{
5378 void *argptr;
5379 int target_size;
5380 const argtype *arg_type = ie->arg_type;
5381 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5382 abi_long ret;
5383
5384 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5385 struct blkpg_partition host_part;
5386
5387 /* Read and convert blkpg */
5388 arg_type++;
5389 target_size = thunk_type_size(arg_type, 0);
5390 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5391 if (!argptr) {
5392 ret = -TARGET_EFAULT;
5393 goto out;
5394 }
5395 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5396 unlock_user(argptr, arg, 0);
5397
5398 switch (host_blkpg->op) {
5399 case BLKPG_ADD_PARTITION:
5400 case BLKPG_DEL_PARTITION:
5401 /* payload is struct blkpg_partition */
5402 break;
5403 default:
5404 /* Unknown opcode */
5405 ret = -TARGET_EINVAL;
5406 goto out;
5407 }
5408
5409 /* Read and convert blkpg->data */
5410 arg = (abi_long)(uintptr_t)host_blkpg->data;
5411 target_size = thunk_type_size(part_arg_type, 0);
5412 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5413 if (!argptr) {
5414 ret = -TARGET_EFAULT;
5415 goto out;
5416 }
5417 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5418 unlock_user(argptr, arg, 0);
5419
5420 /* Swizzle the data pointer to our local copy and call! */
5421 host_blkpg->data = &host_part;
49ca6f3e 5422 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
a59b5e35
AG
5423
5424out:
5425 return ret;
5426}
5427
7ff7b666 5428static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5429 int fd, int cmd, abi_long arg)
7ff7b666
LV
5430{
5431 const argtype *arg_type = ie->arg_type;
5432 const StructEntry *se;
5433 const argtype *field_types;
5434 const int *dst_offsets, *src_offsets;
5435 int target_size;
5436 void *argptr;
b78c522a
MAL
5437 abi_ulong *target_rt_dev_ptr = NULL;
5438 unsigned long *host_rt_dev_ptr = NULL;
7ff7b666
LV
5439 abi_long ret;
5440 int i;
5441
5442 assert(ie->access == IOC_W);
5443 assert(*arg_type == TYPE_PTR);
5444 arg_type++;
5445 assert(*arg_type == TYPE_STRUCT);
5446 target_size = thunk_type_size(arg_type, 0);
5447 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5448 if (!argptr) {
5449 return -TARGET_EFAULT;
5450 }
5451 arg_type++;
5452 assert(*arg_type == (int)STRUCT_rtentry);
5453 se = struct_entries + *arg_type++;
5454 assert(se->convert[0] == NULL);
5455 /* convert struct here to be able to catch rt_dev string */
5456 field_types = se->field_types;
5457 dst_offsets = se->field_offsets[THUNK_HOST];
5458 src_offsets = se->field_offsets[THUNK_TARGET];
5459 for (i = 0; i < se->nb_fields; i++) {
5460 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5461 assert(*field_types == TYPE_PTRVOID);
3d558330 5462 target_rt_dev_ptr = argptr + src_offsets[i];
7ff7b666
LV
5463 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5464 if (*target_rt_dev_ptr != 0) {
5465 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5466 tswapal(*target_rt_dev_ptr));
5467 if (!*host_rt_dev_ptr) {
5468 unlock_user(argptr, arg, 0);
5469 return -TARGET_EFAULT;
5470 }
5471 } else {
5472 *host_rt_dev_ptr = 0;
5473 }
5474 field_types++;
5475 continue;
5476 }
5477 field_types = thunk_convert(buf_temp + dst_offsets[i],
5478 argptr + src_offsets[i],
5479 field_types, THUNK_HOST);
5480 }
5481 unlock_user(argptr, arg, 0);
5482
49ca6f3e 5483 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
b78c522a
MAL
5484
5485 assert(host_rt_dev_ptr != NULL);
5486 assert(target_rt_dev_ptr != NULL);
7ff7b666
LV
5487 if (*host_rt_dev_ptr != 0) {
5488 unlock_user((void *)*host_rt_dev_ptr,
5489 *target_rt_dev_ptr, 0);
5490 }
5491 return ret;
5492}
5493
ca56f5b5 5494static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5495 int fd, int cmd, abi_long arg)
ca56f5b5
PB
5496{
5497 int sig = target_to_host_signal(arg);
49ca6f3e 5498 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
ca56f5b5
PB
5499}
5500
6d5d5dde
DB
5501static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5502 int fd, int cmd, abi_long arg)
5503{
5504 struct timeval tv;
5505 abi_long ret;
5506
5507 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5508 if (is_error(ret)) {
5509 return ret;
5510 }
5511
5512 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5513 if (copy_to_user_timeval(arg, &tv)) {
5514 return -TARGET_EFAULT;
5515 }
5516 } else {
5517 if (copy_to_user_timeval64(arg, &tv)) {
5518 return -TARGET_EFAULT;
5519 }
5520 }
5521
5522 return ret;
5523}
5524
5525static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5526 int fd, int cmd, abi_long arg)
5527{
5528 struct timespec ts;
5529 abi_long ret;
5530
5531 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5532 if (is_error(ret)) {
5533 return ret;
5534 }
5535
5536 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5537 if (host_to_target_timespec(arg, &ts)) {
5538 return -TARGET_EFAULT;
5539 }
5540 } else{
5541 if (host_to_target_timespec64(arg, &ts)) {
5542 return -TARGET_EFAULT;
5543 }
5544 }
5545
5546 return ret;
5547}
5548
2b74f621
AS
5549#ifdef TIOCGPTPEER
5550static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5551 int fd, int cmd, abi_long arg)
5552{
5553 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5554 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5555}
5556#endif
5557
e865b97f
CG
5558#ifdef HAVE_DRM_H
5559
5560static void unlock_drm_version(struct drm_version *host_ver,
5561 struct target_drm_version *target_ver,
5562 bool copy)
5563{
5564 unlock_user(host_ver->name, target_ver->name,
5565 copy ? host_ver->name_len : 0);
5566 unlock_user(host_ver->date, target_ver->date,
5567 copy ? host_ver->date_len : 0);
5568 unlock_user(host_ver->desc, target_ver->desc,
5569 copy ? host_ver->desc_len : 0);
5570}
5571
5572static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5573 struct target_drm_version *target_ver)
5574{
5575 memset(host_ver, 0, sizeof(*host_ver));
5576
5577 __get_user(host_ver->name_len, &target_ver->name_len);
5578 if (host_ver->name_len) {
5579 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5580 target_ver->name_len, 0);
5581 if (!host_ver->name) {
5582 return -EFAULT;
5583 }
5584 }
5585
5586 __get_user(host_ver->date_len, &target_ver->date_len);
5587 if (host_ver->date_len) {
5588 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5589 target_ver->date_len, 0);
5590 if (!host_ver->date) {
5591 goto err;
5592 }
5593 }
5594
5595 __get_user(host_ver->desc_len, &target_ver->desc_len);
5596 if (host_ver->desc_len) {
5597 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5598 target_ver->desc_len, 0);
5599 if (!host_ver->desc) {
5600 goto err;
5601 }
5602 }
5603
5604 return 0;
5605err:
5606 unlock_drm_version(host_ver, target_ver, false);
5607 return -EFAULT;
5608}
5609
5610static inline void host_to_target_drmversion(
5611 struct target_drm_version *target_ver,
5612 struct drm_version *host_ver)
5613{
5614 __put_user(host_ver->version_major, &target_ver->version_major);
5615 __put_user(host_ver->version_minor, &target_ver->version_minor);
5616 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5617 __put_user(host_ver->name_len, &target_ver->name_len);
5618 __put_user(host_ver->date_len, &target_ver->date_len);
5619 __put_user(host_ver->desc_len, &target_ver->desc_len);
5620 unlock_drm_version(host_ver, target_ver, true);
5621}
5622
5623static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5624 int fd, int cmd, abi_long arg)
5625{
5626 struct drm_version *ver;
5627 struct target_drm_version *target_ver;
5628 abi_long ret;
5629
5630 switch (ie->host_cmd) {
5631 case DRM_IOCTL_VERSION:
5632 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5633 return -TARGET_EFAULT;
5634 }
5635 ver = (struct drm_version *)buf_temp;
5636 ret = target_to_host_drmversion(ver, target_ver);
5637 if (!is_error(ret)) {
5638 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5639 if (is_error(ret)) {
5640 unlock_drm_version(ver, target_ver, false);
5641 } else {
5642 host_to_target_drmversion(target_ver, ver);
5643 }
5644 }
5645 unlock_user_struct(target_ver, arg, 0);
5646 return ret;
5647 }
5648 return -TARGET_ENOSYS;
5649}
5650
913b03c2
CG
5651static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5652 struct drm_i915_getparam *gparam,
5653 int fd, abi_long arg)
5654{
5655 abi_long ret;
5656 int value;
5657 struct target_drm_i915_getparam *target_gparam;
5658
5659 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5660 return -TARGET_EFAULT;
5661 }
5662
5663 __get_user(gparam->param, &target_gparam->param);
5664 gparam->value = &value;
5665 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5666 put_user_s32(value, target_gparam->value);
5667
5668 unlock_user_struct(target_gparam, arg, 0);
5669 return ret;
5670}
5671
5672static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5673 int fd, int cmd, abi_long arg)
5674{
5675 switch (ie->host_cmd) {
5676 case DRM_IOCTL_I915_GETPARAM:
5677 return do_ioctl_drm_i915_getparam(ie,
5678 (struct drm_i915_getparam *)buf_temp,
5679 fd, arg);
5680 default:
5681 return -TARGET_ENOSYS;
5682 }
5683}
5684
e865b97f
CG
5685#endif
5686
6addf06a
SCW
5687static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5688 int fd, int cmd, abi_long arg)
5689{
5690 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5691 struct tun_filter *target_filter;
5692 char *target_addr;
5693
5694 assert(ie->access == IOC_W);
5695
5696 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5697 if (!target_filter) {
5698 return -TARGET_EFAULT;
5699 }
5700 filter->flags = tswap16(target_filter->flags);
5701 filter->count = tswap16(target_filter->count);
5702 unlock_user(target_filter, arg, 0);
5703
5704 if (filter->count) {
5705 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5706 MAX_STRUCT_SIZE) {
5707 return -TARGET_EFAULT;
5708 }
5709
5710 target_addr = lock_user(VERIFY_READ,
5711 arg + offsetof(struct tun_filter, addr),
5712 filter->count * ETH_ALEN, 1);
5713 if (!target_addr) {
5714 return -TARGET_EFAULT;
5715 }
5716 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5717 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5718 }
5719
5720 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5721}
5722
79482e59 5723IOCTLEntry ioctl_entries[] = {
001faf32 5724#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
5725 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5726#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5727 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
8cb762fe
HD
5728#define IOCTL_IGNORE(cmd) \
5729 { TARGET_ ## cmd, 0, #cmd },
31e31b8a
FB
5730#include "ioctls.h"
5731 { 0, 0, },
5732};
5733
53a5960a 5734/* ??? Implement proper locking for ioctls. */
0da46a6e 5735/* do_ioctl() Must return target values and target errnos. */
45c874eb 5736static abi_long do_ioctl(int fd, int cmd, abi_long arg)
31e31b8a
FB
5737{
5738 const IOCTLEntry *ie;
5739 const argtype *arg_type;
992f48a0 5740 abi_long ret;
31e31b8a 5741 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
5742 int target_size;
5743 void *argptr;
31e31b8a
FB
5744
5745 ie = ioctl_entries;
5746 for(;;) {
5747 if (ie->target_cmd == 0) {
39be5350
JK
5748 qemu_log_mask(
5749 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 5750 return -TARGET_ENOSYS;
31e31b8a
FB
5751 }
5752 if (ie->target_cmd == cmd)
5753 break;
5754 ie++;
5755 }
5756 arg_type = ie->arg_type;
d2ef05bb
PM
5757 if (ie->do_ioctl) {
5758 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
8cb762fe
HD
5759 } else if (!ie->host_cmd) {
5760 /* Some architectures define BSD ioctls in their headers
5761 that are not implemented in Linux. */
5762 return -TARGET_ENOSYS;
d2ef05bb
PM
5763 }
5764
31e31b8a
FB
5765 switch(arg_type[0]) {
5766 case TYPE_NULL:
5767 /* no argument */
49ca6f3e 5768 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
31e31b8a
FB
5769 break;
5770 case TYPE_PTRVOID:
5771 case TYPE_INT:
c858e537
FB
5772 case TYPE_LONG:
5773 case TYPE_ULONG:
49ca6f3e 5774 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
31e31b8a
FB
5775 break;
5776 case TYPE_PTR:
5777 arg_type++;
53a5960a 5778 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
5779 switch(ie->access) {
5780 case IOC_R:
49ca6f3e 5781 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5782 if (!is_error(ret)) {
579a97f7
FB
5783 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5784 if (!argptr)
5785 return -TARGET_EFAULT;
53a5960a
PB
5786 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5787 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5788 }
5789 break;
5790 case IOC_W:
579a97f7
FB
5791 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5792 if (!argptr)
5793 return -TARGET_EFAULT;
53a5960a
PB
5794 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5795 unlock_user(argptr, arg, 0);
49ca6f3e 5796 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a
FB
5797 break;
5798 default:
5799 case IOC_RW:
579a97f7
FB
5800 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5801 if (!argptr)
5802 return -TARGET_EFAULT;
53a5960a
PB
5803 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5804 unlock_user(argptr, arg, 0);
49ca6f3e 5805 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5806 if (!is_error(ret)) {
579a97f7
FB
5807 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5808 if (!argptr)
5809 return -TARGET_EFAULT;
53a5960a
PB
5810 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5811 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5812 }
5813 break;
5814 }
5815 break;
5816 default:
39be5350
JK
5817 qemu_log_mask(LOG_UNIMP,
5818 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5819 (long)cmd, arg_type[0]);
0da46a6e 5820 ret = -TARGET_ENOSYS;
31e31b8a
FB
5821 break;
5822 }
5823 return ret;
5824}
5825
b39bc503 5826static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
5827 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5828 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5829 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5830 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5831 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5832 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5833 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5834 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5835 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5836 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5837 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5838 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5839 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5840 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
c218b4ed 5841 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
31e31b8a
FB
5842 { 0, 0, 0, 0 }
5843};
5844
b39bc503 5845static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
5846 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5847 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5848 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5849 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5850 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5851 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5852 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5853 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5854 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5855 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5856 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5857 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5858 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5859 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5860 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5861 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5862 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5863 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5864 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5865 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5866 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5867 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5868 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5869 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5870 { 0, 0, 0, 0 }
5871};
5872
b39bc503 5873static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
5874 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5875 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5876 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5877 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5878 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5879 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5880 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5881 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5882 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5883 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5884 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5885 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5886 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5887 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5888 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5889 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5890 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5891 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5892 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5893 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5894 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5895 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5896 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5897 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5898 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5899 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5900 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5901 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5902 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5903 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5904 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5905 { 0, 0, 0, 0 }
5906};
5907
b39bc503 5908static const bitmask_transtbl lflag_tbl[] = {
c218b4ed
FB
5909 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5910 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5911 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5912 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5913 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5914 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5915 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5916 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5917 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5918 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5919 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5920 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5921 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5922 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5923 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5924 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5925 { 0, 0, 0, 0 }
31e31b8a
FB
5926};
5927
5928static void target_to_host_termios (void *dst, const void *src)
5929{
5930 struct host_termios *host = dst;
5931 const struct target_termios *target = src;
3b46e624 5932
5fafdf24 5933 host->c_iflag =
31e31b8a 5934 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 5935 host->c_oflag =
31e31b8a 5936 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 5937 host->c_cflag =
31e31b8a 5938 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 5939 host->c_lflag =
31e31b8a
FB
5940 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5941 host->c_line = target->c_line;
3b46e624 5942
44607123 5943 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
5944 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5945 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 5946 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 5947 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 5948 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 5949 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 5950 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 5951 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 5952 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
5953 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5954 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
5955 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5956 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5957 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5958 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5959 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 5960 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 5961}
3b46e624 5962
31e31b8a
FB
5963static void host_to_target_termios (void *dst, const void *src)
5964{
5965 struct target_termios *target = dst;
5966 const struct host_termios *host = src;
5967
5fafdf24 5968 target->c_iflag =
31e31b8a 5969 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 5970 target->c_oflag =
31e31b8a 5971 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 5972 target->c_cflag =
31e31b8a 5973 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 5974 target->c_lflag =
31e31b8a
FB
5975 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5976 target->c_line = host->c_line;
3b46e624 5977
44607123 5978 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
5979 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5980 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5981 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5982 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5983 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5984 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5985 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5986 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5987 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5988 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5989 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5990 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5991 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5992 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5993 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5994 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5995 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5996}
5997
8e853dc7 5998static const StructEntry struct_termios_def = {
31e31b8a
FB
5999 .convert = { host_to_target_termios, target_to_host_termios },
6000 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
6001 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
888468db 6002 .print = print_termios,
31e31b8a
FB
6003};
6004
180d4ef3 6005static const bitmask_transtbl mmap_flags_tbl[] = {
541e1690
HD
6006 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
6007 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
6008 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
6009 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
6010 MAP_ANONYMOUS, MAP_ANONYMOUS },
6011 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6012 MAP_GROWSDOWN, MAP_GROWSDOWN },
6013 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6014 MAP_DENYWRITE, MAP_DENYWRITE },
6015 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6016 MAP_EXECUTABLE, MAP_EXECUTABLE },
6017 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6018 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6019 MAP_NORESERVE, MAP_NORESERVE },
6020 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6021 /* MAP_STACK had been ignored by the kernel for quite some time.
6022 Recognize it for the target insofar as we do not want to pass
6023 it through to the host. */
6024 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6025 { 0, 0, 0, 0 }
5286db75
FB
6026};
6027
9d12f79d
LV
6028/*
6029 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6030 * TARGET_I386 is defined if TARGET_X86_64 is defined
6031 */
2ab83ea7 6032#if defined(TARGET_I386)
6dbad63e
FB
6033
6034/* NOTE: there is really one LDT for all the threads */
b1d8e52e 6035static uint8_t *ldt_table;
6dbad63e 6036
03acab66 6037static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
6038{
6039 int size;
53a5960a 6040 void *p;
6dbad63e
FB
6041
6042 if (!ldt_table)
6043 return 0;
6044 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6045 if (size > bytecount)
6046 size = bytecount;
579a97f7
FB
6047 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6048 if (!p)
03acab66 6049 return -TARGET_EFAULT;
579a97f7 6050 /* ??? Should this by byteswapped? */
53a5960a
PB
6051 memcpy(p, ldt_table, size);
6052 unlock_user(p, ptr, size);
6dbad63e
FB
6053 return size;
6054}
6055
6056/* XXX: add locking support */
03acab66
FB
6057static abi_long write_ldt(CPUX86State *env,
6058 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
6059{
6060 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 6061 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 6062 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 6063 int seg_not_present, useable, lm;
6dbad63e
FB
6064 uint32_t *lp, entry_1, entry_2;
6065
6066 if (bytecount != sizeof(ldt_info))
03acab66 6067 return -TARGET_EINVAL;
579a97f7 6068 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 6069 return -TARGET_EFAULT;
53a5960a 6070 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6071 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
6072 ldt_info.limit = tswap32(target_ldt_info->limit);
6073 ldt_info.flags = tswap32(target_ldt_info->flags);
6074 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 6075
6dbad63e 6076 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 6077 return -TARGET_EINVAL;
6dbad63e
FB
6078 seg_32bit = ldt_info.flags & 1;
6079 contents = (ldt_info.flags >> 1) & 3;
6080 read_exec_only = (ldt_info.flags >> 3) & 1;
6081 limit_in_pages = (ldt_info.flags >> 4) & 1;
6082 seg_not_present = (ldt_info.flags >> 5) & 1;
6083 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
6084#ifdef TARGET_ABI32
6085 lm = 0;
6086#else
6087 lm = (ldt_info.flags >> 7) & 1;
6088#endif
6dbad63e
FB
6089 if (contents == 3) {
6090 if (oldmode)
03acab66 6091 return -TARGET_EINVAL;
6dbad63e 6092 if (seg_not_present == 0)
03acab66 6093 return -TARGET_EINVAL;
6dbad63e
FB
6094 }
6095 /* allocate the LDT */
6096 if (!ldt_table) {
e441570f
AZ
6097 env->ldt.base = target_mmap(0,
6098 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6099 PROT_READ|PROT_WRITE,
6100 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6101 if (env->ldt.base == -1)
03acab66 6102 return -TARGET_ENOMEM;
3e8f1628 6103 memset(g2h_untagged(env->ldt.base), 0,
e441570f 6104 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 6105 env->ldt.limit = 0xffff;
3e8f1628 6106 ldt_table = g2h_untagged(env->ldt.base);
6dbad63e
FB
6107 }
6108
6109 /* NOTE: same code as Linux kernel */
6110 /* Allow LDTs to be cleared by the user. */
6111 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6112 if (oldmode ||
6113 (contents == 0 &&
6114 read_exec_only == 1 &&
6115 seg_32bit == 0 &&
6116 limit_in_pages == 0 &&
6117 seg_not_present == 1 &&
6118 useable == 0 )) {
6119 entry_1 = 0;
6120 entry_2 = 0;
6121 goto install;
6122 }
6123 }
3b46e624 6124
6dbad63e
FB
6125 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6126 (ldt_info.limit & 0x0ffff);
6127 entry_2 = (ldt_info.base_addr & 0xff000000) |
6128 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6129 (ldt_info.limit & 0xf0000) |
6130 ((read_exec_only ^ 1) << 9) |
6131 (contents << 10) |
6132 ((seg_not_present ^ 1) << 15) |
6133 (seg_32bit << 22) |
6134 (limit_in_pages << 23) |
8d18e893 6135 (lm << 21) |
6dbad63e
FB
6136 0x7000;
6137 if (!oldmode)
6138 entry_2 |= (useable << 20);
14ae3ba7 6139
6dbad63e
FB
6140 /* Install the new entry ... */
6141install:
6142 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6143 lp[0] = tswap32(entry_1);
6144 lp[1] = tswap32(entry_2);
6145 return 0;
6146}
6147
6148/* specific and weird i386 syscalls */
8fcd3692
BS
6149static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6150 unsigned long bytecount)
6dbad63e 6151{
03acab66 6152 abi_long ret;
3b46e624 6153
6dbad63e
FB
6154 switch (func) {
6155 case 0:
6156 ret = read_ldt(ptr, bytecount);
6157 break;
6158 case 1:
6159 ret = write_ldt(env, ptr, bytecount, 1);
6160 break;
6161 case 0x11:
6162 ret = write_ldt(env, ptr, bytecount, 0);
6163 break;
03acab66
FB
6164 default:
6165 ret = -TARGET_ENOSYS;
6166 break;
6dbad63e
FB
6167 }
6168 return ret;
6169}
1b6b029e 6170
9d12f79d 6171#if defined(TARGET_ABI32)
bc22eb44 6172abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893 6173{
3e8f1628 6174 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6175 struct target_modify_ldt_ldt_s ldt_info;
6176 struct target_modify_ldt_ldt_s *target_ldt_info;
6177 int seg_32bit, contents, read_exec_only, limit_in_pages;
6178 int seg_not_present, useable, lm;
6179 uint32_t *lp, entry_1, entry_2;
6180 int i;
6181
6182 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6183 if (!target_ldt_info)
6184 return -TARGET_EFAULT;
6185 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6186 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
6187 ldt_info.limit = tswap32(target_ldt_info->limit);
6188 ldt_info.flags = tswap32(target_ldt_info->flags);
6189 if (ldt_info.entry_number == -1) {
6190 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6191 if (gdt_table[i] == 0) {
6192 ldt_info.entry_number = i;
6193 target_ldt_info->entry_number = tswap32(i);
6194 break;
6195 }
6196 }
6197 }
6198 unlock_user_struct(target_ldt_info, ptr, 1);
6199
6200 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6201 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6202 return -TARGET_EINVAL;
6203 seg_32bit = ldt_info.flags & 1;
6204 contents = (ldt_info.flags >> 1) & 3;
6205 read_exec_only = (ldt_info.flags >> 3) & 1;
6206 limit_in_pages = (ldt_info.flags >> 4) & 1;
6207 seg_not_present = (ldt_info.flags >> 5) & 1;
6208 useable = (ldt_info.flags >> 6) & 1;
6209#ifdef TARGET_ABI32
6210 lm = 0;
6211#else
6212 lm = (ldt_info.flags >> 7) & 1;
6213#endif
6214
6215 if (contents == 3) {
6216 if (seg_not_present == 0)
6217 return -TARGET_EINVAL;
6218 }
6219
6220 /* NOTE: same code as Linux kernel */
6221 /* Allow LDTs to be cleared by the user. */
6222 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6223 if ((contents == 0 &&
6224 read_exec_only == 1 &&
6225 seg_32bit == 0 &&
6226 limit_in_pages == 0 &&
6227 seg_not_present == 1 &&
6228 useable == 0 )) {
6229 entry_1 = 0;
6230 entry_2 = 0;
6231 goto install;
6232 }
6233 }
6234
6235 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6236 (ldt_info.limit & 0x0ffff);
6237 entry_2 = (ldt_info.base_addr & 0xff000000) |
6238 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6239 (ldt_info.limit & 0xf0000) |
6240 ((read_exec_only ^ 1) << 9) |
6241 (contents << 10) |
6242 ((seg_not_present ^ 1) << 15) |
6243 (seg_32bit << 22) |
6244 (limit_in_pages << 23) |
6245 (useable << 20) |
6246 (lm << 21) |
6247 0x7000;
6248
6249 /* Install the new entry ... */
6250install:
6251 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6252 lp[0] = tswap32(entry_1);
6253 lp[1] = tswap32(entry_2);
6254 return 0;
6255}
6256
8fcd3692 6257static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
6258{
6259 struct target_modify_ldt_ldt_s *target_ldt_info;
3e8f1628 6260 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6261 uint32_t base_addr, limit, flags;
6262 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6263 int seg_not_present, useable, lm;
6264 uint32_t *lp, entry_1, entry_2;
6265
6266 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6267 if (!target_ldt_info)
6268 return -TARGET_EFAULT;
6269 idx = tswap32(target_ldt_info->entry_number);
6270 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6271 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6272 unlock_user_struct(target_ldt_info, ptr, 1);
6273 return -TARGET_EINVAL;
6274 }
6275 lp = (uint32_t *)(gdt_table + idx);
6276 entry_1 = tswap32(lp[0]);
6277 entry_2 = tswap32(lp[1]);
6278
6279 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6280 contents = (entry_2 >> 10) & 3;
6281 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6282 seg_32bit = (entry_2 >> 22) & 1;
6283 limit_in_pages = (entry_2 >> 23) & 1;
6284 useable = (entry_2 >> 20) & 1;
6285#ifdef TARGET_ABI32
6286 lm = 0;
6287#else
6288 lm = (entry_2 >> 21) & 1;
6289#endif
6290 flags = (seg_32bit << 0) | (contents << 1) |
6291 (read_exec_only << 3) | (limit_in_pages << 4) |
6292 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6293 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6294 base_addr = (entry_1 >> 16) |
6295 (entry_2 & 0xff000000) |
6296 ((entry_2 & 0xff) << 16);
cbb21eed 6297 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
6298 target_ldt_info->limit = tswap32(limit);
6299 target_ldt_info->flags = tswap32(flags);
6300 unlock_user_struct(target_ldt_info, ptr, 1);
6301 return 0;
6302}
6303
9d12f79d
LV
6304abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6305{
538fabcb 6306 return -TARGET_ENOSYS;
9d12f79d
LV
6307}
6308#else
2667e71c 6309abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 6310{
1add8698 6311 abi_long ret = 0;
d2fd1af7
FB
6312 abi_ulong val;
6313 int idx;
1add8698 6314
d2fd1af7
FB
6315 switch(code) {
6316 case TARGET_ARCH_SET_GS:
6317 case TARGET_ARCH_SET_FS:
6318 if (code == TARGET_ARCH_SET_GS)
6319 idx = R_GS;
6320 else
6321 idx = R_FS;
6322 cpu_x86_load_seg(env, idx, 0);
6323 env->segs[idx].base = addr;
6324 break;
6325 case TARGET_ARCH_GET_GS:
6326 case TARGET_ARCH_GET_FS:
6327 if (code == TARGET_ARCH_GET_GS)
6328 idx = R_GS;
6329 else
6330 idx = R_FS;
6331 val = env->segs[idx].base;
6332 if (put_user(val, addr, abi_ulong))
1add8698 6333 ret = -TARGET_EFAULT;
d2fd1af7
FB
6334 break;
6335 default:
6336 ret = -TARGET_EINVAL;
6337 break;
6338 }
1add8698 6339 return ret;
d2fd1af7 6340}
9d12f79d 6341#endif /* defined(TARGET_ABI32 */
2ab83ea7
FB
6342#endif /* defined(TARGET_I386) */
6343
87e9bf23
RH
6344/*
6345 * These constants are generic. Supply any that are missing from the host.
6346 */
6347#ifndef PR_SET_NAME
6348# define PR_SET_NAME 15
6349# define PR_GET_NAME 16
6350#endif
6351#ifndef PR_SET_FP_MODE
6352# define PR_SET_FP_MODE 45
6353# define PR_GET_FP_MODE 46
6354# define PR_FP_MODE_FR (1 << 0)
6355# define PR_FP_MODE_FRE (1 << 1)
6356#endif
6357#ifndef PR_SVE_SET_VL
6358# define PR_SVE_SET_VL 50
6359# define PR_SVE_GET_VL 51
6360# define PR_SVE_VL_LEN_MASK 0xffff
6361# define PR_SVE_VL_INHERIT (1 << 17)
6362#endif
6363#ifndef PR_PAC_RESET_KEYS
6364# define PR_PAC_RESET_KEYS 54
6365# define PR_PAC_APIAKEY (1 << 0)
6366# define PR_PAC_APIBKEY (1 << 1)
6367# define PR_PAC_APDAKEY (1 << 2)
6368# define PR_PAC_APDBKEY (1 << 3)
6369# define PR_PAC_APGAKEY (1 << 4)
6370#endif
6371#ifndef PR_SET_TAGGED_ADDR_CTRL
6372# define PR_SET_TAGGED_ADDR_CTRL 55
6373# define PR_GET_TAGGED_ADDR_CTRL 56
6374# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6375#endif
6376#ifndef PR_MTE_TCF_SHIFT
6377# define PR_MTE_TCF_SHIFT 1
6378# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6379# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6380# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6381# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6382# define PR_MTE_TAG_SHIFT 3
6383# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6384#endif
220717a6
RH
6385#ifndef PR_SET_IO_FLUSHER
6386# define PR_SET_IO_FLUSHER 57
6387# define PR_GET_IO_FLUSHER 58
6388#endif
6389#ifndef PR_SET_SYSCALL_USER_DISPATCH
6390# define PR_SET_SYSCALL_USER_DISPATCH 59
6391#endif
24d87c18
RH
6392#ifndef PR_SME_SET_VL
6393# define PR_SME_SET_VL 63
6394# define PR_SME_GET_VL 64
6395# define PR_SME_VL_LEN_MASK 0xffff
6396# define PR_SME_VL_INHERIT (1 << 17)
6397#endif
87e9bf23
RH
6398
6399#include "target_prctl.h"
6400
6401static abi_long do_prctl_inval0(CPUArchState *env)
6402{
6403 return -TARGET_EINVAL;
6404}
6405
6406static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6407{
6408 return -TARGET_EINVAL;
6409}
6410
6411#ifndef do_prctl_get_fp_mode
6412#define do_prctl_get_fp_mode do_prctl_inval0
6413#endif
6414#ifndef do_prctl_set_fp_mode
6415#define do_prctl_set_fp_mode do_prctl_inval1
6416#endif
fd72f5d0
RH
6417#ifndef do_prctl_sve_get_vl
6418#define do_prctl_sve_get_vl do_prctl_inval0
87e9bf23 6419#endif
fd72f5d0
RH
6420#ifndef do_prctl_sve_set_vl
6421#define do_prctl_sve_set_vl do_prctl_inval1
87e9bf23
RH
6422#endif
6423#ifndef do_prctl_reset_keys
6424#define do_prctl_reset_keys do_prctl_inval1
6425#endif
6426#ifndef do_prctl_set_tagged_addr_ctrl
6427#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6428#endif
6429#ifndef do_prctl_get_tagged_addr_ctrl
6430#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6431#endif
6e8dcacd
RH
6432#ifndef do_prctl_get_unalign
6433#define do_prctl_get_unalign do_prctl_inval1
6434#endif
6435#ifndef do_prctl_set_unalign
6436#define do_prctl_set_unalign do_prctl_inval1
6437#endif
24d87c18
RH
6438#ifndef do_prctl_sme_get_vl
6439#define do_prctl_sme_get_vl do_prctl_inval0
6440#endif
6441#ifndef do_prctl_sme_set_vl
6442#define do_prctl_sme_set_vl do_prctl_inval1
6443#endif
87e9bf23
RH
6444
6445static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6446 abi_long arg3, abi_long arg4, abi_long arg5)
6447{
6448 abi_long ret;
6449
6450 switch (option) {
6451 case PR_GET_PDEATHSIG:
6452 {
6453 int deathsig;
6454 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6455 arg3, arg4, arg5));
1edebb36
RH
6456 if (!is_error(ret) &&
6457 put_user_s32(host_to_target_signal(deathsig), arg2)) {
87e9bf23
RH
6458 return -TARGET_EFAULT;
6459 }
6460 return ret;
6461 }
f746c659
RH
6462 case PR_SET_PDEATHSIG:
6463 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6464 arg3, arg4, arg5));
87e9bf23
RH
6465 case PR_GET_NAME:
6466 {
6467 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6468 if (!name) {
6469 return -TARGET_EFAULT;
6470 }
6471 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6472 arg3, arg4, arg5));
6473 unlock_user(name, arg2, 16);
6474 return ret;
6475 }
6476 case PR_SET_NAME:
6477 {
6478 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6479 if (!name) {
6480 return -TARGET_EFAULT;
6481 }
6482 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6483 arg3, arg4, arg5));
6484 unlock_user(name, arg2, 0);
6485 return ret;
6486 }
6487 case PR_GET_FP_MODE:
6488 return do_prctl_get_fp_mode(env);
6489 case PR_SET_FP_MODE:
6490 return do_prctl_set_fp_mode(env, arg2);
6491 case PR_SVE_GET_VL:
fd72f5d0 6492 return do_prctl_sve_get_vl(env);
87e9bf23 6493 case PR_SVE_SET_VL:
fd72f5d0 6494 return do_prctl_sve_set_vl(env, arg2);
24d87c18
RH
6495 case PR_SME_GET_VL:
6496 return do_prctl_sme_get_vl(env);
6497 case PR_SME_SET_VL:
6498 return do_prctl_sme_set_vl(env, arg2);
87e9bf23
RH
6499 case PR_PAC_RESET_KEYS:
6500 if (arg3 || arg4 || arg5) {
6501 return -TARGET_EINVAL;
6502 }
6503 return do_prctl_reset_keys(env, arg2);
6504 case PR_SET_TAGGED_ADDR_CTRL:
6505 if (arg3 || arg4 || arg5) {
6506 return -TARGET_EINVAL;
6507 }
6508 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6509 case PR_GET_TAGGED_ADDR_CTRL:
6510 if (arg2 || arg3 || arg4 || arg5) {
6511 return -TARGET_EINVAL;
6512 }
6513 return do_prctl_get_tagged_addr_ctrl(env);
220717a6 6514
6e8dcacd
RH
6515 case PR_GET_UNALIGN:
6516 return do_prctl_get_unalign(env, arg2);
6517 case PR_SET_UNALIGN:
6518 return do_prctl_set_unalign(env, arg2);
6519
4f4e5567
RH
6520 case PR_CAP_AMBIENT:
6521 case PR_CAPBSET_READ:
6522 case PR_CAPBSET_DROP:
220717a6
RH
6523 case PR_GET_DUMPABLE:
6524 case PR_SET_DUMPABLE:
6525 case PR_GET_KEEPCAPS:
6526 case PR_SET_KEEPCAPS:
4f4e5567
RH
6527 case PR_GET_SECUREBITS:
6528 case PR_SET_SECUREBITS:
220717a6
RH
6529 case PR_GET_TIMING:
6530 case PR_SET_TIMING:
6531 case PR_GET_TIMERSLACK:
6532 case PR_SET_TIMERSLACK:
6533 case PR_MCE_KILL:
6534 case PR_MCE_KILL_GET:
6535 case PR_GET_NO_NEW_PRIVS:
6536 case PR_SET_NO_NEW_PRIVS:
6537 case PR_GET_IO_FLUSHER:
6538 case PR_SET_IO_FLUSHER:
6539 /* Some prctl options have no pointer arguments and we can pass on. */
6540 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6541
6542 case PR_GET_CHILD_SUBREAPER:
6543 case PR_SET_CHILD_SUBREAPER:
6544 case PR_GET_SPECULATION_CTRL:
6545 case PR_SET_SPECULATION_CTRL:
6546 case PR_GET_TID_ADDRESS:
6547 /* TODO */
6548 return -TARGET_EINVAL;
6549
6550 case PR_GET_FPEXC:
6551 case PR_SET_FPEXC:
6552 /* Was used for SPE on PowerPC. */
6553 return -TARGET_EINVAL;
6554
6555 case PR_GET_ENDIAN:
6556 case PR_SET_ENDIAN:
6557 case PR_GET_FPEMU:
6558 case PR_SET_FPEMU:
6559 case PR_SET_MM:
87e9bf23
RH
6560 case PR_GET_SECCOMP:
6561 case PR_SET_SECCOMP:
220717a6
RH
6562 case PR_SET_SYSCALL_USER_DISPATCH:
6563 case PR_GET_THP_DISABLE:
6564 case PR_SET_THP_DISABLE:
6565 case PR_GET_TSC:
6566 case PR_SET_TSC:
220717a6 6567 /* Disable to prevent the target disabling stuff we need. */
87e9bf23 6568 return -TARGET_EINVAL;
220717a6 6569
87e9bf23 6570 default:
220717a6
RH
6571 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6572 option);
6573 return -TARGET_EINVAL;
87e9bf23
RH
6574 }
6575}
6576
05098a93 6577#define NEW_STACK_SIZE 0x40000
d865bab5 6578
d865bab5
PB
6579
6580static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6581typedef struct {
9349b4f9 6582 CPUArchState *env;
d865bab5
PB
6583 pthread_mutex_t mutex;
6584 pthread_cond_t cond;
6585 pthread_t thread;
6586 uint32_t tid;
6587 abi_ulong child_tidptr;
6588 abi_ulong parent_tidptr;
6589 sigset_t sigmask;
6590} new_thread_info;
6591
6592static void *clone_func(void *arg)
6593{
6594 new_thread_info *info = arg;
9349b4f9 6595 CPUArchState *env;
0d34282f 6596 CPUState *cpu;
edf8e2af 6597 TaskState *ts;
d865bab5 6598
70903763 6599 rcu_register_thread();
3468b59e 6600 tcg_register_thread();
d865bab5 6601 env = info->env;
29a0af61 6602 cpu = env_cpu(env);
a2247f8e 6603 thread_cpu = cpu;
0429a971 6604 ts = (TaskState *)cpu->opaque;
71ba74f6 6605 info->tid = sys_gettid();
edf8e2af 6606 task_settid(ts);
d865bab5
PB
6607 if (info->child_tidptr)
6608 put_user_u32(info->tid, info->child_tidptr);
6609 if (info->parent_tidptr)
6610 put_user_u32(info->tid, info->parent_tidptr);
5ebdd774 6611 qemu_guest_random_seed_thread_part2(cpu->random_seed);
d865bab5
PB
6612 /* Enable signals. */
6613 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6614 /* Signal to the parent that we're ready. */
6615 pthread_mutex_lock(&info->mutex);
6616 pthread_cond_broadcast(&info->cond);
6617 pthread_mutex_unlock(&info->mutex);
a4dd3d51 6618 /* Wait until the parent has finished initializing the tls state. */
d865bab5
PB
6619 pthread_mutex_lock(&clone_lock);
6620 pthread_mutex_unlock(&clone_lock);
6621 cpu_loop(env);
6622 /* never exits */
6623 return NULL;
6624}
1b6b029e 6625
0da46a6e
TS
6626/* do_fork() Must return host values and target errnos (unlike most
6627 do_*() functions). */
9349b4f9 6628static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
6629 abi_ulong parent_tidptr, target_ulong newtls,
6630 abi_ulong child_tidptr)
1b6b029e 6631{
29a0af61 6632 CPUState *cpu = env_cpu(env);
1b6b029e 6633 int ret;
5cd4393b 6634 TaskState *ts;
0429a971 6635 CPUState *new_cpu;
9349b4f9 6636 CPUArchState *new_env;
d865bab5 6637 sigset_t sigmask;
3b46e624 6638
5ea2fc84
PM
6639 flags &= ~CLONE_IGNORED_FLAGS;
6640
436d124b
AZ
6641 /* Emulate vfork() with fork() */
6642 if (flags & CLONE_VFORK)
6643 flags &= ~(CLONE_VFORK | CLONE_VM);
6644
1b6b029e 6645 if (flags & CLONE_VM) {
0429a971 6646 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
6647 new_thread_info info;
6648 pthread_attr_t attr;
24cb36a6 6649
5ea2fc84
PM
6650 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6651 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6652 return -TARGET_EINVAL;
6653 }
6654
c78d65e8 6655 ts = g_new0(TaskState, 1);
624f7979 6656 init_task_state(ts);
73a988d9
MF
6657
6658 /* Grab a mutex so that thread setup appears atomic. */
6659 pthread_mutex_lock(&clone_lock);
6660
6cc9d67c
RH
6661 /*
6662 * If this is our first additional thread, we need to ensure we
6663 * generate code for parallel execution and flush old translations.
6664 * Do this now so that the copy gets CF_PARALLEL too.
6665 */
6666 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6667 cpu->tcg_cflags |= CF_PARALLEL;
6668 tb_flush(cpu);
6669 }
6670
1b6b029e 6671 /* we create a new CPU instance. */
c5be9f08 6672 new_env = cpu_copy(env);
6e68e076 6673 /* Init regs that differ from the parent. */
608999d1 6674 cpu_clone_regs_child(new_env, newsp, flags);
07a6ecf4 6675 cpu_clone_regs_parent(env, flags);
29a0af61 6676 new_cpu = env_cpu(new_env);
0429a971 6677 new_cpu->opaque = ts;
edf8e2af
MW
6678 ts->bprm = parent_ts->bprm;
6679 ts->info = parent_ts->info;
3d3efba0 6680 ts->signal_mask = parent_ts->signal_mask;
d865bab5 6681
7cfbd386 6682 if (flags & CLONE_CHILD_CLEARTID) {
c2764719
PB
6683 ts->child_tidptr = child_tidptr;
6684 }
6685
7cfbd386 6686 if (flags & CLONE_SETTLS) {
d865bab5 6687 cpu_set_tls (new_env, newtls);
7cfbd386 6688 }
d865bab5 6689
d865bab5
PB
6690 memset(&info, 0, sizeof(info));
6691 pthread_mutex_init(&info.mutex, NULL);
6692 pthread_mutex_lock(&info.mutex);
6693 pthread_cond_init(&info.cond, NULL);
6694 info.env = new_env;
7cfbd386 6695 if (flags & CLONE_CHILD_SETTID) {
d865bab5 6696 info.child_tidptr = child_tidptr;
7cfbd386
PM
6697 }
6698 if (flags & CLONE_PARENT_SETTID) {
d865bab5 6699 info.parent_tidptr = parent_tidptr;
7cfbd386 6700 }
d865bab5
PB
6701
6702 ret = pthread_attr_init(&attr);
48e15fc2
NF
6703 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6704 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
6705 /* It is not safe to deliver signals until the child has finished
6706 initializing, so temporarily block all signals. */
6707 sigfillset(&sigmask);
6708 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
5ebdd774 6709 cpu->random_seed = qemu_guest_random_seed_thread_part1();
d865bab5
PB
6710
6711 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 6712 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
6713
6714 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6715 pthread_attr_destroy(&attr);
6716 if (ret == 0) {
6717 /* Wait for the child to initialize. */
6718 pthread_cond_wait(&info.cond, &info.mutex);
6719 ret = info.tid;
d865bab5
PB
6720 } else {
6721 ret = -1;
6722 }
6723 pthread_mutex_unlock(&info.mutex);
6724 pthread_cond_destroy(&info.cond);
6725 pthread_mutex_destroy(&info.mutex);
6726 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
6727 } else {
6728 /* if no CLONE_VM, we consider it is a fork */
5ea2fc84
PM
6729 if (flags & CLONE_INVALID_FORK_FLAGS) {
6730 return -TARGET_EINVAL;
6731 }
6732
6733 /* We can't support custom termination signals */
6734 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
93b4eff8
TB
6735 return -TARGET_EINVAL;
6736 }
7d92d34e 6737
895ce8bb
HD
6738#if !defined(__NR_pidfd_open) || !defined(TARGET_NR_pidfd_open)
6739 if (flags & CLONE_PIDFD) {
6740 return -TARGET_EINVAL;
6741 }
6742#endif
6743
6744 /* Can not allow CLONE_PIDFD with CLONE_PARENT_SETTID */
6745 if ((flags & CLONE_PIDFD) && (flags & CLONE_PARENT_SETTID)) {
6746 return -TARGET_EINVAL;
6747 }
6748
7d92d34e 6749 if (block_signals()) {
af254a27 6750 return -QEMU_ERESTARTSYS;
7d92d34e
TB
6751 }
6752
d865bab5 6753 fork_start();
1b6b029e 6754 ret = fork();
d865bab5 6755 if (ret == 0) {
2b1319c8 6756 /* Child Process. */
608999d1 6757 cpu_clone_regs_child(env, newsp, flags);
d865bab5 6758 fork_end(1);
2b1319c8
AJ
6759 /* There is a race condition here. The parent process could
6760 theoretically read the TID in the child process before the child
6761 tid is set. This would require using either ptrace
6762 (not implemented) or having *_tidptr to point at a shared memory
6763 mapping. We can't repeat the spinlock hack used above because
6764 the child process gets its own copy of the lock. */
d865bab5 6765 if (flags & CLONE_CHILD_SETTID)
71ba74f6 6766 put_user_u32(sys_gettid(), child_tidptr);
d865bab5 6767 if (flags & CLONE_PARENT_SETTID)
71ba74f6 6768 put_user_u32(sys_gettid(), parent_tidptr);
0429a971 6769 ts = (TaskState *)cpu->opaque;
d865bab5
PB
6770 if (flags & CLONE_SETTLS)
6771 cpu_set_tls (env, newtls);
c2764719
PB
6772 if (flags & CLONE_CHILD_CLEARTID)
6773 ts->child_tidptr = child_tidptr;
d865bab5 6774 } else {
07a6ecf4 6775 cpu_clone_regs_parent(env, flags);
895ce8bb
HD
6776 if (flags & CLONE_PIDFD) {
6777 int pid_fd = 0;
6778#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
6779 int pid_child = ret;
6780 pid_fd = pidfd_open(pid_child, 0);
6781 if (pid_fd >= 0) {
6782 fcntl(pid_fd, F_SETFD, fcntl(pid_fd, F_GETFL)
6783 | FD_CLOEXEC);
6784 } else {
6785 pid_fd = 0;
6786 }
6787#endif
6788 put_user_u32(pid_fd, parent_tidptr);
6789 }
d865bab5
PB
6790 fork_end(0);
6791 }
7de0816f 6792 g_assert(!cpu_in_exclusive_context(cpu));
1b6b029e
FB
6793 }
6794 return ret;
6795}
6796
5f106811
APR
6797/* warning : doesn't handle linux specific flags... */
6798static int target_to_host_fcntl_cmd(int cmd)
6799{
4a545761
SB
6800 int ret;
6801
5f106811 6802 switch(cmd) {
4a545761
SB
6803 case TARGET_F_DUPFD:
6804 case TARGET_F_GETFD:
6805 case TARGET_F_SETFD:
6806 case TARGET_F_GETFL:
6807 case TARGET_F_SETFL:
2d92c682
AS
6808 case TARGET_F_OFD_GETLK:
6809 case TARGET_F_OFD_SETLK:
6810 case TARGET_F_OFD_SETLKW:
4a545761
SB
6811 ret = cmd;
6812 break;
6813 case TARGET_F_GETLK:
6814 ret = F_GETLK64;
6815 break;
6816 case TARGET_F_SETLK:
6817 ret = F_SETLK64;
6818 break;
6819 case TARGET_F_SETLKW:
6820 ret = F_SETLKW64;
6821 break;
6822 case TARGET_F_GETOWN:
6823 ret = F_GETOWN;
6824 break;
6825 case TARGET_F_SETOWN:
6826 ret = F_SETOWN;
6827 break;
6828 case TARGET_F_GETSIG:
6829 ret = F_GETSIG;
6830 break;
6831 case TARGET_F_SETSIG:
6832 ret = F_SETSIG;
6833 break;
5f106811 6834#if TARGET_ABI_BITS == 32
4a545761
SB
6835 case TARGET_F_GETLK64:
6836 ret = F_GETLK64;
6837 break;
6838 case TARGET_F_SETLK64:
6839 ret = F_SETLK64;
6840 break;
6841 case TARGET_F_SETLKW64:
6842 ret = F_SETLKW64;
6843 break;
5f106811 6844#endif
4a545761
SB
6845 case TARGET_F_SETLEASE:
6846 ret = F_SETLEASE;
6847 break;
6848 case TARGET_F_GETLEASE:
6849 ret = F_GETLEASE;
6850 break;
fbd5de9b 6851#ifdef F_DUPFD_CLOEXEC
4a545761
SB
6852 case TARGET_F_DUPFD_CLOEXEC:
6853 ret = F_DUPFD_CLOEXEC;
6854 break;
fbd5de9b 6855#endif
4a545761
SB
6856 case TARGET_F_NOTIFY:
6857 ret = F_NOTIFY;
6858 break;
8d5d3004 6859#ifdef F_GETOWN_EX
4a545761
SB
6860 case TARGET_F_GETOWN_EX:
6861 ret = F_GETOWN_EX;
6862 break;
8d5d3004
AS
6863#endif
6864#ifdef F_SETOWN_EX
4a545761
SB
6865 case TARGET_F_SETOWN_EX:
6866 ret = F_SETOWN_EX;
6867 break;
8d5d3004 6868#endif
ddf31aa8 6869#ifdef F_SETPIPE_SZ
4a545761
SB
6870 case TARGET_F_SETPIPE_SZ:
6871 ret = F_SETPIPE_SZ;
6872 break;
6873 case TARGET_F_GETPIPE_SZ:
6874 ret = F_GETPIPE_SZ;
6875 break;
2bb963ff
SCW
6876#endif
6877#ifdef F_ADD_SEALS
6878 case TARGET_F_ADD_SEALS:
6879 ret = F_ADD_SEALS;
6880 break;
6881 case TARGET_F_GET_SEALS:
6882 ret = F_GET_SEALS;
6883 break;
ddf31aa8 6884#endif
4a545761
SB
6885 default:
6886 ret = -TARGET_EINVAL;
6887 break;
6888 }
6889
6890#if defined(__powerpc64__)
6891 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6892 * is not supported by kernel. The glibc fcntl call actually adjusts
6893 * them to 5, 6 and 7 before making the syscall(). Since we make the
6894 * syscall directly, adjust to what is supported by the kernel.
6895 */
6896 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6897 ret -= F_GETLK64 - 5;
5f106811 6898 }
4a545761
SB
6899#endif
6900
6901 return ret;
5f106811
APR
6902}
6903
ae68ad9f
LV
6904#define FLOCK_TRANSTBL \
6905 switch (type) { \
6906 TRANSTBL_CONVERT(F_RDLCK); \
6907 TRANSTBL_CONVERT(F_WRLCK); \
6908 TRANSTBL_CONVERT(F_UNLCK); \
ae68ad9f
LV
6909 }
6910
6911static int target_to_host_flock(int type)
6912{
6913#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6914 FLOCK_TRANSTBL
6915#undef TRANSTBL_CONVERT
6916 return -TARGET_EINVAL;
6917}
6918
6919static int host_to_target_flock(int type)
6920{
6921#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6922 FLOCK_TRANSTBL
6923#undef TRANSTBL_CONVERT
6924 /* if we don't know how to convert the value coming
6925 * from the host we copy to the target field as-is
6926 */
6927 return type;
6928}
2ba7f730 6929
213d3e9e
PM
6930static inline abi_long copy_from_user_flock(struct flock64 *fl,
6931 abi_ulong target_flock_addr)
7775e9ec 6932{
53a5960a 6933 struct target_flock *target_fl;
ae68ad9f 6934 int l_type;
213d3e9e
PM
6935
6936 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6937 return -TARGET_EFAULT;
6938 }
6939
6940 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6941 l_type = target_to_host_flock(l_type);
6942 if (l_type < 0) {
6943 return l_type;
6944 }
6945 fl->l_type = l_type;
213d3e9e
PM
6946 __get_user(fl->l_whence, &target_fl->l_whence);
6947 __get_user(fl->l_start, &target_fl->l_start);
6948 __get_user(fl->l_len, &target_fl->l_len);
6949 __get_user(fl->l_pid, &target_fl->l_pid);
6950 unlock_user_struct(target_fl, target_flock_addr, 0);
6951 return 0;
6952}
6953
6954static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6955 const struct flock64 *fl)
6956{
6957 struct target_flock *target_fl;
6958 short l_type;
6959
6960 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6961 return -TARGET_EFAULT;
6962 }
6963
ae68ad9f 6964 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6965 __put_user(l_type, &target_fl->l_type);
6966 __put_user(fl->l_whence, &target_fl->l_whence);
6967 __put_user(fl->l_start, &target_fl->l_start);
6968 __put_user(fl->l_len, &target_fl->l_len);
6969 __put_user(fl->l_pid, &target_fl->l_pid);
6970 unlock_user_struct(target_fl, target_flock_addr, 1);
6971 return 0;
6972}
6973
6974typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6975typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6976
6977#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
ffe81d43
RH
6978struct target_oabi_flock64 {
6979 abi_short l_type;
6980 abi_short l_whence;
6981 abi_llong l_start;
6982 abi_llong l_len;
6983 abi_int l_pid;
6984} QEMU_PACKED;
6985
7f254c5c 6986static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
213d3e9e
PM
6987 abi_ulong target_flock_addr)
6988{
7f254c5c 6989 struct target_oabi_flock64 *target_fl;
ae68ad9f 6990 int l_type;
213d3e9e
PM
6991
6992 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6993 return -TARGET_EFAULT;
6994 }
6995
6996 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6997 l_type = target_to_host_flock(l_type);
6998 if (l_type < 0) {
6999 return l_type;
7000 }
7001 fl->l_type = l_type;
213d3e9e
PM
7002 __get_user(fl->l_whence, &target_fl->l_whence);
7003 __get_user(fl->l_start, &target_fl->l_start);
7004 __get_user(fl->l_len, &target_fl->l_len);
7005 __get_user(fl->l_pid, &target_fl->l_pid);
7006 unlock_user_struct(target_fl, target_flock_addr, 0);
7007 return 0;
7008}
7009
7f254c5c 7010static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
213d3e9e
PM
7011 const struct flock64 *fl)
7012{
7f254c5c 7013 struct target_oabi_flock64 *target_fl;
213d3e9e
PM
7014 short l_type;
7015
7016 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7017 return -TARGET_EFAULT;
7018 }
7019
ae68ad9f 7020 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
7021 __put_user(l_type, &target_fl->l_type);
7022 __put_user(fl->l_whence, &target_fl->l_whence);
7023 __put_user(fl->l_start, &target_fl->l_start);
7024 __put_user(fl->l_len, &target_fl->l_len);
7025 __put_user(fl->l_pid, &target_fl->l_pid);
7026 unlock_user_struct(target_fl, target_flock_addr, 1);
7027 return 0;
7028}
7029#endif
7030
7031static inline abi_long copy_from_user_flock64(struct flock64 *fl,
7032 abi_ulong target_flock_addr)
7033{
7034 struct target_flock64 *target_fl;
ae68ad9f 7035 int l_type;
213d3e9e
PM
7036
7037 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7038 return -TARGET_EFAULT;
7039 }
7040
7041 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
7042 l_type = target_to_host_flock(l_type);
7043 if (l_type < 0) {
7044 return l_type;
7045 }
7046 fl->l_type = l_type;
213d3e9e
PM
7047 __get_user(fl->l_whence, &target_fl->l_whence);
7048 __get_user(fl->l_start, &target_fl->l_start);
7049 __get_user(fl->l_len, &target_fl->l_len);
7050 __get_user(fl->l_pid, &target_fl->l_pid);
7051 unlock_user_struct(target_fl, target_flock_addr, 0);
7052 return 0;
7053}
7054
7055static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
7056 const struct flock64 *fl)
7057{
7058 struct target_flock64 *target_fl;
7059 short l_type;
7060
7061 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7062 return -TARGET_EFAULT;
7063 }
7064
ae68ad9f 7065 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
7066 __put_user(l_type, &target_fl->l_type);
7067 __put_user(fl->l_whence, &target_fl->l_whence);
7068 __put_user(fl->l_start, &target_fl->l_start);
7069 __put_user(fl->l_len, &target_fl->l_len);
7070 __put_user(fl->l_pid, &target_fl->l_pid);
7071 unlock_user_struct(target_fl, target_flock_addr, 1);
7072 return 0;
7073}
7074
7075static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7076{
43f238d7 7077 struct flock64 fl64;
8d5d3004
AS
7078#ifdef F_GETOWN_EX
7079 struct f_owner_ex fox;
7080 struct target_f_owner_ex *target_fox;
7081#endif
992f48a0 7082 abi_long ret;
5f106811
APR
7083 int host_cmd = target_to_host_fcntl_cmd(cmd);
7084
7085 if (host_cmd == -TARGET_EINVAL)
7086 return host_cmd;
53a5960a 7087
7775e9ec
FB
7088 switch(cmd) {
7089 case TARGET_F_GETLK:
213d3e9e
PM
7090 ret = copy_from_user_flock(&fl64, arg);
7091 if (ret) {
7092 return ret;
7093 }
435da5e7 7094 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7095 if (ret == 0) {
213d3e9e 7096 ret = copy_to_user_flock(arg, &fl64);
7775e9ec
FB
7097 }
7098 break;
3b46e624 7099
7775e9ec
FB
7100 case TARGET_F_SETLK:
7101 case TARGET_F_SETLKW:
213d3e9e
PM
7102 ret = copy_from_user_flock(&fl64, arg);
7103 if (ret) {
7104 return ret;
7105 }
435da5e7 7106 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7107 break;
3b46e624 7108
7775e9ec 7109 case TARGET_F_GETLK64:
2d92c682 7110 case TARGET_F_OFD_GETLK:
213d3e9e
PM
7111 ret = copy_from_user_flock64(&fl64, arg);
7112 if (ret) {
7113 return ret;
7114 }
435da5e7 7115 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
43f238d7 7116 if (ret == 0) {
213d3e9e 7117 ret = copy_to_user_flock64(arg, &fl64);
43f238d7 7118 }
9ee1fa2c 7119 break;
7775e9ec
FB
7120 case TARGET_F_SETLK64:
7121 case TARGET_F_SETLKW64:
2d92c682
AS
7122 case TARGET_F_OFD_SETLK:
7123 case TARGET_F_OFD_SETLKW:
213d3e9e
PM
7124 ret = copy_from_user_flock64(&fl64, arg);
7125 if (ret) {
7126 return ret;
7127 }
435da5e7 7128 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
7129 break;
7130
5f106811 7131 case TARGET_F_GETFL:
435da5e7 7132 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
7133 if (ret >= 0) {
7134 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7135 }
ffa65c3b
FB
7136 break;
7137
5f106811 7138 case TARGET_F_SETFL:
435da5e7
PM
7139 ret = get_errno(safe_fcntl(fd, host_cmd,
7140 target_to_host_bitmask(arg,
7141 fcntl_flags_tbl)));
5f106811
APR
7142 break;
7143
8d5d3004
AS
7144#ifdef F_GETOWN_EX
7145 case TARGET_F_GETOWN_EX:
435da5e7 7146 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7147 if (ret >= 0) {
7148 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7149 return -TARGET_EFAULT;
7150 target_fox->type = tswap32(fox.type);
7151 target_fox->pid = tswap32(fox.pid);
7152 unlock_user_struct(target_fox, arg, 1);
7153 }
7154 break;
7155#endif
7156
7157#ifdef F_SETOWN_EX
7158 case TARGET_F_SETOWN_EX:
7159 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7160 return -TARGET_EFAULT;
7161 fox.type = tswap32(target_fox->type);
7162 fox.pid = tswap32(target_fox->pid);
7163 unlock_user_struct(target_fox, arg, 0);
435da5e7 7164 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7165 break;
7166#endif
7167
5f106811 7168 case TARGET_F_SETSIG:
a7b4c9b1
TB
7169 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7170 break;
7171
5f106811 7172 case TARGET_F_GETSIG:
a7b4c9b1
TB
7173 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7174 break;
7175
7176 case TARGET_F_SETOWN:
7177 case TARGET_F_GETOWN:
7e22e546
UH
7178 case TARGET_F_SETLEASE:
7179 case TARGET_F_GETLEASE:
7e3b92ec
PM
7180 case TARGET_F_SETPIPE_SZ:
7181 case TARGET_F_GETPIPE_SZ:
2bb963ff
SCW
7182 case TARGET_F_ADD_SEALS:
7183 case TARGET_F_GET_SEALS:
435da5e7 7184 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
ffa65c3b
FB
7185 break;
7186
7775e9ec 7187 default:
435da5e7 7188 ret = get_errno(safe_fcntl(fd, cmd, arg));
7775e9ec
FB
7189 break;
7190 }
7191 return ret;
7192}
7193
67867308 7194#ifdef USE_UID16
7775e9ec 7195
67867308
FB
7196static inline int high2lowuid(int uid)
7197{
7198 if (uid > 65535)
7199 return 65534;
7200 else
7201 return uid;
7202}
7203
7204static inline int high2lowgid(int gid)
7205{
7206 if (gid > 65535)
7207 return 65534;
7208 else
7209 return gid;
7210}
7211
7212static inline int low2highuid(int uid)
7213{
7214 if ((int16_t)uid == -1)
7215 return -1;
7216 else
7217 return uid;
7218}
7219
7220static inline int low2highgid(int gid)
7221{
7222 if ((int16_t)gid == -1)
7223 return -1;
7224 else
7225 return gid;
7226}
0c866a7e
RV
7227static inline int tswapid(int id)
7228{
7229 return tswap16(id);
7230}
76ca310a
PM
7231
7232#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7233
0c866a7e
RV
7234#else /* !USE_UID16 */
7235static inline int high2lowuid(int uid)
7236{
7237 return uid;
7238}
7239static inline int high2lowgid(int gid)
7240{
7241 return gid;
7242}
7243static inline int low2highuid(int uid)
7244{
7245 return uid;
7246}
7247static inline int low2highgid(int gid)
7248{
7249 return gid;
7250}
7251static inline int tswapid(int id)
7252{
7253 return tswap32(id);
7254}
76ca310a
PM
7255
7256#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7257
67867308 7258#endif /* USE_UID16 */
1b6b029e 7259
fd6f7798
PM
7260/* We must do direct syscalls for setting UID/GID, because we want to
7261 * implement the Linux system call semantics of "change only for this thread",
7262 * not the libc/POSIX semantics of "change for all threads in process".
7263 * (See http://ewontfix.com/17/ for more details.)
7264 * We use the 32-bit version of the syscalls if present; if it is not
7265 * then either the host architecture supports 32-bit UIDs natively with
7266 * the standard syscall, or the 16-bit UID is the best we can do.
7267 */
7268#ifdef __NR_setuid32
7269#define __NR_sys_setuid __NR_setuid32
7270#else
7271#define __NR_sys_setuid __NR_setuid
7272#endif
7273#ifdef __NR_setgid32
7274#define __NR_sys_setgid __NR_setgid32
7275#else
7276#define __NR_sys_setgid __NR_setgid
7277#endif
7278#ifdef __NR_setresuid32
7279#define __NR_sys_setresuid __NR_setresuid32
7280#else
7281#define __NR_sys_setresuid __NR_setresuid
7282#endif
7283#ifdef __NR_setresgid32
7284#define __NR_sys_setresgid __NR_setresgid32
7285#else
7286#define __NR_sys_setresgid __NR_setresgid
7287#endif
7288
7289_syscall1(int, sys_setuid, uid_t, uid)
7290_syscall1(int, sys_setgid, gid_t, gid)
7291_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7292_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7293
31e31b8a
FB
7294void syscall_init(void)
7295{
2ab83ea7
FB
7296 IOCTLEntry *ie;
7297 const argtype *arg_type;
7298 int size;
7299
8be656b8
AG
7300 thunk_init(STRUCT_MAX);
7301
001faf32 7302#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 7303#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
7304#include "syscall_types.h"
7305#undef STRUCT
7306#undef STRUCT_SPECIAL
2ab83ea7
FB
7307
7308 /* we patch the ioctl size if necessary. We rely on the fact that
7309 no ioctl has all the bits at '1' in the size field */
7310 ie = ioctl_entries;
7311 while (ie->target_cmd != 0) {
7312 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7313 TARGET_IOC_SIZEMASK) {
7314 arg_type = ie->arg_type;
7315 if (arg_type[0] != TYPE_PTR) {
5fafdf24 7316 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
7317 ie->target_cmd);
7318 exit(1);
7319 }
7320 arg_type++;
7321 size = thunk_type_size(arg_type, 0);
5fafdf24 7322 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
7323 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7324 (size << TARGET_IOC_SIZESHIFT);
7325 }
b92c47c1 7326
2ab83ea7 7327 /* automatic consistency check if same arch */
872ea0c0
AZ
7328#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7329 (defined(__x86_64__) && defined(TARGET_X86_64))
7330 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7331 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7332 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
7333 }
7334#endif
7335 ie++;
7336 }
31e31b8a 7337}
c573ff67 7338
ce4defa0 7339#ifdef TARGET_NR_truncate64
a0939b89 7340static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
992f48a0
BS
7341 abi_long arg2,
7342 abi_long arg3,
7343 abi_long arg4)
ce4defa0 7344{
8bf8e9df 7345 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
ce4defa0
PB
7346 arg2 = arg3;
7347 arg3 = arg4;
48e515d4 7348 }
ce4defa0
PB
7349 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7350}
7351#endif
7352
7353#ifdef TARGET_NR_ftruncate64
a0939b89 7354static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
992f48a0
BS
7355 abi_long arg2,
7356 abi_long arg3,
7357 abi_long arg4)
ce4defa0 7358{
8bf8e9df 7359 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
ce4defa0
PB
7360 arg2 = arg3;
7361 arg3 = arg4;
48e515d4 7362 }
ce4defa0
PB
7363 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7364}
7365#endif
7366
859e8a89
AF
7367#if defined(TARGET_NR_timer_settime) || \
7368 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
2c86c90f 7369static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
f4f1e10a
ECL
7370 abi_ulong target_addr)
7371{
2c86c90f
FB
7372 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7373 offsetof(struct target_itimerspec,
7374 it_interval)) ||
7375 target_to_host_timespec(&host_its->it_value, target_addr +
7376 offsetof(struct target_itimerspec,
7377 it_value))) {
f4f1e10a
ECL
7378 return -TARGET_EFAULT;
7379 }
7380
f4f1e10a
ECL
7381 return 0;
7382}
859e8a89 7383#endif
f4f1e10a 7384
828cb3a1
FB
7385#if defined(TARGET_NR_timer_settime64) || \
7386 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7387static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7388 abi_ulong target_addr)
7389{
7390 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7391 offsetof(struct target__kernel_itimerspec,
7392 it_interval)) ||
7393 target_to_host_timespec64(&host_its->it_value, target_addr +
7394 offsetof(struct target__kernel_itimerspec,
7395 it_value))) {
7396 return -TARGET_EFAULT;
7397 }
7398
7399 return 0;
7400}
7401#endif
7402
859e8a89
AF
7403#if ((defined(TARGET_NR_timerfd_gettime) || \
7404 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
2c86c90f 7405 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
f4f1e10a 7406static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
2c86c90f
FB
7407 struct itimerspec *host_its)
7408{
7409 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7410 it_interval),
7411 &host_its->it_interval) ||
7412 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7413 it_value),
7414 &host_its->it_value)) {
f4f1e10a
ECL
7415 return -TARGET_EFAULT;
7416 }
f4f1e10a
ECL
7417 return 0;
7418}
859e8a89 7419#endif
f4f1e10a 7420
828cb3a1
FB
7421#if ((defined(TARGET_NR_timerfd_gettime64) || \
7422 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7423 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7424static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7425 struct itimerspec *host_its)
7426{
7427 if (host_to_target_timespec64(target_addr +
7428 offsetof(struct target__kernel_itimerspec,
7429 it_interval),
7430 &host_its->it_interval) ||
7431 host_to_target_timespec64(target_addr +
7432 offsetof(struct target__kernel_itimerspec,
7433 it_value),
7434 &host_its->it_value)) {
7435 return -TARGET_EFAULT;
7436 }
7437 return 0;
7438}
7439#endif
7440
859e8a89
AF
7441#if defined(TARGET_NR_adjtimex) || \
7442 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
19f59bce
AM
7443static inline abi_long target_to_host_timex(struct timex *host_tx,
7444 abi_long target_addr)
7445{
7446 struct target_timex *target_tx;
7447
7448 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7449 return -TARGET_EFAULT;
7450 }
7451
7452 __get_user(host_tx->modes, &target_tx->modes);
7453 __get_user(host_tx->offset, &target_tx->offset);
7454 __get_user(host_tx->freq, &target_tx->freq);
7455 __get_user(host_tx->maxerror, &target_tx->maxerror);
7456 __get_user(host_tx->esterror, &target_tx->esterror);
7457 __get_user(host_tx->status, &target_tx->status);
7458 __get_user(host_tx->constant, &target_tx->constant);
7459 __get_user(host_tx->precision, &target_tx->precision);
7460 __get_user(host_tx->tolerance, &target_tx->tolerance);
7461 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7462 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7463 __get_user(host_tx->tick, &target_tx->tick);
7464 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7465 __get_user(host_tx->jitter, &target_tx->jitter);
7466 __get_user(host_tx->shift, &target_tx->shift);
7467 __get_user(host_tx->stabil, &target_tx->stabil);
7468 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7469 __get_user(host_tx->calcnt, &target_tx->calcnt);
7470 __get_user(host_tx->errcnt, &target_tx->errcnt);
7471 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7472 __get_user(host_tx->tai, &target_tx->tai);
7473
7474 unlock_user_struct(target_tx, target_addr, 0);
7475 return 0;
7476}
7477
7478static inline abi_long host_to_target_timex(abi_long target_addr,
7479 struct timex *host_tx)
7480{
7481 struct target_timex *target_tx;
7482
7483 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7484 return -TARGET_EFAULT;
7485 }
7486
7487 __put_user(host_tx->modes, &target_tx->modes);
7488 __put_user(host_tx->offset, &target_tx->offset);
7489 __put_user(host_tx->freq, &target_tx->freq);
7490 __put_user(host_tx->maxerror, &target_tx->maxerror);
7491 __put_user(host_tx->esterror, &target_tx->esterror);
7492 __put_user(host_tx->status, &target_tx->status);
7493 __put_user(host_tx->constant, &target_tx->constant);
7494 __put_user(host_tx->precision, &target_tx->precision);
7495 __put_user(host_tx->tolerance, &target_tx->tolerance);
7496 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7497 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7498 __put_user(host_tx->tick, &target_tx->tick);
7499 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7500 __put_user(host_tx->jitter, &target_tx->jitter);
7501 __put_user(host_tx->shift, &target_tx->shift);
7502 __put_user(host_tx->stabil, &target_tx->stabil);
7503 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7504 __put_user(host_tx->calcnt, &target_tx->calcnt);
7505 __put_user(host_tx->errcnt, &target_tx->errcnt);
7506 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7507 __put_user(host_tx->tai, &target_tx->tai);
7508
7509 unlock_user_struct(target_tx, target_addr, 1);
7510 return 0;
7511}
859e8a89 7512#endif
19f59bce 7513
6ac03b2c
FB
7514
7515#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7516static inline abi_long target_to_host_timex64(struct timex *host_tx,
7517 abi_long target_addr)
7518{
7519 struct target__kernel_timex *target_tx;
7520
7521 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7522 offsetof(struct target__kernel_timex,
7523 time))) {
7524 return -TARGET_EFAULT;
7525 }
7526
7527 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7528 return -TARGET_EFAULT;
7529 }
7530
7531 __get_user(host_tx->modes, &target_tx->modes);
7532 __get_user(host_tx->offset, &target_tx->offset);
7533 __get_user(host_tx->freq, &target_tx->freq);
7534 __get_user(host_tx->maxerror, &target_tx->maxerror);
7535 __get_user(host_tx->esterror, &target_tx->esterror);
7536 __get_user(host_tx->status, &target_tx->status);
7537 __get_user(host_tx->constant, &target_tx->constant);
7538 __get_user(host_tx->precision, &target_tx->precision);
7539 __get_user(host_tx->tolerance, &target_tx->tolerance);
7540 __get_user(host_tx->tick, &target_tx->tick);
7541 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7542 __get_user(host_tx->jitter, &target_tx->jitter);
7543 __get_user(host_tx->shift, &target_tx->shift);
7544 __get_user(host_tx->stabil, &target_tx->stabil);
7545 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7546 __get_user(host_tx->calcnt, &target_tx->calcnt);
7547 __get_user(host_tx->errcnt, &target_tx->errcnt);
7548 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7549 __get_user(host_tx->tai, &target_tx->tai);
7550
7551 unlock_user_struct(target_tx, target_addr, 0);
7552 return 0;
7553}
7554
7555static inline abi_long host_to_target_timex64(abi_long target_addr,
7556 struct timex *host_tx)
7557{
7558 struct target__kernel_timex *target_tx;
7559
7560 if (copy_to_user_timeval64(target_addr +
7561 offsetof(struct target__kernel_timex, time),
7562 &host_tx->time)) {
7563 return -TARGET_EFAULT;
7564 }
7565
7566 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7567 return -TARGET_EFAULT;
7568 }
7569
7570 __put_user(host_tx->modes, &target_tx->modes);
7571 __put_user(host_tx->offset, &target_tx->offset);
7572 __put_user(host_tx->freq, &target_tx->freq);
7573 __put_user(host_tx->maxerror, &target_tx->maxerror);
7574 __put_user(host_tx->esterror, &target_tx->esterror);
7575 __put_user(host_tx->status, &target_tx->status);
7576 __put_user(host_tx->constant, &target_tx->constant);
7577 __put_user(host_tx->precision, &target_tx->precision);
7578 __put_user(host_tx->tolerance, &target_tx->tolerance);
7579 __put_user(host_tx->tick, &target_tx->tick);
7580 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7581 __put_user(host_tx->jitter, &target_tx->jitter);
7582 __put_user(host_tx->shift, &target_tx->shift);
7583 __put_user(host_tx->stabil, &target_tx->stabil);
7584 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7585 __put_user(host_tx->calcnt, &target_tx->calcnt);
7586 __put_user(host_tx->errcnt, &target_tx->errcnt);
7587 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7588 __put_user(host_tx->tai, &target_tx->tai);
7589
7590 unlock_user_struct(target_tx, target_addr, 1);
7591 return 0;
7592}
7593#endif
7594
96ff758c
MF
7595#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7596#define sigev_notify_thread_id _sigev_un._tid
7597#endif
7598
c065976f
PM
7599static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7600 abi_ulong target_addr)
7601{
7602 struct target_sigevent *target_sevp;
7603
7604 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7605 return -TARGET_EFAULT;
7606 }
7607
7608 /* This union is awkward on 64 bit systems because it has a 32 bit
7609 * integer and a pointer in it; we follow the conversion approach
7610 * used for handling sigval types in signal.c so the guest should get
7611 * the correct value back even if we did a 64 bit byteswap and it's
7612 * using the 32 bit integer.
7613 */
7614 host_sevp->sigev_value.sival_ptr =
7615 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7616 host_sevp->sigev_signo =
7617 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7618 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
96ff758c 7619 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
c065976f
PM
7620
7621 unlock_user_struct(target_sevp, target_addr, 1);
7622 return 0;
7623}
7624
6f6a4032
TM
7625#if defined(TARGET_NR_mlockall)
7626static inline int target_to_host_mlockall_arg(int arg)
7627{
7628 int result = 0;
7629
02e5d7d7 7630 if (arg & TARGET_MCL_CURRENT) {
6f6a4032
TM
7631 result |= MCL_CURRENT;
7632 }
02e5d7d7 7633 if (arg & TARGET_MCL_FUTURE) {
6f6a4032
TM
7634 result |= MCL_FUTURE;
7635 }
02e5d7d7
FB
7636#ifdef MCL_ONFAULT
7637 if (arg & TARGET_MCL_ONFAULT) {
7638 result |= MCL_ONFAULT;
7639 }
7640#endif
7641
6f6a4032
TM
7642 return result;
7643}
7644#endif
7645
fe080593
HD
7646static inline int target_to_host_msync_arg(abi_long arg)
7647{
7648 return ((arg & TARGET_MS_ASYNC) ? MS_ASYNC : 0) |
7649 ((arg & TARGET_MS_INVALIDATE) ? MS_INVALIDATE : 0) |
7650 ((arg & TARGET_MS_SYNC) ? MS_SYNC : 0) |
7651 (arg & ~(TARGET_MS_ASYNC | TARGET_MS_INVALIDATE | TARGET_MS_SYNC));
7652}
7653
4f7f8924
AR
7654#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7655 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7656 defined(TARGET_NR_newfstatat))
a0939b89 7657static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
6a24a778
AZ
7658 abi_ulong target_addr,
7659 struct stat *host_st)
7660{
09701199 7661#if defined(TARGET_ARM) && defined(TARGET_ABI32)
0effdc29 7662 if (cpu_env->eabi) {
6a24a778
AZ
7663 struct target_eabi_stat64 *target_st;
7664
7665 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7666 return -TARGET_EFAULT;
7667 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7668 __put_user(host_st->st_dev, &target_st->st_dev);
7669 __put_user(host_st->st_ino, &target_st->st_ino);
7670#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7671 __put_user(host_st->st_ino, &target_st->__st_ino);
7672#endif
7673 __put_user(host_st->st_mode, &target_st->st_mode);
7674 __put_user(host_st->st_nlink, &target_st->st_nlink);
7675 __put_user(host_st->st_uid, &target_st->st_uid);
7676 __put_user(host_st->st_gid, &target_st->st_gid);
7677 __put_user(host_st->st_rdev, &target_st->st_rdev);
7678 __put_user(host_st->st_size, &target_st->st_size);
7679 __put_user(host_st->st_blksize, &target_st->st_blksize);
7680 __put_user(host_st->st_blocks, &target_st->st_blocks);
7681 __put_user(host_st->st_atime, &target_st->target_st_atime);
7682 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7683 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7684#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7685 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7686 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7687 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7688#endif
6a24a778
AZ
7689 unlock_user_struct(target_st, target_addr, 1);
7690 } else
7691#endif
7692 {
20d155bc 7693#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 7694 struct target_stat64 *target_st;
20d155bc
SW
7695#else
7696 struct target_stat *target_st;
9d33b76b 7697#endif
6a24a778
AZ
7698
7699 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7700 return -TARGET_EFAULT;
9d33b76b 7701 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
7702 __put_user(host_st->st_dev, &target_st->st_dev);
7703 __put_user(host_st->st_ino, &target_st->st_ino);
7704#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7705 __put_user(host_st->st_ino, &target_st->__st_ino);
7706#endif
7707 __put_user(host_st->st_mode, &target_st->st_mode);
7708 __put_user(host_st->st_nlink, &target_st->st_nlink);
7709 __put_user(host_st->st_uid, &target_st->st_uid);
7710 __put_user(host_st->st_gid, &target_st->st_gid);
7711 __put_user(host_st->st_rdev, &target_st->st_rdev);
7712 /* XXX: better use of kernel struct */
7713 __put_user(host_st->st_size, &target_st->st_size);
7714 __put_user(host_st->st_blksize, &target_st->st_blksize);
7715 __put_user(host_st->st_blocks, &target_st->st_blocks);
7716 __put_user(host_st->st_atime, &target_st->target_st_atime);
7717 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7718 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7719#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7720 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7721 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7722 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7723#endif
6a24a778
AZ
7724 unlock_user_struct(target_st, target_addr, 1);
7725 }
7726
7727 return 0;
7728}
4f7f8924 7729#endif
6a24a778 7730
efa92184
AR
7731#if defined(TARGET_NR_statx) && defined(__NR_statx)
7732static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7733 abi_ulong target_addr)
7734{
7735 struct target_statx *target_stx;
7736
7737 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7738 return -TARGET_EFAULT;
7739 }
7740 memset(target_stx, 0, sizeof(*target_stx));
7741
7742 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7743 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7744 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7745 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7746 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7747 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7748 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7749 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7750 __put_user(host_stx->stx_size, &target_stx->stx_size);
7751 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7752 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7753 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7754 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
d1e26707
AC
7755 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7756 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7757 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7758 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7759 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7760 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
efa92184
AR
7761 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7762 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7763 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7764 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7765
7766 unlock_user_struct(target_stx, target_addr, 1);
7767
7768 return 0;
7769}
7770#endif
7771
14690296
AF
7772static int do_sys_futex(int *uaddr, int op, int val,
7773 const struct timespec *timeout, int *uaddr2,
7774 int val3)
7775{
7776#if HOST_LONG_BITS == 64
7777#if defined(__NR_futex)
7778 /* always a 64-bit time_t, it doesn't define _time64 version */
7779 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7780
7781#endif
7782#else /* HOST_LONG_BITS == 64 */
7783#if defined(__NR_futex_time64)
7784 if (sizeof(timeout->tv_sec) == 8) {
7785 /* _time64 function on 32bit arch */
7786 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7787 }
7788#endif
7789#if defined(__NR_futex)
7790 /* old function on 32bit arch */
7791 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7792#endif
7793#endif /* HOST_LONG_BITS == 64 */
7794 g_assert_not_reached();
7795}
7796
7797static int do_safe_futex(int *uaddr, int op, int val,
7798 const struct timespec *timeout, int *uaddr2,
7799 int val3)
7800{
7801#if HOST_LONG_BITS == 64
7802#if defined(__NR_futex)
7803 /* always a 64-bit time_t, it doesn't define _time64 version */
7804 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7805#endif
7806#else /* HOST_LONG_BITS == 64 */
7807#if defined(__NR_futex_time64)
7808 if (sizeof(timeout->tv_sec) == 8) {
7809 /* _time64 function on 32bit arch */
7810 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7811 val3));
7812 }
7813#endif
7814#if defined(__NR_futex)
7815 /* old function on 32bit arch */
7816 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7817#endif
7818#endif /* HOST_LONG_BITS == 64 */
7819 return -TARGET_ENOSYS;
7820}
efa92184 7821
bd0c5661
PB
7822/* ??? Using host futex calls even when target atomic operations
7823 are not really atomic probably breaks things. However implementing
7824 futexes locally would make futexes shared between multiple processes
7825 tricky. However they're probably useless because guest atomic
7826 operations won't work either. */
0fbc0f8d
RH
7827#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
7828static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
7829 int op, int val, target_ulong timeout,
7830 target_ulong uaddr2, int val3)
bd0c5661 7831{
57b9ccd4
RH
7832 struct timespec ts, *pts = NULL;
7833 void *haddr2 = NULL;
a16aae0c 7834 int base_op;
bd0c5661 7835
57b9ccd4 7836 /* We assume FUTEX_* constants are the same on both host and target. */
a29ccd63 7837#ifdef FUTEX_CMD_MASK
a16aae0c 7838 base_op = op & FUTEX_CMD_MASK;
a29ccd63 7839#else
a16aae0c 7840 base_op = op;
a29ccd63 7841#endif
a16aae0c 7842 switch (base_op) {
bd0c5661 7843 case FUTEX_WAIT:
cce246e0 7844 case FUTEX_WAIT_BITSET:
57b9ccd4
RH
7845 val = tswap32(val);
7846 break;
c72a90df
RH
7847 case FUTEX_WAIT_REQUEUE_PI:
7848 val = tswap32(val);
7849 haddr2 = g2h(cpu, uaddr2);
7850 break;
7851 case FUTEX_LOCK_PI:
7852 case FUTEX_LOCK_PI2:
7853 break;
bd0c5661 7854 case FUTEX_WAKE:
a6180f8a 7855 case FUTEX_WAKE_BITSET:
c72a90df
RH
7856 case FUTEX_TRYLOCK_PI:
7857 case FUTEX_UNLOCK_PI:
57b9ccd4
RH
7858 timeout = 0;
7859 break;
bd0c5661 7860 case FUTEX_FD:
0f946731 7861 val = target_to_host_signal(val);
57b9ccd4
RH
7862 timeout = 0;
7863 break;
bd0c5661 7864 case FUTEX_CMP_REQUEUE:
c72a90df 7865 case FUTEX_CMP_REQUEUE_PI:
57b9ccd4
RH
7866 val3 = tswap32(val3);
7867 /* fall through */
7868 case FUTEX_REQUEUE:
a16aae0c 7869 case FUTEX_WAKE_OP:
57b9ccd4
RH
7870 /*
7871 * For these, the 4th argument is not TIMEOUT, but VAL2.
7872 * But the prototype of do_safe_futex takes a pointer, so
7873 * insert casts to satisfy the compiler. We do not need
7874 * to tswap VAL2 since it's not compared to guest memory.
7875 */
7876 pts = (struct timespec *)(uintptr_t)timeout;
7877 timeout = 0;
7878 haddr2 = g2h(cpu, uaddr2);
7879 break;
bd0c5661
PB
7880 default:
7881 return -TARGET_ENOSYS;
7882 }
57b9ccd4
RH
7883 if (timeout) {
7884 pts = &ts;
7885 if (time64
7886 ? target_to_host_timespec64(pts, timeout)
7887 : target_to_host_timespec(pts, timeout)) {
7888 return -TARGET_EFAULT;
7889 }
7890 }
7891 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
bd0c5661 7892}
859e8a89 7893#endif
14690296 7894
0f0426f3
LV
7895#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7896static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7897 abi_long handle, abi_long mount_id,
7898 abi_long flags)
7899{
7900 struct file_handle *target_fh;
7901 struct file_handle *fh;
7902 int mid = 0;
7903 abi_long ret;
7904 char *name;
7905 unsigned int size, total_size;
7906
7907 if (get_user_s32(size, handle)) {
7908 return -TARGET_EFAULT;
7909 }
7910
7911 name = lock_user_string(pathname);
7912 if (!name) {
7913 return -TARGET_EFAULT;
7914 }
7915
7916 total_size = sizeof(struct file_handle) + size;
7917 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7918 if (!target_fh) {
7919 unlock_user(name, pathname, 0);
7920 return -TARGET_EFAULT;
7921 }
7922
7923 fh = g_malloc0(total_size);
7924 fh->handle_bytes = size;
7925
7926 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7927 unlock_user(name, pathname, 0);
7928
7929 /* man name_to_handle_at(2):
7930 * Other than the use of the handle_bytes field, the caller should treat
7931 * the file_handle structure as an opaque data type
7932 */
7933
7934 memcpy(target_fh, fh, total_size);
7935 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7936 target_fh->handle_type = tswap32(fh->handle_type);
7937 g_free(fh);
7938 unlock_user(target_fh, handle, total_size);
7939
7940 if (put_user_s32(mid, mount_id)) {
7941 return -TARGET_EFAULT;
7942 }
7943
7944 return ret;
7945
7946}
7947#endif
7948
7949#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7950static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7951 abi_long flags)
7952{
7953 struct file_handle *target_fh;
7954 struct file_handle *fh;
7955 unsigned int size, total_size;
7956 abi_long ret;
7957
7958 if (get_user_s32(size, handle)) {
7959 return -TARGET_EFAULT;
7960 }
7961
7962 total_size = sizeof(struct file_handle) + size;
7963 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7964 if (!target_fh) {
7965 return -TARGET_EFAULT;
7966 }
7967
e9d49d51 7968 fh = g_memdup(target_fh, total_size);
0f0426f3
LV
7969 fh->handle_bytes = size;
7970 fh->handle_type = tswap32(target_fh->handle_type);
7971
7972 ret = get_errno(open_by_handle_at(mount_fd, fh,
7973 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7974
7975 g_free(fh);
7976
7977 unlock_user(target_fh, handle, total_size);
7978
7979 return ret;
7980}
7981#endif
bd0c5661 7982
e36800c9
LV
7983#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7984
e36800c9
LV
7985static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7986{
7987 int host_flags;
7988 target_sigset_t *target_mask;
7989 sigset_t host_mask;
7990 abi_long ret;
7991
78721301 7992 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
e36800c9
LV
7993 return -TARGET_EINVAL;
7994 }
7995 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7996 return -TARGET_EFAULT;
7997 }
7998
7999 target_to_host_sigset(&host_mask, target_mask);
8000
8001 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
8002
8003 ret = get_errno(signalfd(fd, &host_mask, host_flags));
8004 if (ret >= 0) {
8005 fd_trans_register(ret, &target_signalfd_trans);
8006 }
8007
8008 unlock_user_struct(target_mask, mask, 0);
8009
8010 return ret;
8011}
8012#endif
8013
1d9d8b55
PB
8014/* Map host to target signal numbers for the wait family of syscalls.
8015 Assume all other status bits are the same. */
a05c6409 8016int host_to_target_waitstatus(int status)
1d9d8b55
PB
8017{
8018 if (WIFSIGNALED(status)) {
8019 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
8020 }
8021 if (WIFSTOPPED(status)) {
8022 return (host_to_target_signal(WSTOPSIG(status)) << 8)
8023 | (status & 0xff);
8024 }
8025 return status;
8026}
8027
a0939b89 8028static int open_self_cmdline(CPUArchState *cpu_env, int fd)
76b94245 8029{
0effdc29 8030 CPUState *cpu = env_cpu(cpu_env);
58de8b96
AS
8031 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
8032 int i;
76b94245 8033
58de8b96
AS
8034 for (i = 0; i < bprm->argc; i++) {
8035 size_t len = strlen(bprm->argv[i]) + 1;
76b94245 8036
58de8b96 8037 if (write(fd, bprm->argv[i], len) != len) {
76b94245 8038 return -1;
76b94245
WVS
8039 }
8040 }
8041
58de8b96 8042 return 0;
76b94245
WVS
8043}
8044
a0939b89 8045static int open_self_maps(CPUArchState *cpu_env, int fd)
36c08d49 8046{
0effdc29 8047 CPUState *cpu = env_cpu(cpu_env);
0429a971 8048 TaskState *ts = cpu->opaque;
01ef6b9e
AB
8049 GSList *map_info = read_self_maps();
8050 GSList *s;
bb55173c 8051 int count;
1a49ef2a 8052
01ef6b9e
AB
8053 for (s = map_info; s; s = g_slist_next(s)) {
8054 MapInfo *e = (MapInfo *) s->data;
1a49ef2a 8055
01ef6b9e
AB
8056 if (h2g_valid(e->start)) {
8057 unsigned long min = e->start;
8058 unsigned long max = e->end;
d67f4aaa 8059 int flags = page_get_flags(h2g(min));
01ef6b9e
AB
8060 const char *path;
8061
8062 max = h2g_valid(max - 1) ?
3e8f1628 8063 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
01ef6b9e 8064
d67f4aaa
MI
8065 if (page_check_range(h2g(min), max - min, flags) == -1) {
8066 continue;
8067 }
01ef6b9e 8068
0a3346b5
HD
8069#ifdef TARGET_HPPA
8070 if (h2g(max) == ts->info->stack_limit) {
8071#else
d67f4aaa 8072 if (h2g(min) == ts->info->stack_limit) {
0a3346b5 8073#endif
bb55173c 8074 path = "[stack]";
01ef6b9e
AB
8075 } else {
8076 path = e->path;
d67f4aaa 8077 }
01ef6b9e 8078
bb55173c
AB
8079 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8080 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8081 h2g(min), h2g(max - 1) + 1,
08f3a96b
NS
8082 (flags & PAGE_READ) ? 'r' : '-',
8083 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8084 (flags & PAGE_EXEC) ? 'x' : '-',
e13685a6 8085 e->is_priv ? 'p' : 's',
bb55173c
AB
8086 (uint64_t) e->offset, e->dev, e->inode);
8087 if (path) {
8088 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8089 } else {
8090 dprintf(fd, "\n");
8091 }
1a49ef2a
AG
8092 }
8093 }
8094
01ef6b9e
AB
8095 free_self_maps(map_info);
8096
bf02adcd
RH
8097#ifdef TARGET_VSYSCALL_PAGE
8098 /*
8099 * We only support execution from the vsyscall page.
8100 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8101 */
bb55173c
AB
8102 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8103 " --xp 00000000 00:00 0",
8104 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8105 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
bf02adcd
RH
8106#endif
8107
36c08d49
AG
8108 return 0;
8109}
8110
a0939b89 8111static int open_self_stat(CPUArchState *cpu_env, int fd)
480b8e7d 8112{
0effdc29 8113 CPUState *cpu = env_cpu(cpu_env);
0429a971 8114 TaskState *ts = cpu->opaque;
7ad4d5a4 8115 g_autoptr(GString) buf = g_string_new(NULL);
480b8e7d
AG
8116 int i;
8117
8118 for (i = 0; i < 44; i++) {
7ad4d5a4
AB
8119 if (i == 0) {
8120 /* pid */
8121 g_string_printf(buf, FMT_pid " ", getpid());
8122 } else if (i == 1) {
8123 /* app name */
8124 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8125 bin = bin ? bin + 1 : ts->bprm->argv[0];
8126 g_string_printf(buf, "(%.15s) ", bin);
25bb27c7
AS
8127 } else if (i == 2) {
8128 /* task state */
8129 g_string_assign(buf, "R "); /* we are running right now */
7aa9fe3a
AS
8130 } else if (i == 3) {
8131 /* ppid */
8132 g_string_printf(buf, FMT_pid " ", getppid());
eb33cdae
CE
8133 } else if (i == 21) {
8134 /* starttime */
8135 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
7ad4d5a4
AB
8136 } else if (i == 27) {
8137 /* stack bottom */
8138 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8139 } else {
8140 /* for the rest, there is MasterCard */
8141 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8142 }
8143
8144 if (write(fd, buf->str, buf->len) != buf->len) {
8145 return -1;
8146 }
480b8e7d
AG
8147 }
8148
8149 return 0;
8150}
8151
a0939b89 8152static int open_self_auxv(CPUArchState *cpu_env, int fd)
257450ee 8153{
0effdc29 8154 CPUState *cpu = env_cpu(cpu_env);
0429a971 8155 TaskState *ts = cpu->opaque;
257450ee
AG
8156 abi_ulong auxv = ts->info->saved_auxv;
8157 abi_ulong len = ts->info->auxv_len;
8158 char *ptr;
8159
8160 /*
8161 * Auxiliary vector is stored in target process stack.
8162 * read in whole auxv vector and copy it to file
8163 */
8164 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8165 if (ptr != NULL) {
8166 while (len > 0) {
8167 ssize_t r;
8168 r = write(fd, ptr, len);
8169 if (r <= 0) {
8170 break;
8171 }
8172 len -= r;
8173 ptr += r;
8174 }
8175 lseek(fd, 0, SEEK_SET);
8176 unlock_user(ptr, auxv, len);
8177 }
8178
8179 return 0;
8180}
8181
463d8e73
AS
8182static int is_proc_myself(const char *filename, const char *entry)
8183{
8184 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8185 filename += strlen("/proc/");
8186 if (!strncmp(filename, "self/", strlen("self/"))) {
8187 filename += strlen("self/");
8188 } else if (*filename >= '1' && *filename <= '9') {
8189 char myself[80];
8190 snprintf(myself, sizeof(myself), "%d/", getpid());
8191 if (!strncmp(filename, myself, strlen(myself))) {
8192 filename += strlen(myself);
8193 } else {
8194 return 0;
8195 }
8196 } else {
8197 return 0;
8198 }
8199 if (!strcmp(filename, entry)) {
8200 return 1;
8201 }
8202 }
8203 return 0;
8204}
8205
bd5ccd61
HD
8206static void excp_dump_file(FILE *logfile, CPUArchState *env,
8207 const char *fmt, int code)
8208{
8209 if (logfile) {
8210 CPUState *cs = env_cpu(env);
8211
8212 fprintf(logfile, fmt, code);
8213 fprintf(logfile, "Failing executable: %s\n", exec_path);
8214 cpu_dump_state(cs, logfile, 0);
8215 open_self_maps(env, fileno(logfile));
8216 }
8217}
8218
8219void target_exception_dump(CPUArchState *env, const char *fmt, int code)
8220{
8221 /* dump to console */
8222 excp_dump_file(stderr, env, fmt, code);
8223
8224 /* dump to log file */
8225 if (qemu_log_separate()) {
8226 FILE *logfile = qemu_log_trylock();
8227
8228 excp_dump_file(logfile, env, fmt, code);
8229 qemu_log_unlock(logfile);
8230 }
8231}
8232
ee3eb3a7 8233#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
93a5661d 8234 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
de6b9933
LV
8235static int is_proc(const char *filename, const char *entry)
8236{
8237 return strcmp(filename, entry) == 0;
8238}
fff69382 8239#endif
de6b9933 8240
ee3eb3a7 8241#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
a0939b89 8242static int open_net_route(CPUArchState *cpu_env, int fd)
de6b9933
LV
8243{
8244 FILE *fp;
8245 char *line = NULL;
8246 size_t len = 0;
8247 ssize_t read;
8248
8249 fp = fopen("/proc/net/route", "r");
8250 if (fp == NULL) {
a3ca7bb2 8251 return -1;
de6b9933
LV
8252 }
8253
8254 /* read header */
8255
8256 read = getline(&line, &len, fp);
8257 dprintf(fd, "%s", line);
8258
8259 /* read routes */
8260
8261 while ((read = getline(&line, &len, fp)) != -1) {
8262 char iface[16];
8263 uint32_t dest, gw, mask;
8264 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
9d0bd0cd
PM
8265 int fields;
8266
8267 fields = sscanf(line,
8268 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8269 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8270 &mask, &mtu, &window, &irtt);
8271 if (fields != 11) {
8272 continue;
8273 }
de6b9933
LV
8274 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8275 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8276 metric, tswap32(mask), mtu, window, irtt);
8277 }
8278
8279 free(line);
8280 fclose(fp);
8281
8282 return 0;
8283}
8284#endif
8285
fff69382 8286#if defined(TARGET_SPARC)
a0939b89 8287static int open_cpuinfo(CPUArchState *cpu_env, int fd)
fff69382
LV
8288{
8289 dprintf(fd, "type\t\t: sun4u\n");
8290 return 0;
8291}
8292#endif
8293
93a5661d 8294#if defined(TARGET_HPPA)
a0939b89 8295static int open_cpuinfo(CPUArchState *cpu_env, int fd)
93a5661d 8296{
e0174afe
HD
8297 int i, num_cpus;
8298
8299 num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8300 for (i = 0; i < num_cpus; i++) {
8301 dprintf(fd, "processor\t: %d\n", i);
8302 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8303 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8304 dprintf(fd, "capabilities\t: os32\n");
8305 dprintf(fd, "model\t\t: 9000/778/B160L - "
8306 "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
8307 }
93a5661d
HD
8308 return 0;
8309}
8310#endif
8311
4ab6713e 8312#if defined(TARGET_M68K)
a0939b89 8313static int open_hardware(CPUArchState *cpu_env, int fd)
4ab6713e
LV
8314{
8315 dprintf(fd, "Model:\t\tqemu-m68k\n");
8316 return 0;
8317}
8318#endif
8319
a0939b89 8320static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
3be14d05
AG
8321{
8322 struct fake_open {
8323 const char *filename;
a0939b89 8324 int (*fill)(CPUArchState *cpu_env, int fd);
de6b9933 8325 int (*cmp)(const char *s1, const char *s2);
3be14d05
AG
8326 };
8327 const struct fake_open *fake_open;
8328 static const struct fake_open fakes[] = {
de6b9933
LV
8329 { "maps", open_self_maps, is_proc_myself },
8330 { "stat", open_self_stat, is_proc_myself },
8331 { "auxv", open_self_auxv, is_proc_myself },
76b94245 8332 { "cmdline", open_self_cmdline, is_proc_myself },
ee3eb3a7 8333#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
de6b9933 8334 { "/proc/net/route", open_net_route, is_proc },
fff69382 8335#endif
93a5661d 8336#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
fff69382 8337 { "/proc/cpuinfo", open_cpuinfo, is_proc },
4ab6713e
LV
8338#endif
8339#if defined(TARGET_M68K)
8340 { "/proc/hardware", open_hardware, is_proc },
de6b9933
LV
8341#endif
8342 { NULL, NULL, NULL }
3be14d05
AG
8343 };
8344
aa07f5ec 8345 if (is_proc_myself(pathname, "exe")) {
00ed8a34 8346 return safe_openat(dirfd, exec_path, flags, mode);
aa07f5ec
MO
8347 }
8348
3be14d05 8349 for (fake_open = fakes; fake_open->filename; fake_open++) {
de6b9933 8350 if (fake_open->cmp(pathname, fake_open->filename)) {
3be14d05
AG
8351 break;
8352 }
8353 }
8354
8355 if (fake_open->filename) {
8356 const char *tmpdir;
8357 char filename[PATH_MAX];
8358 int fd, r;
8359
5b63de6b 8360 fd = memfd_create("qemu-open", 0);
3be14d05 8361 if (fd < 0) {
5b63de6b
RM
8362 if (errno != ENOSYS) {
8363 return fd;
8364 }
8365 /* create temporary file to map stat to */
8366 tmpdir = getenv("TMPDIR");
8367 if (!tmpdir)
8368 tmpdir = "/tmp";
8369 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8370 fd = mkstemp(filename);
8371 if (fd < 0) {
8372 return fd;
8373 }
8374 unlink(filename);
3be14d05 8375 }
3be14d05
AG
8376
8377 if ((r = fake_open->fill(cpu_env, fd))) {
a3ca7bb2 8378 int e = errno;
3be14d05 8379 close(fd);
a3ca7bb2 8380 errno = e;
3be14d05
AG
8381 return r;
8382 }
8383 lseek(fd, 0, SEEK_SET);
8384
8385 return fd;
8386 }
8387
c10a0738 8388 return safe_openat(dirfd, path(pathname), flags, mode);
3be14d05
AG
8389}
8390
55bbe4d5 8391static int do_execveat(CPUArchState *cpu_env, int dirfd,
156e1f67 8392 abi_long pathname, abi_long guest_argp,
55bbe4d5 8393 abi_long guest_envp, int flags)
156e1f67
DD
8394{
8395 int ret;
8396 char **argp, **envp;
8397 int argc, envc;
8398 abi_ulong gp;
8399 abi_ulong addr;
8400 char **q;
8401 void *p;
8402
8403 argc = 0;
8404
8405 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
8406 if (get_user_ual(addr, gp)) {
8407 return -TARGET_EFAULT;
8408 }
8409 if (!addr) {
8410 break;
8411 }
8412 argc++;
8413 }
8414 envc = 0;
8415 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
8416 if (get_user_ual(addr, gp)) {
8417 return -TARGET_EFAULT;
8418 }
8419 if (!addr) {
8420 break;
8421 }
8422 envc++;
8423 }
8424
8425 argp = g_new0(char *, argc + 1);
8426 envp = g_new0(char *, envc + 1);
8427
8428 for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
8429 if (get_user_ual(addr, gp)) {
8430 goto execve_efault;
8431 }
8432 if (!addr) {
8433 break;
8434 }
8435 *q = lock_user_string(addr);
8436 if (!*q) {
8437 goto execve_efault;
8438 }
8439 }
8440 *q = NULL;
8441
8442 for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
8443 if (get_user_ual(addr, gp)) {
8444 goto execve_efault;
8445 }
8446 if (!addr) {
8447 break;
8448 }
8449 *q = lock_user_string(addr);
8450 if (!*q) {
8451 goto execve_efault;
8452 }
8453 }
8454 *q = NULL;
8455
8456 /*
8457 * Although execve() is not an interruptible syscall it is
8458 * a special case where we must use the safe_syscall wrapper:
8459 * if we allow a signal to happen before we make the host
8460 * syscall then we will 'lose' it, because at the point of
8461 * execve the process leaves QEMU's control. So we use the
8462 * safe syscall wrapper to ensure that we either take the
8463 * signal as a guest signal, or else it does not happen
8464 * before the execve completes and makes it the other
8465 * program's problem.
8466 */
8467 p = lock_user_string(pathname);
8468 if (!p) {
8469 goto execve_efault;
8470 }
8471
8472 if (is_proc_myself(p, "exe")) {
55bbe4d5 8473 ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags));
156e1f67 8474 } else {
55bbe4d5 8475 ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
156e1f67
DD
8476 }
8477
8478 unlock_user(p, pathname, 0);
8479
8480 goto execve_end;
8481
8482execve_efault:
8483 ret = -TARGET_EFAULT;
8484
8485execve_end:
8486 for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
8487 if (get_user_ual(addr, gp) || !addr) {
8488 break;
8489 }
8490 unlock_user(*q, addr, 0);
8491 }
8492 for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
8493 if (get_user_ual(addr, gp) || !addr) {
8494 break;
8495 }
8496 unlock_user(*q, addr, 0);
8497 }
8498
8499 g_free(argp);
8500 g_free(envp);
8501 return ret;
8502}
8503
aecc8861
AG
8504#define TIMER_MAGIC 0x0caf0000
8505#define TIMER_MAGIC_MASK 0xffff0000
8506
8507/* Convert QEMU provided timer ID back to internal 16bit index format */
8508static target_timer_t get_timer_id(abi_long arg)
8509{
8510 target_timer_t timerid = arg;
8511
8512 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8513 return -TARGET_EINVAL;
8514 }
8515
8516 timerid &= 0xffff;
8517
8518 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8519 return -TARGET_EINVAL;
8520 }
8521
8522 return timerid;
8523}
8524
2e0a8713
ST
8525static int target_to_host_cpu_mask(unsigned long *host_mask,
8526 size_t host_size,
8527 abi_ulong target_addr,
8528 size_t target_size)
8529{
8530 unsigned target_bits = sizeof(abi_ulong) * 8;
8531 unsigned host_bits = sizeof(*host_mask) * 8;
8532 abi_ulong *target_mask;
8533 unsigned i, j;
8534
8535 assert(host_size >= target_size);
8536
8537 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8538 if (!target_mask) {
8539 return -TARGET_EFAULT;
8540 }
8541 memset(host_mask, 0, host_size);
8542
8543 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8544 unsigned bit = i * target_bits;
8545 abi_ulong val;
8546
8547 __get_user(val, &target_mask[i]);
8548 for (j = 0; j < target_bits; j++, bit++) {
8549 if (val & (1UL << j)) {
8550 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8551 }
8552 }
8553 }
8554
8555 unlock_user(target_mask, target_addr, 0);
8556 return 0;
8557}
8558
8559static int host_to_target_cpu_mask(const unsigned long *host_mask,
8560 size_t host_size,
8561 abi_ulong target_addr,
8562 size_t target_size)
8563{
8564 unsigned target_bits = sizeof(abi_ulong) * 8;
8565 unsigned host_bits = sizeof(*host_mask) * 8;
8566 abi_ulong *target_mask;
8567 unsigned i, j;
8568
8569 assert(host_size >= target_size);
8570
8571 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8572 if (!target_mask) {
8573 return -TARGET_EFAULT;
8574 }
8575
8576 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8577 unsigned bit = i * target_bits;
8578 abi_ulong val = 0;
8579
8580 for (j = 0; j < target_bits; j++, bit++) {
8581 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8582 val |= 1UL << j;
8583 }
8584 }
8585 __put_user(val, &target_mask[i]);
8586 }
8587
8588 unlock_user(target_mask, target_addr, target_size);
8589 return 0;
8590}
8591
fd08ddb9 8592#ifdef TARGET_NR_getdents
aee14c77 8593static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8594{
aee14c77
RH
8595 g_autofree void *hdirp = NULL;
8596 void *tdirp;
8597 int hlen, hoff, toff;
8598 int hreclen, treclen;
8599 off64_t prev_diroff = 0;
8600
8601 hdirp = g_try_malloc(count);
8602 if (!hdirp) {
8603 return -TARGET_ENOMEM;
8604 }
fd08ddb9
RH
8605
8606#ifdef EMULATE_GETDENTS_WITH_GETDENTS
aee14c77
RH
8607 hlen = sys_getdents(dirfd, hdirp, count);
8608#else
8609 hlen = sys_getdents64(dirfd, hdirp, count);
8610#endif
fd08ddb9 8611
aee14c77
RH
8612 hlen = get_errno(hlen);
8613 if (is_error(hlen)) {
8614 return hlen;
fd08ddb9
RH
8615 }
8616
aee14c77
RH
8617 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8618 if (!tdirp) {
fd08ddb9
RH
8619 return -TARGET_EFAULT;
8620 }
aee14c77
RH
8621
8622 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8623#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8624 struct linux_dirent *hde = hdirp + hoff;
fd08ddb9 8625#else
aee14c77
RH
8626 struct linux_dirent64 *hde = hdirp + hoff;
8627#endif
8628 struct target_dirent *tde = tdirp + toff;
8629 int namelen;
8630 uint8_t type;
fd08ddb9 8631
aee14c77
RH
8632 namelen = strlen(hde->d_name);
8633 hreclen = hde->d_reclen;
8634 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8635 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
fd08ddb9 8636
aee14c77 8637 if (toff + treclen > count) {
fd08ddb9 8638 /*
aee14c77
RH
8639 * If the host struct is smaller than the target struct, or
8640 * requires less alignment and thus packs into less space,
8641 * then the host can return more entries than we can pass
8642 * on to the guest.
fd08ddb9 8643 */
aee14c77
RH
8644 if (toff == 0) {
8645 toff = -TARGET_EINVAL; /* result buffer is too small */
8646 break;
8647 }
8648 /*
8649 * Return what we have, resetting the file pointer to the
8650 * location of the first record not returned.
8651 */
8652 lseek64(dirfd, prev_diroff, SEEK_SET);
8653 break;
fd08ddb9 8654 }
aee14c77
RH
8655
8656 prev_diroff = hde->d_off;
8657 tde->d_ino = tswapal(hde->d_ino);
8658 tde->d_off = tswapal(hde->d_off);
8659 tde->d_reclen = tswap16(treclen);
8660 memcpy(tde->d_name, hde->d_name, namelen + 1);
8661
8662 /*
8663 * The getdents type is in what was formerly a padding byte at the
8664 * end of the structure.
8665 */
8666#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8667 type = *((uint8_t *)hde + hreclen - 1);
8668#else
8669 type = hde->d_type;
fd08ddb9 8670#endif
aee14c77
RH
8671 *((uint8_t *)tde + treclen - 1) = type;
8672 }
8673
8674 unlock_user(tdirp, arg2, toff);
8675 return toff;
fd08ddb9
RH
8676}
8677#endif /* TARGET_NR_getdents */
8678
8679#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
aee14c77 8680static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8681{
aee14c77
RH
8682 g_autofree void *hdirp = NULL;
8683 void *tdirp;
8684 int hlen, hoff, toff;
8685 int hreclen, treclen;
8686 off64_t prev_diroff = 0;
8687
8688 hdirp = g_try_malloc(count);
8689 if (!hdirp) {
8690 return -TARGET_ENOMEM;
8691 }
fd08ddb9 8692
aee14c77
RH
8693 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8694 if (is_error(hlen)) {
8695 return hlen;
8696 }
8697
8698 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8699 if (!tdirp) {
fd08ddb9
RH
8700 return -TARGET_EFAULT;
8701 }
aee14c77
RH
8702
8703 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8704 struct linux_dirent64 *hde = hdirp + hoff;
8705 struct target_dirent64 *tde = tdirp + toff;
8706 int namelen;
8707
8708 namelen = strlen(hde->d_name) + 1;
8709 hreclen = hde->d_reclen;
8710 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8711 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8712
8713 if (toff + treclen > count) {
8714 /*
8715 * If the host struct is smaller than the target struct, or
8716 * requires less alignment and thus packs into less space,
8717 * then the host can return more entries than we can pass
8718 * on to the guest.
8719 */
8720 if (toff == 0) {
8721 toff = -TARGET_EINVAL; /* result buffer is too small */
fd08ddb9
RH
8722 break;
8723 }
aee14c77
RH
8724 /*
8725 * Return what we have, resetting the file pointer to the
8726 * location of the first record not returned.
8727 */
8728 lseek64(dirfd, prev_diroff, SEEK_SET);
8729 break;
fd08ddb9 8730 }
aee14c77
RH
8731
8732 prev_diroff = hde->d_off;
8733 tde->d_ino = tswap64(hde->d_ino);
8734 tde->d_off = tswap64(hde->d_off);
8735 tde->d_reclen = tswap16(treclen);
8736 tde->d_type = hde->d_type;
8737 memcpy(tde->d_name, hde->d_name, namelen);
fd08ddb9 8738 }
aee14c77
RH
8739
8740 unlock_user(tdirp, arg2, toff);
8741 return toff;
fd08ddb9
RH
8742}
8743#endif /* TARGET_NR_getdents64 */
8744
e10fbe8f
YT
8745#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8746_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8747#endif
8748
dc1ce18b
RH
8749/* This is an internal helper for do_syscall so that it is easier
8750 * to have a single return point, so that actions, such as logging
8751 * of syscall results, can be performed.
8752 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8753 */
a0939b89 8754static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
dc1ce18b
RH
8755 abi_long arg2, abi_long arg3, abi_long arg4,
8756 abi_long arg5, abi_long arg6, abi_long arg7,
8757 abi_long arg8)
31e31b8a 8758{
29a0af61 8759 CPUState *cpu = env_cpu(cpu_env);
992f48a0 8760 abi_long ret;
4f7f8924
AR
8761#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8762 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
efa92184
AR
8763 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8764 || defined(TARGET_NR_statx)
31e31b8a 8765 struct stat st;
4f7f8924
AR
8766#endif
8767#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8768 || defined(TARGET_NR_fstatfs)
56c8f68f 8769 struct statfs stfs;
4f7f8924 8770#endif
53a5960a 8771 void *p;
3b46e624 8772
31e31b8a
FB
8773 switch(num) {
8774 case TARGET_NR_exit:
9b056fcc 8775 /* In old applications this may be used to implement _exit(2).
6f9ff551 8776 However in threaded applications it is used for thread termination,
9b056fcc
AF
8777 and _exit_group is used for application termination.
8778 Do thread termination if we have more then one thread. */
a0995886
TB
8779
8780 if (block_signals()) {
af254a27 8781 return -QEMU_ERESTARTSYS;
a0995886
TB
8782 }
8783
1f81ce90 8784 pthread_mutex_lock(&clone_lock);
dd1f6349 8785
bdc44640 8786 if (CPU_NEXT(first_cpu)) {
1f81ce90 8787 TaskState *ts = cpu->opaque;
9b056fcc 8788
6490d9aa
RH
8789 if (ts->child_tidptr) {
8790 put_user_u32(0, ts->child_tidptr);
8791 do_sys_futex(g2h(cpu, ts->child_tidptr),
8792 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
8793 }
8794
8795 object_unparent(OBJECT(cpu));
1f81ce90
AB
8796 object_unref(OBJECT(cpu));
8797 /*
8798 * At this point the CPU should be unrealized and removed
8799 * from cpu lists. We can clean-up the rest of the thread
8800 * data without the lock held.
8801 */
dd1f6349 8802
1f81ce90 8803 pthread_mutex_unlock(&clone_lock);
dd1f6349 8804
a2247f8e 8805 thread_cpu = NULL;
9b056fcc 8806 g_free(ts);
70903763 8807 rcu_unregister_thread();
9b056fcc
AF
8808 pthread_exit(NULL);
8809 }
dd1f6349 8810
1f81ce90 8811 pthread_mutex_unlock(&clone_lock);
708b6a64 8812 preexit_cleanup(cpu_env, arg1);
c2764719 8813 _exit(arg1);
72eb7ea8 8814 return 0; /* avoid warning */
31e31b8a 8815 case TARGET_NR_read:
ba584f1d
AS
8816 if (arg2 == 0 && arg3 == 0) {
8817 return get_errno(safe_read(arg1, 0, 0));
72eb7ea8 8818 } else {
38d840e6 8819 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
2852aafd 8820 return -TARGET_EFAULT;
50afd02b 8821 ret = get_errno(safe_read(arg1, p, arg3));
e36800c9 8822 if (ret >= 0 &&
5d4d3665
LV
8823 fd_trans_host_to_target_data(arg1)) {
8824 ret = fd_trans_host_to_target_data(arg1)(p, ret);
e36800c9 8825 }
38d840e6
AJ
8826 unlock_user(p, arg2, ret);
8827 }
72eb7ea8 8828 return ret;
31e31b8a 8829 case TARGET_NR_write:
58cfa6c2
TGJ
8830 if (arg2 == 0 && arg3 == 0) {
8831 return get_errno(safe_write(arg1, 0, 0));
8832 }
579a97f7 8833 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
2852aafd 8834 return -TARGET_EFAULT;
04b9bcf9
LV
8835 if (fd_trans_target_to_host_data(arg1)) {
8836 void *copy = g_malloc(arg3);
8837 memcpy(copy, p, arg3);
8838 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8839 if (ret >= 0) {
8840 ret = get_errno(safe_write(arg1, copy, ret));
8841 }
8842 g_free(copy);
8843 } else {
8844 ret = get_errno(safe_write(arg1, p, arg3));
8845 }
53a5960a 8846 unlock_user(p, arg2, 0);
72eb7ea8
RH
8847 return ret;
8848
704eff6c 8849#ifdef TARGET_NR_open
31e31b8a 8850 case TARGET_NR_open:
2f619698 8851 if (!(p = lock_user_string(arg1)))
2852aafd 8852 return -TARGET_EFAULT;
0b2effd7
RV
8853 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8854 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8855 arg3));
e36800c9 8856 fd_trans_unregister(ret);
53a5960a 8857 unlock_user(p, arg1, 0);
72eb7ea8 8858 return ret;
704eff6c 8859#endif
82424832 8860 case TARGET_NR_openat:
579a97f7 8861 if (!(p = lock_user_string(arg2)))
2852aafd 8862 return -TARGET_EFAULT;
0b2effd7
RV
8863 ret = get_errno(do_openat(cpu_env, arg1, p,
8864 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8865 arg4));
e36800c9 8866 fd_trans_unregister(ret);
579a97f7 8867 unlock_user(p, arg2, 0);
72eb7ea8 8868 return ret;
0f0426f3
LV
8869#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8870 case TARGET_NR_name_to_handle_at:
8871 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
72eb7ea8 8872 return ret;
0f0426f3
LV
8873#endif
8874#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8875 case TARGET_NR_open_by_handle_at:
8876 ret = do_open_by_handle_at(arg1, arg2, arg3);
e36800c9 8877 fd_trans_unregister(ret);
72eb7ea8 8878 return ret;
cc054c6f
HD
8879#endif
8880#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
8881 case TARGET_NR_pidfd_open:
8882 return get_errno(pidfd_open(arg1, arg2));
8883#endif
8884#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
8885 case TARGET_NR_pidfd_send_signal:
8886 {
46187d70 8887 siginfo_t uinfo, *puinfo;
cc054c6f 8888
46187d70
LV
8889 if (arg3) {
8890 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8891 if (!p) {
8892 return -TARGET_EFAULT;
8893 }
8894 target_to_host_siginfo(&uinfo, p);
8895 unlock_user(p, arg3, 0);
8896 puinfo = &uinfo;
8897 } else {
8898 puinfo = NULL;
cc054c6f 8899 }
cc054c6f 8900 ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
46187d70 8901 puinfo, arg4));
cc054c6f
HD
8902 }
8903 return ret;
8904#endif
8905#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
8906 case TARGET_NR_pidfd_getfd:
8907 return get_errno(pidfd_getfd(arg1, arg2, arg3));
0f0426f3 8908#endif
31e31b8a 8909 case TARGET_NR_close:
e36800c9 8910 fd_trans_unregister(arg1);
72eb7ea8 8911 return get_errno(close(arg1));
af804f39
HD
8912#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
8913 case TARGET_NR_close_range:
8914 ret = get_errno(sys_close_range(arg1, arg2, arg3));
8915 if (ret == 0 && !(arg3 & CLOSE_RANGE_CLOEXEC)) {
8916 abi_long fd, maxfd;
8917 maxfd = MIN(arg2, target_fd_max);
8918 for (fd = arg1; fd < maxfd; fd++) {
8919 fd_trans_unregister(fd);
8920 }
8921 }
8922 return ret;
8923#endif
72eb7ea8 8924
31e31b8a 8925 case TARGET_NR_brk:
72eb7ea8 8926 return do_brk(arg1);
704eff6c 8927#ifdef TARGET_NR_fork
31e31b8a 8928 case TARGET_NR_fork:
72eb7ea8 8929 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
704eff6c 8930#endif
e5febef5 8931#ifdef TARGET_NR_waitpid
31e31b8a
FB
8932 case TARGET_NR_waitpid:
8933 {
53a5960a 8934 int status;
4af80a37 8935 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
5379557b 8936 if (!is_error(ret) && arg2 && ret
1d9d8b55 8937 && put_user_s32(host_to_target_waitstatus(status), arg2))
2852aafd 8938 return -TARGET_EFAULT;
31e31b8a 8939 }
72eb7ea8 8940 return ret;
e5febef5 8941#endif
f0cbb613
PB
8942#ifdef TARGET_NR_waitid
8943 case TARGET_NR_waitid:
8944 {
8945 siginfo_t info;
8946 info.si_pid = 0;
4af80a37 8947 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
f0cbb613 8948 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 8949 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
2852aafd 8950 return -TARGET_EFAULT;
f0cbb613 8951 host_to_target_siginfo(p, &info);
c227f099 8952 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
8953 }
8954 }
72eb7ea8 8955 return ret;
f0cbb613 8956#endif
7a3148a9 8957#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 8958 case TARGET_NR_creat:
579a97f7 8959 if (!(p = lock_user_string(arg1)))
2852aafd 8960 return -TARGET_EFAULT;
53a5960a 8961 ret = get_errno(creat(p, arg2));
e36800c9 8962 fd_trans_unregister(ret);
53a5960a 8963 unlock_user(p, arg1, 0);
72eb7ea8 8964 return ret;
7a3148a9 8965#endif
704eff6c 8966#ifdef TARGET_NR_link
31e31b8a 8967 case TARGET_NR_link:
53a5960a
PB
8968 {
8969 void * p2;
8970 p = lock_user_string(arg1);
8971 p2 = lock_user_string(arg2);
579a97f7
FB
8972 if (!p || !p2)
8973 ret = -TARGET_EFAULT;
8974 else
8975 ret = get_errno(link(p, p2));
53a5960a
PB
8976 unlock_user(p2, arg2, 0);
8977 unlock_user(p, arg1, 0);
8978 }
72eb7ea8 8979 return ret;
704eff6c 8980#endif
c0d472b1 8981#if defined(TARGET_NR_linkat)
64f0ce4c 8982 case TARGET_NR_linkat:
64f0ce4c
TS
8983 {
8984 void * p2 = NULL;
579a97f7 8985 if (!arg2 || !arg4)
2852aafd 8986 return -TARGET_EFAULT;
64f0ce4c
TS
8987 p = lock_user_string(arg2);
8988 p2 = lock_user_string(arg4);
579a97f7 8989 if (!p || !p2)
0da46a6e 8990 ret = -TARGET_EFAULT;
64f0ce4c 8991 else
c0d472b1 8992 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
8993 unlock_user(p, arg2, 0);
8994 unlock_user(p2, arg4, 0);
64f0ce4c 8995 }
72eb7ea8 8996 return ret;
64f0ce4c 8997#endif
704eff6c 8998#ifdef TARGET_NR_unlink
31e31b8a 8999 case TARGET_NR_unlink:
579a97f7 9000 if (!(p = lock_user_string(arg1)))
2852aafd 9001 return -TARGET_EFAULT;
53a5960a
PB
9002 ret = get_errno(unlink(p));
9003 unlock_user(p, arg1, 0);
72eb7ea8 9004 return ret;
704eff6c 9005#endif
c0d472b1 9006#if defined(TARGET_NR_unlinkat)
8170f56b 9007 case TARGET_NR_unlinkat:
579a97f7 9008 if (!(p = lock_user_string(arg2)))
2852aafd 9009 return -TARGET_EFAULT;
c0d472b1 9010 ret = get_errno(unlinkat(arg1, p, arg3));
579a97f7 9011 unlock_user(p, arg2, 0);
72eb7ea8 9012 return ret;
b7d35e65 9013#endif
55bbe4d5
DD
9014 case TARGET_NR_execveat:
9015 return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5);
31e31b8a 9016 case TARGET_NR_execve:
55bbe4d5 9017 return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
31e31b8a 9018 case TARGET_NR_chdir:
579a97f7 9019 if (!(p = lock_user_string(arg1)))
2852aafd 9020 return -TARGET_EFAULT;
53a5960a
PB
9021 ret = get_errno(chdir(p));
9022 unlock_user(p, arg1, 0);
72eb7ea8 9023 return ret;
a315a145 9024#ifdef TARGET_NR_time
31e31b8a
FB
9025 case TARGET_NR_time:
9026 {
53a5960a
PB
9027 time_t host_time;
9028 ret = get_errno(time(&host_time));
2f619698
FB
9029 if (!is_error(ret)
9030 && arg1
9031 && put_user_sal(host_time, arg1))
2852aafd 9032 return -TARGET_EFAULT;
31e31b8a 9033 }
72eb7ea8 9034 return ret;
a315a145 9035#endif
704eff6c 9036#ifdef TARGET_NR_mknod
31e31b8a 9037 case TARGET_NR_mknod:
579a97f7 9038 if (!(p = lock_user_string(arg1)))
2852aafd 9039 return -TARGET_EFAULT;
53a5960a
PB
9040 ret = get_errno(mknod(p, arg2, arg3));
9041 unlock_user(p, arg1, 0);
72eb7ea8 9042 return ret;
704eff6c 9043#endif
c0d472b1 9044#if defined(TARGET_NR_mknodat)
75ac37a0 9045 case TARGET_NR_mknodat:
579a97f7 9046 if (!(p = lock_user_string(arg2)))
2852aafd 9047 return -TARGET_EFAULT;
c0d472b1 9048 ret = get_errno(mknodat(arg1, p, arg3, arg4));
579a97f7 9049 unlock_user(p, arg2, 0);
72eb7ea8 9050 return ret;
75ac37a0 9051#endif
704eff6c 9052#ifdef TARGET_NR_chmod
31e31b8a 9053 case TARGET_NR_chmod:
579a97f7 9054 if (!(p = lock_user_string(arg1)))
2852aafd 9055 return -TARGET_EFAULT;
53a5960a
PB
9056 ret = get_errno(chmod(p, arg2));
9057 unlock_user(p, arg1, 0);
72eb7ea8 9058 return ret;
704eff6c 9059#endif
4f7f8924 9060#ifdef TARGET_NR_lseek
31e31b8a 9061 case TARGET_NR_lseek:
72eb7ea8 9062 return get_errno(lseek(arg1, arg2, arg3));
4f7f8924 9063#endif
9231733a
RH
9064#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
9065 /* Alpha specific */
7a3148a9 9066 case TARGET_NR_getxpid:
0effdc29 9067 cpu_env->ir[IR_A4] = getppid();
72eb7ea8 9068 return get_errno(getpid());
7a3148a9 9069#endif
9231733a
RH
9070#ifdef TARGET_NR_getpid
9071 case TARGET_NR_getpid:
72eb7ea8 9072 return get_errno(getpid());
9231733a 9073#endif
31e31b8a 9074 case TARGET_NR_mount:
356d771b
PB
9075 {
9076 /* need to look at the data field */
9077 void *p2, *p3;
9078
9079 if (arg1) {
9080 p = lock_user_string(arg1);
9081 if (!p) {
2852aafd 9082 return -TARGET_EFAULT;
356d771b
PB
9083 }
9084 } else {
9085 p = NULL;
9086 }
9087
9088 p2 = lock_user_string(arg2);
9089 if (!p2) {
9090 if (arg1) {
9091 unlock_user(p, arg1, 0);
9092 }
2852aafd 9093 return -TARGET_EFAULT;
356d771b
PB
9094 }
9095
9096 if (arg3) {
9097 p3 = lock_user_string(arg3);
9098 if (!p3) {
9099 if (arg1) {
579a97f7 9100 unlock_user(p, arg1, 0);
356d771b
PB
9101 }
9102 unlock_user(p2, arg2, 0);
2852aafd 9103 return -TARGET_EFAULT;
356d771b
PB
9104 }
9105 } else {
9106 p3 = NULL;
9107 }
9108
9109 /* FIXME - arg5 should be locked, but it isn't clear how to
9110 * do that since it's not guaranteed to be a NULL-terminated
9111 * string.
9112 */
9113 if (!arg5) {
9114 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
9115 } else {
3e8f1628 9116 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
356d771b
PB
9117 }
9118 ret = get_errno(ret);
9119
9120 if (arg1) {
9121 unlock_user(p, arg1, 0);
9122 }
9123 unlock_user(p2, arg2, 0);
9124 if (arg3) {
9125 unlock_user(p3, arg3, 0);
9126 }
9127 }
72eb7ea8 9128 return ret;
6eb9dbf6
LV
9129#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
9130#if defined(TARGET_NR_umount)
31e31b8a 9131 case TARGET_NR_umount:
6eb9dbf6
LV
9132#endif
9133#if defined(TARGET_NR_oldumount)
9134 case TARGET_NR_oldumount:
9135#endif
579a97f7 9136 if (!(p = lock_user_string(arg1)))
2852aafd 9137 return -TARGET_EFAULT;
53a5960a
PB
9138 ret = get_errno(umount(p));
9139 unlock_user(p, arg1, 0);
72eb7ea8 9140 return ret;
e5febef5 9141#endif
7a3148a9 9142#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
9143 case TARGET_NR_stime:
9144 {
0f1f2d45
LV
9145 struct timespec ts;
9146 ts.tv_nsec = 0;
9147 if (get_user_sal(ts.tv_sec, arg1)) {
2852aafd 9148 return -TARGET_EFAULT;
0f1f2d45
LV
9149 }
9150 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
31e31b8a 9151 }
7a3148a9 9152#endif
7a3148a9 9153#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a 9154 case TARGET_NR_alarm:
72eb7ea8 9155 return alarm(arg1);
7a3148a9 9156#endif
7a3148a9 9157#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a 9158 case TARGET_NR_pause:
f59ec606
TB
9159 if (!block_signals()) {
9160 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9161 }
72eb7ea8 9162 return -TARGET_EINTR;
7a3148a9 9163#endif
e5febef5 9164#ifdef TARGET_NR_utime
31e31b8a 9165 case TARGET_NR_utime:
ebc05488 9166 {
53a5960a
PB
9167 struct utimbuf tbuf, *host_tbuf;
9168 struct target_utimbuf *target_tbuf;
9169 if (arg2) {
579a97f7 9170 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
2852aafd 9171 return -TARGET_EFAULT;
cbb21eed
MB
9172 tbuf.actime = tswapal(target_tbuf->actime);
9173 tbuf.modtime = tswapal(target_tbuf->modtime);
53a5960a
PB
9174 unlock_user_struct(target_tbuf, arg2, 0);
9175 host_tbuf = &tbuf;
f72e8ff4 9176 } else {
53a5960a 9177 host_tbuf = NULL;
f72e8ff4 9178 }
579a97f7 9179 if (!(p = lock_user_string(arg1)))
2852aafd 9180 return -TARGET_EFAULT;
53a5960a
PB
9181 ret = get_errno(utime(p, host_tbuf));
9182 unlock_user(p, arg1, 0);
ebc05488 9183 }
72eb7ea8 9184 return ret;
e5febef5 9185#endif
704eff6c 9186#ifdef TARGET_NR_utimes
978a66ff
FB
9187 case TARGET_NR_utimes:
9188 {
978a66ff 9189 struct timeval *tvp, tv[2];
53a5960a 9190 if (arg2) {
788f5ec4
TS
9191 if (copy_from_user_timeval(&tv[0], arg2)
9192 || copy_from_user_timeval(&tv[1],
9193 arg2 + sizeof(struct target_timeval)))
2852aafd 9194 return -TARGET_EFAULT;
978a66ff
FB
9195 tvp = tv;
9196 } else {
9197 tvp = NULL;
9198 }
579a97f7 9199 if (!(p = lock_user_string(arg1)))
2852aafd 9200 return -TARGET_EFAULT;
53a5960a
PB
9201 ret = get_errno(utimes(p, tvp));
9202 unlock_user(p, arg1, 0);
978a66ff 9203 }
72eb7ea8 9204 return ret;
704eff6c 9205#endif
c0d472b1 9206#if defined(TARGET_NR_futimesat)
ac8a6556
AZ
9207 case TARGET_NR_futimesat:
9208 {
9209 struct timeval *tvp, tv[2];
9210 if (arg3) {
9211 if (copy_from_user_timeval(&tv[0], arg3)
9212 || copy_from_user_timeval(&tv[1],
9213 arg3 + sizeof(struct target_timeval)))
2852aafd 9214 return -TARGET_EFAULT;
ac8a6556
AZ
9215 tvp = tv;
9216 } else {
9217 tvp = NULL;
9218 }
2852aafd
RH
9219 if (!(p = lock_user_string(arg2))) {
9220 return -TARGET_EFAULT;
9221 }
c0d472b1 9222 ret = get_errno(futimesat(arg1, path(p), tvp));
ac8a6556
AZ
9223 unlock_user(p, arg2, 0);
9224 }
72eb7ea8 9225 return ret;
ac8a6556 9226#endif
704eff6c 9227#ifdef TARGET_NR_access
31e31b8a 9228 case TARGET_NR_access:
2852aafd
RH
9229 if (!(p = lock_user_string(arg1))) {
9230 return -TARGET_EFAULT;
9231 }
719f908e 9232 ret = get_errno(access(path(p), arg2));
53a5960a 9233 unlock_user(p, arg1, 0);
72eb7ea8 9234 return ret;
704eff6c 9235#endif
92a34c10
TS
9236#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9237 case TARGET_NR_faccessat:
2852aafd
RH
9238 if (!(p = lock_user_string(arg2))) {
9239 return -TARGET_EFAULT;
9240 }
c0d472b1 9241 ret = get_errno(faccessat(arg1, p, arg3, 0));
579a97f7 9242 unlock_user(p, arg2, 0);
72eb7ea8 9243 return ret;
92a34c10 9244#endif
35a2c85f
WX
9245#if defined(TARGET_NR_faccessat2)
9246 case TARGET_NR_faccessat2:
9247 if (!(p = lock_user_string(arg2))) {
9248 return -TARGET_EFAULT;
9249 }
9250 ret = get_errno(faccessat(arg1, p, arg3, arg4));
9251 unlock_user(p, arg2, 0);
9252 return ret;
9253#endif
7a3148a9 9254#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a 9255 case TARGET_NR_nice:
72eb7ea8 9256 return get_errno(nice(arg1));
ebc05488 9257#endif
31e31b8a 9258 case TARGET_NR_sync:
04369ff2 9259 sync();
72eb7ea8 9260 return 0;
5a03cd00
AM
9261#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9262 case TARGET_NR_syncfs:
72eb7ea8 9263 return get_errno(syncfs(arg1));
5a03cd00 9264#endif
31e31b8a 9265 case TARGET_NR_kill:
72eb7ea8 9266 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
704eff6c 9267#ifdef TARGET_NR_rename
31e31b8a 9268 case TARGET_NR_rename:
53a5960a
PB
9269 {
9270 void *p2;
9271 p = lock_user_string(arg1);
9272 p2 = lock_user_string(arg2);
579a97f7
FB
9273 if (!p || !p2)
9274 ret = -TARGET_EFAULT;
9275 else
9276 ret = get_errno(rename(p, p2));
53a5960a
PB
9277 unlock_user(p2, arg2, 0);
9278 unlock_user(p, arg1, 0);
9279 }
72eb7ea8 9280 return ret;
704eff6c 9281#endif
c0d472b1 9282#if defined(TARGET_NR_renameat)
722183f6 9283 case TARGET_NR_renameat:
722183f6 9284 {
579a97f7 9285 void *p2;
722183f6
TS
9286 p = lock_user_string(arg2);
9287 p2 = lock_user_string(arg4);
579a97f7 9288 if (!p || !p2)
0da46a6e 9289 ret = -TARGET_EFAULT;
722183f6 9290 else
c0d472b1 9291 ret = get_errno(renameat(arg1, p, arg3, p2));
579a97f7
FB
9292 unlock_user(p2, arg4, 0);
9293 unlock_user(p, arg2, 0);
722183f6 9294 }
72eb7ea8 9295 return ret;
95d0307c
AS
9296#endif
9297#if defined(TARGET_NR_renameat2)
9298 case TARGET_NR_renameat2:
9299 {
9300 void *p2;
9301 p = lock_user_string(arg2);
9302 p2 = lock_user_string(arg4);
9303 if (!p || !p2) {
9304 ret = -TARGET_EFAULT;
9305 } else {
9306 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9307 }
9308 unlock_user(p2, arg4, 0);
9309 unlock_user(p, arg2, 0);
9310 }
72eb7ea8 9311 return ret;
722183f6 9312#endif
704eff6c 9313#ifdef TARGET_NR_mkdir
31e31b8a 9314 case TARGET_NR_mkdir:
579a97f7 9315 if (!(p = lock_user_string(arg1)))
2852aafd 9316 return -TARGET_EFAULT;
53a5960a
PB
9317 ret = get_errno(mkdir(p, arg2));
9318 unlock_user(p, arg1, 0);
72eb7ea8 9319 return ret;
704eff6c 9320#endif
c0d472b1 9321#if defined(TARGET_NR_mkdirat)
4472ad0d 9322 case TARGET_NR_mkdirat:
579a97f7 9323 if (!(p = lock_user_string(arg2)))
2852aafd 9324 return -TARGET_EFAULT;
c0d472b1 9325 ret = get_errno(mkdirat(arg1, p, arg3));
579a97f7 9326 unlock_user(p, arg2, 0);
72eb7ea8 9327 return ret;
4472ad0d 9328#endif
704eff6c 9329#ifdef TARGET_NR_rmdir
31e31b8a 9330 case TARGET_NR_rmdir:
579a97f7 9331 if (!(p = lock_user_string(arg1)))
2852aafd 9332 return -TARGET_EFAULT;
53a5960a
PB
9333 ret = get_errno(rmdir(p));
9334 unlock_user(p, arg1, 0);
72eb7ea8 9335 return ret;
704eff6c 9336#endif
31e31b8a
FB
9337 case TARGET_NR_dup:
9338 ret = get_errno(dup(arg1));
e36800c9
LV
9339 if (ret >= 0) {
9340 fd_trans_dup(arg1, ret);
9341 }
72eb7ea8 9342 return ret;
704eff6c 9343#ifdef TARGET_NR_pipe
31e31b8a 9344 case TARGET_NR_pipe:
72eb7ea8 9345 return do_pipe(cpu_env, arg1, 0, 0);
704eff6c 9346#endif
099d6b0f
RV
9347#ifdef TARGET_NR_pipe2
9348 case TARGET_NR_pipe2:
72eb7ea8
RH
9349 return do_pipe(cpu_env, arg1,
9350 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
099d6b0f 9351#endif
31e31b8a 9352 case TARGET_NR_times:
32f36bce 9353 {
53a5960a 9354 struct target_tms *tmsp;
32f36bce
FB
9355 struct tms tms;
9356 ret = get_errno(times(&tms));
53a5960a 9357 if (arg1) {
579a97f7
FB
9358 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9359 if (!tmsp)
2852aafd 9360 return -TARGET_EFAULT;
cbb21eed
MB
9361 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9362 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9363 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9364 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
32f36bce 9365 }
c596ed17
FB
9366 if (!is_error(ret))
9367 ret = host_to_target_clock_t(ret);
32f36bce 9368 }
72eb7ea8 9369 return ret;
31e31b8a 9370 case TARGET_NR_acct:
38d840e6
AJ
9371 if (arg1 == 0) {
9372 ret = get_errno(acct(NULL));
9373 } else {
2852aafd
RH
9374 if (!(p = lock_user_string(arg1))) {
9375 return -TARGET_EFAULT;
9376 }
38d840e6
AJ
9377 ret = get_errno(acct(path(p)));
9378 unlock_user(p, arg1, 0);
9379 }
72eb7ea8 9380 return ret;
8070e7be 9381#ifdef TARGET_NR_umount2
31e31b8a 9382 case TARGET_NR_umount2:
579a97f7 9383 if (!(p = lock_user_string(arg1)))
2852aafd 9384 return -TARGET_EFAULT;
53a5960a
PB
9385 ret = get_errno(umount2(p, arg2));
9386 unlock_user(p, arg1, 0);
72eb7ea8 9387 return ret;
ebc05488 9388#endif
31e31b8a 9389 case TARGET_NR_ioctl:
72eb7ea8 9390 return do_ioctl(arg1, arg2, arg3);
47ae93cd 9391#ifdef TARGET_NR_fcntl
31e31b8a 9392 case TARGET_NR_fcntl:
72eb7ea8 9393 return do_fcntl(arg1, arg2, arg3);
ebc05488 9394#endif
31e31b8a 9395 case TARGET_NR_setpgid:
72eb7ea8 9396 return get_errno(setpgid(arg1, arg2));
31e31b8a 9397 case TARGET_NR_umask:
72eb7ea8 9398 return get_errno(umask(arg1));
31e31b8a 9399 case TARGET_NR_chroot:
579a97f7 9400 if (!(p = lock_user_string(arg1)))
2852aafd 9401 return -TARGET_EFAULT;
53a5960a
PB
9402 ret = get_errno(chroot(p));
9403 unlock_user(p, arg1, 0);
72eb7ea8 9404 return ret;
704eff6c 9405#ifdef TARGET_NR_dup2
31e31b8a
FB
9406 case TARGET_NR_dup2:
9407 ret = get_errno(dup2(arg1, arg2));
e36800c9
LV
9408 if (ret >= 0) {
9409 fd_trans_dup(arg1, arg2);
9410 }
72eb7ea8 9411 return ret;
704eff6c 9412#endif
d0927938
UH
9413#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9414 case TARGET_NR_dup3:
10fa993a
PM
9415 {
9416 int host_flags;
9417
9418 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9419 return -EINVAL;
9420 }
9421 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9422 ret = get_errno(dup3(arg1, arg2, host_flags));
e36800c9
LV
9423 if (ret >= 0) {
9424 fd_trans_dup(arg1, arg2);
9425 }
72eb7ea8 9426 return ret;
10fa993a 9427 }
d0927938 9428#endif
7a3148a9 9429#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a 9430 case TARGET_NR_getppid:
72eb7ea8 9431 return get_errno(getppid());
7a3148a9 9432#endif
704eff6c 9433#ifdef TARGET_NR_getpgrp
31e31b8a 9434 case TARGET_NR_getpgrp:
72eb7ea8 9435 return get_errno(getpgrp());
704eff6c 9436#endif
31e31b8a 9437 case TARGET_NR_setsid:
72eb7ea8 9438 return get_errno(setsid());
e5febef5 9439#ifdef TARGET_NR_sigaction
31e31b8a 9440 case TARGET_NR_sigaction:
31e31b8a 9441 {
02d0de10 9442#if defined(TARGET_MIPS)
106ec879
FB
9443 struct target_sigaction act, oact, *pact, *old_act;
9444
9445 if (arg2) {
579a97f7 9446 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9447 return -TARGET_EFAULT;
106ec879
FB
9448 act._sa_handler = old_act->_sa_handler;
9449 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9450 act.sa_flags = old_act->sa_flags;
9451 unlock_user_struct(old_act, arg2, 0);
9452 pact = &act;
9453 } else {
9454 pact = NULL;
9455 }
9456
02fb28e8 9457 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
106ec879
FB
9458
9459 if (!is_error(ret) && arg3) {
579a97f7 9460 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9461 return -TARGET_EFAULT;
106ec879
FB
9462 old_act->_sa_handler = oact._sa_handler;
9463 old_act->sa_flags = oact.sa_flags;
9464 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9465 old_act->sa_mask.sig[1] = 0;
9466 old_act->sa_mask.sig[2] = 0;
9467 old_act->sa_mask.sig[3] = 0;
9468 unlock_user_struct(old_act, arg3, 1);
9469 }
6049f4f8
RH
9470#else
9471 struct target_old_sigaction *old_act;
9472 struct target_sigaction act, oact, *pact;
9473 if (arg2) {
9474 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9475 return -TARGET_EFAULT;
6049f4f8
RH
9476 act._sa_handler = old_act->_sa_handler;
9477 target_siginitset(&act.sa_mask, old_act->sa_mask);
9478 act.sa_flags = old_act->sa_flags;
ca192277 9479#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9480 act.sa_restorer = old_act->sa_restorer;
ca192277 9481#endif
6049f4f8
RH
9482 unlock_user_struct(old_act, arg2, 0);
9483 pact = &act;
9484 } else {
9485 pact = NULL;
9486 }
02fb28e8 9487 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
6049f4f8
RH
9488 if (!is_error(ret) && arg3) {
9489 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9490 return -TARGET_EFAULT;
6049f4f8
RH
9491 old_act->_sa_handler = oact._sa_handler;
9492 old_act->sa_mask = oact.sa_mask.sig[0];
9493 old_act->sa_flags = oact.sa_flags;
ca192277 9494#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9495 old_act->sa_restorer = oact.sa_restorer;
ca192277 9496#endif
6049f4f8
RH
9497 unlock_user_struct(old_act, arg3, 1);
9498 }
388bb21a 9499#endif
31e31b8a 9500 }
72eb7ea8 9501 return ret;
e5febef5 9502#endif
66fb9763 9503 case TARGET_NR_rt_sigaction:
53a5960a 9504 {
0f6f9903
RH
9505 /*
9506 * For Alpha and SPARC this is a 5 argument syscall, with
78bfef72
PM
9507 * a 'restorer' parameter which must be copied into the
9508 * sa_restorer field of the sigaction struct.
9509 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9510 * and arg5 is the sigsetsize.
78bfef72 9511 */
0f6f9903
RH
9512#if defined(TARGET_ALPHA)
9513 target_ulong sigsetsize = arg4;
9514 target_ulong restorer = arg5;
9515#elif defined(TARGET_SPARC)
78bfef72
PM
9516 target_ulong restorer = arg4;
9517 target_ulong sigsetsize = arg5;
9518#else
9519 target_ulong sigsetsize = arg4;
02fb28e8 9520 target_ulong restorer = 0;
78bfef72 9521#endif
fb80439b
RH
9522 struct target_sigaction *act = NULL;
9523 struct target_sigaction *oact = NULL;
53a5960a 9524
78bfef72 9525 if (sigsetsize != sizeof(target_sigset_t)) {
72eb7ea8 9526 return -TARGET_EINVAL;
c815701e 9527 }
fb80439b
RH
9528 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9529 return -TARGET_EFAULT;
78bfef72 9530 }
fb80439b
RH
9531 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9532 ret = -TARGET_EFAULT;
9533 } else {
9534 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9535 if (oact) {
9536 unlock_user_struct(oact, arg3, 1);
579a97f7 9537 }
fb80439b
RH
9538 }
9539 if (act) {
53a5960a 9540 unlock_user_struct(act, arg2, 0);
fb80439b 9541 }
53a5960a 9542 }
72eb7ea8 9543 return ret;
7a3148a9 9544#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 9545 case TARGET_NR_sgetmask:
66fb9763
FB
9546 {
9547 sigset_t cur_set;
992f48a0 9548 abi_ulong target_set;
3d3efba0
PM
9549 ret = do_sigprocmask(0, NULL, &cur_set);
9550 if (!ret) {
9551 host_to_target_old_sigset(&target_set, &cur_set);
9552 ret = target_set;
9553 }
66fb9763 9554 }
72eb7ea8 9555 return ret;
7a3148a9
JM
9556#endif
9557#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 9558 case TARGET_NR_ssetmask:
66fb9763 9559 {
a8617d8c 9560 sigset_t set, oset;
992f48a0 9561 abi_ulong target_set = arg1;
66fb9763 9562 target_to_host_old_sigset(&set, &target_set);
3d3efba0
PM
9563 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9564 if (!ret) {
9565 host_to_target_old_sigset(&target_set, &oset);
9566 ret = target_set;
9567 }
66fb9763 9568 }
72eb7ea8 9569 return ret;
7a3148a9 9570#endif
e5febef5 9571#ifdef TARGET_NR_sigprocmask
66fb9763
FB
9572 case TARGET_NR_sigprocmask:
9573 {
a5b3b13b
RH
9574#if defined(TARGET_ALPHA)
9575 sigset_t set, oldset;
9576 abi_ulong mask;
9577 int how;
9578
9579 switch (arg1) {
9580 case TARGET_SIG_BLOCK:
9581 how = SIG_BLOCK;
9582 break;
9583 case TARGET_SIG_UNBLOCK:
9584 how = SIG_UNBLOCK;
9585 break;
9586 case TARGET_SIG_SETMASK:
9587 how = SIG_SETMASK;
9588 break;
9589 default:
259841c1 9590 return -TARGET_EINVAL;
a5b3b13b
RH
9591 }
9592 mask = arg2;
9593 target_to_host_old_sigset(&set, &mask);
9594
3d3efba0 9595 ret = do_sigprocmask(how, &set, &oldset);
a5b3b13b
RH
9596 if (!is_error(ret)) {
9597 host_to_target_old_sigset(&mask, &oldset);
9598 ret = mask;
0effdc29 9599 cpu_env->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
9600 }
9601#else
66fb9763 9602 sigset_t set, oldset, *set_ptr;
a5b3b13b 9603 int how;
3b46e624 9604
53a5960a 9605 if (arg2) {
ebce1719
PV
9606 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9607 if (!p) {
9608 return -TARGET_EFAULT;
9609 }
9610 target_to_host_old_sigset(&set, p);
9611 unlock_user(p, arg2, 0);
9612 set_ptr = &set;
a5b3b13b 9613 switch (arg1) {
66fb9763
FB
9614 case TARGET_SIG_BLOCK:
9615 how = SIG_BLOCK;
9616 break;
9617 case TARGET_SIG_UNBLOCK:
9618 how = SIG_UNBLOCK;
9619 break;
9620 case TARGET_SIG_SETMASK:
9621 how = SIG_SETMASK;
9622 break;
9623 default:
259841c1 9624 return -TARGET_EINVAL;
66fb9763 9625 }
66fb9763
FB
9626 } else {
9627 how = 0;
9628 set_ptr = NULL;
9629 }
3d3efba0 9630 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9631 if (!is_error(ret) && arg3) {
c227f099 9632 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9633 return -TARGET_EFAULT;
53a5960a 9634 host_to_target_old_sigset(p, &oldset);
c227f099 9635 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 9636 }
a5b3b13b 9637#endif
66fb9763 9638 }
72eb7ea8 9639 return ret;
e5febef5 9640#endif
66fb9763
FB
9641 case TARGET_NR_rt_sigprocmask:
9642 {
9643 int how = arg1;
9644 sigset_t set, oldset, *set_ptr;
3b46e624 9645
c815701e 9646 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9647 return -TARGET_EINVAL;
c815701e
PM
9648 }
9649
53a5960a 9650 if (arg2) {
d3ced2a5
SCW
9651 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9652 if (!p) {
9653 return -TARGET_EFAULT;
9654 }
9655 target_to_host_sigset(&set, p);
9656 unlock_user(p, arg2, 0);
9657 set_ptr = &set;
66fb9763
FB
9658 switch(how) {
9659 case TARGET_SIG_BLOCK:
9660 how = SIG_BLOCK;
9661 break;
9662 case TARGET_SIG_UNBLOCK:
9663 how = SIG_UNBLOCK;
9664 break;
9665 case TARGET_SIG_SETMASK:
9666 how = SIG_SETMASK;
9667 break;
9668 default:
259841c1 9669 return -TARGET_EINVAL;
66fb9763 9670 }
66fb9763
FB
9671 } else {
9672 how = 0;
9673 set_ptr = NULL;
9674 }
3d3efba0 9675 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9676 if (!is_error(ret) && arg3) {
c227f099 9677 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9678 return -TARGET_EFAULT;
53a5960a 9679 host_to_target_sigset(p, &oldset);
c227f099 9680 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
9681 }
9682 }
72eb7ea8 9683 return ret;
e5febef5 9684#ifdef TARGET_NR_sigpending
66fb9763
FB
9685 case TARGET_NR_sigpending:
9686 {
9687 sigset_t set;
9688 ret = get_errno(sigpending(&set));
9689 if (!is_error(ret)) {
c227f099 9690 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9691 return -TARGET_EFAULT;
53a5960a 9692 host_to_target_old_sigset(p, &set);
c227f099 9693 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9694 }
9695 }
72eb7ea8 9696 return ret;
e5febef5 9697#endif
66fb9763
FB
9698 case TARGET_NR_rt_sigpending:
9699 {
9700 sigset_t set;
c815701e
PM
9701
9702 /* Yes, this check is >, not != like most. We follow the kernel's
9703 * logic and it does it like this because it implements
9704 * NR_sigpending through the same code path, and in that case
9705 * the old_sigset_t is smaller in size.
9706 */
9707 if (arg2 > sizeof(target_sigset_t)) {
72eb7ea8 9708 return -TARGET_EINVAL;
c815701e
PM
9709 }
9710
66fb9763
FB
9711 ret = get_errno(sigpending(&set));
9712 if (!is_error(ret)) {
c227f099 9713 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9714 return -TARGET_EFAULT;
53a5960a 9715 host_to_target_sigset(p, &set);
c227f099 9716 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9717 }
9718 }
72eb7ea8 9719 return ret;
e5febef5 9720#ifdef TARGET_NR_sigsuspend
66fb9763
FB
9721 case TARGET_NR_sigsuspend:
9722 {
0a99f093
RH
9723 sigset_t *set;
9724
f43ce12b 9725#if defined(TARGET_ALPHA)
0a99f093 9726 TaskState *ts = cpu->opaque;
7fb5ef35
RH
9727 /* target_to_host_old_sigset will bswap back */
9728 abi_ulong mask = tswapal(arg1);
0a99f093
RH
9729 set = &ts->sigsuspend_mask;
9730 target_to_host_old_sigset(set, &mask);
f43ce12b 9731#else
0a99f093
RH
9732 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
9733 if (ret != 0) {
9734 return ret;
3d3efba0 9735 }
0a99f093
RH
9736#endif
9737 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9738 finish_sigsuspend_mask(ret);
66fb9763 9739 }
72eb7ea8 9740 return ret;
e5febef5 9741#endif
66fb9763
FB
9742 case TARGET_NR_rt_sigsuspend:
9743 {
0a99f093 9744 sigset_t *set;
c815701e 9745
0a99f093
RH
9746 ret = process_sigsuspend_mask(&set, arg1, arg2);
9747 if (ret != 0) {
9748 return ret;
3d3efba0 9749 }
0a99f093
RH
9750 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9751 finish_sigsuspend_mask(ret);
66fb9763 9752 }
72eb7ea8 9753 return ret;
859e8a89 9754#ifdef TARGET_NR_rt_sigtimedwait
66fb9763
FB
9755 case TARGET_NR_rt_sigtimedwait:
9756 {
66fb9763
FB
9757 sigset_t set;
9758 struct timespec uts, *puts;
9759 siginfo_t uinfo;
3b46e624 9760
c815701e 9761 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9762 return -TARGET_EINVAL;
c815701e
PM
9763 }
9764
c227f099 9765 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
2852aafd 9766 return -TARGET_EFAULT;
53a5960a
PB
9767 target_to_host_sigset(&set, p);
9768 unlock_user(p, arg1, 0);
9769 if (arg3) {
66fb9763 9770 puts = &uts;
4d213001
FB
9771 if (target_to_host_timespec(puts, arg3)) {
9772 return -TARGET_EFAULT;
9773 }
66fb9763
FB
9774 } else {
9775 puts = NULL;
9776 }
b3f82330
PM
9777 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9778 SIGSET_T_SIZE));
974a196d
PJ
9779 if (!is_error(ret)) {
9780 if (arg2) {
9781 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9782 0);
9783 if (!p) {
2852aafd 9784 return -TARGET_EFAULT;
974a196d
PJ
9785 }
9786 host_to_target_siginfo(p, &uinfo);
9787 unlock_user(p, arg2, sizeof(target_siginfo_t));
9788 }
9789 ret = host_to_target_signal(ret);
66fb9763
FB
9790 }
9791 }
72eb7ea8 9792 return ret;
ddcbde15
FB
9793#endif
9794#ifdef TARGET_NR_rt_sigtimedwait_time64
9795 case TARGET_NR_rt_sigtimedwait_time64:
9796 {
9797 sigset_t set;
9798 struct timespec uts, *puts;
9799 siginfo_t uinfo;
9800
9801 if (arg4 != sizeof(target_sigset_t)) {
9802 return -TARGET_EINVAL;
9803 }
9804
9805 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9806 if (!p) {
9807 return -TARGET_EFAULT;
9808 }
9809 target_to_host_sigset(&set, p);
9810 unlock_user(p, arg1, 0);
9811 if (arg3) {
9812 puts = &uts;
9813 if (target_to_host_timespec64(puts, arg3)) {
9814 return -TARGET_EFAULT;
9815 }
9816 } else {
9817 puts = NULL;
9818 }
9819 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9820 SIGSET_T_SIZE));
9821 if (!is_error(ret)) {
9822 if (arg2) {
9823 p = lock_user(VERIFY_WRITE, arg2,
9824 sizeof(target_siginfo_t), 0);
9825 if (!p) {
9826 return -TARGET_EFAULT;
9827 }
9828 host_to_target_siginfo(p, &uinfo);
9829 unlock_user(p, arg2, sizeof(target_siginfo_t));
9830 }
9831 ret = host_to_target_signal(ret);
9832 }
9833 }
9834 return ret;
859e8a89 9835#endif
66fb9763
FB
9836 case TARGET_NR_rt_sigqueueinfo:
9837 {
9838 siginfo_t uinfo;
4debae6f
PM
9839
9840 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9841 if (!p) {
2852aafd 9842 return -TARGET_EFAULT;
4debae6f 9843 }
53a5960a 9844 target_to_host_siginfo(&uinfo, p);
d8b6d892 9845 unlock_user(p, arg3, 0);
9b9145f0 9846 ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
66fb9763 9847 }
72eb7ea8 9848 return ret;
cf8b8bfc
MS
9849 case TARGET_NR_rt_tgsigqueueinfo:
9850 {
9851 siginfo_t uinfo;
9852
9853 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9854 if (!p) {
2852aafd 9855 return -TARGET_EFAULT;
cf8b8bfc
MS
9856 }
9857 target_to_host_siginfo(&uinfo, p);
9858 unlock_user(p, arg4, 0);
9b9145f0 9859 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
cf8b8bfc 9860 }
72eb7ea8 9861 return ret;
e5febef5 9862#ifdef TARGET_NR_sigreturn
66fb9763 9863 case TARGET_NR_sigreturn:
3d3efba0 9864 if (block_signals()) {
af254a27 9865 return -QEMU_ERESTARTSYS;
3d3efba0 9866 }
72eb7ea8 9867 return do_sigreturn(cpu_env);
e5febef5 9868#endif
66fb9763 9869 case TARGET_NR_rt_sigreturn:
3d3efba0 9870 if (block_signals()) {
af254a27 9871 return -QEMU_ERESTARTSYS;
3d3efba0 9872 }
72eb7ea8 9873 return do_rt_sigreturn(cpu_env);
31e31b8a 9874 case TARGET_NR_sethostname:
579a97f7 9875 if (!(p = lock_user_string(arg1)))
2852aafd 9876 return -TARGET_EFAULT;
53a5960a
PB
9877 ret = get_errno(sethostname(p, arg2));
9878 unlock_user(p, arg1, 0);
72eb7ea8 9879 return ret;
4f7f8924 9880#ifdef TARGET_NR_setrlimit
31e31b8a 9881 case TARGET_NR_setrlimit:
9de5e440 9882 {
e22b7015 9883 int resource = target_to_host_resource(arg1);
53a5960a 9884 struct target_rlimit *target_rlim;
9de5e440 9885 struct rlimit rlim;
579a97f7 9886 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
2852aafd 9887 return -TARGET_EFAULT;
81bbe906
TY
9888 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9889 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 9890 unlock_user_struct(target_rlim, arg2, 0);
5dfa88f7
MF
9891 /*
9892 * If we just passed through resource limit settings for memory then
9893 * they would also apply to QEMU's own allocations, and QEMU will
9894 * crash or hang or die if its allocations fail. Ideally we would
9895 * track the guest allocations in QEMU and apply the limits ourselves.
9896 * For now, just tell the guest the call succeeded but don't actually
9897 * limit anything.
9898 */
9899 if (resource != RLIMIT_AS &&
9900 resource != RLIMIT_DATA &&
9901 resource != RLIMIT_STACK) {
9902 return get_errno(setrlimit(resource, &rlim));
9903 } else {
9904 return 0;
9905 }
9de5e440 9906 }
4f7f8924
AR
9907#endif
9908#ifdef TARGET_NR_getrlimit
31e31b8a 9909 case TARGET_NR_getrlimit:
9de5e440 9910 {
e22b7015 9911 int resource = target_to_host_resource(arg1);
53a5960a 9912 struct target_rlimit *target_rlim;
9de5e440 9913 struct rlimit rlim;
3b46e624 9914
9de5e440
FB
9915 ret = get_errno(getrlimit(resource, &rlim));
9916 if (!is_error(ret)) {
579a97f7 9917 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 9918 return -TARGET_EFAULT;
81bbe906
TY
9919 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9920 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 9921 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
9922 }
9923 }
72eb7ea8 9924 return ret;
4f7f8924 9925#endif
31e31b8a 9926 case TARGET_NR_getrusage:
b409186b
FB
9927 {
9928 struct rusage rusage;
b409186b
FB
9929 ret = get_errno(getrusage(arg1, &rusage));
9930 if (!is_error(ret)) {
a39fb273 9931 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
9932 }
9933 }
72eb7ea8 9934 return ret;
859e8a89 9935#if defined(TARGET_NR_gettimeofday)
31e31b8a
FB
9936 case TARGET_NR_gettimeofday:
9937 {
31e31b8a 9938 struct timeval tv;
a52f5f87
RH
9939 struct timezone tz;
9940
9941 ret = get_errno(gettimeofday(&tv, &tz));
31e31b8a 9942 if (!is_error(ret)) {
a52f5f87
RH
9943 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
9944 return -TARGET_EFAULT;
9945 }
9946 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
2852aafd 9947 return -TARGET_EFAULT;
a52f5f87 9948 }
31e31b8a
FB
9949 }
9950 }
72eb7ea8 9951 return ret;
859e8a89
AF
9952#endif
9953#if defined(TARGET_NR_settimeofday)
31e31b8a
FB
9954 case TARGET_NR_settimeofday:
9955 {
b67d8031 9956 struct timeval tv, *ptv = NULL;
ef4467e9
PB
9957 struct timezone tz, *ptz = NULL;
9958
b67d8031
PB
9959 if (arg1) {
9960 if (copy_from_user_timeval(&tv, arg1)) {
2852aafd 9961 return -TARGET_EFAULT;
b67d8031
PB
9962 }
9963 ptv = &tv;
9964 }
ef4467e9
PB
9965
9966 if (arg2) {
9967 if (copy_from_user_timezone(&tz, arg2)) {
2852aafd 9968 return -TARGET_EFAULT;
ef4467e9
PB
9969 }
9970 ptz = &tz;
9971 }
9972
72eb7ea8 9973 return get_errno(settimeofday(ptv, ptz));
31e31b8a 9974 }
859e8a89 9975#endif
9468a5d4 9976#if defined(TARGET_NR_select)
31e31b8a 9977 case TARGET_NR_select:
5457dc9e
LV
9978#if defined(TARGET_WANT_NI_OLD_SELECT)
9979 /* some architectures used to have old_select here
9980 * but now ENOSYS it.
9981 */
9982 ret = -TARGET_ENOSYS;
9983#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9984 ret = do_old_select(arg1);
9468a5d4 9985#else
5457dc9e 9986 ret = do_select(arg1, arg2, arg3, arg4, arg5);
9468a5d4 9987#endif
72eb7ea8 9988 return ret;
9e42382f
RV
9989#endif
9990#ifdef TARGET_NR_pselect6
9991 case TARGET_NR_pselect6:
e5ce9688
FB
9992 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9993#endif
9994#ifdef TARGET_NR_pselect6_time64
9995 case TARGET_NR_pselect6_time64:
9996 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
048f6b4d 9997#endif
704eff6c 9998#ifdef TARGET_NR_symlink
31e31b8a 9999 case TARGET_NR_symlink:
53a5960a
PB
10000 {
10001 void *p2;
10002 p = lock_user_string(arg1);
10003 p2 = lock_user_string(arg2);
579a97f7
FB
10004 if (!p || !p2)
10005 ret = -TARGET_EFAULT;
10006 else
10007 ret = get_errno(symlink(p, p2));
53a5960a
PB
10008 unlock_user(p2, arg2, 0);
10009 unlock_user(p, arg1, 0);
10010 }
72eb7ea8 10011 return ret;
704eff6c 10012#endif
c0d472b1 10013#if defined(TARGET_NR_symlinkat)
f0b6243d 10014 case TARGET_NR_symlinkat:
f0b6243d 10015 {
579a97f7 10016 void *p2;
f0b6243d
TS
10017 p = lock_user_string(arg1);
10018 p2 = lock_user_string(arg3);
579a97f7 10019 if (!p || !p2)
0da46a6e 10020 ret = -TARGET_EFAULT;
f0b6243d 10021 else
c0d472b1 10022 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
10023 unlock_user(p2, arg3, 0);
10024 unlock_user(p, arg1, 0);
f0b6243d 10025 }
72eb7ea8 10026 return ret;
f0b6243d 10027#endif
704eff6c 10028#ifdef TARGET_NR_readlink
31e31b8a 10029 case TARGET_NR_readlink:
53a5960a 10030 {
463d8e73 10031 void *p2;
53a5960a 10032 p = lock_user_string(arg1);
579a97f7 10033 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 10034 if (!p || !p2) {
579a97f7 10035 ret = -TARGET_EFAULT;
f17f4989
MF
10036 } else if (!arg3) {
10037 /* Short circuit this for the magic exe check. */
10038 ret = -TARGET_EINVAL;
463d8e73 10039 } else if (is_proc_myself((const char *)p, "exe")) {
258bec39
HD
10040 /*
10041 * Don't worry about sign mismatch as earlier mapping
10042 * logic would have thrown a bad address error.
10043 */
10044 ret = MIN(strlen(exec_path), arg3);
10045 /* We cannot NUL terminate the string. */
10046 memcpy(p2, exec_path, ret);
463d8e73
AS
10047 } else {
10048 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 10049 }
53a5960a
PB
10050 unlock_user(p2, arg2, ret);
10051 unlock_user(p, arg1, 0);
10052 }
72eb7ea8 10053 return ret;
704eff6c 10054#endif
c0d472b1 10055#if defined(TARGET_NR_readlinkat)
5e0ccb18 10056 case TARGET_NR_readlinkat:
5e0ccb18 10057 {
579a97f7 10058 void *p2;
5e0ccb18 10059 p = lock_user_string(arg2);
579a97f7 10060 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
10061 if (!p || !p2) {
10062 ret = -TARGET_EFAULT;
65d4830d
JN
10063 } else if (!arg4) {
10064 /* Short circuit this for the magic exe check. */
10065 ret = -TARGET_EINVAL;
463d8e73 10066 } else if (is_proc_myself((const char *)p, "exe")) {
258bec39
HD
10067 /*
10068 * Don't worry about sign mismatch as earlier mapping
10069 * logic would have thrown a bad address error.
10070 */
10071 ret = MIN(strlen(exec_path), arg4);
10072 /* We cannot NUL terminate the string. */
10073 memcpy(p2, exec_path, ret);
463d8e73 10074 } else {
c0d472b1 10075 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 10076 }
579a97f7
FB
10077 unlock_user(p2, arg3, ret);
10078 unlock_user(p, arg2, 0);
5e0ccb18 10079 }
72eb7ea8 10080 return ret;
5e0ccb18 10081#endif
e5febef5 10082#ifdef TARGET_NR_swapon
31e31b8a 10083 case TARGET_NR_swapon:
579a97f7 10084 if (!(p = lock_user_string(arg1)))
2852aafd 10085 return -TARGET_EFAULT;
53a5960a
PB
10086 ret = get_errno(swapon(p, arg2));
10087 unlock_user(p, arg1, 0);
72eb7ea8 10088 return ret;
e5febef5 10089#endif
31e31b8a 10090 case TARGET_NR_reboot:
c07ecc68
LV
10091 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
10092 /* arg4 must be ignored in all other cases */
10093 p = lock_user_string(arg4);
10094 if (!p) {
2852aafd 10095 return -TARGET_EFAULT;
c07ecc68
LV
10096 }
10097 ret = get_errno(reboot(arg1, arg2, arg3, p));
10098 unlock_user(p, arg4, 0);
10099 } else {
10100 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
10101 }
72eb7ea8 10102 return ret;
e5febef5 10103#ifdef TARGET_NR_mmap
31e31b8a 10104 case TARGET_NR_mmap:
09701199
AG
10105#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
10106 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
10107 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
10108 || defined(TARGET_S390X)
31e31b8a 10109 {
992f48a0
BS
10110 abi_ulong *v;
10111 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7 10112 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
2852aafd 10113 return -TARGET_EFAULT;
cbb21eed
MB
10114 v1 = tswapal(v[0]);
10115 v2 = tswapal(v[1]);
10116 v3 = tswapal(v[2]);
10117 v4 = tswapal(v[3]);
10118 v5 = tswapal(v[4]);
10119 v6 = tswapal(v[5]);
53a5960a 10120 unlock_user(v, arg1, 0);
5fafdf24 10121 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
10122 target_to_host_bitmask(v4, mmap_flags_tbl),
10123 v5, v6));
31e31b8a 10124 }
31e31b8a 10125#else
ee1bf83d 10126 /* mmap pointers are always untagged */
5fafdf24
TS
10127 ret = get_errno(target_mmap(arg1, arg2, arg3,
10128 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
10129 arg5,
10130 arg6));
31e31b8a 10131#endif
72eb7ea8 10132 return ret;
e5febef5 10133#endif
a315a145 10134#ifdef TARGET_NR_mmap2
6fb883e8 10135 case TARGET_NR_mmap2:
bb7ec043 10136#ifndef MMAP_SHIFT
c573ff67 10137#define MMAP_SHIFT 12
c573ff67 10138#endif
72eb7ea8
RH
10139 ret = target_mmap(arg1, arg2, arg3,
10140 target_to_host_bitmask(arg4, mmap_flags_tbl),
10141 arg5, arg6 << MMAP_SHIFT);
10142 return get_errno(ret);
a315a145 10143#endif
31e31b8a 10144 case TARGET_NR_munmap:
ee1bf83d 10145 arg1 = cpu_untagged_addr(cpu, arg1);
72eb7ea8 10146 return get_errno(target_munmap(arg1, arg2));
9de5e440 10147 case TARGET_NR_mprotect:
ee1bf83d 10148 arg1 = cpu_untagged_addr(cpu, arg1);
97374d38 10149 {
0429a971 10150 TaskState *ts = cpu->opaque;
97374d38
PB
10151 /* Special hack to detect libc making the stack executable. */
10152 if ((arg3 & PROT_GROWSDOWN)
10153 && arg1 >= ts->info->stack_limit
10154 && arg1 <= ts->info->start_stack) {
10155 arg3 &= ~PROT_GROWSDOWN;
10156 arg2 = arg2 + arg1 - ts->info->stack_limit;
10157 arg1 = ts->info->stack_limit;
10158 }
10159 }
72eb7ea8 10160 return get_errno(target_mprotect(arg1, arg2, arg3));
e5febef5 10161#ifdef TARGET_NR_mremap
9de5e440 10162 case TARGET_NR_mremap:
ee1bf83d
RH
10163 arg1 = cpu_untagged_addr(cpu, arg1);
10164 /* mremap new_addr (arg5) is always untagged */
72eb7ea8 10165 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
e5febef5 10166#endif
53a5960a 10167 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 10168#ifdef TARGET_NR_msync
9de5e440 10169 case TARGET_NR_msync:
fe080593
HD
10170 return get_errno(msync(g2h(cpu, arg1), arg2,
10171 target_to_host_msync_arg(arg3)));
e5febef5
TS
10172#endif
10173#ifdef TARGET_NR_mlock
9de5e440 10174 case TARGET_NR_mlock:
3e8f1628 10175 return get_errno(mlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10176#endif
10177#ifdef TARGET_NR_munlock
9de5e440 10178 case TARGET_NR_munlock:
3e8f1628 10179 return get_errno(munlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10180#endif
10181#ifdef TARGET_NR_mlockall
9de5e440 10182 case TARGET_NR_mlockall:
72eb7ea8 10183 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
e5febef5
TS
10184#endif
10185#ifdef TARGET_NR_munlockall
9de5e440 10186 case TARGET_NR_munlockall:
72eb7ea8 10187 return get_errno(munlockall());
e5febef5 10188#endif
4f7f8924 10189#ifdef TARGET_NR_truncate
31e31b8a 10190 case TARGET_NR_truncate:
579a97f7 10191 if (!(p = lock_user_string(arg1)))
2852aafd 10192 return -TARGET_EFAULT;
53a5960a
PB
10193 ret = get_errno(truncate(p, arg2));
10194 unlock_user(p, arg1, 0);
72eb7ea8 10195 return ret;
4f7f8924
AR
10196#endif
10197#ifdef TARGET_NR_ftruncate
31e31b8a 10198 case TARGET_NR_ftruncate:
72eb7ea8 10199 return get_errno(ftruncate(arg1, arg2));
4f7f8924 10200#endif
31e31b8a 10201 case TARGET_NR_fchmod:
72eb7ea8 10202 return get_errno(fchmod(arg1, arg2));
c0d472b1 10203#if defined(TARGET_NR_fchmodat)
814d7977 10204 case TARGET_NR_fchmodat:
579a97f7 10205 if (!(p = lock_user_string(arg2)))
2852aafd 10206 return -TARGET_EFAULT;
c0d472b1 10207 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 10208 unlock_user(p, arg2, 0);
72eb7ea8 10209 return ret;
814d7977 10210#endif
31e31b8a 10211 case TARGET_NR_getpriority:
95c09828
RH
10212 /* Note that negative values are valid for getpriority, so we must
10213 differentiate based on errno settings. */
10214 errno = 0;
10215 ret = getpriority(arg1, arg2);
10216 if (ret == -1 && errno != 0) {
72eb7ea8 10217 return -host_to_target_errno(errno);
95c09828
RH
10218 }
10219#ifdef TARGET_ALPHA
10220 /* Return value is the unbiased priority. Signal no error. */
0effdc29 10221 cpu_env->ir[IR_V0] = 0;
95c09828
RH
10222#else
10223 /* Return value is a biased priority to avoid negative numbers. */
10224 ret = 20 - ret;
10225#endif
72eb7ea8 10226 return ret;
31e31b8a 10227 case TARGET_NR_setpriority:
72eb7ea8 10228 return get_errno(setpriority(arg1, arg2, arg3));
4f7f8924 10229#ifdef TARGET_NR_statfs
31e31b8a 10230 case TARGET_NR_statfs:
2852aafd
RH
10231 if (!(p = lock_user_string(arg1))) {
10232 return -TARGET_EFAULT;
10233 }
53a5960a
PB
10234 ret = get_errno(statfs(path(p), &stfs));
10235 unlock_user(p, arg1, 0);
31e31b8a
FB
10236 convert_statfs:
10237 if (!is_error(ret)) {
53a5960a 10238 struct target_statfs *target_stfs;
3b46e624 10239
579a97f7 10240 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
2852aafd 10241 return -TARGET_EFAULT;
579a97f7
FB
10242 __put_user(stfs.f_type, &target_stfs->f_type);
10243 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10244 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10245 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10246 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10247 __put_user(stfs.f_files, &target_stfs->f_files);
10248 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10249 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10250 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10251 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10252 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
d4247ec2
SL
10253#ifdef _STATFS_F_FLAGS
10254 __put_user(stfs.f_flags, &target_stfs->f_flags);
10255#else
10256 __put_user(0, &target_stfs->f_flags);
10257#endif
229d3376 10258 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 10259 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a 10260 }
72eb7ea8 10261 return ret;
4f7f8924
AR
10262#endif
10263#ifdef TARGET_NR_fstatfs
31e31b8a 10264 case TARGET_NR_fstatfs:
56c8f68f 10265 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 10266 goto convert_statfs;
4f7f8924 10267#endif
56c8f68f
FB
10268#ifdef TARGET_NR_statfs64
10269 case TARGET_NR_statfs64:
2852aafd
RH
10270 if (!(p = lock_user_string(arg1))) {
10271 return -TARGET_EFAULT;
10272 }
53a5960a
PB
10273 ret = get_errno(statfs(path(p), &stfs));
10274 unlock_user(p, arg1, 0);
56c8f68f
FB
10275 convert_statfs64:
10276 if (!is_error(ret)) {
53a5960a 10277 struct target_statfs64 *target_stfs;
3b46e624 10278
579a97f7 10279 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
2852aafd 10280 return -TARGET_EFAULT;
579a97f7
FB
10281 __put_user(stfs.f_type, &target_stfs->f_type);
10282 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10283 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10284 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10285 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10286 __put_user(stfs.f_files, &target_stfs->f_files);
10287 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10288 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10289 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10290 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10291 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
b94e2b4e
F
10292#ifdef _STATFS_F_FLAGS
10293 __put_user(stfs.f_flags, &target_stfs->f_flags);
10294#else
10295 __put_user(0, &target_stfs->f_flags);
10296#endif
229d3376 10297 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 10298 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f 10299 }
72eb7ea8 10300 return ret;
56c8f68f
FB
10301 case TARGET_NR_fstatfs64:
10302 ret = get_errno(fstatfs(arg1, &stfs));
10303 goto convert_statfs64;
10304#endif
e5febef5 10305#ifdef TARGET_NR_socketcall
31e31b8a 10306 case TARGET_NR_socketcall:
72eb7ea8 10307 return do_socketcall(arg1, arg2);
e5febef5 10308#endif
3532fa74
FB
10309#ifdef TARGET_NR_accept
10310 case TARGET_NR_accept:
72eb7ea8 10311 return do_accept4(arg1, arg2, arg3, 0);
a94b4987
PM
10312#endif
10313#ifdef TARGET_NR_accept4
10314 case TARGET_NR_accept4:
72eb7ea8 10315 return do_accept4(arg1, arg2, arg3, arg4);
3532fa74
FB
10316#endif
10317#ifdef TARGET_NR_bind
10318 case TARGET_NR_bind:
72eb7ea8 10319 return do_bind(arg1, arg2, arg3);
3532fa74
FB
10320#endif
10321#ifdef TARGET_NR_connect
10322 case TARGET_NR_connect:
72eb7ea8 10323 return do_connect(arg1, arg2, arg3);
3532fa74
FB
10324#endif
10325#ifdef TARGET_NR_getpeername
10326 case TARGET_NR_getpeername:
72eb7ea8 10327 return do_getpeername(arg1, arg2, arg3);
3532fa74
FB
10328#endif
10329#ifdef TARGET_NR_getsockname
10330 case TARGET_NR_getsockname:
72eb7ea8 10331 return do_getsockname(arg1, arg2, arg3);
3532fa74
FB
10332#endif
10333#ifdef TARGET_NR_getsockopt
10334 case TARGET_NR_getsockopt:
72eb7ea8 10335 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
3532fa74
FB
10336#endif
10337#ifdef TARGET_NR_listen
10338 case TARGET_NR_listen:
72eb7ea8 10339 return get_errno(listen(arg1, arg2));
3532fa74
FB
10340#endif
10341#ifdef TARGET_NR_recv
10342 case TARGET_NR_recv:
72eb7ea8 10343 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10344#endif
10345#ifdef TARGET_NR_recvfrom
10346 case TARGET_NR_recvfrom:
72eb7ea8 10347 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10348#endif
10349#ifdef TARGET_NR_recvmsg
10350 case TARGET_NR_recvmsg:
72eb7ea8 10351 return do_sendrecvmsg(arg1, arg2, arg3, 0);
3532fa74
FB
10352#endif
10353#ifdef TARGET_NR_send
10354 case TARGET_NR_send:
72eb7ea8 10355 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10356#endif
10357#ifdef TARGET_NR_sendmsg
10358 case TARGET_NR_sendmsg:
72eb7ea8 10359 return do_sendrecvmsg(arg1, arg2, arg3, 1);
3532fa74 10360#endif
f19e00d7
AG
10361#ifdef TARGET_NR_sendmmsg
10362 case TARGET_NR_sendmmsg:
72eb7ea8 10363 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
859e8a89
AF
10364#endif
10365#ifdef TARGET_NR_recvmmsg
f19e00d7 10366 case TARGET_NR_recvmmsg:
72eb7ea8 10367 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
f19e00d7 10368#endif
3532fa74
FB
10369#ifdef TARGET_NR_sendto
10370 case TARGET_NR_sendto:
72eb7ea8 10371 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10372#endif
10373#ifdef TARGET_NR_shutdown
10374 case TARGET_NR_shutdown:
72eb7ea8 10375 return get_errno(shutdown(arg1, arg2));
3532fa74 10376#endif
f894efd1
LV
10377#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10378 case TARGET_NR_getrandom:
10379 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10380 if (!p) {
2852aafd 10381 return -TARGET_EFAULT;
f894efd1
LV
10382 }
10383 ret = get_errno(getrandom(p, arg2, arg3));
10384 unlock_user(p, arg1, ret);
72eb7ea8 10385 return ret;
f894efd1 10386#endif
3532fa74
FB
10387#ifdef TARGET_NR_socket
10388 case TARGET_NR_socket:
72eb7ea8 10389 return do_socket(arg1, arg2, arg3);
3532fa74
FB
10390#endif
10391#ifdef TARGET_NR_socketpair
10392 case TARGET_NR_socketpair:
72eb7ea8 10393 return do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
10394#endif
10395#ifdef TARGET_NR_setsockopt
10396 case TARGET_NR_setsockopt:
72eb7ea8 10397 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
3532fa74 10398#endif
da2c8ad7 10399#if defined(TARGET_NR_syslog)
31e31b8a 10400 case TARGET_NR_syslog:
da2c8ad7
AM
10401 {
10402 int len = arg2;
7494b0f9 10403
da2c8ad7
AM
10404 switch (arg1) {
10405 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10406 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10407 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10408 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10409 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10410 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10411 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10412 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
72eb7ea8 10413 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
da2c8ad7
AM
10414 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10415 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10416 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10417 {
da2c8ad7 10418 if (len < 0) {
259841c1 10419 return -TARGET_EINVAL;
da2c8ad7 10420 }
da2c8ad7 10421 if (len == 0) {
72eb7ea8 10422 return 0;
da2c8ad7
AM
10423 }
10424 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10425 if (!p) {
259841c1 10426 return -TARGET_EFAULT;
da2c8ad7
AM
10427 }
10428 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10429 unlock_user(p, arg2, arg3);
10430 }
72eb7ea8 10431 return ret;
da2c8ad7 10432 default:
72eb7ea8 10433 return -TARGET_EINVAL;
da2c8ad7
AM
10434 }
10435 }
10436 break;
10437#endif
31e31b8a 10438 case TARGET_NR_setitimer:
66fb9763 10439 {
66fb9763
FB
10440 struct itimerval value, ovalue, *pvalue;
10441
53a5960a 10442 if (arg2) {
66fb9763 10443 pvalue = &value;
788f5ec4
TS
10444 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10445 || copy_from_user_timeval(&pvalue->it_value,
10446 arg2 + sizeof(struct target_timeval)))
2852aafd 10447 return -TARGET_EFAULT;
66fb9763
FB
10448 } else {
10449 pvalue = NULL;
10450 }
10451 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 10452 if (!is_error(ret) && arg3) {
788f5ec4
TS
10453 if (copy_to_user_timeval(arg3,
10454 &ovalue.it_interval)
10455 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10456 &ovalue.it_value))
2852aafd 10457 return -TARGET_EFAULT;
66fb9763
FB
10458 }
10459 }
72eb7ea8 10460 return ret;
31e31b8a 10461 case TARGET_NR_getitimer:
66fb9763 10462 {
66fb9763 10463 struct itimerval value;
3b46e624 10464
66fb9763 10465 ret = get_errno(getitimer(arg1, &value));
53a5960a 10466 if (!is_error(ret) && arg2) {
788f5ec4
TS
10467 if (copy_to_user_timeval(arg2,
10468 &value.it_interval)
10469 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10470 &value.it_value))
2852aafd 10471 return -TARGET_EFAULT;
66fb9763
FB
10472 }
10473 }
72eb7ea8 10474 return ret;
704eff6c 10475#ifdef TARGET_NR_stat
31e31b8a 10476 case TARGET_NR_stat:
2852aafd
RH
10477 if (!(p = lock_user_string(arg1))) {
10478 return -TARGET_EFAULT;
10479 }
53a5960a
PB
10480 ret = get_errno(stat(path(p), &st));
10481 unlock_user(p, arg1, 0);
31e31b8a 10482 goto do_stat;
704eff6c
CG
10483#endif
10484#ifdef TARGET_NR_lstat
31e31b8a 10485 case TARGET_NR_lstat:
2852aafd
RH
10486 if (!(p = lock_user_string(arg1))) {
10487 return -TARGET_EFAULT;
10488 }
53a5960a
PB
10489 ret = get_errno(lstat(path(p), &st));
10490 unlock_user(p, arg1, 0);
31e31b8a 10491 goto do_stat;
704eff6c 10492#endif
4f7f8924 10493#ifdef TARGET_NR_fstat
31e31b8a
FB
10494 case TARGET_NR_fstat:
10495 {
10496 ret = get_errno(fstat(arg1, &st));
704eff6c 10497#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
31e31b8a 10498 do_stat:
704eff6c 10499#endif
31e31b8a 10500 if (!is_error(ret)) {
53a5960a 10501 struct target_stat *target_st;
e3584658 10502
579a97f7 10503 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
2852aafd 10504 return -TARGET_EFAULT;
12727917 10505 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
10506 __put_user(st.st_dev, &target_st->st_dev);
10507 __put_user(st.st_ino, &target_st->st_ino);
10508 __put_user(st.st_mode, &target_st->st_mode);
10509 __put_user(st.st_uid, &target_st->st_uid);
10510 __put_user(st.st_gid, &target_st->st_gid);
10511 __put_user(st.st_nlink, &target_st->st_nlink);
10512 __put_user(st.st_rdev, &target_st->st_rdev);
10513 __put_user(st.st_size, &target_st->st_size);
10514 __put_user(st.st_blksize, &target_st->st_blksize);
10515 __put_user(st.st_blocks, &target_st->st_blocks);
10516 __put_user(st.st_atime, &target_st->target_st_atime);
10517 __put_user(st.st_mtime, &target_st->target_st_mtime);
10518 __put_user(st.st_ctime, &target_st->target_st_ctime);
febf6fad 10519#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
5f992db6
CYT
10520 __put_user(st.st_atim.tv_nsec,
10521 &target_st->target_st_atime_nsec);
10522 __put_user(st.st_mtim.tv_nsec,
10523 &target_st->target_st_mtime_nsec);
10524 __put_user(st.st_ctim.tv_nsec,
10525 &target_st->target_st_ctime_nsec);
10526#endif
53a5960a 10527 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
10528 }
10529 }
72eb7ea8 10530 return ret;
ebc05488 10531#endif
31e31b8a 10532 case TARGET_NR_vhangup:
72eb7ea8 10533 return get_errno(vhangup());
42ad6ae9
FB
10534#ifdef TARGET_NR_syscall
10535 case TARGET_NR_syscall:
72eb7ea8
RH
10536 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10537 arg6, arg7, arg8, 0);
ebc05488 10538#endif
859e8a89 10539#if defined(TARGET_NR_wait4)
31e31b8a
FB
10540 case TARGET_NR_wait4:
10541 {
10542 int status;
992f48a0 10543 abi_long status_ptr = arg2;
31e31b8a 10544 struct rusage rusage, *rusage_ptr;
992f48a0 10545 abi_ulong target_rusage = arg4;
a39fb273 10546 abi_long rusage_err;
31e31b8a
FB
10547 if (target_rusage)
10548 rusage_ptr = &rusage;
10549 else
10550 rusage_ptr = NULL;
4af80a37 10551 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
31e31b8a 10552 if (!is_error(ret)) {
5379557b 10553 if (status_ptr && ret) {
1d9d8b55 10554 status = host_to_target_waitstatus(status);
2f619698 10555 if (put_user_s32(status, status_ptr))
2852aafd 10556 return -TARGET_EFAULT;
31e31b8a 10557 }
a39fb273
PJ
10558 if (target_rusage) {
10559 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10560 if (rusage_err) {
10561 ret = rusage_err;
10562 }
10563 }
31e31b8a
FB
10564 }
10565 }
72eb7ea8 10566 return ret;
859e8a89 10567#endif
e5febef5 10568#ifdef TARGET_NR_swapoff
31e31b8a 10569 case TARGET_NR_swapoff:
579a97f7 10570 if (!(p = lock_user_string(arg1)))
2852aafd 10571 return -TARGET_EFAULT;
53a5960a
PB
10572 ret = get_errno(swapoff(p));
10573 unlock_user(p, arg1, 0);
72eb7ea8 10574 return ret;
e5febef5 10575#endif
31e31b8a 10576 case TARGET_NR_sysinfo:
a5448a7d 10577 {
53a5960a 10578 struct target_sysinfo *target_value;
a5448a7d
FB
10579 struct sysinfo value;
10580 ret = get_errno(sysinfo(&value));
53a5960a 10581 if (!is_error(ret) && arg1)
a5448a7d 10582 {
579a97f7 10583 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
2852aafd 10584 return -TARGET_EFAULT;
a5448a7d
FB
10585 __put_user(value.uptime, &target_value->uptime);
10586 __put_user(value.loads[0], &target_value->loads[0]);
10587 __put_user(value.loads[1], &target_value->loads[1]);
10588 __put_user(value.loads[2], &target_value->loads[2]);
10589 __put_user(value.totalram, &target_value->totalram);
10590 __put_user(value.freeram, &target_value->freeram);
10591 __put_user(value.sharedram, &target_value->sharedram);
10592 __put_user(value.bufferram, &target_value->bufferram);
10593 __put_user(value.totalswap, &target_value->totalswap);
10594 __put_user(value.freeswap, &target_value->freeswap);
10595 __put_user(value.procs, &target_value->procs);
10596 __put_user(value.totalhigh, &target_value->totalhigh);
10597 __put_user(value.freehigh, &target_value->freehigh);
10598 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 10599 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
10600 }
10601 }
72eb7ea8 10602 return ret;
e5febef5 10603#ifdef TARGET_NR_ipc
31e31b8a 10604 case TARGET_NR_ipc:
72eb7ea8 10605 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
e5febef5 10606#endif
e5289087
AJ
10607#ifdef TARGET_NR_semget
10608 case TARGET_NR_semget:
72eb7ea8 10609 return get_errno(semget(arg1, arg2, arg3));
e5289087
AJ
10610#endif
10611#ifdef TARGET_NR_semop
10612 case TARGET_NR_semop:
cac46eb0 10613 return do_semtimedop(arg1, arg2, arg3, 0, false);
d8c08b1e
MK
10614#endif
10615#ifdef TARGET_NR_semtimedop
10616 case TARGET_NR_semtimedop:
cac46eb0
FB
10617 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10618#endif
10619#ifdef TARGET_NR_semtimedop_time64
10620 case TARGET_NR_semtimedop_time64:
10621 return do_semtimedop(arg1, arg2, arg3, arg4, true);
e5289087
AJ
10622#endif
10623#ifdef TARGET_NR_semctl
10624 case TARGET_NR_semctl:
72eb7ea8 10625 return do_semctl(arg1, arg2, arg3, arg4);
e5289087 10626#endif
eeb438c1
AJ
10627#ifdef TARGET_NR_msgctl
10628 case TARGET_NR_msgctl:
72eb7ea8 10629 return do_msgctl(arg1, arg2, arg3);
eeb438c1
AJ
10630#endif
10631#ifdef TARGET_NR_msgget
10632 case TARGET_NR_msgget:
72eb7ea8 10633 return get_errno(msgget(arg1, arg2));
eeb438c1
AJ
10634#endif
10635#ifdef TARGET_NR_msgrcv
10636 case TARGET_NR_msgrcv:
72eb7ea8 10637 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
eeb438c1
AJ
10638#endif
10639#ifdef TARGET_NR_msgsnd
10640 case TARGET_NR_msgsnd:
72eb7ea8 10641 return do_msgsnd(arg1, arg2, arg3, arg4);
88a8c984
RV
10642#endif
10643#ifdef TARGET_NR_shmget
10644 case TARGET_NR_shmget:
72eb7ea8 10645 return get_errno(shmget(arg1, arg2, arg3));
88a8c984
RV
10646#endif
10647#ifdef TARGET_NR_shmctl
10648 case TARGET_NR_shmctl:
72eb7ea8 10649 return do_shmctl(arg1, arg2, arg3);
88a8c984
RV
10650#endif
10651#ifdef TARGET_NR_shmat
10652 case TARGET_NR_shmat:
72eb7ea8 10653 return do_shmat(cpu_env, arg1, arg2, arg3);
88a8c984
RV
10654#endif
10655#ifdef TARGET_NR_shmdt
10656 case TARGET_NR_shmdt:
72eb7ea8 10657 return do_shmdt(arg1);
eeb438c1 10658#endif
31e31b8a 10659 case TARGET_NR_fsync:
72eb7ea8 10660 return get_errno(fsync(arg1));
31e31b8a 10661 case TARGET_NR_clone:
4ce6243d
PM
10662 /* Linux manages to have three different orderings for its
10663 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10664 * match the kernel's CONFIG_CLONE_* settings.
10665 * Microblaze is further special in that it uses a sixth
10666 * implicit argument to clone for the TLS pointer.
10667 */
10668#if defined(TARGET_MICROBLAZE)
a5b3bdcb 10669 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
10670#elif defined(TARGET_CLONE_BACKWARDS)
10671 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10672#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 10673 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 10674#else
4ce6243d 10675 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 10676#endif
72eb7ea8 10677 return ret;
ec86b0fb
FB
10678#ifdef __NR_exit_group
10679 /* new thread calls */
10680 case TARGET_NR_exit_group:
708b6a64 10681 preexit_cleanup(cpu_env, arg1);
72eb7ea8 10682 return get_errno(exit_group(arg1));
ec86b0fb 10683#endif
31e31b8a 10684 case TARGET_NR_setdomainname:
579a97f7 10685 if (!(p = lock_user_string(arg1)))
2852aafd 10686 return -TARGET_EFAULT;
53a5960a
PB
10687 ret = get_errno(setdomainname(p, arg2));
10688 unlock_user(p, arg1, 0);
72eb7ea8 10689 return ret;
31e31b8a
FB
10690 case TARGET_NR_uname:
10691 /* no need to transcode because we use the linux syscall */
29e619b1
FB
10692 {
10693 struct new_utsname * buf;
3b46e624 10694
579a97f7 10695 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
2852aafd 10696 return -TARGET_EFAULT;
29e619b1
FB
10697 ret = get_errno(sys_uname(buf));
10698 if (!is_error(ret)) {
332c9781 10699 /* Overwrite the native machine name with whatever is being
29e619b1 10700 emulated. */
871f95c6
PMD
10701 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10702 sizeof(buf->machine));
c5937220 10703 /* Allow the user to override the reported release. */
332c9781
PM
10704 if (qemu_uname_release && *qemu_uname_release) {
10705 g_strlcpy(buf->release, qemu_uname_release,
10706 sizeof(buf->release));
10707 }
29e619b1 10708 }
53a5960a 10709 unlock_user_struct(buf, arg1, 1);
29e619b1 10710 }
72eb7ea8 10711 return ret;
6dbad63e 10712#ifdef TARGET_I386
31e31b8a 10713 case TARGET_NR_modify_ldt:
72eb7ea8 10714 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
84409ddb 10715#if !defined(TARGET_X86_64)
5cd4393b 10716 case TARGET_NR_vm86:
72eb7ea8 10717 return do_vm86(cpu_env, arg1, arg2);
84409ddb 10718#endif
6dbad63e 10719#endif
859e8a89 10720#if defined(TARGET_NR_adjtimex)
31e31b8a 10721 case TARGET_NR_adjtimex:
19f59bce
AM
10722 {
10723 struct timex host_buf;
10724
10725 if (target_to_host_timex(&host_buf, arg1) != 0) {
2852aafd 10726 return -TARGET_EFAULT;
19f59bce
AM
10727 }
10728 ret = get_errno(adjtimex(&host_buf));
10729 if (!is_error(ret)) {
10730 if (host_to_target_timex(arg1, &host_buf) != 0) {
2852aafd 10731 return -TARGET_EFAULT;
19f59bce
AM
10732 }
10733 }
10734 }
72eb7ea8 10735 return ret;
859e8a89 10736#endif
38860a03
AM
10737#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10738 case TARGET_NR_clock_adjtime:
10739 {
10740 struct timex htx, *phtx = &htx;
10741
10742 if (target_to_host_timex(phtx, arg2) != 0) {
2852aafd 10743 return -TARGET_EFAULT;
38860a03
AM
10744 }
10745 ret = get_errno(clock_adjtime(arg1, phtx));
10746 if (!is_error(ret) && phtx) {
10747 if (host_to_target_timex(arg2, phtx) != 0) {
2852aafd 10748 return -TARGET_EFAULT;
38860a03
AM
10749 }
10750 }
10751 }
72eb7ea8 10752 return ret;
6ac03b2c
FB
10753#endif
10754#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10755 case TARGET_NR_clock_adjtime64:
10756 {
10757 struct timex htx;
10758
10759 if (target_to_host_timex64(&htx, arg2) != 0) {
10760 return -TARGET_EFAULT;
10761 }
10762 ret = get_errno(clock_adjtime(arg1, &htx));
10763 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10764 return -TARGET_EFAULT;
10765 }
10766 }
10767 return ret;
38860a03 10768#endif
31e31b8a 10769 case TARGET_NR_getpgid:
72eb7ea8 10770 return get_errno(getpgid(arg1));
31e31b8a 10771 case TARGET_NR_fchdir:
72eb7ea8 10772 return get_errno(fchdir(arg1));
31e31b8a 10773 case TARGET_NR_personality:
72eb7ea8 10774 return get_errno(personality(arg1));
7a3148a9 10775#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
10776 case TARGET_NR__llseek:
10777 {
0c1592d9 10778 int64_t res;
d35b261c 10779#if !defined(__NR_llseek)
9fea273c 10780 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
0c1592d9
PM
10781 if (res == -1) {
10782 ret = get_errno(res);
10783 } else {
10784 ret = 0;
10785 }
4f2ac237 10786#else
31e31b8a 10787 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 10788#endif
0c1592d9 10789 if ((ret == 0) && put_user_s64(res, arg4)) {
2852aafd 10790 return -TARGET_EFAULT;
0c1592d9 10791 }
31e31b8a 10792 }
72eb7ea8 10793 return ret;
7a3148a9 10794#endif
704eff6c 10795#ifdef TARGET_NR_getdents
31e31b8a 10796 case TARGET_NR_getdents:
fd08ddb9 10797 return do_getdents(arg1, arg2, arg3);
704eff6c 10798#endif /* TARGET_NR_getdents */
3ae43202 10799#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99 10800 case TARGET_NR_getdents64:
fd08ddb9 10801 return do_getdents64(arg1, arg2, arg3);
a541f297 10802#endif /* TARGET_NR_getdents64 */
9468a5d4 10803#if defined(TARGET_NR__newselect)
31e31b8a 10804 case TARGET_NR__newselect:
72eb7ea8 10805 return do_select(arg1, arg2, arg3, arg4, arg5);
e5febef5 10806#endif
e5ce9688 10807#ifdef TARGET_NR_poll
9de5e440 10808 case TARGET_NR_poll:
e5ce9688
FB
10809 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10810#endif
10811#ifdef TARGET_NR_ppoll
d8035d4c 10812 case TARGET_NR_ppoll:
e5ce9688
FB
10813 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10814#endif
10815#ifdef TARGET_NR_ppoll_time64
10816 case TARGET_NR_ppoll_time64:
10817 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
e5febef5 10818#endif
31e31b8a 10819 case TARGET_NR_flock:
9de5e440
FB
10820 /* NOTE: the flock constant seems to be the same for every
10821 Linux platform */
72eb7ea8 10822 return get_errno(safe_flock(arg1, arg2));
31e31b8a
FB
10823 case TARGET_NR_readv:
10824 {
f287b2c2
RH
10825 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10826 if (vec != NULL) {
918c03ed 10827 ret = get_errno(safe_readv(arg1, vec, arg3));
f287b2c2
RH
10828 unlock_iovec(vec, arg2, arg3, 1);
10829 } else {
10830 ret = -host_to_target_errno(errno);
10831 }
31e31b8a 10832 }
72eb7ea8 10833 return ret;
31e31b8a
FB
10834 case TARGET_NR_writev:
10835 {
f287b2c2
RH
10836 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10837 if (vec != NULL) {
918c03ed 10838 ret = get_errno(safe_writev(arg1, vec, arg3));
f287b2c2
RH
10839 unlock_iovec(vec, arg2, arg3, 0);
10840 } else {
10841 ret = -host_to_target_errno(errno);
10842 }
31e31b8a 10843 }
72eb7ea8 10844 return ret;
0f26386c
DJ
10845#if defined(TARGET_NR_preadv)
10846 case TARGET_NR_preadv:
10847 {
10848 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10849 if (vec != NULL) {
9ac22517
MF
10850 unsigned long low, high;
10851
10852 target_to_host_low_high(arg4, arg5, &low, &high);
10853 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
0f26386c
DJ
10854 unlock_iovec(vec, arg2, arg3, 1);
10855 } else {
10856 ret = -host_to_target_errno(errno);
f8d00fba
DJ
10857 }
10858 }
72eb7ea8 10859 return ret;
f8d00fba
DJ
10860#endif
10861#if defined(TARGET_NR_pwritev)
10862 case TARGET_NR_pwritev:
10863 {
10864 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10865 if (vec != NULL) {
9ac22517
MF
10866 unsigned long low, high;
10867
10868 target_to_host_low_high(arg4, arg5, &low, &high);
10869 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
f8d00fba
DJ
10870 unlock_iovec(vec, arg2, arg3, 0);
10871 } else {
10872 ret = -host_to_target_errno(errno);
0f26386c
DJ
10873 }
10874 }
72eb7ea8 10875 return ret;
0f26386c 10876#endif
31e31b8a 10877 case TARGET_NR_getsid:
72eb7ea8 10878 return get_errno(getsid(arg1));
7a3148a9 10879#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 10880 case TARGET_NR_fdatasync:
72eb7ea8 10881 return get_errno(fdatasync(arg1));
704eff6c 10882#endif
737de1d1
MF
10883 case TARGET_NR_sched_getaffinity:
10884 {
10885 unsigned int mask_size;
10886 unsigned long *mask;
10887
10888 /*
10889 * sched_getaffinity needs multiples of ulong, so need to take
10890 * care of mismatches between target ulong and host ulong sizes.
10891 */
10892 if (arg2 & (sizeof(abi_ulong) - 1)) {
72eb7ea8 10893 return -TARGET_EINVAL;
737de1d1
MF
10894 }
10895 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10896
10897 mask = alloca(mask_size);
2e0a8713 10898 memset(mask, 0, mask_size);
737de1d1
MF
10899 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10900
10901 if (!is_error(ret)) {
be3bd286
PM
10902 if (ret > arg2) {
10903 /* More data returned than the caller's buffer will fit.
10904 * This only happens if sizeof(abi_long) < sizeof(long)
10905 * and the caller passed us a buffer holding an odd number
10906 * of abi_longs. If the host kernel is actually using the
10907 * extra 4 bytes then fail EINVAL; otherwise we can just
10908 * ignore them and only copy the interesting part.
10909 */
10910 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10911 if (numcpus > arg2 * 8) {
72eb7ea8 10912 return -TARGET_EINVAL;
be3bd286
PM
10913 }
10914 ret = arg2;
10915 }
10916
5fdefcf8 10917 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
2852aafd 10918 return -TARGET_EFAULT;
5fdefcf8 10919 }
737de1d1
MF
10920 }
10921 }
72eb7ea8 10922 return ret;
737de1d1
MF
10923 case TARGET_NR_sched_setaffinity:
10924 {
10925 unsigned int mask_size;
10926 unsigned long *mask;
10927
10928 /*
10929 * sched_setaffinity needs multiples of ulong, so need to take
10930 * care of mismatches between target ulong and host ulong sizes.
10931 */
10932 if (arg2 & (sizeof(abi_ulong) - 1)) {
72eb7ea8 10933 return -TARGET_EINVAL;
737de1d1
MF
10934 }
10935 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
737de1d1 10936 mask = alloca(mask_size);
2e0a8713
ST
10937
10938 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10939 if (ret) {
72eb7ea8 10940 return ret;
737de1d1 10941 }
737de1d1 10942
72eb7ea8 10943 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
737de1d1 10944 }
b827c3ed
ST
10945 case TARGET_NR_getcpu:
10946 {
10947 unsigned cpu, node;
10948 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10949 arg2 ? &node : NULL,
10950 NULL));
10951 if (is_error(ret)) {
259841c1 10952 return ret;
b827c3ed
ST
10953 }
10954 if (arg1 && put_user_u32(cpu, arg1)) {
2852aafd 10955 return -TARGET_EFAULT;
b827c3ed
ST
10956 }
10957 if (arg2 && put_user_u32(node, arg2)) {
2852aafd 10958 return -TARGET_EFAULT;
b827c3ed
ST
10959 }
10960 }
72eb7ea8 10961 return ret;
31e31b8a 10962 case TARGET_NR_sched_setparam:
5cd4393b 10963 {
407a119b 10964 struct target_sched_param *target_schp;
5cd4393b 10965 struct sched_param schp;
53a5960a 10966
a1d5c5b2
TM
10967 if (arg2 == 0) {
10968 return -TARGET_EINVAL;
10969 }
407a119b 10970 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
2852aafd 10971 return -TARGET_EFAULT;
407a119b 10972 }
5cd4393b 10973 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10974 unlock_user_struct(target_schp, arg2, 0);
407a119b 10975 return get_errno(sys_sched_setparam(arg1, &schp));
5cd4393b 10976 }
31e31b8a 10977 case TARGET_NR_sched_getparam:
5cd4393b 10978 {
407a119b 10979 struct target_sched_param *target_schp;
5cd4393b 10980 struct sched_param schp;
a1d5c5b2
TM
10981
10982 if (arg2 == 0) {
10983 return -TARGET_EINVAL;
10984 }
407a119b 10985 ret = get_errno(sys_sched_getparam(arg1, &schp));
5cd4393b 10986 if (!is_error(ret)) {
407a119b 10987 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
2852aafd 10988 return -TARGET_EFAULT;
407a119b 10989 }
5cd4393b 10990 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 10991 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
10992 }
10993 }
72eb7ea8 10994 return ret;
31e31b8a 10995 case TARGET_NR_sched_setscheduler:
5cd4393b 10996 {
407a119b 10997 struct target_sched_param *target_schp;
5cd4393b 10998 struct sched_param schp;
a1d5c5b2
TM
10999 if (arg3 == 0) {
11000 return -TARGET_EINVAL;
11001 }
407a119b 11002 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
2852aafd 11003 return -TARGET_EFAULT;
407a119b 11004 }
5cd4393b 11005 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 11006 unlock_user_struct(target_schp, arg3, 0);
407a119b 11007 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
5cd4393b 11008 }
31e31b8a 11009 case TARGET_NR_sched_getscheduler:
407a119b 11010 return get_errno(sys_sched_getscheduler(arg1));
45ad761c
TT
11011 case TARGET_NR_sched_getattr:
11012 {
11013 struct target_sched_attr *target_scha;
11014 struct sched_attr scha;
11015 if (arg2 == 0) {
11016 return -TARGET_EINVAL;
11017 }
11018 if (arg3 > sizeof(scha)) {
11019 arg3 = sizeof(scha);
11020 }
11021 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
11022 if (!is_error(ret)) {
11023 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11024 if (!target_scha) {
11025 return -TARGET_EFAULT;
11026 }
11027 target_scha->size = tswap32(scha.size);
11028 target_scha->sched_policy = tswap32(scha.sched_policy);
11029 target_scha->sched_flags = tswap64(scha.sched_flags);
11030 target_scha->sched_nice = tswap32(scha.sched_nice);
11031 target_scha->sched_priority = tswap32(scha.sched_priority);
11032 target_scha->sched_runtime = tswap64(scha.sched_runtime);
11033 target_scha->sched_deadline = tswap64(scha.sched_deadline);
11034 target_scha->sched_period = tswap64(scha.sched_period);
11035 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
11036 target_scha->sched_util_min = tswap32(scha.sched_util_min);
11037 target_scha->sched_util_max = tswap32(scha.sched_util_max);
11038 }
11039 unlock_user(target_scha, arg2, arg3);
11040 }
11041 return ret;
11042 }
11043 case TARGET_NR_sched_setattr:
11044 {
11045 struct target_sched_attr *target_scha;
11046 struct sched_attr scha;
11047 uint32_t size;
11048 int zeroed;
11049 if (arg2 == 0) {
11050 return -TARGET_EINVAL;
11051 }
11052 if (get_user_u32(size, arg2)) {
11053 return -TARGET_EFAULT;
11054 }
11055 if (!size) {
11056 size = offsetof(struct target_sched_attr, sched_util_min);
11057 }
11058 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
11059 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11060 return -TARGET_EFAULT;
11061 }
11062 return -TARGET_E2BIG;
11063 }
11064
11065 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
11066 if (zeroed < 0) {
11067 return zeroed;
11068 } else if (zeroed == 0) {
11069 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11070 return -TARGET_EFAULT;
11071 }
11072 return -TARGET_E2BIG;
11073 }
11074 if (size > sizeof(struct target_sched_attr)) {
11075 size = sizeof(struct target_sched_attr);
11076 }
11077
11078 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
11079 if (!target_scha) {
11080 return -TARGET_EFAULT;
11081 }
11082 scha.size = size;
11083 scha.sched_policy = tswap32(target_scha->sched_policy);
11084 scha.sched_flags = tswap64(target_scha->sched_flags);
11085 scha.sched_nice = tswap32(target_scha->sched_nice);
11086 scha.sched_priority = tswap32(target_scha->sched_priority);
11087 scha.sched_runtime = tswap64(target_scha->sched_runtime);
11088 scha.sched_deadline = tswap64(target_scha->sched_deadline);
11089 scha.sched_period = tswap64(target_scha->sched_period);
11090 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
11091 scha.sched_util_min = tswap32(target_scha->sched_util_min);
11092 scha.sched_util_max = tswap32(target_scha->sched_util_max);
11093 }
11094 unlock_user(target_scha, arg2, 0);
11095 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
11096 }
31e31b8a 11097 case TARGET_NR_sched_yield:
72eb7ea8 11098 return get_errno(sched_yield());
31e31b8a 11099 case TARGET_NR_sched_get_priority_max:
72eb7ea8 11100 return get_errno(sched_get_priority_max(arg1));
31e31b8a 11101 case TARGET_NR_sched_get_priority_min:
72eb7ea8 11102 return get_errno(sched_get_priority_min(arg1));
859e8a89 11103#ifdef TARGET_NR_sched_rr_get_interval
31e31b8a 11104 case TARGET_NR_sched_rr_get_interval:
5cd4393b 11105 {
5cd4393b
FB
11106 struct timespec ts;
11107 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11108 if (!is_error(ret)) {
d4290c40 11109 ret = host_to_target_timespec(arg2, &ts);
5cd4393b
FB
11110 }
11111 }
72eb7ea8 11112 return ret;
859e8a89 11113#endif
ddcbde15
FB
11114#ifdef TARGET_NR_sched_rr_get_interval_time64
11115 case TARGET_NR_sched_rr_get_interval_time64:
11116 {
11117 struct timespec ts;
11118 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11119 if (!is_error(ret)) {
11120 ret = host_to_target_timespec64(arg2, &ts);
11121 }
11122 }
11123 return ret;
11124#endif
859e8a89 11125#if defined(TARGET_NR_nanosleep)
31e31b8a 11126 case TARGET_NR_nanosleep:
1b6b029e 11127 {
1b6b029e 11128 struct timespec req, rem;
53a5960a 11129 target_to_host_timespec(&req, arg1);
9e518226 11130 ret = get_errno(safe_nanosleep(&req, &rem));
53a5960a
PB
11131 if (is_error(ret) && arg2) {
11132 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
11133 }
11134 }
72eb7ea8 11135 return ret;
859e8a89 11136#endif
31e31b8a 11137 case TARGET_NR_prctl:
87e9bf23 11138 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
39b9aae1 11139 break;
d2fd1af7
FB
11140#ifdef TARGET_NR_arch_prctl
11141 case TARGET_NR_arch_prctl:
72eb7ea8 11142 return do_arch_prctl(cpu_env, arg1, arg2);
d2fd1af7 11143#endif
f2c7ba15
AJ
11144#ifdef TARGET_NR_pread64
11145 case TARGET_NR_pread64:
8bf8e9df 11146 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
11147 arg4 = arg5;
11148 arg5 = arg6;
11149 }
2bd3f899
PM
11150 if (arg2 == 0 && arg3 == 0) {
11151 /* Special-case NULL buffer and zero length, which should succeed */
11152 p = 0;
11153 } else {
11154 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11155 if (!p) {
11156 return -TARGET_EFAULT;
11157 }
11158 }
f2c7ba15
AJ
11159 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11160 unlock_user(p, arg2, ret);
72eb7ea8 11161 return ret;
f2c7ba15 11162 case TARGET_NR_pwrite64:
8bf8e9df 11163 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
11164 arg4 = arg5;
11165 arg5 = arg6;
11166 }
2bd3f899
PM
11167 if (arg2 == 0 && arg3 == 0) {
11168 /* Special-case NULL buffer and zero length, which should succeed */
11169 p = 0;
11170 } else {
11171 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11172 if (!p) {
11173 return -TARGET_EFAULT;
11174 }
11175 }
f2c7ba15
AJ
11176 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11177 unlock_user(p, arg2, 0);
72eb7ea8 11178 return ret;
67867308 11179#endif
31e31b8a 11180 case TARGET_NR_getcwd:
579a97f7 11181 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
2852aafd 11182 return -TARGET_EFAULT;
53a5960a
PB
11183 ret = get_errno(sys_getcwd1(p, arg2));
11184 unlock_user(p, arg1, ret);
72eb7ea8 11185 return ret;
31e31b8a
FB
11186 case TARGET_NR_capget:
11187 case TARGET_NR_capset:
e0eb210e
PM
11188 {
11189 struct target_user_cap_header *target_header;
11190 struct target_user_cap_data *target_data = NULL;
11191 struct __user_cap_header_struct header;
11192 struct __user_cap_data_struct data[2];
11193 struct __user_cap_data_struct *dataptr = NULL;
11194 int i, target_datalen;
11195 int data_items = 1;
11196
11197 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
2852aafd 11198 return -TARGET_EFAULT;
e0eb210e
PM
11199 }
11200 header.version = tswap32(target_header->version);
11201 header.pid = tswap32(target_header->pid);
11202
ec864874 11203 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
11204 /* Version 2 and up takes pointer to two user_data structs */
11205 data_items = 2;
11206 }
11207
11208 target_datalen = sizeof(*target_data) * data_items;
11209
11210 if (arg2) {
11211 if (num == TARGET_NR_capget) {
11212 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11213 } else {
11214 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11215 }
11216 if (!target_data) {
11217 unlock_user_struct(target_header, arg1, 0);
2852aafd 11218 return -TARGET_EFAULT;
e0eb210e
PM
11219 }
11220
11221 if (num == TARGET_NR_capset) {
11222 for (i = 0; i < data_items; i++) {
11223 data[i].effective = tswap32(target_data[i].effective);
11224 data[i].permitted = tswap32(target_data[i].permitted);
11225 data[i].inheritable = tswap32(target_data[i].inheritable);
11226 }
11227 }
11228
11229 dataptr = data;
11230 }
11231
11232 if (num == TARGET_NR_capget) {
11233 ret = get_errno(capget(&header, dataptr));
11234 } else {
11235 ret = get_errno(capset(&header, dataptr));
11236 }
11237
11238 /* The kernel always updates version for both capget and capset */
11239 target_header->version = tswap32(header.version);
11240 unlock_user_struct(target_header, arg1, 1);
11241
11242 if (arg2) {
11243 if (num == TARGET_NR_capget) {
11244 for (i = 0; i < data_items; i++) {
11245 target_data[i].effective = tswap32(data[i].effective);
11246 target_data[i].permitted = tswap32(data[i].permitted);
11247 target_data[i].inheritable = tswap32(data[i].inheritable);
11248 }
11249 unlock_user(target_data, arg2, target_datalen);
11250 } else {
11251 unlock_user(target_data, arg2, 0);
11252 }
11253 }
72eb7ea8 11254 return ret;
e0eb210e 11255 }
31e31b8a 11256 case TARGET_NR_sigaltstack:
6b208755 11257 return do_sigaltstack(arg1, arg2, cpu_env);
a8fd1aba
PM
11258
11259#ifdef CONFIG_SENDFILE
4f7f8924 11260#ifdef TARGET_NR_sendfile
a8fd1aba
PM
11261 case TARGET_NR_sendfile:
11262 {
11263 off_t *offp = NULL;
11264 off_t off;
11265 if (arg3) {
11266 ret = get_user_sal(off, arg3);
11267 if (is_error(ret)) {
72eb7ea8 11268 return ret;
a8fd1aba
PM
11269 }
11270 offp = &off;
11271 }
11272 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11273 if (!is_error(ret) && arg3) {
11274 abi_long ret2 = put_user_sal(off, arg3);
11275 if (is_error(ret2)) {
11276 ret = ret2;
11277 }
11278 }
72eb7ea8 11279 return ret;
a8fd1aba 11280 }
4f7f8924 11281#endif
a8fd1aba
PM
11282#ifdef TARGET_NR_sendfile64
11283 case TARGET_NR_sendfile64:
11284 {
11285 off_t *offp = NULL;
11286 off_t off;
11287 if (arg3) {
11288 ret = get_user_s64(off, arg3);
11289 if (is_error(ret)) {
72eb7ea8 11290 return ret;
a8fd1aba
PM
11291 }
11292 offp = &off;
11293 }
11294 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11295 if (!is_error(ret) && arg3) {
11296 abi_long ret2 = put_user_s64(off, arg3);
11297 if (is_error(ret2)) {
11298 ret = ret2;
11299 }
11300 }
72eb7ea8 11301 return ret;
a8fd1aba
PM
11302 }
11303#endif
ebc05488 11304#endif
048f6b4d 11305#ifdef TARGET_NR_vfork
31e31b8a 11306 case TARGET_NR_vfork:
72eb7ea8
RH
11307 return get_errno(do_fork(cpu_env,
11308 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11309 0, 0, 0, 0));
048f6b4d 11310#endif
ebc05488 11311#ifdef TARGET_NR_ugetrlimit
31e31b8a 11312 case TARGET_NR_ugetrlimit:
728584be
FB
11313 {
11314 struct rlimit rlim;
e22b7015
WT
11315 int resource = target_to_host_resource(arg1);
11316 ret = get_errno(getrlimit(resource, &rlim));
728584be 11317 if (!is_error(ret)) {
53a5960a 11318 struct target_rlimit *target_rlim;
579a97f7 11319 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 11320 return -TARGET_EFAULT;
81bbe906
TY
11321 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11322 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 11323 unlock_user_struct(target_rlim, arg2, 1);
728584be 11324 }
72eb7ea8 11325 return ret;
728584be 11326 }
ebc05488 11327#endif
a315a145 11328#ifdef TARGET_NR_truncate64
31e31b8a 11329 case TARGET_NR_truncate64:
579a97f7 11330 if (!(p = lock_user_string(arg1)))
2852aafd 11331 return -TARGET_EFAULT;
53a5960a
PB
11332 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11333 unlock_user(p, arg1, 0);
72eb7ea8 11334 return ret;
a315a145
FB
11335#endif
11336#ifdef TARGET_NR_ftruncate64
31e31b8a 11337 case TARGET_NR_ftruncate64:
72eb7ea8 11338 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
a315a145
FB
11339#endif
11340#ifdef TARGET_NR_stat64
31e31b8a 11341 case TARGET_NR_stat64:
2852aafd
RH
11342 if (!(p = lock_user_string(arg1))) {
11343 return -TARGET_EFAULT;
11344 }
53a5960a
PB
11345 ret = get_errno(stat(path(p), &st));
11346 unlock_user(p, arg1, 0);
6a24a778
AZ
11347 if (!is_error(ret))
11348 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11349 return ret;
a315a145
FB
11350#endif
11351#ifdef TARGET_NR_lstat64
31e31b8a 11352 case TARGET_NR_lstat64:
2852aafd
RH
11353 if (!(p = lock_user_string(arg1))) {
11354 return -TARGET_EFAULT;
11355 }
53a5960a
PB
11356 ret = get_errno(lstat(path(p), &st));
11357 unlock_user(p, arg1, 0);
6a24a778
AZ
11358 if (!is_error(ret))
11359 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11360 return ret;
a315a145
FB
11361#endif
11362#ifdef TARGET_NR_fstat64
31e31b8a 11363 case TARGET_NR_fstat64:
6a24a778
AZ
11364 ret = get_errno(fstat(arg1, &st));
11365 if (!is_error(ret))
11366 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11367 return ret;
ce4defa0 11368#endif
c0d472b1 11369#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 11370#ifdef TARGET_NR_fstatat64
6a24a778 11371 case TARGET_NR_fstatat64:
9d33b76b
AJ
11372#endif
11373#ifdef TARGET_NR_newfstatat
11374 case TARGET_NR_newfstatat:
11375#endif
2852aafd
RH
11376 if (!(p = lock_user_string(arg2))) {
11377 return -TARGET_EFAULT;
11378 }
c0d472b1 11379 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
2852aafd 11380 unlock_user(p, arg2, 0);
6a24a778
AZ
11381 if (!is_error(ret))
11382 ret = host_to_target_stat64(cpu_env, arg3, &st);
72eb7ea8 11383 return ret;
a315a145 11384#endif
efa92184
AR
11385#if defined(TARGET_NR_statx)
11386 case TARGET_NR_statx:
11387 {
11388 struct target_statx *target_stx;
11389 int dirfd = arg1;
11390 int flags = arg3;
11391
11392 p = lock_user_string(arg2);
11393 if (p == NULL) {
11394 return -TARGET_EFAULT;
11395 }
11396#if defined(__NR_statx)
11397 {
11398 /*
11399 * It is assumed that struct statx is architecture independent.
11400 */
11401 struct target_statx host_stx;
11402 int mask = arg4;
11403
11404 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11405 if (!is_error(ret)) {
11406 if (host_to_target_statx(&host_stx, arg5) != 0) {
11407 unlock_user(p, arg2, 0);
11408 return -TARGET_EFAULT;
11409 }
11410 }
11411
11412 if (ret != -TARGET_ENOSYS) {
11413 unlock_user(p, arg2, 0);
11414 return ret;
11415 }
11416 }
11417#endif
11418 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11419 unlock_user(p, arg2, 0);
11420
11421 if (!is_error(ret)) {
11422 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11423 return -TARGET_EFAULT;
11424 }
11425 memset(target_stx, 0, sizeof(*target_stx));
11426 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11427 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11428 __put_user(st.st_ino, &target_stx->stx_ino);
11429 __put_user(st.st_mode, &target_stx->stx_mode);
11430 __put_user(st.st_uid, &target_stx->stx_uid);
11431 __put_user(st.st_gid, &target_stx->stx_gid);
11432 __put_user(st.st_nlink, &target_stx->stx_nlink);
11433 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11434 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11435 __put_user(st.st_size, &target_stx->stx_size);
11436 __put_user(st.st_blksize, &target_stx->stx_blksize);
11437 __put_user(st.st_blocks, &target_stx->stx_blocks);
11438 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11439 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11440 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11441 unlock_user_struct(target_stx, arg5, 1);
11442 }
11443 }
11444 return ret;
11445#endif
704eff6c 11446#ifdef TARGET_NR_lchown
67867308 11447 case TARGET_NR_lchown:
579a97f7 11448 if (!(p = lock_user_string(arg1)))
2852aafd 11449 return -TARGET_EFAULT;
53a5960a
PB
11450 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11451 unlock_user(p, arg1, 0);
72eb7ea8 11452 return ret;
704eff6c 11453#endif
0c866a7e 11454#ifdef TARGET_NR_getuid
67867308 11455 case TARGET_NR_getuid:
72eb7ea8 11456 return get_errno(high2lowuid(getuid()));
0c866a7e
RV
11457#endif
11458#ifdef TARGET_NR_getgid
67867308 11459 case TARGET_NR_getgid:
72eb7ea8 11460 return get_errno(high2lowgid(getgid()));
0c866a7e
RV
11461#endif
11462#ifdef TARGET_NR_geteuid
67867308 11463 case TARGET_NR_geteuid:
72eb7ea8 11464 return get_errno(high2lowuid(geteuid()));
0c866a7e
RV
11465#endif
11466#ifdef TARGET_NR_getegid
67867308 11467 case TARGET_NR_getegid:
72eb7ea8 11468 return get_errno(high2lowgid(getegid()));
0c866a7e 11469#endif
67867308 11470 case TARGET_NR_setreuid:
72eb7ea8 11471 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
67867308 11472 case TARGET_NR_setregid:
72eb7ea8 11473 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
67867308
FB
11474 case TARGET_NR_getgroups:
11475 {
11476 int gidsetsize = arg1;
0c866a7e 11477 target_id *target_grouplist;
67867308
FB
11478 gid_t *grouplist;
11479 int i;
11480
11481 grouplist = alloca(gidsetsize * sizeof(gid_t));
11482 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11483 if (gidsetsize == 0)
72eb7ea8 11484 return ret;
67867308 11485 if (!is_error(ret)) {
03903ffc 11486 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7 11487 if (!target_grouplist)
2852aafd 11488 return -TARGET_EFAULT;
a2155fcc 11489 for(i = 0;i < ret; i++)
0c866a7e 11490 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 11491 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
11492 }
11493 }
72eb7ea8 11494 return ret;
67867308
FB
11495 case TARGET_NR_setgroups:
11496 {
11497 int gidsetsize = arg1;
0c866a7e 11498 target_id *target_grouplist;
f2b79ce9 11499 gid_t *grouplist = NULL;
67867308 11500 int i;
f2b79ce9
DA
11501 if (gidsetsize) {
11502 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 11503 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9 11504 if (!target_grouplist) {
259841c1 11505 return -TARGET_EFAULT;
f2b79ce9
DA
11506 }
11507 for (i = 0; i < gidsetsize; i++) {
11508 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11509 }
11510 unlock_user(target_grouplist, arg2, 0);
579a97f7 11511 }
72eb7ea8 11512 return get_errno(setgroups(gidsetsize, grouplist));
67867308 11513 }
67867308 11514 case TARGET_NR_fchown:
72eb7ea8 11515 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
c0d472b1 11516#if defined(TARGET_NR_fchownat)
ccfa72b7 11517 case TARGET_NR_fchownat:
579a97f7 11518 if (!(p = lock_user_string(arg2)))
2852aafd 11519 return -TARGET_EFAULT;
c0d472b1
PM
11520 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11521 low2highgid(arg4), arg5));
579a97f7 11522 unlock_user(p, arg2, 0);
72eb7ea8 11523 return ret;
ccfa72b7 11524#endif
67867308
FB
11525#ifdef TARGET_NR_setresuid
11526 case TARGET_NR_setresuid:
72eb7ea8
RH
11527 return get_errno(sys_setresuid(low2highuid(arg1),
11528 low2highuid(arg2),
11529 low2highuid(arg3)));
67867308
FB
11530#endif
11531#ifdef TARGET_NR_getresuid
11532 case TARGET_NR_getresuid:
11533 {
53a5960a 11534 uid_t ruid, euid, suid;
67867308
FB
11535 ret = get_errno(getresuid(&ruid, &euid, &suid));
11536 if (!is_error(ret)) {
76ca310a
PM
11537 if (put_user_id(high2lowuid(ruid), arg1)
11538 || put_user_id(high2lowuid(euid), arg2)
11539 || put_user_id(high2lowuid(suid), arg3))
2852aafd 11540 return -TARGET_EFAULT;
67867308
FB
11541 }
11542 }
72eb7ea8 11543 return ret;
67867308
FB
11544#endif
11545#ifdef TARGET_NR_getresgid
11546 case TARGET_NR_setresgid:
72eb7ea8
RH
11547 return get_errno(sys_setresgid(low2highgid(arg1),
11548 low2highgid(arg2),
11549 low2highgid(arg3)));
67867308
FB
11550#endif
11551#ifdef TARGET_NR_getresgid
11552 case TARGET_NR_getresgid:
11553 {
53a5960a 11554 gid_t rgid, egid, sgid;
67867308
FB
11555 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11556 if (!is_error(ret)) {
76ca310a
PM
11557 if (put_user_id(high2lowgid(rgid), arg1)
11558 || put_user_id(high2lowgid(egid), arg2)
11559 || put_user_id(high2lowgid(sgid), arg3))
2852aafd 11560 return -TARGET_EFAULT;
67867308
FB
11561 }
11562 }
72eb7ea8 11563 return ret;
67867308 11564#endif
704eff6c 11565#ifdef TARGET_NR_chown
67867308 11566 case TARGET_NR_chown:
579a97f7 11567 if (!(p = lock_user_string(arg1)))
2852aafd 11568 return -TARGET_EFAULT;
53a5960a
PB
11569 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11570 unlock_user(p, arg1, 0);
72eb7ea8 11571 return ret;
704eff6c 11572#endif
67867308 11573 case TARGET_NR_setuid:
72eb7ea8 11574 return get_errno(sys_setuid(low2highuid(arg1)));
67867308 11575 case TARGET_NR_setgid:
72eb7ea8 11576 return get_errno(sys_setgid(low2highgid(arg1)));
67867308 11577 case TARGET_NR_setfsuid:
72eb7ea8 11578 return get_errno(setfsuid(arg1));
67867308 11579 case TARGET_NR_setfsgid:
72eb7ea8 11580 return get_errno(setfsgid(arg1));
67867308 11581
a315a145 11582#ifdef TARGET_NR_lchown32
31e31b8a 11583 case TARGET_NR_lchown32:
579a97f7 11584 if (!(p = lock_user_string(arg1)))
2852aafd 11585 return -TARGET_EFAULT;
53a5960a
PB
11586 ret = get_errno(lchown(p, arg2, arg3));
11587 unlock_user(p, arg1, 0);
72eb7ea8 11588 return ret;
a315a145
FB
11589#endif
11590#ifdef TARGET_NR_getuid32
31e31b8a 11591 case TARGET_NR_getuid32:
72eb7ea8 11592 return get_errno(getuid());
a315a145 11593#endif
64b4d28c
AJ
11594
11595#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11596 /* Alpha specific */
11597 case TARGET_NR_getxuid:
ba0e276d
RH
11598 {
11599 uid_t euid;
11600 euid=geteuid();
0effdc29 11601 cpu_env->ir[IR_A4]=euid;
ba0e276d 11602 }
72eb7ea8 11603 return get_errno(getuid());
64b4d28c
AJ
11604#endif
11605#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11606 /* Alpha specific */
11607 case TARGET_NR_getxgid:
ba0e276d
RH
11608 {
11609 uid_t egid;
11610 egid=getegid();
0effdc29 11611 cpu_env->ir[IR_A4]=egid;
ba0e276d 11612 }
72eb7ea8 11613 return get_errno(getgid());
64b4d28c 11614#endif
ba0e276d
RH
11615#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11616 /* Alpha specific */
11617 case TARGET_NR_osf_getsysinfo:
11618 ret = -TARGET_EOPNOTSUPP;
11619 switch (arg1) {
11620 case TARGET_GSI_IEEE_FP_CONTROL:
11621 {
21ba8564 11622 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
0effdc29 11623 uint64_t swcr = cpu_env->swcr;
21ba8564
RH
11624
11625 swcr &= ~SWCR_STATUS_MASK;
11626 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
ba0e276d
RH
11627
11628 if (put_user_u64 (swcr, arg2))
2852aafd 11629 return -TARGET_EFAULT;
ba0e276d
RH
11630 ret = 0;
11631 }
11632 break;
11633
11634 /* case GSI_IEEE_STATE_AT_SIGNAL:
11635 -- Not implemented in linux kernel.
11636 case GSI_UACPROC:
11637 -- Retrieves current unaligned access state; not much used.
11638 case GSI_PROC_TYPE:
11639 -- Retrieves implver information; surely not used.
11640 case GSI_GET_HWRPB:
11641 -- Grabs a copy of the HWRPB; surely not used.
11642 */
11643 }
72eb7ea8 11644 return ret;
ba0e276d
RH
11645#endif
11646#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11647 /* Alpha specific */
11648 case TARGET_NR_osf_setsysinfo:
11649 ret = -TARGET_EOPNOTSUPP;
11650 switch (arg1) {
11651 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d 11652 {
21ba8564 11653 uint64_t swcr, fpcr;
ba0e276d 11654
6e06d515 11655 if (get_user_u64 (swcr, arg2)) {
2852aafd 11656 return -TARGET_EFAULT;
6e06d515 11657 }
ba0e276d 11658
21ba8564
RH
11659 /*
11660 * The kernel calls swcr_update_status to update the
11661 * status bits from the fpcr at every point that it
11662 * could be queried. Therefore, we store the status
11663 * bits only in FPCR.
11664 */
0effdc29 11665 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
21ba8564
RH
11666
11667 fpcr = cpu_alpha_load_fpcr(cpu_env);
11668 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11669 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
6e06d515 11670 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 11671 ret = 0;
6e06d515
RH
11672 }
11673 break;
11674
11675 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11676 {
21ba8564 11677 uint64_t exc, fpcr, fex;
6e06d515
RH
11678
11679 if (get_user_u64(exc, arg2)) {
2852aafd 11680 return -TARGET_EFAULT;
6e06d515 11681 }
21ba8564
RH
11682 exc &= SWCR_STATUS_MASK;
11683 fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 11684
21ba8564
RH
11685 /* Old exceptions are not signaled. */
11686 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11687 fex = exc & ~fex;
11688 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
0effdc29 11689 fex &= (cpu_env)->swcr;
6e06d515 11690
21ba8564
RH
11691 /* Update the hardware fpcr. */
11692 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
6e06d515 11693 cpu_alpha_store_fpcr(cpu_env, fpcr);
6e06d515 11694
21ba8564
RH
11695 if (fex) {
11696 int si_code = TARGET_FPE_FLTUNK;
6e06d515 11697 target_siginfo_t info;
21ba8564
RH
11698
11699 if (fex & SWCR_TRAP_ENABLE_DNO) {
11700 si_code = TARGET_FPE_FLTUND;
11701 }
11702 if (fex & SWCR_TRAP_ENABLE_INE) {
11703 si_code = TARGET_FPE_FLTRES;
11704 }
11705 if (fex & SWCR_TRAP_ENABLE_UNF) {
11706 si_code = TARGET_FPE_FLTUND;
11707 }
11708 if (fex & SWCR_TRAP_ENABLE_OVF) {
11709 si_code = TARGET_FPE_FLTOVF;
11710 }
11711 if (fex & SWCR_TRAP_ENABLE_DZE) {
11712 si_code = TARGET_FPE_FLTDIV;
11713 }
11714 if (fex & SWCR_TRAP_ENABLE_INV) {
11715 si_code = TARGET_FPE_FLTINV;
11716 }
11717
6e06d515
RH
11718 info.si_signo = SIGFPE;
11719 info.si_errno = 0;
11720 info.si_code = si_code;
0effdc29
PMD
11721 info._sifields._sigfault._addr = (cpu_env)->pc;
11722 queue_signal(cpu_env, info.si_signo,
9d2803f7 11723 QEMU_SI_FAULT, &info);
ba0e276d 11724 }
21ba8564 11725 ret = 0;
ba0e276d
RH
11726 }
11727 break;
11728
11729 /* case SSI_NVPAIRS:
11730 -- Used with SSIN_UACPROC to enable unaligned accesses.
11731 case SSI_IEEE_STATE_AT_SIGNAL:
11732 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11733 -- Not implemented in linux kernel
11734 */
11735 }
72eb7ea8 11736 return ret;
ba0e276d
RH
11737#endif
11738#ifdef TARGET_NR_osf_sigprocmask
11739 /* Alpha specific. */
11740 case TARGET_NR_osf_sigprocmask:
11741 {
11742 abi_ulong mask;
bc088ba1 11743 int how;
ba0e276d
RH
11744 sigset_t set, oldset;
11745
11746 switch(arg1) {
11747 case TARGET_SIG_BLOCK:
11748 how = SIG_BLOCK;
11749 break;
11750 case TARGET_SIG_UNBLOCK:
11751 how = SIG_UNBLOCK;
11752 break;
11753 case TARGET_SIG_SETMASK:
11754 how = SIG_SETMASK;
11755 break;
11756 default:
259841c1 11757 return -TARGET_EINVAL;
ba0e276d
RH
11758 }
11759 mask = arg2;
11760 target_to_host_old_sigset(&set, &mask);
3d3efba0
PM
11761 ret = do_sigprocmask(how, &set, &oldset);
11762 if (!ret) {
11763 host_to_target_old_sigset(&mask, &oldset);
11764 ret = mask;
11765 }
ba0e276d 11766 }
72eb7ea8 11767 return ret;
ba0e276d 11768#endif
64b4d28c 11769
a315a145 11770#ifdef TARGET_NR_getgid32
31e31b8a 11771 case TARGET_NR_getgid32:
72eb7ea8 11772 return get_errno(getgid());
a315a145
FB
11773#endif
11774#ifdef TARGET_NR_geteuid32
31e31b8a 11775 case TARGET_NR_geteuid32:
72eb7ea8 11776 return get_errno(geteuid());
a315a145
FB
11777#endif
11778#ifdef TARGET_NR_getegid32
31e31b8a 11779 case TARGET_NR_getegid32:
72eb7ea8 11780 return get_errno(getegid());
a315a145
FB
11781#endif
11782#ifdef TARGET_NR_setreuid32
31e31b8a 11783 case TARGET_NR_setreuid32:
72eb7ea8 11784 return get_errno(setreuid(arg1, arg2));
a315a145
FB
11785#endif
11786#ifdef TARGET_NR_setregid32
31e31b8a 11787 case TARGET_NR_setregid32:
72eb7ea8 11788 return get_errno(setregid(arg1, arg2));
a315a145
FB
11789#endif
11790#ifdef TARGET_NR_getgroups32
31e31b8a 11791 case TARGET_NR_getgroups32:
99c475ab
FB
11792 {
11793 int gidsetsize = arg1;
53a5960a 11794 uint32_t *target_grouplist;
99c475ab
FB
11795 gid_t *grouplist;
11796 int i;
11797
11798 grouplist = alloca(gidsetsize * sizeof(gid_t));
11799 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11800 if (gidsetsize == 0)
72eb7ea8 11801 return ret;
99c475ab 11802 if (!is_error(ret)) {
579a97f7
FB
11803 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11804 if (!target_grouplist) {
259841c1 11805 return -TARGET_EFAULT;
579a97f7 11806 }
a2155fcc 11807 for(i = 0;i < ret; i++)
53a5960a
PB
11808 target_grouplist[i] = tswap32(grouplist[i]);
11809 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
11810 }
11811 }
72eb7ea8 11812 return ret;
a315a145
FB
11813#endif
11814#ifdef TARGET_NR_setgroups32
31e31b8a 11815 case TARGET_NR_setgroups32:
99c475ab
FB
11816 {
11817 int gidsetsize = arg1;
53a5960a 11818 uint32_t *target_grouplist;
99c475ab
FB
11819 gid_t *grouplist;
11820 int i;
3b46e624 11821
99c475ab 11822 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
11823 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11824 if (!target_grouplist) {
259841c1 11825 return -TARGET_EFAULT;
579a97f7 11826 }
99c475ab 11827 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
11828 grouplist[i] = tswap32(target_grouplist[i]);
11829 unlock_user(target_grouplist, arg2, 0);
72eb7ea8 11830 return get_errno(setgroups(gidsetsize, grouplist));
99c475ab 11831 }
a315a145
FB
11832#endif
11833#ifdef TARGET_NR_fchown32
31e31b8a 11834 case TARGET_NR_fchown32:
72eb7ea8 11835 return get_errno(fchown(arg1, arg2, arg3));
a315a145
FB
11836#endif
11837#ifdef TARGET_NR_setresuid32
31e31b8a 11838 case TARGET_NR_setresuid32:
72eb7ea8 11839 return get_errno(sys_setresuid(arg1, arg2, arg3));
a315a145
FB
11840#endif
11841#ifdef TARGET_NR_getresuid32
31e31b8a 11842 case TARGET_NR_getresuid32:
b03c60f3 11843 {
53a5960a 11844 uid_t ruid, euid, suid;
b03c60f3
FB
11845 ret = get_errno(getresuid(&ruid, &euid, &suid));
11846 if (!is_error(ret)) {
2f619698
FB
11847 if (put_user_u32(ruid, arg1)
11848 || put_user_u32(euid, arg2)
11849 || put_user_u32(suid, arg3))
2852aafd 11850 return -TARGET_EFAULT;
b03c60f3
FB
11851 }
11852 }
72eb7ea8 11853 return ret;
a315a145
FB
11854#endif
11855#ifdef TARGET_NR_setresgid32
31e31b8a 11856 case TARGET_NR_setresgid32:
72eb7ea8 11857 return get_errno(sys_setresgid(arg1, arg2, arg3));
a315a145
FB
11858#endif
11859#ifdef TARGET_NR_getresgid32
31e31b8a 11860 case TARGET_NR_getresgid32:
b03c60f3 11861 {
53a5960a 11862 gid_t rgid, egid, sgid;
b03c60f3
FB
11863 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11864 if (!is_error(ret)) {
2f619698
FB
11865 if (put_user_u32(rgid, arg1)
11866 || put_user_u32(egid, arg2)
11867 || put_user_u32(sgid, arg3))
2852aafd 11868 return -TARGET_EFAULT;
b03c60f3
FB
11869 }
11870 }
72eb7ea8 11871 return ret;
a315a145
FB
11872#endif
11873#ifdef TARGET_NR_chown32
31e31b8a 11874 case TARGET_NR_chown32:
579a97f7 11875 if (!(p = lock_user_string(arg1)))
2852aafd 11876 return -TARGET_EFAULT;
53a5960a
PB
11877 ret = get_errno(chown(p, arg2, arg3));
11878 unlock_user(p, arg1, 0);
72eb7ea8 11879 return ret;
a315a145
FB
11880#endif
11881#ifdef TARGET_NR_setuid32
31e31b8a 11882 case TARGET_NR_setuid32:
72eb7ea8 11883 return get_errno(sys_setuid(arg1));
a315a145
FB
11884#endif
11885#ifdef TARGET_NR_setgid32
31e31b8a 11886 case TARGET_NR_setgid32:
72eb7ea8 11887 return get_errno(sys_setgid(arg1));
a315a145
FB
11888#endif
11889#ifdef TARGET_NR_setfsuid32
31e31b8a 11890 case TARGET_NR_setfsuid32:
72eb7ea8 11891 return get_errno(setfsuid(arg1));
a315a145
FB
11892#endif
11893#ifdef TARGET_NR_setfsgid32
31e31b8a 11894 case TARGET_NR_setfsgid32:
72eb7ea8 11895 return get_errno(setfsgid(arg1));
a315a145 11896#endif
ffa65c3b 11897#ifdef TARGET_NR_mincore
31e31b8a 11898 case TARGET_NR_mincore:
04bb9ace 11899 {
259841c1 11900 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
98a3331a 11901 if (!a) {
259841c1 11902 return -TARGET_ENOMEM;
98a3331a 11903 }
98a3331a
FSM
11904 p = lock_user_string(arg3);
11905 if (!p) {
259841c1
RH
11906 ret = -TARGET_EFAULT;
11907 } else {
11908 ret = get_errno(mincore(a, arg2, p));
11909 unlock_user(p, arg3, ret);
98a3331a 11910 }
04bb9ace
AJ
11911 unlock_user(a, arg1, 0);
11912 }
72eb7ea8 11913 return ret;
ffa65c3b 11914#endif
408321b6
AJ
11915#ifdef TARGET_NR_arm_fadvise64_64
11916 case TARGET_NR_arm_fadvise64_64:
e0156a9d
PM
11917 /* arm_fadvise64_64 looks like fadvise64_64 but
11918 * with different argument order: fd, advice, offset, len
11919 * rather than the usual fd, offset, len, advice.
11920 * Note that offset and len are both 64-bit so appear as
11921 * pairs of 32-bit registers.
11922 */
11923 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11924 target_offset64(arg5, arg6), arg2);
72eb7ea8 11925 return -host_to_target_errno(ret);
408321b6 11926#endif
badd3cd8 11927
eeed2291 11928#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
badd3cd8
PM
11929
11930#ifdef TARGET_NR_fadvise64_64
11931 case TARGET_NR_fadvise64_64:
64a563dd 11932#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
43046b5a
LV
11933 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11934 ret = arg2;
11935 arg2 = arg3;
11936 arg3 = arg4;
11937 arg4 = arg5;
11938 arg5 = arg6;
11939 arg6 = ret;
11940#else
badd3cd8 11941 /* 6 args: fd, offset (high, low), len (high, low), advice */
8bf8e9df 11942 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11943 /* offset is in (3,4), len in (5,6) and advice in 7 */
11944 arg2 = arg3;
11945 arg3 = arg4;
11946 arg4 = arg5;
11947 arg5 = arg6;
11948 arg6 = arg7;
11949 }
43046b5a 11950#endif
72eb7ea8
RH
11951 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11952 target_offset64(arg4, arg5), arg6);
11953 return -host_to_target_errno(ret);
badd3cd8
PM
11954#endif
11955
11956#ifdef TARGET_NR_fadvise64
11957 case TARGET_NR_fadvise64:
11958 /* 5 args: fd, offset (high, low), len, advice */
8bf8e9df 11959 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11960 /* offset is in (3,4), len in 5 and advice in 6 */
11961 arg2 = arg3;
11962 arg3 = arg4;
11963 arg4 = arg5;
11964 arg5 = arg6;
11965 }
72eb7ea8
RH
11966 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11967 return -host_to_target_errno(ret);
408321b6 11968#endif
badd3cd8
PM
11969
11970#else /* not a 32-bit ABI */
e0156a9d 11971#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
11972#ifdef TARGET_NR_fadvise64_64
11973 case TARGET_NR_fadvise64_64:
11974#endif
e72d2cc7
UH
11975#ifdef TARGET_NR_fadvise64
11976 case TARGET_NR_fadvise64:
11977#endif
11978#ifdef TARGET_S390X
11979 switch (arg4) {
11980 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11981 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11982 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11983 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11984 default: break;
11985 }
11986#endif
72eb7ea8 11987 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
408321b6 11988#endif
badd3cd8
PM
11989#endif /* end of 64-bit ABI fadvise handling */
11990
ffa65c3b 11991#ifdef TARGET_NR_madvise
31e31b8a 11992 case TARGET_NR_madvise:
892a4f6a 11993 return target_madvise(arg1, arg2, arg3);
ffa65c3b 11994#endif
bbf5f2a1 11995#ifdef TARGET_NR_fcntl64
31e31b8a 11996 case TARGET_NR_fcntl64:
77e4672d 11997 {
bbf5f2a1
AB
11998 int cmd;
11999 struct flock64 fl;
213d3e9e
PM
12000 from_flock64_fn *copyfrom = copy_from_user_flock64;
12001 to_flock64_fn *copyto = copy_to_user_flock64;
12002
ce4defa0 12003#ifdef TARGET_ARM
0effdc29 12004 if (!cpu_env->eabi) {
7f254c5c
LV
12005 copyfrom = copy_from_user_oabi_flock64;
12006 copyto = copy_to_user_oabi_flock64;
213d3e9e 12007 }
ce4defa0 12008#endif
77e4672d 12009
bbf5f2a1 12010 cmd = target_to_host_fcntl_cmd(arg2);
31b63193 12011 if (cmd == -TARGET_EINVAL) {
72eb7ea8 12012 return cmd;
31b63193 12013 }
b1e341eb 12014
60cd49d5 12015 switch(arg2) {
b1e341eb 12016 case TARGET_F_GETLK64:
213d3e9e
PM
12017 ret = copyfrom(&fl, arg3);
12018 if (ret) {
12019 break;
5813427b 12020 }
af8ab2bf 12021 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
213d3e9e
PM
12022 if (ret == 0) {
12023 ret = copyto(arg3, &fl);
12024 }
77e4672d
FB
12025 break;
12026
b1e341eb
TS
12027 case TARGET_F_SETLK64:
12028 case TARGET_F_SETLKW64:
213d3e9e
PM
12029 ret = copyfrom(&fl, arg3);
12030 if (ret) {
12031 break;
ce4defa0 12032 }
435da5e7 12033 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
77e4672d 12034 break;
60cd49d5 12035 default:
5f106811 12036 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
12037 break;
12038 }
72eb7ea8 12039 return ret;
77e4672d 12040 }
60cd49d5 12041#endif
7d600c80
TS
12042#ifdef TARGET_NR_cacheflush
12043 case TARGET_NR_cacheflush:
12044 /* self-modifying code is handled automatically, so nothing needed */
72eb7ea8 12045 return 0;
7d600c80 12046#endif
c573ff67
FB
12047#ifdef TARGET_NR_getpagesize
12048 case TARGET_NR_getpagesize:
72eb7ea8 12049 return TARGET_PAGE_SIZE;
ebc05488 12050#endif
31e31b8a 12051 case TARGET_NR_gettid:
71ba74f6 12052 return get_errno(sys_gettid());
e5febef5 12053#ifdef TARGET_NR_readahead
31e31b8a 12054 case TARGET_NR_readahead:
eeed2291 12055#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
8bf8e9df 12056 if (regpairs_aligned(cpu_env, num)) {
2054ac9b
AJ
12057 arg2 = arg3;
12058 arg3 = arg4;
12059 arg4 = arg5;
12060 }
77c6850f 12061 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
2054ac9b
AJ
12062#else
12063 ret = get_errno(readahead(arg1, arg2, arg3));
12064#endif
72eb7ea8 12065 return ret;
e5febef5 12066#endif
a790ae38 12067#ifdef CONFIG_ATTR
ebc05488 12068#ifdef TARGET_NR_setxattr
31e31b8a
FB
12069 case TARGET_NR_listxattr:
12070 case TARGET_NR_llistxattr:
fb5590f7
PM
12071 {
12072 void *p, *b = 0;
12073 if (arg2) {
12074 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12075 if (!b) {
72eb7ea8 12076 return -TARGET_EFAULT;
fb5590f7
PM
12077 }
12078 }
12079 p = lock_user_string(arg1);
12080 if (p) {
12081 if (num == TARGET_NR_listxattr) {
12082 ret = get_errno(listxattr(p, b, arg3));
12083 } else {
12084 ret = get_errno(llistxattr(p, b, arg3));
12085 }
12086 } else {
12087 ret = -TARGET_EFAULT;
12088 }
12089 unlock_user(p, arg1, 0);
12090 unlock_user(b, arg2, arg3);
72eb7ea8 12091 return ret;
fb5590f7 12092 }
31e31b8a 12093 case TARGET_NR_flistxattr:
fb5590f7
PM
12094 {
12095 void *b = 0;
12096 if (arg2) {
12097 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12098 if (!b) {
72eb7ea8 12099 return -TARGET_EFAULT;
fb5590f7
PM
12100 }
12101 }
12102 ret = get_errno(flistxattr(arg1, b, arg3));
12103 unlock_user(b, arg2, arg3);
72eb7ea8 12104 return ret;
fb5590f7 12105 }
a790ae38 12106 case TARGET_NR_setxattr:
30297b55 12107 case TARGET_NR_lsetxattr:
a790ae38 12108 {
e3c33ec6
PM
12109 void *p, *n, *v = 0;
12110 if (arg3) {
12111 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12112 if (!v) {
72eb7ea8 12113 return -TARGET_EFAULT;
e3c33ec6
PM
12114 }
12115 }
a790ae38
ACH
12116 p = lock_user_string(arg1);
12117 n = lock_user_string(arg2);
e3c33ec6 12118 if (p && n) {
30297b55
PM
12119 if (num == TARGET_NR_setxattr) {
12120 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12121 } else {
12122 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12123 }
a790ae38
ACH
12124 } else {
12125 ret = -TARGET_EFAULT;
12126 }
12127 unlock_user(p, arg1, 0);
12128 unlock_user(n, arg2, 0);
12129 unlock_user(v, arg3, 0);
12130 }
72eb7ea8 12131 return ret;
30297b55
PM
12132 case TARGET_NR_fsetxattr:
12133 {
12134 void *n, *v = 0;
12135 if (arg3) {
12136 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12137 if (!v) {
72eb7ea8 12138 return -TARGET_EFAULT;
30297b55
PM
12139 }
12140 }
12141 n = lock_user_string(arg2);
12142 if (n) {
12143 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12144 } else {
12145 ret = -TARGET_EFAULT;
12146 }
12147 unlock_user(n, arg2, 0);
12148 unlock_user(v, arg3, 0);
12149 }
72eb7ea8 12150 return ret;
a790ae38 12151 case TARGET_NR_getxattr:
30297b55 12152 case TARGET_NR_lgetxattr:
a790ae38 12153 {
e3c33ec6
PM
12154 void *p, *n, *v = 0;
12155 if (arg3) {
12156 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12157 if (!v) {
72eb7ea8 12158 return -TARGET_EFAULT;
e3c33ec6
PM
12159 }
12160 }
a790ae38
ACH
12161 p = lock_user_string(arg1);
12162 n = lock_user_string(arg2);
e3c33ec6 12163 if (p && n) {
30297b55
PM
12164 if (num == TARGET_NR_getxattr) {
12165 ret = get_errno(getxattr(p, n, v, arg4));
12166 } else {
12167 ret = get_errno(lgetxattr(p, n, v, arg4));
12168 }
a790ae38
ACH
12169 } else {
12170 ret = -TARGET_EFAULT;
12171 }
12172 unlock_user(p, arg1, 0);
12173 unlock_user(n, arg2, 0);
12174 unlock_user(v, arg3, arg4);
12175 }
72eb7ea8 12176 return ret;
30297b55
PM
12177 case TARGET_NR_fgetxattr:
12178 {
12179 void *n, *v = 0;
12180 if (arg3) {
12181 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12182 if (!v) {
72eb7ea8 12183 return -TARGET_EFAULT;
30297b55
PM
12184 }
12185 }
12186 n = lock_user_string(arg2);
12187 if (n) {
12188 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12189 } else {
12190 ret = -TARGET_EFAULT;
12191 }
12192 unlock_user(n, arg2, 0);
12193 unlock_user(v, arg3, arg4);
12194 }
72eb7ea8 12195 return ret;
a790ae38 12196 case TARGET_NR_removexattr:
30297b55 12197 case TARGET_NR_lremovexattr:
a790ae38
ACH
12198 {
12199 void *p, *n;
12200 p = lock_user_string(arg1);
12201 n = lock_user_string(arg2);
12202 if (p && n) {
30297b55
PM
12203 if (num == TARGET_NR_removexattr) {
12204 ret = get_errno(removexattr(p, n));
12205 } else {
12206 ret = get_errno(lremovexattr(p, n));
12207 }
a790ae38
ACH
12208 } else {
12209 ret = -TARGET_EFAULT;
12210 }
12211 unlock_user(p, arg1, 0);
12212 unlock_user(n, arg2, 0);
12213 }
72eb7ea8 12214 return ret;
30297b55
PM
12215 case TARGET_NR_fremovexattr:
12216 {
12217 void *n;
12218 n = lock_user_string(arg2);
12219 if (n) {
12220 ret = get_errno(fremovexattr(arg1, n));
12221 } else {
12222 ret = -TARGET_EFAULT;
12223 }
12224 unlock_user(n, arg2, 0);
12225 }
72eb7ea8 12226 return ret;
ebc05488 12227#endif
a790ae38 12228#endif /* CONFIG_ATTR */
ebc05488 12229#ifdef TARGET_NR_set_thread_area
5cd4393b 12230 case TARGET_NR_set_thread_area:
8d18e893 12231#if defined(TARGET_MIPS)
0effdc29 12232 cpu_env->active_tc.CP0_UserLocal = arg1;
72eb7ea8 12233 return 0;
ef96779b
EI
12234#elif defined(TARGET_CRIS)
12235 if (arg1 & 0xff)
12236 ret = -TARGET_EINVAL;
12237 else {
0effdc29 12238 cpu_env->pregs[PR_PID] = arg1;
ef96779b
EI
12239 ret = 0;
12240 }
72eb7ea8 12241 return ret;
8d18e893 12242#elif defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12243 return do_set_thread_area(cpu_env, arg1);
1ccd9374
PM
12244#elif defined(TARGET_M68K)
12245 {
0429a971 12246 TaskState *ts = cpu->opaque;
1ccd9374 12247 ts->tp_value = arg1;
72eb7ea8 12248 return 0;
1ccd9374 12249 }
6f5b89a0 12250#else
10f45d98 12251 return -TARGET_ENOSYS;
6f5b89a0
TS
12252#endif
12253#endif
12254#ifdef TARGET_NR_get_thread_area
5cd4393b 12255 case TARGET_NR_get_thread_area:
8d18e893 12256#if defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12257 return do_get_thread_area(cpu_env, arg1);
1ccd9374
PM
12258#elif defined(TARGET_M68K)
12259 {
0429a971 12260 TaskState *ts = cpu->opaque;
72eb7ea8 12261 return ts->tp_value;
1ccd9374 12262 }
8d18e893 12263#else
10f45d98 12264 return -TARGET_ENOSYS;
48dc41eb 12265#endif
8d18e893 12266#endif
48dc41eb
FB
12267#ifdef TARGET_NR_getdomainname
12268 case TARGET_NR_getdomainname:
10f45d98 12269 return -TARGET_ENOSYS;
ebc05488 12270#endif
6f5b89a0 12271
12e3340c
MF
12272#ifdef TARGET_NR_clock_settime
12273 case TARGET_NR_clock_settime:
12274 {
12275 struct timespec ts;
12276
12277 ret = target_to_host_timespec(&ts, arg2);
12278 if (!is_error(ret)) {
12279 ret = get_errno(clock_settime(arg1, &ts));
12280 }
72eb7ea8 12281 return ret;
12e3340c
MF
12282 }
12283#endif
c6c8d102
AF
12284#ifdef TARGET_NR_clock_settime64
12285 case TARGET_NR_clock_settime64:
12286 {
12287 struct timespec ts;
12288
12289 ret = target_to_host_timespec64(&ts, arg2);
12290 if (!is_error(ret)) {
12291 ret = get_errno(clock_settime(arg1, &ts));
12292 }
12293 return ret;
12294 }
12295#endif
b5906f95
TS
12296#ifdef TARGET_NR_clock_gettime
12297 case TARGET_NR_clock_gettime:
12298 {
12299 struct timespec ts;
12300 ret = get_errno(clock_gettime(arg1, &ts));
12301 if (!is_error(ret)) {
b9f9908e 12302 ret = host_to_target_timespec(arg2, &ts);
b5906f95 12303 }
72eb7ea8 12304 return ret;
b5906f95
TS
12305 }
12306#endif
c6c8d102
AF
12307#ifdef TARGET_NR_clock_gettime64
12308 case TARGET_NR_clock_gettime64:
12309 {
12310 struct timespec ts;
12311 ret = get_errno(clock_gettime(arg1, &ts));
12312 if (!is_error(ret)) {
12313 ret = host_to_target_timespec64(arg2, &ts);
12314 }
12315 return ret;
12316 }
12317#endif
b5906f95
TS
12318#ifdef TARGET_NR_clock_getres
12319 case TARGET_NR_clock_getres:
12320 {
12321 struct timespec ts;
12322 ret = get_errno(clock_getres(arg1, &ts));
12323 if (!is_error(ret)) {
12324 host_to_target_timespec(arg2, &ts);
12325 }
72eb7ea8 12326 return ret;
b5906f95
TS
12327 }
12328#endif
828cb3a1
FB
12329#ifdef TARGET_NR_clock_getres_time64
12330 case TARGET_NR_clock_getres_time64:
12331 {
12332 struct timespec ts;
12333 ret = get_errno(clock_getres(arg1, &ts));
12334 if (!is_error(ret)) {
12335 host_to_target_timespec64(arg2, &ts);
12336 }
12337 return ret;
12338 }
12339#endif
63d7651b
PB
12340#ifdef TARGET_NR_clock_nanosleep
12341 case TARGET_NR_clock_nanosleep:
12342 {
12343 struct timespec ts;
b09d6406
FB
12344 if (target_to_host_timespec(&ts, arg3)) {
12345 return -TARGET_EFAULT;
12346 }
9e518226
PM
12347 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12348 &ts, arg4 ? &ts : NULL));
8ec68a0a
LV
12349 /*
12350 * if the call is interrupted by a signal handler, it fails
12351 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12352 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12353 */
b09d6406
FB
12354 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12355 host_to_target_timespec(arg4, &ts)) {
12356 return -TARGET_EFAULT;
8ec68a0a 12357 }
8fbe8fdf 12358
72eb7ea8 12359 return ret;
63d7651b
PB
12360 }
12361#endif
6ac03b2c
FB
12362#ifdef TARGET_NR_clock_nanosleep_time64
12363 case TARGET_NR_clock_nanosleep_time64:
12364 {
12365 struct timespec ts;
12366
12367 if (target_to_host_timespec64(&ts, arg3)) {
12368 return -TARGET_EFAULT;
12369 }
12370
12371 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12372 &ts, arg4 ? &ts : NULL));
12373
12374 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12375 host_to_target_timespec64(arg4, &ts)) {
12376 return -TARGET_EFAULT;
12377 }
12378 return ret;
12379 }
12380#endif
b5906f95 12381
9a7f682c 12382#if defined(TARGET_NR_set_tid_address)
6f5b89a0 12383 case TARGET_NR_set_tid_address:
9a7f682c
HD
12384 {
12385 TaskState *ts = cpu->opaque;
12386 ts->child_tidptr = arg1;
12387 /* do not call host set_tid_address() syscall, instead return tid() */
12388 return get_errno(sys_gettid());
12389 }
6f5b89a0
TS
12390#endif
12391
4cae1d16 12392 case TARGET_NR_tkill:
72eb7ea8 12393 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16 12394
71455574 12395 case TARGET_NR_tgkill:
72eb7ea8
RH
12396 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12397 target_to_host_signal(arg3)));
71455574 12398
4f2b1fe8
TS
12399#ifdef TARGET_NR_set_robust_list
12400 case TARGET_NR_set_robust_list:
e9a970a8
PM
12401 case TARGET_NR_get_robust_list:
12402 /* The ABI for supporting robust futexes has userspace pass
12403 * the kernel a pointer to a linked list which is updated by
12404 * userspace after the syscall; the list is walked by the kernel
12405 * when the thread exits. Since the linked list in QEMU guest
12406 * memory isn't a valid linked list for the host and we have
12407 * no way to reliably intercept the thread-death event, we can't
12408 * support these. Silently return ENOSYS so that guest userspace
12409 * falls back to a non-robust futex implementation (which should
12410 * be OK except in the corner case of the guest crashing while
12411 * holding a mutex that is shared with another process via
12412 * shared memory).
12413 */
10f45d98 12414 return -TARGET_ENOSYS;
4f2b1fe8
TS
12415#endif
12416
1acae9f2 12417#if defined(TARGET_NR_utimensat)
9007f0ef
TS
12418 case TARGET_NR_utimensat:
12419 {
ebc996f3
RV
12420 struct timespec *tsp, ts[2];
12421 if (!arg3) {
12422 tsp = NULL;
12423 } else {
b3a3af70
FB
12424 if (target_to_host_timespec(ts, arg3)) {
12425 return -TARGET_EFAULT;
12426 }
12427 if (target_to_host_timespec(ts + 1, arg3 +
12428 sizeof(struct target_timespec))) {
12429 return -TARGET_EFAULT;
12430 }
ebc996f3
RV
12431 tsp = ts;
12432 }
9007f0ef 12433 if (!arg2)
ebc996f3 12434 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 12435 else {
579a97f7 12436 if (!(p = lock_user_string(arg2))) {
259841c1 12437 return -TARGET_EFAULT;
579a97f7 12438 }
ebc996f3 12439 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 12440 unlock_user(p, arg2, 0);
cac46eb0
FB
12441 }
12442 }
12443 return ret;
12444#endif
12445#ifdef TARGET_NR_utimensat_time64
12446 case TARGET_NR_utimensat_time64:
12447 {
12448 struct timespec *tsp, ts[2];
12449 if (!arg3) {
12450 tsp = NULL;
12451 } else {
12452 if (target_to_host_timespec64(ts, arg3)) {
12453 return -TARGET_EFAULT;
12454 }
12455 if (target_to_host_timespec64(ts + 1, arg3 +
12456 sizeof(struct target__kernel_timespec))) {
12457 return -TARGET_EFAULT;
12458 }
12459 tsp = ts;
12460 }
12461 if (!arg2)
12462 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12463 else {
12464 p = lock_user_string(arg2);
12465 if (!p) {
12466 return -TARGET_EFAULT;
12467 }
12468 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12469 unlock_user(p, arg2, 0);
9007f0ef
TS
12470 }
12471 }
72eb7ea8 12472 return ret;
9007f0ef 12473#endif
859e8a89 12474#ifdef TARGET_NR_futex
bd0c5661 12475 case TARGET_NR_futex:
0fbc0f8d 12476 return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
859e8a89 12477#endif
14690296
AF
12478#ifdef TARGET_NR_futex_time64
12479 case TARGET_NR_futex_time64:
0fbc0f8d 12480 return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
14690296 12481#endif
33f53ac5
PB
12482#ifdef CONFIG_INOTIFY
12483#if defined(TARGET_NR_inotify_init)
39b59763 12484 case TARGET_NR_inotify_init:
33f53ac5 12485 ret = get_errno(inotify_init());
b929f7e5
PMD
12486 if (ret >= 0) {
12487 fd_trans_register(ret, &target_inotify_trans);
12488 }
72eb7ea8 12489 return ret;
39b59763 12490#endif
33f53ac5 12491#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
c05c7a73 12492 case TARGET_NR_inotify_init1:
33f53ac5 12493 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
fea243e9 12494 fcntl_flags_tbl)));
b929f7e5
PMD
12495 if (ret >= 0) {
12496 fd_trans_register(ret, &target_inotify_trans);
12497 }
72eb7ea8 12498 return ret;
c05c7a73 12499#endif
33f53ac5 12500#if defined(TARGET_NR_inotify_add_watch)
39b59763
AJ
12501 case TARGET_NR_inotify_add_watch:
12502 p = lock_user_string(arg2);
33f53ac5 12503 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
39b59763 12504 unlock_user(p, arg2, 0);
72eb7ea8 12505 return ret;
39b59763 12506#endif
33f53ac5 12507#if defined(TARGET_NR_inotify_rm_watch)
39b59763 12508 case TARGET_NR_inotify_rm_watch:
33f53ac5
PB
12509 return get_errno(inotify_rm_watch(arg1, arg2));
12510#endif
39b59763 12511#endif
9007f0ef 12512
8ec9cf89 12513#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
12514 case TARGET_NR_mq_open:
12515 {
c7536ab6 12516 struct mq_attr posix_mq_attr;
26400775 12517 struct mq_attr *pposix_mq_attr;
c7536ab6 12518 int host_flags;
24e1003a 12519
c7536ab6 12520 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
26400775
LD
12521 pposix_mq_attr = NULL;
12522 if (arg4) {
12523 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
2852aafd 12524 return -TARGET_EFAULT;
26400775
LD
12525 }
12526 pposix_mq_attr = &posix_mq_attr;
c7536ab6 12527 }
24e1003a 12528 p = lock_user_string(arg1 - 1);
c7536ab6 12529 if (!p) {
2852aafd 12530 return -TARGET_EFAULT;
b6ce1f6b 12531 }
26400775 12532 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
24e1003a
AJ
12533 unlock_user (p, arg1, 0);
12534 }
72eb7ea8 12535 return ret;
24e1003a
AJ
12536
12537 case TARGET_NR_mq_unlink:
12538 p = lock_user_string(arg1 - 1);
3211215e 12539 if (!p) {
72eb7ea8 12540 return -TARGET_EFAULT;
3211215e 12541 }
24e1003a
AJ
12542 ret = get_errno(mq_unlink(p));
12543 unlock_user (p, arg1, 0);
72eb7ea8 12544 return ret;
24e1003a 12545
859e8a89 12546#ifdef TARGET_NR_mq_timedsend
24e1003a
AJ
12547 case TARGET_NR_mq_timedsend:
12548 {
12549 struct timespec ts;
12550
12551 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12552 if (arg5 != 0) {
dcbcf5cf
FB
12553 if (target_to_host_timespec(&ts, arg5)) {
12554 return -TARGET_EFAULT;
12555 }
d40ecd66 12556 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
dcbcf5cf
FB
12557 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12558 return -TARGET_EFAULT;
12559 }
d40ecd66
PM
12560 } else {
12561 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
24e1003a 12562 }
24e1003a
AJ
12563 unlock_user (p, arg2, arg3);
12564 }
72eb7ea8 12565 return ret;
859e8a89 12566#endif
d107e375
FB
12567#ifdef TARGET_NR_mq_timedsend_time64
12568 case TARGET_NR_mq_timedsend_time64:
12569 {
12570 struct timespec ts;
12571
12572 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12573 if (arg5 != 0) {
12574 if (target_to_host_timespec64(&ts, arg5)) {
12575 return -TARGET_EFAULT;
12576 }
12577 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12578 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12579 return -TARGET_EFAULT;
12580 }
12581 } else {
12582 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12583 }
12584 unlock_user(p, arg2, arg3);
12585 }
12586 return ret;
12587#endif
24e1003a 12588
859e8a89 12589#ifdef TARGET_NR_mq_timedreceive
24e1003a
AJ
12590 case TARGET_NR_mq_timedreceive:
12591 {
12592 struct timespec ts;
12593 unsigned int prio;
12594
12595 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12596 if (arg5 != 0) {
dcbcf5cf
FB
12597 if (target_to_host_timespec(&ts, arg5)) {
12598 return -TARGET_EFAULT;
12599 }
d40ecd66
PM
12600 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12601 &prio, &ts));
dcbcf5cf
FB
12602 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12603 return -TARGET_EFAULT;
12604 }
d40ecd66
PM
12605 } else {
12606 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12607 &prio, NULL));
24e1003a 12608 }
24e1003a
AJ
12609 unlock_user (p, arg2, arg3);
12610 if (arg4 != 0)
12611 put_user_u32(prio, arg4);
12612 }
72eb7ea8 12613 return ret;
859e8a89 12614#endif
d107e375
FB
12615#ifdef TARGET_NR_mq_timedreceive_time64
12616 case TARGET_NR_mq_timedreceive_time64:
12617 {
12618 struct timespec ts;
12619 unsigned int prio;
12620
12621 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12622 if (arg5 != 0) {
12623 if (target_to_host_timespec64(&ts, arg5)) {
12624 return -TARGET_EFAULT;
12625 }
12626 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12627 &prio, &ts));
12628 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12629 return -TARGET_EFAULT;
12630 }
12631 } else {
12632 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12633 &prio, NULL));
12634 }
12635 unlock_user(p, arg2, arg3);
12636 if (arg4 != 0) {
12637 put_user_u32(prio, arg4);
12638 }
12639 }
12640 return ret;
12641#endif
24e1003a
AJ
12642
12643 /* Not implemented for now... */
12644/* case TARGET_NR_mq_notify: */
12645/* break; */
12646
12647 case TARGET_NR_mq_getsetattr:
12648 {
12649 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12650 ret = 0;
24e1003a
AJ
12651 if (arg2 != 0) {
12652 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
a23ea409
MF
12653 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12654 &posix_mq_attr_out));
12655 } else if (arg3 != 0) {
12656 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
12657 }
12658 if (ret == 0 && arg3 != 0) {
12659 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
24e1003a 12660 }
24e1003a 12661 }
72eb7ea8 12662 return ret;
24e1003a
AJ
12663#endif
12664
3ce34dfb
VS
12665#ifdef CONFIG_SPLICE
12666#ifdef TARGET_NR_tee
12667 case TARGET_NR_tee:
12668 {
12669 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12670 }
72eb7ea8 12671 return ret;
3ce34dfb
VS
12672#endif
12673#ifdef TARGET_NR_splice
12674 case TARGET_NR_splice:
12675 {
12676 loff_t loff_in, loff_out;
12677 loff_t *ploff_in = NULL, *ploff_out = NULL;
17644b36
AS
12678 if (arg2) {
12679 if (get_user_u64(loff_in, arg2)) {
2852aafd 12680 return -TARGET_EFAULT;
17644b36 12681 }
3ce34dfb
VS
12682 ploff_in = &loff_in;
12683 }
17644b36
AS
12684 if (arg4) {
12685 if (get_user_u64(loff_out, arg4)) {
2852aafd 12686 return -TARGET_EFAULT;
17644b36 12687 }
3ce34dfb
VS
12688 ploff_out = &loff_out;
12689 }
12690 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
17644b36
AS
12691 if (arg2) {
12692 if (put_user_u64(loff_in, arg2)) {
2852aafd 12693 return -TARGET_EFAULT;
17644b36
AS
12694 }
12695 }
12696 if (arg4) {
12697 if (put_user_u64(loff_out, arg4)) {
2852aafd 12698 return -TARGET_EFAULT;
17644b36
AS
12699 }
12700 }
3ce34dfb 12701 }
72eb7ea8 12702 return ret;
3ce34dfb
VS
12703#endif
12704#ifdef TARGET_NR_vmsplice
12705 case TARGET_NR_vmsplice:
12706 {
f287b2c2
RH
12707 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12708 if (vec != NULL) {
12709 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12710 unlock_iovec(vec, arg2, arg3, 0);
12711 } else {
12712 ret = -host_to_target_errno(errno);
12713 }
3ce34dfb 12714 }
72eb7ea8 12715 return ret;
3ce34dfb
VS
12716#endif
12717#endif /* CONFIG_SPLICE */
c2882b96
RV
12718#ifdef CONFIG_EVENTFD
12719#if defined(TARGET_NR_eventfd)
12720 case TARGET_NR_eventfd:
12721 ret = get_errno(eventfd(arg1, 0));
b929f7e5
PMD
12722 if (ret >= 0) {
12723 fd_trans_register(ret, &target_eventfd_trans);
12724 }
72eb7ea8 12725 return ret;
c2882b96
RV
12726#endif
12727#if defined(TARGET_NR_eventfd2)
12728 case TARGET_NR_eventfd2:
5947c697 12729 {
78721301 12730 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
5947c697
PJ
12731 if (arg2 & TARGET_O_NONBLOCK) {
12732 host_flags |= O_NONBLOCK;
12733 }
12734 if (arg2 & TARGET_O_CLOEXEC) {
12735 host_flags |= O_CLOEXEC;
12736 }
12737 ret = get_errno(eventfd(arg1, host_flags));
b929f7e5
PMD
12738 if (ret >= 0) {
12739 fd_trans_register(ret, &target_eventfd_trans);
12740 }
72eb7ea8 12741 return ret;
5947c697 12742 }
c2882b96
RV
12743#endif
12744#endif /* CONFIG_EVENTFD */
d0927938
UH
12745#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12746 case TARGET_NR_fallocate:
eeed2291 12747#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
20249ae1
AG
12748 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12749 target_offset64(arg5, arg6)));
12750#else
d0927938 12751 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 12752#endif
72eb7ea8 12753 return ret;
c727f47d
PM
12754#endif
12755#if defined(CONFIG_SYNC_FILE_RANGE)
12756#if defined(TARGET_NR_sync_file_range)
12757 case TARGET_NR_sync_file_range:
eeed2291 12758#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
bfcedc57
RV
12759#if defined(TARGET_MIPS)
12760 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12761 target_offset64(arg5, arg6), arg7));
12762#else
c727f47d
PM
12763 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12764 target_offset64(arg4, arg5), arg6));
bfcedc57 12765#endif /* !TARGET_MIPS */
c727f47d
PM
12766#else
12767 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12768#endif
72eb7ea8 12769 return ret;
c727f47d 12770#endif
5bcb4986
LV
12771#if defined(TARGET_NR_sync_file_range2) || \
12772 defined(TARGET_NR_arm_sync_file_range)
c727f47d
PM
12773#if defined(TARGET_NR_sync_file_range2)
12774 case TARGET_NR_sync_file_range2:
5bcb4986
LV
12775#endif
12776#if defined(TARGET_NR_arm_sync_file_range)
12777 case TARGET_NR_arm_sync_file_range:
12778#endif
c727f47d 12779 /* This is like sync_file_range but the arguments are reordered */
eeed2291 12780#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
c727f47d
PM
12781 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12782 target_offset64(arg5, arg6), arg2));
12783#else
12784 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12785#endif
72eb7ea8 12786 return ret;
c727f47d 12787#endif
3b6edd16 12788#endif
e36800c9
LV
12789#if defined(TARGET_NR_signalfd4)
12790 case TARGET_NR_signalfd4:
72eb7ea8 12791 return do_signalfd4(arg1, arg2, arg4);
e36800c9
LV
12792#endif
12793#if defined(TARGET_NR_signalfd)
12794 case TARGET_NR_signalfd:
72eb7ea8 12795 return do_signalfd4(arg1, arg2, 0);
e36800c9 12796#endif
3b6edd16
PM
12797#if defined(CONFIG_EPOLL)
12798#if defined(TARGET_NR_epoll_create)
12799 case TARGET_NR_epoll_create:
72eb7ea8 12800 return get_errno(epoll_create(arg1));
3b6edd16
PM
12801#endif
12802#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12803 case TARGET_NR_epoll_create1:
386d3865 12804 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
3b6edd16
PM
12805#endif
12806#if defined(TARGET_NR_epoll_ctl)
12807 case TARGET_NR_epoll_ctl:
12808 {
12809 struct epoll_event ep;
12810 struct epoll_event *epp = 0;
12811 if (arg4) {
c7811022
L
12812 if (arg2 != EPOLL_CTL_DEL) {
12813 struct target_epoll_event *target_ep;
12814 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12815 return -TARGET_EFAULT;
12816 }
12817 ep.events = tswap32(target_ep->events);
12818 /*
12819 * The epoll_data_t union is just opaque data to the kernel,
12820 * so we transfer all 64 bits across and need not worry what
12821 * actual data type it is.
12822 */
12823 ep.data.u64 = tswap64(target_ep->data.u64);
12824 unlock_user_struct(target_ep, arg4, 0);
3b6edd16 12825 }
c7811022
L
12826 /*
12827 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12828 * non-null pointer, even though this argument is ignored.
12829 *
3b6edd16 12830 */
3b6edd16
PM
12831 epp = &ep;
12832 }
72eb7ea8 12833 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
3b6edd16
PM
12834 }
12835#endif
12836
227f0214 12837#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12838#if defined(TARGET_NR_epoll_wait)
12839 case TARGET_NR_epoll_wait:
12840#endif
227f0214 12841#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12842 case TARGET_NR_epoll_pwait:
12843#endif
12844 {
12845 struct target_epoll_event *target_ep;
12846 struct epoll_event *ep;
12847 int epfd = arg1;
12848 int maxevents = arg3;
12849 int timeout = arg4;
12850
2ba7fae3 12851 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
72eb7ea8 12852 return -TARGET_EINVAL;
2ba7fae3
PM
12853 }
12854
3b6edd16
PM
12855 target_ep = lock_user(VERIFY_WRITE, arg2,
12856 maxevents * sizeof(struct target_epoll_event), 1);
12857 if (!target_ep) {
2852aafd 12858 return -TARGET_EFAULT;
3b6edd16
PM
12859 }
12860
04c95f4d
PM
12861 ep = g_try_new(struct epoll_event, maxevents);
12862 if (!ep) {
12863 unlock_user(target_ep, arg2, 0);
72eb7ea8 12864 return -TARGET_ENOMEM;
04c95f4d 12865 }
3b6edd16
PM
12866
12867 switch (num) {
227f0214 12868#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12869 case TARGET_NR_epoll_pwait:
12870 {
cd0e31a4 12871 sigset_t *set = NULL;
3b6edd16
PM
12872
12873 if (arg5) {
cd0e31a4
RH
12874 ret = process_sigsuspend_mask(&set, arg5, arg6);
12875 if (ret != 0) {
c815701e
PM
12876 break;
12877 }
3b6edd16
PM
12878 }
12879
227f0214
PM
12880 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12881 set, SIGSET_T_SIZE));
cd0e31a4
RH
12882
12883 if (set) {
12884 finish_sigsuspend_mask(ret);
12885 }
3b6edd16
PM
12886 break;
12887 }
12888#endif
12889#if defined(TARGET_NR_epoll_wait)
12890 case TARGET_NR_epoll_wait:
227f0214
PM
12891 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12892 NULL, 0));
3b6edd16
PM
12893 break;
12894#endif
12895 default:
12896 ret = -TARGET_ENOSYS;
12897 }
12898 if (!is_error(ret)) {
12899 int i;
12900 for (i = 0; i < ret; i++) {
12901 target_ep[i].events = tswap32(ep[i].events);
12902 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12903 }
04c95f4d
PM
12904 unlock_user(target_ep, arg2,
12905 ret * sizeof(struct target_epoll_event));
12906 } else {
12907 unlock_user(target_ep, arg2, 0);
3b6edd16 12908 }
04c95f4d 12909 g_free(ep);
72eb7ea8 12910 return ret;
3b6edd16
PM
12911 }
12912#endif
163a05a8
PM
12913#endif
12914#ifdef TARGET_NR_prlimit64
12915 case TARGET_NR_prlimit64:
12916 {
12917 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12918 struct target_rlimit64 *target_rnew, *target_rold;
12919 struct host_rlimit64 rnew, rold, *rnewp = 0;
95018018 12920 int resource = target_to_host_resource(arg2);
055d92f8
TK
12921
12922 if (arg3 && (resource != RLIMIT_AS &&
12923 resource != RLIMIT_DATA &&
12924 resource != RLIMIT_STACK)) {
163a05a8 12925 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
2852aafd 12926 return -TARGET_EFAULT;
163a05a8 12927 }
9c1da8b5
IL
12928 __get_user(rnew.rlim_cur, &target_rnew->rlim_cur);
12929 __get_user(rnew.rlim_max, &target_rnew->rlim_max);
163a05a8
PM
12930 unlock_user_struct(target_rnew, arg3, 0);
12931 rnewp = &rnew;
12932 }
12933
95018018 12934 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
163a05a8
PM
12935 if (!is_error(ret) && arg4) {
12936 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
2852aafd 12937 return -TARGET_EFAULT;
163a05a8 12938 }
9c1da8b5
IL
12939 __put_user(rold.rlim_cur, &target_rold->rlim_cur);
12940 __put_user(rold.rlim_max, &target_rold->rlim_max);
163a05a8
PM
12941 unlock_user_struct(target_rold, arg4, 1);
12942 }
72eb7ea8 12943 return ret;
163a05a8 12944 }
3d21d29c
RH
12945#endif
12946#ifdef TARGET_NR_gethostname
12947 case TARGET_NR_gethostname:
12948 {
12949 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12950 if (name) {
12951 ret = get_errno(gethostname(name, arg2));
12952 unlock_user(name, arg1, arg2);
12953 } else {
12954 ret = -TARGET_EFAULT;
12955 }
72eb7ea8 12956 return ret;
3d21d29c 12957 }
89aaf1a6
RV
12958#endif
12959#ifdef TARGET_NR_atomic_cmpxchg_32
12960 case TARGET_NR_atomic_cmpxchg_32:
12961 {
12962 /* should use start_exclusive from main.c */
12963 abi_ulong mem_value;
12964 if (get_user_u32(mem_value, arg6)) {
12965 target_siginfo_t info;
12966 info.si_signo = SIGSEGV;
12967 info.si_errno = 0;
12968 info.si_code = TARGET_SEGV_MAPERR;
12969 info._sifields._sigfault._addr = arg6;
0effdc29 12970 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
89aaf1a6
RV
12971 ret = 0xdeadbeef;
12972
12973 }
12974 if (mem_value == arg2)
12975 put_user_u32(arg1, arg6);
72eb7ea8 12976 return mem_value;
89aaf1a6
RV
12977 }
12978#endif
12979#ifdef TARGET_NR_atomic_barrier
12980 case TARGET_NR_atomic_barrier:
72eb7ea8
RH
12981 /* Like the kernel implementation and the
12982 qemu arm barrier, no-op this? */
12983 return 0;
d0927938 12984#endif
f4f1e10a
ECL
12985
12986#ifdef TARGET_NR_timer_create
12987 case TARGET_NR_timer_create:
12988 {
12989 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12990
12991 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
f4f1e10a
ECL
12992
12993 int clkid = arg1;
12994 int timer_index = next_free_host_timer();
12995
12996 if (timer_index < 0) {
12997 ret = -TARGET_EAGAIN;
12998 } else {
12999 timer_t *phtimer = g_posix_timers + timer_index;
13000
13001 if (arg2) {
f4f1e10a 13002 phost_sevp = &host_sevp;
c065976f
PM
13003 ret = target_to_host_sigevent(phost_sevp, arg2);
13004 if (ret != 0) {
9e59899f 13005 free_host_timer_slot(timer_index);
72eb7ea8 13006 return ret;
c065976f 13007 }
f4f1e10a
ECL
13008 }
13009
13010 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
13011 if (ret) {
9e59899f 13012 free_host_timer_slot(timer_index);
f4f1e10a 13013 } else {
aecc8861 13014 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
9e59899f
PM
13015 timer_delete(*phtimer);
13016 free_host_timer_slot(timer_index);
2852aafd 13017 return -TARGET_EFAULT;
f4f1e10a 13018 }
f4f1e10a
ECL
13019 }
13020 }
72eb7ea8 13021 return ret;
f4f1e10a
ECL
13022 }
13023#endif
13024
13025#ifdef TARGET_NR_timer_settime
13026 case TARGET_NR_timer_settime:
13027 {
13028 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
13029 * struct itimerspec * old_value */
aecc8861 13030 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13031
aecc8861
AG
13032 if (timerid < 0) {
13033 ret = timerid;
13034 } else if (arg3 == 0) {
f4f1e10a
ECL
13035 ret = -TARGET_EINVAL;
13036 } else {
e52a99f7 13037 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
13038 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13039
40c80b5e 13040 if (target_to_host_itimerspec(&hspec_new, arg3)) {
2852aafd 13041 return -TARGET_EFAULT;
40c80b5e 13042 }
f4f1e10a
ECL
13043 ret = get_errno(
13044 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
40c80b5e 13045 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
2852aafd 13046 return -TARGET_EFAULT;
40c80b5e 13047 }
f4f1e10a 13048 }
72eb7ea8 13049 return ret;
f4f1e10a
ECL
13050 }
13051#endif
13052
828cb3a1
FB
13053#ifdef TARGET_NR_timer_settime64
13054 case TARGET_NR_timer_settime64:
13055 {
13056 target_timer_t timerid = get_timer_id(arg1);
13057
13058 if (timerid < 0) {
13059 ret = timerid;
13060 } else if (arg3 == 0) {
13061 ret = -TARGET_EINVAL;
13062 } else {
13063 timer_t htimer = g_posix_timers[timerid];
13064 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13065
13066 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
13067 return -TARGET_EFAULT;
13068 }
13069 ret = get_errno(
13070 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
13071 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
13072 return -TARGET_EFAULT;
13073 }
13074 }
13075 return ret;
13076 }
13077#endif
13078
f4f1e10a
ECL
13079#ifdef TARGET_NR_timer_gettime
13080 case TARGET_NR_timer_gettime:
13081 {
13082 /* args: timer_t timerid, struct itimerspec *curr_value */
aecc8861 13083 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13084
aecc8861
AG
13085 if (timerid < 0) {
13086 ret = timerid;
13087 } else if (!arg2) {
13088 ret = -TARGET_EFAULT;
f4f1e10a 13089 } else {
e52a99f7 13090 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
13091 struct itimerspec hspec;
13092 ret = get_errno(timer_gettime(htimer, &hspec));
13093
13094 if (host_to_target_itimerspec(arg2, &hspec)) {
13095 ret = -TARGET_EFAULT;
13096 }
13097 }
72eb7ea8 13098 return ret;
f4f1e10a
ECL
13099 }
13100#endif
13101
828cb3a1
FB
13102#ifdef TARGET_NR_timer_gettime64
13103 case TARGET_NR_timer_gettime64:
13104 {
13105 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13106 target_timer_t timerid = get_timer_id(arg1);
13107
13108 if (timerid < 0) {
13109 ret = timerid;
13110 } else if (!arg2) {
13111 ret = -TARGET_EFAULT;
13112 } else {
13113 timer_t htimer = g_posix_timers[timerid];
13114 struct itimerspec hspec;
13115 ret = get_errno(timer_gettime(htimer, &hspec));
13116
13117 if (host_to_target_itimerspec64(arg2, &hspec)) {
13118 ret = -TARGET_EFAULT;
13119 }
13120 }
13121 return ret;
13122 }
13123#endif
13124
f4f1e10a
ECL
13125#ifdef TARGET_NR_timer_getoverrun
13126 case TARGET_NR_timer_getoverrun:
13127 {
13128 /* args: timer_t timerid */
aecc8861 13129 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13130
aecc8861
AG
13131 if (timerid < 0) {
13132 ret = timerid;
f4f1e10a 13133 } else {
e52a99f7 13134 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
13135 ret = get_errno(timer_getoverrun(htimer));
13136 }
72eb7ea8 13137 return ret;
f4f1e10a
ECL
13138 }
13139#endif
13140
13141#ifdef TARGET_NR_timer_delete
13142 case TARGET_NR_timer_delete:
13143 {
13144 /* args: timer_t timerid */
aecc8861 13145 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13146
aecc8861
AG
13147 if (timerid < 0) {
13148 ret = timerid;
f4f1e10a 13149 } else {
e52a99f7 13150 timer_t htimer = g_posix_timers[timerid];
f4f1e10a 13151 ret = get_errno(timer_delete(htimer));
9e59899f 13152 free_host_timer_slot(timerid);
f4f1e10a 13153 }
72eb7ea8 13154 return ret;
f4f1e10a
ECL
13155 }
13156#endif
13157
51834341
RV
13158#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13159 case TARGET_NR_timerfd_create:
d759a62b
MM
13160 ret = get_errno(timerfd_create(arg1,
13161 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
13162 if (ret >= 0) {
13163 fd_trans_register(ret, &target_timerfd_trans);
13164 }
13165 return ret;
51834341
RV
13166#endif
13167
13168#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13169 case TARGET_NR_timerfd_gettime:
13170 {
13171 struct itimerspec its_curr;
13172
13173 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13174
13175 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
2852aafd 13176 return -TARGET_EFAULT;
51834341
RV
13177 }
13178 }
72eb7ea8 13179 return ret;
51834341
RV
13180#endif
13181
828cb3a1
FB
13182#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13183 case TARGET_NR_timerfd_gettime64:
13184 {
13185 struct itimerspec its_curr;
13186
13187 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13188
13189 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13190 return -TARGET_EFAULT;
13191 }
13192 }
13193 return ret;
13194#endif
13195
51834341
RV
13196#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13197 case TARGET_NR_timerfd_settime:
13198 {
13199 struct itimerspec its_new, its_old, *p_new;
13200
13201 if (arg3) {
13202 if (target_to_host_itimerspec(&its_new, arg3)) {
2852aafd 13203 return -TARGET_EFAULT;
51834341
RV
13204 }
13205 p_new = &its_new;
13206 } else {
13207 p_new = NULL;
13208 }
13209
13210 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13211
13212 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
2852aafd 13213 return -TARGET_EFAULT;
51834341
RV
13214 }
13215 }
72eb7ea8 13216 return ret;
51834341
RV
13217#endif
13218
828cb3a1
FB
13219#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13220 case TARGET_NR_timerfd_settime64:
13221 {
13222 struct itimerspec its_new, its_old, *p_new;
13223
13224 if (arg3) {
13225 if (target_to_host_itimerspec64(&its_new, arg3)) {
13226 return -TARGET_EFAULT;
13227 }
13228 p_new = &its_new;
13229 } else {
13230 p_new = NULL;
13231 }
13232
13233 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13234
13235 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13236 return -TARGET_EFAULT;
13237 }
13238 }
13239 return ret;
13240#endif
13241
ab31cda3
PB
13242#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13243 case TARGET_NR_ioprio_get:
72eb7ea8 13244 return get_errno(ioprio_get(arg1, arg2));
ab31cda3
PB
13245#endif
13246
13247#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13248 case TARGET_NR_ioprio_set:
72eb7ea8 13249 return get_errno(ioprio_set(arg1, arg2, arg3));
ab31cda3
PB
13250#endif
13251
9af5c906
RV
13252#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13253 case TARGET_NR_setns:
72eb7ea8 13254 return get_errno(setns(arg1, arg2));
9af5c906
RV
13255#endif
13256#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13257 case TARGET_NR_unshare:
72eb7ea8 13258 return get_errno(unshare(arg1));
9af5c906 13259#endif
2f14788c
LV
13260#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13261 case TARGET_NR_kcmp:
72eb7ea8 13262 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
2f14788c 13263#endif
fa97e38e
RH
13264#ifdef TARGET_NR_swapcontext
13265 case TARGET_NR_swapcontext:
13266 /* PowerPC specific. */
72eb7ea8 13267 return do_swapcontext(cpu_env, arg1, arg2, arg3);
fa97e38e 13268#endif
9bdfa4d2
SCW
13269#ifdef TARGET_NR_memfd_create
13270 case TARGET_NR_memfd_create:
13271 p = lock_user_string(arg1);
13272 if (!p) {
13273 return -TARGET_EFAULT;
13274 }
13275 ret = get_errno(memfd_create(p, arg2));
13276 fd_trans_unregister(ret);
13277 unlock_user(p, arg1, 0);
13278 return ret;
13279#endif
8500476f
AS
13280#if defined TARGET_NR_membarrier && defined __NR_membarrier
13281 case TARGET_NR_membarrier:
13282 return get_errno(membarrier(arg1, arg2));
13283#endif
9af5c906 13284
84946457
AS
13285#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13286 case TARGET_NR_copy_file_range:
13287 {
13288 loff_t inoff, outoff;
13289 loff_t *pinoff = NULL, *poutoff = NULL;
13290
13291 if (arg2) {
13292 if (get_user_u64(inoff, arg2)) {
13293 return -TARGET_EFAULT;
13294 }
13295 pinoff = &inoff;
13296 }
13297 if (arg4) {
13298 if (get_user_u64(outoff, arg4)) {
13299 return -TARGET_EFAULT;
13300 }
13301 poutoff = &outoff;
13302 }
0fa259dd 13303 /* Do not sign-extend the count parameter. */
84946457 13304 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
0fa259dd 13305 (abi_ulong)arg5, arg6));
84946457
AS
13306 if (!is_error(ret) && ret > 0) {
13307 if (arg2) {
13308 if (put_user_u64(inoff, arg2)) {
13309 return -TARGET_EFAULT;
13310 }
13311 }
13312 if (arg4) {
13313 if (put_user_u64(outoff, arg4)) {
13314 return -TARGET_EFAULT;
13315 }
13316 }
13317 }
13318 }
13319 return ret;
13320#endif
13321
e10fbe8f
YT
13322#if defined(TARGET_NR_pivot_root)
13323 case TARGET_NR_pivot_root:
13324 {
13325 void *p2;
13326 p = lock_user_string(arg1); /* new_root */
13327 p2 = lock_user_string(arg2); /* put_old */
13328 if (!p || !p2) {
13329 ret = -TARGET_EFAULT;
13330 } else {
13331 ret = get_errno(pivot_root(p, p2));
13332 }
13333 unlock_user(p2, arg2, 0);
13334 unlock_user(p, arg1, 0);
13335 }
13336 return ret;
13337#endif
13338
31e31b8a 13339 default:
122f9c83 13340 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
72eb7ea8 13341 return -TARGET_ENOSYS;
31e31b8a 13342 }
31e31b8a
FB
13343 return ret;
13344}
dc1ce18b 13345
a0939b89 13346abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
dc1ce18b
RH
13347 abi_long arg2, abi_long arg3, abi_long arg4,
13348 abi_long arg5, abi_long arg6, abi_long arg7,
13349 abi_long arg8)
13350{
29a0af61 13351 CPUState *cpu = env_cpu(cpu_env);
dc1ce18b
RH
13352 abi_long ret;
13353
13354#ifdef DEBUG_ERESTARTSYS
13355 /* Debug-only code for exercising the syscall-restart code paths
13356 * in the per-architecture cpu main loops: restart every syscall
13357 * the guest makes once before letting it through.
13358 */
13359 {
13360 static bool flag;
13361 flag = !flag;
13362 if (flag) {
af254a27 13363 return -QEMU_ERESTARTSYS;
dc1ce18b
RH
13364 }
13365 }
13366#endif
13367
c36f7a64
EC
13368 record_syscall_start(cpu, num, arg1,
13369 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
dc1ce18b 13370
4b25a506 13371 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119 13372 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
4b25a506
JK
13373 }
13374
13375 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13376 arg5, arg6, arg7, arg8);
13377
13378 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119
FB
13379 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13380 arg3, arg4, arg5, arg6);
dc1ce18b
RH
13381 }
13382
c36f7a64 13383 record_syscall_return(cpu, num, ret);
dc1ce18b
RH
13384 return ret;
13385}