]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/syscall.c
Merge tag 'pull-aspeed-20230207' of https://github.com/legoater/qemu into staging
[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"
31e31b8a
FB
25#include <elf.h>
26#include <endian.h>
c56dc774 27#include <grp.h>
d08d3bb8
TS
28#include <sys/ipc.h>
29#include <sys/msg.h>
31e31b8a 30#include <sys/wait.h>
31e31b8a 31#include <sys/mount.h>
586b0bef
JS
32#include <sys/file.h>
33#include <sys/fsuid.h>
34#include <sys/personality.h>
39b9aae1 35#include <sys/prctl.h>
31e31b8a 36#include <sys/resource.h>
31e31b8a 37#include <sys/swap.h>
e0eb210e 38#include <linux/capability.h>
31e31b8a 39#include <sched.h>
19f59bce 40#include <sys/timex.h>
31e31b8a 41#include <sys/socket.h>
6d5d5dde 42#include <linux/sockios.h>
607175e0 43#include <sys/un.h>
31e31b8a 44#include <sys/uio.h>
0839f11c 45#include <poll.h>
32f36bce 46#include <sys/times.h>
8853f86e 47#include <sys/shm.h>
fa294816 48#include <sys/sem.h>
56c8f68f 49#include <sys/statfs.h>
ebc05488 50#include <utime.h>
a5448a7d 51#include <sys/sysinfo.h>
e36800c9 52#include <sys/signalfd.h>
72f03900 53//#include <sys/user.h>
22db1213 54#include <netinet/in.h>
8853f86e 55#include <netinet/ip.h>
7854b056 56#include <netinet/tcp.h>
fe51b0a5 57#include <netinet/udp.h>
86fcd946 58#include <linux/wireless.h>
920394db 59#include <linux/icmp.h>
ee1ac3a1 60#include <linux/icmpv6.h>
6addf06a 61#include <linux/if_tun.h>
22db1213 62#include <linux/in6.h>
ee1ac3a1 63#include <linux/errqueue.h>
d6d6d6fe 64#include <linux/random.h>
d80a1905
RV
65#ifdef CONFIG_TIMERFD
66#include <sys/timerfd.h>
67#endif
c2882b96
RV
68#ifdef CONFIG_EVENTFD
69#include <sys/eventfd.h>
70#endif
3b6edd16
PM
71#ifdef CONFIG_EPOLL
72#include <sys/epoll.h>
73#endif
a790ae38 74#ifdef CONFIG_ATTR
1de7afc9 75#include "qemu/xattr.h"
a790ae38 76#endif
a8fd1aba
PM
77#ifdef CONFIG_SENDFILE
78#include <sys/sendfile.h>
79#endif
4a9d5f89 80#ifdef HAVE_SYS_KCOV_H
bd27e675
AM
81#include <sys/kcov.h>
82#endif
31e31b8a
FB
83
84#define termios host_termios
85#define winsize host_winsize
86#define termio host_termio
04369ff2
FB
87#define sgttyb host_sgttyb /* same as target */
88#define tchars host_tchars /* same as target */
89#define ltchars host_ltchars /* same as target */
31e31b8a
FB
90
91#include <linux/termios.h>
92#include <linux/unistd.h>
31e31b8a
FB
93#include <linux/cdrom.h>
94#include <linux/hdreg.h>
95#include <linux/soundcard.h>
19b84f3c 96#include <linux/kd.h>
8fbd6b52 97#include <linux/mtio.h>
350d1779 98#include <linux/fs.h>
ab22b4dd 99#include <linux/fd.h>
dace20dc 100#if defined(CONFIG_FIEMAP)
285da2b9 101#include <linux/fiemap.h>
dace20dc 102#endif
f7680a55 103#include <linux/fb.h>
6c753a63
CT
104#if defined(CONFIG_USBFS)
105#include <linux/usbdevice_fs.h>
a133367e 106#include <linux/usb/ch9.h>
6c753a63 107#endif
f7680a55 108#include <linux/vt.h>
56e904ec 109#include <linux/dm-ioctl.h>
c07ecc68 110#include <linux/reboot.h>
7ff7b666 111#include <linux/route.h>
f57d4192 112#include <linux/filter.h>
fff8c539 113#include <linux/blkpg.h>
a82ea939 114#include <netpacket/packet.h>
6c5b5645 115#include <linux/netlink.h>
f31dddd2 116#include <linux/if_alg.h>
68365f96 117#include <linux/rtc.h>
1c4c6fcd 118#include <sound/asound.h>
48f670ec 119#ifdef HAVE_BTRFS_H
d6092e08
FB
120#include <linux/btrfs.h>
121#endif
e865b97f
CG
122#ifdef HAVE_DRM_H
123#include <libdrm/drm.h>
913b03c2 124#include <libdrm/i915_drm.h>
e865b97f 125#endif
d7e4036e 126#include "linux_loop.h"
18cb0088 127#include "uname.h"
31e31b8a 128
3ef693a0 129#include "qemu.h"
3b249d26 130#include "user-internals.h"
a44d57a3 131#include "strace.h"
2113aed6 132#include "signal-common.h"
3ad0a769 133#include "loader.h"
5423e6d3 134#include "user-mmap.h"
bbf15aaf 135#include "user/safe-syscall.h"
5ebdd774 136#include "qemu/guest-random.h"
01ef6b9e 137#include "qemu/selfmap.h"
c36f7a64 138#include "user/syscall-trace.h"
5da4063f 139#include "special-errno.h"
51977e25 140#include "qapi/error.h"
f7e6a401 141#include "fd-trans.h"
dcb32f1d 142#include "tcg/tcg.h"
bd5ccd61 143#include "cpu_loop-common.h"
31e31b8a 144
5ea2fc84
PM
145#ifndef CLONE_IO
146#define CLONE_IO 0x80000000 /* Clone io context */
147#endif
148
149/* We can't directly call the host clone syscall, because this will
150 * badly confuse libc (breaking mutexes, for example). So we must
151 * divide clone flags into:
152 * * flag combinations that look like pthread_create()
153 * * flag combinations that look like fork()
154 * * flags we can implement within QEMU itself
155 * * flags we can't support and will return an error for
156 */
157/* For thread creation, all these flags must be present; for
158 * fork, none must be present.
159 */
160#define CLONE_THREAD_FLAGS \
161 (CLONE_VM | CLONE_FS | CLONE_FILES | \
162 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
163
164/* These flags are ignored:
165 * CLONE_DETACHED is now ignored by the kernel;
166 * CLONE_IO is just an optimisation hint to the I/O scheduler
167 */
168#define CLONE_IGNORED_FLAGS \
169 (CLONE_DETACHED | CLONE_IO)
170
171/* Flags for fork which we can implement within QEMU itself */
172#define CLONE_OPTIONAL_FORK_FLAGS \
173 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
174 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
175
176/* Flags for thread creation which we can implement within QEMU itself */
177#define CLONE_OPTIONAL_THREAD_FLAGS \
178 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
179 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
180
181#define CLONE_INVALID_FORK_FLAGS \
182 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
183
184#define CLONE_INVALID_THREAD_FLAGS \
185 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
186 CLONE_IGNORED_FLAGS))
187
188/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
189 * have almost all been allocated. We cannot support any of
190 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
191 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
192 * The checks against the invalid thread masks above will catch these.
193 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
194 */
30813cea 195
71a8f7fe
TB
196/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
197 * once. This exercises the codepaths for restart.
198 */
199//#define DEBUG_ERESTARTSYS
31e31b8a 200
1a9353d2 201//#include <linux/msdos_fs.h>
540a736f
RH
202#define VFAT_IOCTL_READDIR_BOTH \
203 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
204#define VFAT_IOCTL_READDIR_SHORT \
205 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
1a9353d2 206
70a194b9
FB
207#undef _syscall0
208#undef _syscall1
209#undef _syscall2
210#undef _syscall3
211#undef _syscall4
212#undef _syscall5
83fcb515 213#undef _syscall6
70a194b9 214
83fcb515 215#define _syscall0(type,name) \
8fcd3692 216static type name (void) \
83fcb515
FB
217{ \
218 return syscall(__NR_##name); \
219}
70a194b9 220
83fcb515 221#define _syscall1(type,name,type1,arg1) \
8fcd3692 222static type name (type1 arg1) \
83fcb515
FB
223{ \
224 return syscall(__NR_##name, arg1); \
70a194b9
FB
225}
226
83fcb515 227#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 228static type name (type1 arg1,type2 arg2) \
83fcb515
FB
229{ \
230 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
231}
232
83fcb515 233#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 234static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
235{ \
236 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
237}
238
83fcb515 239#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 240static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
241{ \
242 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
243}
244
83fcb515
FB
245#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
246 type5,arg5) \
8fcd3692 247static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
248{ \
249 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
250}
251
83fcb515
FB
252
253#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
254 type5,arg5,type6,arg6) \
8fcd3692
BS
255static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
256 type6 arg6) \
83fcb515
FB
257{ \
258 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 259}
83fcb515 260
70a194b9 261
31e31b8a 262#define __NR_sys_uname __NR_uname
72f03900 263#define __NR_sys_getcwd1 __NR_getcwd
72f03900 264#define __NR_sys_getdents __NR_getdents
dab2ed99 265#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 266#define __NR_sys_getpriority __NR_getpriority
66fb9763 267#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
cf8b8bfc 268#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
7494b0f9 269#define __NR_sys_syslog __NR_syslog
14690296
AF
270#if defined(__NR_futex)
271# define __NR_sys_futex __NR_futex
272#endif
273#if defined(__NR_futex_time64)
274# define __NR_sys_futex_time64 __NR_futex_time64
275#endif
efa92184 276#define __NR_sys_statx __NR_statx
31e31b8a 277
b1cef6d0 278#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
9af9eaaa
FB
279#define __NR__llseek __NR_lseek
280#endif
281
a29e5ba2
JH
282/* Newer kernel ports have llseek() instead of _llseek() */
283#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
284#define TARGET_NR__llseek TARGET_NR_llseek
285#endif
286
78721301
HD
287/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
288#ifndef TARGET_O_NONBLOCK_MASK
289#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
290#endif
291
71ba74f6
DB
292#define __NR_sys_gettid __NR_gettid
293_syscall0(int, sys_gettid)
2b3f64cb
PM
294
295/* For the 64-bit guest on 32-bit host case we must emulate
296 * getdents using getdents64, because otherwise the host
297 * might hand us back more dirent records than we can fit
298 * into the guest buffer after structure format conversion.
299 * Otherwise we emulate getdents with getdents if the host has it.
300 */
301#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
302#define EMULATE_GETDENTS_WITH_GETDENTS
303#endif
304
305#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
3b3f24ad 306_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3307e236 307#endif
2b3f64cb
PM
308#if (defined(TARGET_NR_getdents) && \
309 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
3307e236 310 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
3b3f24ad
AJ
311_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
312#endif
d35b261c 313#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
314_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
315 loff_t *, res, uint, wh);
316#endif
c1a402a7 317_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
cf8b8bfc
MS
318_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
319 siginfo_t *, uinfo)
3b3f24ad 320_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
3b3f24ad
AJ
321#ifdef __NR_exit_group
322_syscall1(int,exit_group,int,error_code)
323#endif
af804f39
HD
324#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
325#define __NR_sys_close_range __NR_close_range
326_syscall3(int,sys_close_range,int,first,int,last,int,flags)
327#ifndef CLOSE_RANGE_CLOEXEC
328#define CLOSE_RANGE_CLOEXEC (1U << 2)
329#endif
330#endif
14690296 331#if defined(__NR_futex)
3b3f24ad
AJ
332_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
333 const struct timespec *,timeout,int *,uaddr2,int,val3)
334#endif
14690296
AF
335#if defined(__NR_futex_time64)
336_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
337 const struct timespec *,timeout,int *,uaddr2,int,val3)
338#endif
cc054c6f
HD
339#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
340_syscall2(int, pidfd_open, pid_t, pid, unsigned int, flags);
341#endif
342#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
343_syscall4(int, pidfd_send_signal, int, pidfd, int, sig, siginfo_t *, info,
344 unsigned int, flags);
345#endif
346#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
347_syscall3(int, pidfd_getfd, int, pidfd, int, targetfd, unsigned int, flags);
348#endif
737de1d1
MF
349#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
350_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
351 unsigned long *, user_mask_ptr);
352#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
353_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
354 unsigned long *, user_mask_ptr);
45ad761c
TT
355/* sched_attr is not defined in glibc */
356struct sched_attr {
357 uint32_t size;
358 uint32_t sched_policy;
359 uint64_t sched_flags;
360 int32_t sched_nice;
361 uint32_t sched_priority;
362 uint64_t sched_runtime;
363 uint64_t sched_deadline;
364 uint64_t sched_period;
365 uint32_t sched_util_min;
366 uint32_t sched_util_max;
367};
368#define __NR_sys_sched_getattr __NR_sched_getattr
369_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
370 unsigned int, size, unsigned int, flags);
371#define __NR_sys_sched_setattr __NR_sched_setattr
372_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
373 unsigned int, flags);
407a119b
TT
374#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
375_syscall1(int, sys_sched_getscheduler, pid_t, pid);
376#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
377_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
378 const struct sched_param *, param);
379#define __NR_sys_sched_getparam __NR_sched_getparam
380_syscall2(int, sys_sched_getparam, pid_t, pid,
381 struct sched_param *, param);
382#define __NR_sys_sched_setparam __NR_sched_setparam
383_syscall2(int, sys_sched_setparam, pid_t, pid,
384 const struct sched_param *, param);
b827c3ed
ST
385#define __NR_sys_getcpu __NR_getcpu
386_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
0f6b4d21
AG
387_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
388 void *, arg);
e0eb210e
PM
389_syscall2(int, capget, struct __user_cap_header_struct *, header,
390 struct __user_cap_data_struct *, data);
391_syscall2(int, capset, struct __user_cap_header_struct *, header,
392 struct __user_cap_data_struct *, data);
ab31cda3
PB
393#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
394_syscall2(int, ioprio_get, int, which, int, who)
395#endif
396#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
397_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
398#endif
f894efd1
LV
399#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
400_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
401#endif
3b3f24ad 402
2f14788c
LV
403#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
404_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
405 unsigned long, idx1, unsigned long, idx2)
406#endif
407
efa92184
AR
408/*
409 * It is assumed that struct statx is architecture independent.
410 */
411#if defined(TARGET_NR_statx) && defined(__NR_statx)
412_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
413 unsigned int, mask, struct target_statx *, statxbuf)
414#endif
8500476f
AS
415#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
416_syscall2(int, membarrier, int, cmd, int, flags)
417#endif
efa92184 418
180d4ef3 419static const bitmask_transtbl fcntl_flags_tbl[] = {
3b3f24ad
AJ
420 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
421 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
422 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
423 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
424 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
425 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
426 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
427 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
afc8763f 428 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
3b3f24ad
AJ
429 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
430 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
431 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
432 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
3b3f24ad
AJ
433#if defined(O_DIRECT)
434 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
afc8763f
RH
435#endif
436#if defined(O_NOATIME)
437 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
438#endif
439#if defined(O_CLOEXEC)
440 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
441#endif
442#if defined(O_PATH)
443 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
5f9cee46
RV
444#endif
445#if defined(O_TMPFILE)
446 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
afc8763f
RH
447#endif
448 /* Don't terminate the list prematurely on 64-bit host+guest. */
449#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
450 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
3b3f24ad
AJ
451#endif
452 { 0, 0, 0, 0 }
453};
454
0f6bb195 455_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
3b3f24ad 456
cac46eb0 457#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
700fa58e 458#if defined(__NR_utimensat)
1acae9f2 459#define __NR_sys_utimensat __NR_utimensat
9007f0ef
TS
460_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
461 const struct timespec *,tsp,int,flags)
1acae9f2
PM
462#else
463static int sys_utimensat(int dirfd, const char *pathname,
464 const struct timespec times[2], int flags)
465{
466 errno = ENOSYS;
467 return -1;
468}
9007f0ef 469#endif
1acae9f2 470#endif /* TARGET_NR_utimensat */
3b3f24ad 471
95d0307c
AS
472#ifdef TARGET_NR_renameat2
473#if defined(__NR_renameat2)
474#define __NR_sys_renameat2 __NR_renameat2
475_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
476 const char *, new, unsigned int, flags)
477#else
478static int sys_renameat2(int oldfd, const char *old,
479 int newfd, const char *new, int flags)
480{
481 if (flags == 0) {
482 return renameat(oldfd, old, newfd, new);
483 }
484 errno = ENOSYS;
485 return -1;
486}
487#endif
488#endif /* TARGET_NR_renameat2 */
489
3b3f24ad 490#ifdef CONFIG_INOTIFY
8690e420 491#include <sys/inotify.h>
3b3f24ad
AJ
492#else
493/* Userspace can usually survive runtime without inotify */
494#undef TARGET_NR_inotify_init
c05c7a73 495#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
496#undef TARGET_NR_inotify_add_watch
497#undef TARGET_NR_inotify_rm_watch
498#endif /* CONFIG_INOTIFY */
499
163a05a8
PM
500#if defined(TARGET_NR_prlimit64)
501#ifndef __NR_prlimit64
502# define __NR_prlimit64 -1
503#endif
504#define __NR_sys_prlimit64 __NR_prlimit64
505/* The glibc rlimit structure may not be that used by the underlying syscall */
506struct host_rlimit64 {
507 uint64_t rlim_cur;
508 uint64_t rlim_max;
509};
510_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
511 const struct host_rlimit64 *, new_limit,
512 struct host_rlimit64 *, old_limit)
513#endif
514
f4f1e10a
ECL
515
516#if defined(TARGET_NR_timer_create)
6f9ff551 517/* Maximum of 32 active POSIX timers allowed at any one time. */
9e59899f
PM
518#define GUEST_TIMER_MAX 32
519static timer_t g_posix_timers[GUEST_TIMER_MAX];
520static int g_posix_timer_allocated[GUEST_TIMER_MAX];
f4f1e10a
ECL
521
522static inline int next_free_host_timer(void)
523{
9e59899f
PM
524 int k;
525 for (k = 0; k < ARRAY_SIZE(g_posix_timer_allocated); k++) {
526 if (qatomic_xchg(g_posix_timer_allocated + k, 1) == 0) {
f4f1e10a
ECL
527 return k;
528 }
529 }
530 return -1;
531}
9e59899f
PM
532
533static inline void free_host_timer_slot(int id)
534{
535 qatomic_store_release(g_posix_timer_allocated + id, 0);
536}
f4f1e10a
ECL
537#endif
538
3ffe3268 539static inline int host_to_target_errno(int host_errno)
637947f1 540{
3ffe3268
PMD
541 switch (host_errno) {
542#define E(X) case X: return TARGET_##X;
543#include "errnos.c.inc"
544#undef E
545 default:
546 return host_errno;
2466119c 547 }
637947f1
TS
548}
549
3ffe3268 550static inline int target_to_host_errno(int target_errno)
b92c47c1 551{
3ffe3268
PMD
552 switch (target_errno) {
553#define E(X) case TARGET_##X: return X;
554#include "errnos.c.inc"
555#undef E
556 default:
557 return target_errno;
2466119c 558 }
b92c47c1
TS
559}
560
892a4f6a 561abi_long get_errno(abi_long ret)
31e31b8a
FB
562{
563 if (ret == -1)
637947f1 564 return -host_to_target_errno(errno);
31e31b8a
FB
565 else
566 return ret;
567}
568
7dcdaeaf 569const char *target_strerror(int err)
b92c47c1 570{
af254a27 571 if (err == QEMU_ERESTARTSYS) {
da2a34f7
PM
572 return "To be restarted";
573 }
57a0c938 574 if (err == QEMU_ESIGRETURN) {
da2a34f7
PM
575 return "Successful exit from sigreturn";
576 }
577
b92c47c1
TS
578 return strerror(target_to_host_errno(err));
579}
580
45ad761c
TT
581static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
582{
583 int i;
584 uint8_t b;
585 if (usize <= ksize) {
586 return 1;
587 }
588 for (i = ksize; i < usize; i++) {
589 if (get_user_u8(b, addr + i)) {
590 return -TARGET_EFAULT;
591 }
592 if (b != 0) {
593 return 0;
594 }
595 }
596 return 1;
597}
598
4d330cee
TB
599#define safe_syscall0(type, name) \
600static type safe_##name(void) \
601{ \
602 return safe_syscall(__NR_##name); \
603}
604
605#define safe_syscall1(type, name, type1, arg1) \
606static type safe_##name(type1 arg1) \
607{ \
608 return safe_syscall(__NR_##name, arg1); \
609}
610
611#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
612static type safe_##name(type1 arg1, type2 arg2) \
613{ \
614 return safe_syscall(__NR_##name, arg1, arg2); \
615}
616
617#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
618static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
619{ \
620 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
621}
622
623#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
624 type4, arg4) \
625static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
626{ \
627 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
628}
629
630#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
631 type4, arg4, type5, arg5) \
632static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
633 type5 arg5) \
634{ \
635 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
636}
637
638#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
639 type4, arg4, type5, arg5, type6, arg6) \
640static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
641 type5 arg5, type6 arg6) \
642{ \
643 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
644}
645
50afd02b
TB
646safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
647safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
c10a0738
TB
648safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
649 int, flags, mode_t, mode)
859e8a89 650#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
4af80a37
TB
651safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
652 struct rusage *, rusage)
859e8a89 653#endif
4af80a37
TB
654safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
655 int, options, struct rusage *, rusage)
55bbe4d5
DD
656safe_syscall5(int, execveat, int, dirfd, const char *, filename,
657 char **, argv, char **, envp, int, flags)
859e8a89 658#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 659 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
6df9d38d
PM
660safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
661 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
859e8a89 662#endif
e5ce9688 663#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
a6130237
PM
664safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
665 struct timespec *, tsp, const sigset_t *, sigmask,
666 size_t, sigsetsize)
859e8a89 667#endif
227f0214
PM
668safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
669 int, maxevents, int, timeout, const sigset_t *, sigmask,
670 size_t, sigsetsize)
14690296 671#if defined(__NR_futex)
d509eeb1
PM
672safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
673 const struct timespec *,timeout,int *,uaddr2,int,val3)
859e8a89 674#endif
14690296
AF
675#if defined(__NR_futex_time64)
676safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
677 const struct timespec *,timeout,int *,uaddr2,int,val3)
678#endif
2fe4fba1 679safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
bef653d9
PM
680safe_syscall2(int, kill, pid_t, pid, int, sig)
681safe_syscall2(int, tkill, int, tid, int, sig)
682safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
918c03ed
PM
683safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
684safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
0f26386c
DJ
685safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
686 unsigned long, pos_l, unsigned long, pos_h)
f8d00fba
DJ
687safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
688 unsigned long, pos_l, unsigned long, pos_h)
2a3c7619
PM
689safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
690 socklen_t, addrlen)
66687530
PM
691safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
692 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
693safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
694 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
695safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
696safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
2a845989 697safe_syscall2(int, flock, int, fd, int, operation)
ddcbde15 698#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
b3f82330
PM
699safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
700 const struct timespec *, uts, size_t, sigsetsize)
859e8a89 701#endif
ff6dc130
PM
702safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
703 int, flags)
859e8a89 704#if defined(TARGET_NR_nanosleep)
9e518226
PM
705safe_syscall2(int, nanosleep, const struct timespec *, req,
706 struct timespec *, rem)
859e8a89 707#endif
6ac03b2c
FB
708#if defined(TARGET_NR_clock_nanosleep) || \
709 defined(TARGET_NR_clock_nanosleep_time64)
9e518226
PM
710safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
711 const struct timespec *, req, struct timespec *, rem)
712#endif
524fa340 713#ifdef __NR_ipc
d8c08b1e
MK
714#ifdef __s390x__
715safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
716 void *, ptr)
717#else
89f9fe44
PM
718safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
719 void *, ptr, long, fifth)
86e63695 720#endif
d8c08b1e 721#endif
86e63695
LV
722#ifdef __NR_msgsnd
723safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
724 int, flags)
86e63695
LV
725#endif
726#ifdef __NR_msgrcv
727safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
728 long, msgtype, int, flags)
86e63695
LV
729#endif
730#ifdef __NR_semtimedop
731safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
732 unsigned, nsops, const struct timespec *, timeout)
89f9fe44 733#endif
d107e375
FB
734#if defined(TARGET_NR_mq_timedsend) || \
735 defined(TARGET_NR_mq_timedsend_time64)
d40ecd66
PM
736safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
737 size_t, len, unsigned, prio, const struct timespec *, timeout)
859e8a89 738#endif
d107e375
FB
739#if defined(TARGET_NR_mq_timedreceive) || \
740 defined(TARGET_NR_mq_timedreceive_time64)
d40ecd66
PM
741safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
742 size_t, len, unsigned *, prio, const struct timespec *, timeout)
743#endif
84946457
AS
744#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
745safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
746 int, outfd, loff_t *, poutoff, size_t, length,
747 unsigned int, flags)
748#endif
749
49ca6f3e
PM
750/* We do ioctl like this rather than via safe_syscall3 to preserve the
751 * "third argument might be integer or pointer or not present" behaviour of
752 * the libc function.
753 */
754#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
435da5e7
PM
755/* Similarly for fcntl. Note that callers must always:
756 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
757 * use the flock64 struct rather than unsuffixed flock
758 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
759 */
760#ifdef __NR_fcntl64
761#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
762#else
763#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
764#endif
50afd02b 765
8289d112
PB
766static inline int host_to_target_sock_type(int host_type)
767{
768 int target_type;
769
770 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
771 case SOCK_DGRAM:
772 target_type = TARGET_SOCK_DGRAM;
773 break;
774 case SOCK_STREAM:
775 target_type = TARGET_SOCK_STREAM;
776 break;
777 default:
778 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
779 break;
780 }
781
782#if defined(SOCK_CLOEXEC)
783 if (host_type & SOCK_CLOEXEC) {
784 target_type |= TARGET_SOCK_CLOEXEC;
785 }
786#endif
787
788#if defined(SOCK_NONBLOCK)
789 if (host_type & SOCK_NONBLOCK) {
790 target_type |= TARGET_SOCK_NONBLOCK;
791 }
792#endif
793
794 return target_type;
795}
796
992f48a0
BS
797static abi_ulong target_brk;
798static abi_ulong target_original_brk;
4d1de87c 799static abi_ulong brk_page;
31e31b8a 800
992f48a0 801void target_set_brk(abi_ulong new_brk)
31e31b8a 802{
4c1de73d 803 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
4d1de87c 804 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
805}
806
4d1de87c
CV
807//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
808#define DEBUGF_BRK(message, args...)
809
0da46a6e 810/* do_brk() must return target values and target errnos. */
992f48a0 811abi_long do_brk(abi_ulong new_brk)
31e31b8a 812{
992f48a0 813 abi_long mapped_addr;
ef4330c2 814 abi_ulong new_alloc_size;
31e31b8a 815
ee1bf83d
RH
816 /* brk pointers are always untagged */
817
3a0c6c4a 818 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
4d1de87c
CV
819
820 if (!new_brk) {
3a0c6c4a 821 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
53a5960a 822 return target_brk;
4d1de87c
CV
823 }
824 if (new_brk < target_original_brk) {
3a0c6c4a
PB
825 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
826 target_brk);
7ab240ad 827 return target_brk;
4d1de87c 828 }
3b46e624 829
4d1de87c
CV
830 /* If the new brk is less than the highest page reserved to the
831 * target heap allocation, set it and we're almost done... */
832 if (new_brk <= brk_page) {
833 /* Heap contents are initialized to zero, as for anonymous
834 * mapped pages. */
835 if (new_brk > target_brk) {
3e8f1628 836 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
4d1de87c 837 }
31e31b8a 838 target_brk = new_brk;
3a0c6c4a 839 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
72e21db7 840 return target_brk;
31e31b8a
FB
841 }
842
00faf08c
PM
843 /* We need to allocate more memory after the brk... Note that
844 * we don't use MAP_FIXED because that will map over the top of
845 * any existing mapping (like the one with the host libc or qemu
846 * itself); instead we treat "mapped but at wrong address" as
847 * a failure and unmap again.
848 */
4d1de87c 849 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
5fafdf24 850 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 851 PROT_READ|PROT_WRITE,
00faf08c
PM
852 MAP_ANON|MAP_PRIVATE, 0, 0));
853
854 if (mapped_addr == brk_page) {
70afc343
CV
855 /* Heap contents are initialized to zero, as for anonymous
856 * mapped pages. Technically the new pages are already
857 * initialized to zero since they *are* anonymous mapped
858 * pages, however we have to take care with the contents that
859 * come from the remaining part of the previous page: it may
860 * contains garbage data due to a previous heap usage (grown
861 * then shrunken). */
3e8f1628 862 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
70afc343 863
00faf08c 864 target_brk = new_brk;
4d1de87c 865 brk_page = HOST_PAGE_ALIGN(target_brk);
3a0c6c4a
PB
866 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
867 target_brk);
00faf08c
PM
868 return target_brk;
869 } else if (mapped_addr != -1) {
870 /* Mapped but at wrong address, meaning there wasn't actually
871 * enough space for this brk.
872 */
873 target_munmap(mapped_addr, new_alloc_size);
874 mapped_addr = -1;
3a0c6c4a 875 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
4d1de87c
CV
876 }
877 else {
3a0c6c4a 878 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
00faf08c 879 }
7ab240ad 880
7dd46c02
RH
881#if defined(TARGET_ALPHA)
882 /* We (partially) emulate OSF/1 on Alpha, which requires we
883 return a proper errno, not an unchanged brk value. */
00faf08c 884 return -TARGET_ENOMEM;
7dd46c02 885#endif
00faf08c 886 /* For everything else, return the previous break. */
7ab240ad 887 return target_brk;
31e31b8a
FB
888}
889
859e8a89 890#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 891 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
26edcf41
TS
892static inline abi_long copy_from_user_fdset(fd_set *fds,
893 abi_ulong target_fds_addr,
894 int n)
31e31b8a 895{
26edcf41
TS
896 int i, nw, j, k;
897 abi_ulong b, *target_fds;
898
b1b2db29 899 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
900 if (!(target_fds = lock_user(VERIFY_READ,
901 target_fds_addr,
902 sizeof(abi_ulong) * nw,
903 1)))
904 return -TARGET_EFAULT;
905
906 FD_ZERO(fds);
907 k = 0;
908 for (i = 0; i < nw; i++) {
909 /* grab the abi_ulong */
910 __get_user(b, &target_fds[i]);
911 for (j = 0; j < TARGET_ABI_BITS; j++) {
912 /* check the bit inside the abi_ulong */
913 if ((b >> j) & 1)
914 FD_SET(k, fds);
915 k++;
31e31b8a 916 }
31e31b8a 917 }
26edcf41
TS
918
919 unlock_user(target_fds, target_fds_addr, 0);
920
921 return 0;
31e31b8a
FB
922}
923
055e0906
MF
924static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
925 abi_ulong target_fds_addr,
926 int n)
927{
928 if (target_fds_addr) {
929 if (copy_from_user_fdset(fds, target_fds_addr, n))
930 return -TARGET_EFAULT;
931 *fds_ptr = fds;
932 } else {
933 *fds_ptr = NULL;
934 }
935 return 0;
936}
937
26edcf41
TS
938static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
939 const fd_set *fds,
940 int n)
31e31b8a 941{
31e31b8a 942 int i, nw, j, k;
992f48a0 943 abi_long v;
26edcf41 944 abi_ulong *target_fds;
31e31b8a 945
b1b2db29 946 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
947 if (!(target_fds = lock_user(VERIFY_WRITE,
948 target_fds_addr,
949 sizeof(abi_ulong) * nw,
950 0)))
951 return -TARGET_EFAULT;
952
953 k = 0;
954 for (i = 0; i < nw; i++) {
955 v = 0;
956 for (j = 0; j < TARGET_ABI_BITS; j++) {
9ab709be 957 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
26edcf41 958 k++;
31e31b8a 959 }
26edcf41 960 __put_user(v, &target_fds[i]);
31e31b8a 961 }
26edcf41
TS
962
963 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
964
965 return 0;
31e31b8a 966}
859e8a89 967#endif
31e31b8a 968
c596ed17
FB
969#if defined(__alpha__)
970#define HOST_HZ 1024
971#else
972#define HOST_HZ 100
973#endif
974
992f48a0 975static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
976{
977#if HOST_HZ == TARGET_HZ
978 return ticks;
979#else
980 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
981#endif
982}
983
579a97f7
FB
984static inline abi_long host_to_target_rusage(abi_ulong target_addr,
985 const struct rusage *rusage)
b409186b 986{
53a5960a
PB
987 struct target_rusage *target_rusage;
988
579a97f7
FB
989 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
990 return -TARGET_EFAULT;
cbb21eed
MB
991 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
992 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
993 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
994 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
995 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
996 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
997 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
998 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
999 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
1000 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
1001 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
1002 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
1003 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
1004 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
1005 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
1006 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
1007 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
1008 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
53a5960a 1009 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
1010
1011 return 0;
b409186b
FB
1012}
1013
859e8a89 1014#ifdef TARGET_NR_setrlimit
cbb21eed 1015static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
81bbe906 1016{
cbb21eed 1017 abi_ulong target_rlim_swap;
95b33b2f
WT
1018 rlim_t result;
1019
cbb21eed
MB
1020 target_rlim_swap = tswapal(target_rlim);
1021 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1022 return RLIM_INFINITY;
1023
1024 result = target_rlim_swap;
1025 if (target_rlim_swap != (rlim_t)result)
1026 return RLIM_INFINITY;
95b33b2f
WT
1027
1028 return result;
81bbe906 1029}
859e8a89 1030#endif
81bbe906 1031
859e8a89 1032#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
cbb21eed 1033static inline abi_ulong host_to_target_rlim(rlim_t rlim)
81bbe906 1034{
cbb21eed
MB
1035 abi_ulong target_rlim_swap;
1036 abi_ulong result;
95b33b2f 1037
cbb21eed 1038 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
95b33b2f 1039 target_rlim_swap = TARGET_RLIM_INFINITY;
81bbe906 1040 else
95b33b2f 1041 target_rlim_swap = rlim;
cbb21eed 1042 result = tswapal(target_rlim_swap);
95b33b2f
WT
1043
1044 return result;
81bbe906 1045}
859e8a89 1046#endif
81bbe906 1047
e22b7015
WT
1048static inline int target_to_host_resource(int code)
1049{
1050 switch (code) {
1051 case TARGET_RLIMIT_AS:
1052 return RLIMIT_AS;
1053 case TARGET_RLIMIT_CORE:
1054 return RLIMIT_CORE;
1055 case TARGET_RLIMIT_CPU:
1056 return RLIMIT_CPU;
1057 case TARGET_RLIMIT_DATA:
1058 return RLIMIT_DATA;
1059 case TARGET_RLIMIT_FSIZE:
1060 return RLIMIT_FSIZE;
1061 case TARGET_RLIMIT_LOCKS:
1062 return RLIMIT_LOCKS;
1063 case TARGET_RLIMIT_MEMLOCK:
1064 return RLIMIT_MEMLOCK;
1065 case TARGET_RLIMIT_MSGQUEUE:
1066 return RLIMIT_MSGQUEUE;
1067 case TARGET_RLIMIT_NICE:
1068 return RLIMIT_NICE;
1069 case TARGET_RLIMIT_NOFILE:
1070 return RLIMIT_NOFILE;
1071 case TARGET_RLIMIT_NPROC:
1072 return RLIMIT_NPROC;
1073 case TARGET_RLIMIT_RSS:
1074 return RLIMIT_RSS;
1075 case TARGET_RLIMIT_RTPRIO:
1076 return RLIMIT_RTPRIO;
c3a28d71 1077#ifdef RLIMIT_RTTIME
244fd083
SB
1078 case TARGET_RLIMIT_RTTIME:
1079 return RLIMIT_RTTIME;
c3a28d71 1080#endif
e22b7015
WT
1081 case TARGET_RLIMIT_SIGPENDING:
1082 return RLIMIT_SIGPENDING;
1083 case TARGET_RLIMIT_STACK:
1084 return RLIMIT_STACK;
1085 default:
1086 return code;
1087 }
1088}
1089
788f5ec4
TS
1090static inline abi_long copy_from_user_timeval(struct timeval *tv,
1091 abi_ulong target_tv_addr)
31e31b8a 1092{
53a5960a
PB
1093 struct target_timeval *target_tv;
1094
6d5d5dde 1095 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
579a97f7 1096 return -TARGET_EFAULT;
6d5d5dde 1097 }
788f5ec4
TS
1098
1099 __get_user(tv->tv_sec, &target_tv->tv_sec);
1100 __get_user(tv->tv_usec, &target_tv->tv_usec);
1101
1102 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
1103
1104 return 0;
31e31b8a
FB
1105}
1106
788f5ec4
TS
1107static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1108 const struct timeval *tv)
31e31b8a 1109{
53a5960a
PB
1110 struct target_timeval *target_tv;
1111
6d5d5dde
DB
1112 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1113 return -TARGET_EFAULT;
1114 }
1115
1116 __put_user(tv->tv_sec, &target_tv->tv_sec);
1117 __put_user(tv->tv_usec, &target_tv->tv_usec);
1118
1119 unlock_user_struct(target_tv, target_tv_addr, 1);
1120
1121 return 0;
1122}
1123
6ac03b2c
FB
1124#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1125static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1126 abi_ulong target_tv_addr)
1127{
1128 struct target__kernel_sock_timeval *target_tv;
1129
1130 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1131 return -TARGET_EFAULT;
1132 }
1133
1134 __get_user(tv->tv_sec, &target_tv->tv_sec);
1135 __get_user(tv->tv_usec, &target_tv->tv_usec);
1136
1137 unlock_user_struct(target_tv, target_tv_addr, 0);
1138
1139 return 0;
1140}
1141#endif
1142
6d5d5dde 1143static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
6ac03b2c 1144 const struct timeval *tv)
6d5d5dde
DB
1145{
1146 struct target__kernel_sock_timeval *target_tv;
1147
1148 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
579a97f7 1149 return -TARGET_EFAULT;
6d5d5dde 1150 }
788f5ec4
TS
1151
1152 __put_user(tv->tv_sec, &target_tv->tv_sec);
1153 __put_user(tv->tv_usec, &target_tv->tv_usec);
1154
1155 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
1156
1157 return 0;
31e31b8a
FB
1158}
1159
859e8a89
AF
1160#if defined(TARGET_NR_futex) || \
1161 defined(TARGET_NR_rt_sigtimedwait) || \
1162 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1163 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1164 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
d8c08b1e 1165 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
2c86c90f
FB
1166 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1167 defined(TARGET_NR_timer_settime) || \
1168 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
6d5d5dde
DB
1169static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1170 abi_ulong target_addr)
1171{
1172 struct target_timespec *target_ts;
1173
1174 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1175 return -TARGET_EFAULT;
1176 }
1177 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1178 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1179 unlock_user_struct(target_ts, target_addr, 0);
1180 return 0;
1181}
859e8a89 1182#endif
6d5d5dde 1183
828cb3a1
FB
1184#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1185 defined(TARGET_NR_timer_settime64) || \
d107e375
FB
1186 defined(TARGET_NR_mq_timedsend_time64) || \
1187 defined(TARGET_NR_mq_timedreceive_time64) || \
6ac03b2c 1188 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
ddcbde15 1189 defined(TARGET_NR_clock_nanosleep_time64) || \
cac46eb0
FB
1190 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1191 defined(TARGET_NR_utimensat) || \
1192 defined(TARGET_NR_utimensat_time64) || \
e5ce9688
FB
1193 defined(TARGET_NR_semtimedop_time64) || \
1194 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
c6c8d102
AF
1195static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1196 abi_ulong target_addr)
1197{
1198 struct target__kernel_timespec *target_ts;
1199
1200 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1201 return -TARGET_EFAULT;
1202 }
1203 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1204 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
00576757
LV
1205 /* in 32bit mode, this drops the padding */
1206 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
c6c8d102
AF
1207 unlock_user_struct(target_ts, target_addr, 0);
1208 return 0;
1209}
1210#endif
1211
6d5d5dde
DB
1212static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1213 struct timespec *host_ts)
1214{
1215 struct target_timespec *target_ts;
1216
1217 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1218 return -TARGET_EFAULT;
1219 }
1220 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1221 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1222 unlock_user_struct(target_ts, target_addr, 1);
1223 return 0;
1224}
1225
1226static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1227 struct timespec *host_ts)
1228{
1229 struct target__kernel_timespec *target_ts;
1230
1231 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1232 return -TARGET_EFAULT;
1233 }
1234 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1235 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1236 unlock_user_struct(target_ts, target_addr, 1);
1237 return 0;
1238}
1239
a52f5f87
RH
1240#if defined(TARGET_NR_gettimeofday)
1241static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1242 struct timezone *tz)
1243{
1244 struct target_timezone *target_tz;
1245
1246 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1247 return -TARGET_EFAULT;
1248 }
1249
1250 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1251 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1252
1253 unlock_user_struct(target_tz, target_tz_addr, 1);
1254
1255 return 0;
1256}
1257#endif
1258
859e8a89 1259#if defined(TARGET_NR_settimeofday)
ef4467e9
PB
1260static inline abi_long copy_from_user_timezone(struct timezone *tz,
1261 abi_ulong target_tz_addr)
1262{
1263 struct target_timezone *target_tz;
1264
1265 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1266 return -TARGET_EFAULT;
1267 }
1268
1269 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1270 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1271
1272 unlock_user_struct(target_tz, target_tz_addr, 0);
1273
1274 return 0;
1275}
859e8a89 1276#endif
ef4467e9 1277
8ec9cf89
NF
1278#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1279#include <mqueue.h>
1280
24e1003a
AJ
1281static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1282 abi_ulong target_mq_attr_addr)
1283{
1284 struct target_mq_attr *target_mq_attr;
1285
1286 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1287 target_mq_attr_addr, 1))
1288 return -TARGET_EFAULT;
1289
1290 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1291 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1292 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1293 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1294
1295 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1296
1297 return 0;
1298}
1299
1300static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1301 const struct mq_attr *attr)
1302{
1303 struct target_mq_attr *target_mq_attr;
1304
1305 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1306 target_mq_attr_addr, 0))
1307 return -TARGET_EFAULT;
1308
1309 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1310 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1311 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1312 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1313
1314 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1315
1316 return 0;
1317}
8ec9cf89 1318#endif
31e31b8a 1319
055e0906 1320#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 1321/* do_select() must return target values and target errnos. */
992f48a0 1322static abi_long do_select(int n,
26edcf41
TS
1323 abi_ulong rfd_addr, abi_ulong wfd_addr,
1324 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
1325{
1326 fd_set rfds, wfds, efds;
1327 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
6df9d38d
PM
1328 struct timeval tv;
1329 struct timespec ts, *ts_ptr;
992f48a0 1330 abi_long ret;
31e31b8a 1331
055e0906
MF
1332 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1333 if (ret) {
1334 return ret;
53a5960a 1335 }
055e0906
MF
1336 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1337 if (ret) {
1338 return ret;
53a5960a 1339 }
055e0906
MF
1340 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1341 if (ret) {
1342 return ret;
53a5960a 1343 }
3b46e624 1344
26edcf41 1345 if (target_tv_addr) {
788f5ec4
TS
1346 if (copy_from_user_timeval(&tv, target_tv_addr))
1347 return -TARGET_EFAULT;
6df9d38d
PM
1348 ts.tv_sec = tv.tv_sec;
1349 ts.tv_nsec = tv.tv_usec * 1000;
1350 ts_ptr = &ts;
31e31b8a 1351 } else {
6df9d38d 1352 ts_ptr = NULL;
31e31b8a 1353 }
26edcf41 1354
6df9d38d
PM
1355 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1356 ts_ptr, NULL));
53a5960a 1357
26edcf41
TS
1358 if (!is_error(ret)) {
1359 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1360 return -TARGET_EFAULT;
1361 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1362 return -TARGET_EFAULT;
1363 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1364 return -TARGET_EFAULT;
31e31b8a 1365
6df9d38d
PM
1366 if (target_tv_addr) {
1367 tv.tv_sec = ts.tv_sec;
1368 tv.tv_usec = ts.tv_nsec / 1000;
1369 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1370 return -TARGET_EFAULT;
1371 }
1372 }
31e31b8a 1373 }
579a97f7 1374
31e31b8a
FB
1375 return ret;
1376}
5457dc9e
LV
1377
1378#if defined(TARGET_WANT_OLD_SYS_SELECT)
1379static abi_long do_old_select(abi_ulong arg1)
1380{
1381 struct target_sel_arg_struct *sel;
1382 abi_ulong inp, outp, exp, tvp;
1383 long nsel;
1384
1385 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1386 return -TARGET_EFAULT;
1387 }
1388
1389 nsel = tswapal(sel->n);
1390 inp = tswapal(sel->inp);
1391 outp = tswapal(sel->outp);
1392 exp = tswapal(sel->exp);
1393 tvp = tswapal(sel->tvp);
1394
1395 unlock_user_struct(sel, arg1, 0);
1396
1397 return do_select(nsel, inp, outp, exp, tvp);
1398}
1399#endif
055e0906 1400#endif
31e31b8a 1401
e5ce9688
FB
1402#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1403static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1404 abi_long arg4, abi_long arg5, abi_long arg6,
1405 bool time64)
1406{
1407 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1408 fd_set rfds, wfds, efds;
1409 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1410 struct timespec ts, *ts_ptr;
1411 abi_long ret;
1412
1413 /*
1414 * The 6th arg is actually two args smashed together,
1415 * so we cannot use the C library.
1416 */
e5ce9688
FB
1417 struct {
1418 sigset_t *set;
1419 size_t size;
1420 } sig, *sig_ptr;
1421
1422 abi_ulong arg_sigset, arg_sigsize, *arg7;
e5ce9688
FB
1423
1424 n = arg1;
1425 rfd_addr = arg2;
1426 wfd_addr = arg3;
1427 efd_addr = arg4;
1428 ts_addr = arg5;
1429
1430 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1431 if (ret) {
1432 return ret;
1433 }
1434 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1435 if (ret) {
1436 return ret;
1437 }
1438 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1439 if (ret) {
1440 return ret;
1441 }
1442
1443 /*
1444 * This takes a timespec, and not a timeval, so we cannot
1445 * use the do_select() helper ...
1446 */
1447 if (ts_addr) {
1448 if (time64) {
1449 if (target_to_host_timespec64(&ts, ts_addr)) {
1450 return -TARGET_EFAULT;
1451 }
1452 } else {
1453 if (target_to_host_timespec(&ts, ts_addr)) {
1454 return -TARGET_EFAULT;
1455 }
1456 }
1457 ts_ptr = &ts;
1458 } else {
1459 ts_ptr = NULL;
1460 }
1461
1462 /* Extract the two packed args for the sigset */
cb226034 1463 sig_ptr = NULL;
e5ce9688 1464 if (arg6) {
e5ce9688
FB
1465 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1466 if (!arg7) {
1467 return -TARGET_EFAULT;
1468 }
1469 arg_sigset = tswapal(arg7[0]);
1470 arg_sigsize = tswapal(arg7[1]);
1471 unlock_user(arg7, arg6, 0);
1472
1473 if (arg_sigset) {
cb226034
RH
1474 ret = process_sigsuspend_mask(&sig.set, arg_sigset, arg_sigsize);
1475 if (ret != 0) {
1476 return ret;
e5ce9688 1477 }
cb226034
RH
1478 sig_ptr = &sig;
1479 sig.size = SIGSET_T_SIZE;
e5ce9688 1480 }
e5ce9688
FB
1481 }
1482
1483 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1484 ts_ptr, sig_ptr));
1485
cb226034
RH
1486 if (sig_ptr) {
1487 finish_sigsuspend_mask(ret);
1488 }
1489
e5ce9688
FB
1490 if (!is_error(ret)) {
1491 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1492 return -TARGET_EFAULT;
1493 }
1494 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1495 return -TARGET_EFAULT;
1496 }
1497 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1498 return -TARGET_EFAULT;
1499 }
1500 if (time64) {
1501 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1502 return -TARGET_EFAULT;
1503 }
1504 } else {
1505 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1506 return -TARGET_EFAULT;
1507 }
1508 }
1509 }
1510 return ret;
1511}
1512#endif
1513
1514#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1515 defined(TARGET_NR_ppoll_time64)
1516static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1517 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1518{
1519 struct target_pollfd *target_pfd;
1520 unsigned int nfds = arg2;
1521 struct pollfd *pfd;
1522 unsigned int i;
1523 abi_long ret;
1524
1525 pfd = NULL;
1526 target_pfd = NULL;
1527 if (nfds) {
1528 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1529 return -TARGET_EINVAL;
1530 }
1531 target_pfd = lock_user(VERIFY_WRITE, arg1,
1532 sizeof(struct target_pollfd) * nfds, 1);
1533 if (!target_pfd) {
1534 return -TARGET_EFAULT;
1535 }
1536
1537 pfd = alloca(sizeof(struct pollfd) * nfds);
1538 for (i = 0; i < nfds; i++) {
1539 pfd[i].fd = tswap32(target_pfd[i].fd);
1540 pfd[i].events = tswap16(target_pfd[i].events);
1541 }
1542 }
1543 if (ppoll) {
1544 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
db36aa7d 1545 sigset_t *set = NULL;
e5ce9688
FB
1546
1547 if (arg3) {
1548 if (time64) {
1549 if (target_to_host_timespec64(timeout_ts, arg3)) {
1550 unlock_user(target_pfd, arg1, 0);
1551 return -TARGET_EFAULT;
1552 }
1553 } else {
1554 if (target_to_host_timespec(timeout_ts, arg3)) {
1555 unlock_user(target_pfd, arg1, 0);
1556 return -TARGET_EFAULT;
1557 }
1558 }
1559 } else {
1560 timeout_ts = NULL;
1561 }
1562
1563 if (arg4) {
db36aa7d
RH
1564 ret = process_sigsuspend_mask(&set, arg4, arg5);
1565 if (ret != 0) {
e5ce9688 1566 unlock_user(target_pfd, arg1, 0);
db36aa7d 1567 return ret;
e5ce9688 1568 }
e5ce9688
FB
1569 }
1570
1571 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1572 set, SIGSET_T_SIZE));
1573
db36aa7d
RH
1574 if (set) {
1575 finish_sigsuspend_mask(ret);
1576 }
e5ce9688
FB
1577 if (!is_error(ret) && arg3) {
1578 if (time64) {
1579 if (host_to_target_timespec64(arg3, timeout_ts)) {
1580 return -TARGET_EFAULT;
1581 }
1582 } else {
1583 if (host_to_target_timespec(arg3, timeout_ts)) {
1584 return -TARGET_EFAULT;
1585 }
1586 }
1587 }
e5ce9688
FB
1588 } else {
1589 struct timespec ts, *pts;
1590
1591 if (arg3 >= 0) {
1592 /* Convert ms to secs, ns */
1593 ts.tv_sec = arg3 / 1000;
1594 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1595 pts = &ts;
1596 } else {
1597 /* -ve poll() timeout means "infinite" */
1598 pts = NULL;
1599 }
1600 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1601 }
1602
1603 if (!is_error(ret)) {
1604 for (i = 0; i < nfds; i++) {
1605 target_pfd[i].revents = tswap16(pfd[i].revents);
1606 }
1607 }
1608 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1609 return ret;
1610}
1611#endif
1612
a0939b89 1613static abi_long do_pipe(CPUArchState *cpu_env, abi_ulong pipedes,
fb41a66e 1614 int flags, int is_pipe2)
099d6b0f
RV
1615{
1616 int host_pipe[2];
1617 abi_long ret;
499d8055 1618 ret = pipe2(host_pipe, flags);
099d6b0f
RV
1619
1620 if (is_error(ret))
1621 return get_errno(ret);
fb41a66e
RH
1622
1623 /* Several targets have special calling conventions for the original
1624 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1625 if (!is_pipe2) {
1626#if defined(TARGET_ALPHA)
0effdc29 1627 cpu_env->ir[IR_A4] = host_pipe[1];
fb41a66e
RH
1628 return host_pipe[0];
1629#elif defined(TARGET_MIPS)
0effdc29 1630 cpu_env->active_tc.gpr[3] = host_pipe[1];
fb41a66e
RH
1631 return host_pipe[0];
1632#elif defined(TARGET_SH4)
0effdc29 1633 cpu_env->gregs[1] = host_pipe[1];
fb41a66e 1634 return host_pipe[0];
82f05b69 1635#elif defined(TARGET_SPARC)
0effdc29 1636 cpu_env->regwptr[1] = host_pipe[1];
82f05b69 1637 return host_pipe[0];
597c0212 1638#endif
fb41a66e
RH
1639 }
1640
099d6b0f 1641 if (put_user_s32(host_pipe[0], pipedes)
6f200f51 1642 || put_user_s32(host_pipe[1], pipedes + sizeof(abi_int)))
099d6b0f 1643 return -TARGET_EFAULT;
099d6b0f
RV
1644 return get_errno(ret);
1645}
1646
b975b83b
LL
1647static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1648 abi_ulong target_addr,
1649 socklen_t len)
1650{
1651 struct target_ip_mreqn *target_smreqn;
1652
1653 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1654 if (!target_smreqn)
1655 return -TARGET_EFAULT;
1656 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1657 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1658 if (len == sizeof(struct target_ip_mreqn))
cbb21eed 1659 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
b975b83b
LL
1660 unlock_user(target_smreqn, target_addr, 0);
1661
1662 return 0;
1663}
1664
7b36f782 1665static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
579a97f7
FB
1666 abi_ulong target_addr,
1667 socklen_t len)
7854b056 1668{
607175e0
AJ
1669 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1670 sa_family_t sa_family;
53a5960a
PB
1671 struct target_sockaddr *target_saddr;
1672
7b36f782
LV
1673 if (fd_trans_target_to_host_addr(fd)) {
1674 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1675 }
1676
579a97f7
FB
1677 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1678 if (!target_saddr)
1679 return -TARGET_EFAULT;
607175e0
AJ
1680
1681 sa_family = tswap16(target_saddr->sa_family);
1682
1683 /* Oops. The caller might send a incomplete sun_path; sun_path
1684 * must be terminated by \0 (see the manual page), but
1685 * unfortunately it is quite common to specify sockaddr_un
1686 * length as "strlen(x->sun_path)" while it should be
1687 * "strlen(...) + 1". We'll fix that here if needed.
1688 * Linux kernel has a similar feature.
1689 */
1690
1691 if (sa_family == AF_UNIX) {
1692 if (len < unix_maxlen && len > 0) {
1693 char *cp = (char*)target_saddr;
1694
1695 if ( cp[len-1] && !cp[len] )
1696 len++;
1697 }
1698 if (len > unix_maxlen)
1699 len = unix_maxlen;
1700 }
1701
53a5960a 1702 memcpy(addr, target_saddr, len);
607175e0 1703 addr->sa_family = sa_family;
6c5b5645
LV
1704 if (sa_family == AF_NETLINK) {
1705 struct sockaddr_nl *nladdr;
1706
1707 nladdr = (struct sockaddr_nl *)addr;
1708 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1709 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1710 } else if (sa_family == AF_PACKET) {
33a29b51
JT
1711 struct target_sockaddr_ll *lladdr;
1712
1713 lladdr = (struct target_sockaddr_ll *)addr;
1714 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1715 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1716 }
53a5960a 1717 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1718
1719 return 0;
7854b056
FB
1720}
1721
579a97f7
FB
1722static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1723 struct sockaddr *addr,
1724 socklen_t len)
7854b056 1725{
53a5960a
PB
1726 struct target_sockaddr *target_saddr;
1727
a1e22192
PM
1728 if (len == 0) {
1729 return 0;
1730 }
6860710c 1731 assert(addr);
a1e22192 1732
579a97f7
FB
1733 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1734 if (!target_saddr)
1735 return -TARGET_EFAULT;
53a5960a 1736 memcpy(target_saddr, addr, len);
a1e22192
PM
1737 if (len >= offsetof(struct target_sockaddr, sa_family) +
1738 sizeof(target_saddr->sa_family)) {
1739 target_saddr->sa_family = tswap16(addr->sa_family);
1740 }
a47401bc
PMD
1741 if (addr->sa_family == AF_NETLINK &&
1742 len >= sizeof(struct target_sockaddr_nl)) {
1743 struct target_sockaddr_nl *target_nl =
1744 (struct target_sockaddr_nl *)target_saddr;
6c5b5645
LV
1745 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1746 target_nl->nl_groups = tswap32(target_nl->nl_groups);
a82ea939
LV
1747 } else if (addr->sa_family == AF_PACKET) {
1748 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1749 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1750 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
ee1ac3a1
HD
1751 } else if (addr->sa_family == AF_INET6 &&
1752 len >= sizeof(struct target_sockaddr_in6)) {
1753 struct target_sockaddr_in6 *target_in6 =
1754 (struct target_sockaddr_in6 *)target_saddr;
1755 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
6c5b5645 1756 }
53a5960a 1757 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1758
1759 return 0;
7854b056
FB
1760}
1761
5a4a898d
FB
1762static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1763 struct target_msghdr *target_msgh)
7854b056
FB
1764{
1765 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1766 abi_long msg_controllen;
1767 abi_ulong target_cmsg_addr;
ee104587 1768 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056 1769 socklen_t space = 0;
5a4a898d 1770
cbb21eed 1771 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1772 if (msg_controllen < sizeof (struct target_cmsghdr))
1773 goto the_end;
cbb21eed 1774 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1775 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
ee104587 1776 target_cmsg_start = target_cmsg;
5a4a898d
FB
1777 if (!target_cmsg)
1778 return -TARGET_EFAULT;
7854b056
FB
1779
1780 while (cmsg && target_cmsg) {
1781 void *data = CMSG_DATA(cmsg);
1782 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1783
cbb21eed 1784 int len = tswapal(target_cmsg->cmsg_len)
ad762b99 1785 - sizeof(struct target_cmsghdr);
7854b056
FB
1786
1787 space += CMSG_SPACE(len);
1788 if (space > msgh->msg_controllen) {
1789 space -= CMSG_SPACE(len);
c2aeb258
PM
1790 /* This is a QEMU bug, since we allocated the payload
1791 * area ourselves (unlike overflow in host-to-target
1792 * conversion, which is just the guest giving us a buffer
1793 * that's too small). It can't happen for the payload types
1794 * we currently support; if it becomes an issue in future
1795 * we would need to improve our allocation strategy to
1796 * something more intelligent than "twice the size of the
1797 * target buffer we're reading from".
1798 */
39be5350
JK
1799 qemu_log_mask(LOG_UNIMP,
1800 ("Unsupported ancillary data %d/%d: "
1801 "unhandled msg size\n"),
1802 tswap32(target_cmsg->cmsg_level),
1803 tswap32(target_cmsg->cmsg_type));
7854b056
FB
1804 break;
1805 }
1806
dbf4f796
PJ
1807 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1808 cmsg->cmsg_level = SOL_SOCKET;
1809 } else {
1810 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1811 }
7854b056
FB
1812 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1813 cmsg->cmsg_len = CMSG_LEN(len);
1814
30b8b68e 1815 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
7854b056
FB
1816 int *fd = (int *)data;
1817 int *target_fd = (int *)target_data;
1818 int i, numfds = len / sizeof(int);
1819
876e23cb
PM
1820 for (i = 0; i < numfds; i++) {
1821 __get_user(fd[i], target_fd + i);
1822 }
30b8b68e
AS
1823 } else if (cmsg->cmsg_level == SOL_SOCKET
1824 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1825 struct ucred *cred = (struct ucred *)data;
1826 struct target_ucred *target_cred =
1827 (struct target_ucred *)target_data;
1828
876e23cb
PM
1829 __get_user(cred->pid, &target_cred->pid);
1830 __get_user(cred->uid, &target_cred->uid);
1831 __get_user(cred->gid, &target_cred->gid);
27404b6c
HD
1832 } else if (cmsg->cmsg_level == SOL_ALG) {
1833 uint32_t *dst = (uint32_t *)data;
1834
1835 memcpy(dst, target_data, len);
1836 /* fix endianess of first 32-bit word */
1837 if (len >= sizeof(uint32_t)) {
1838 *dst = tswap32(*dst);
1839 }
30b8b68e 1840 } else {
39be5350
JK
1841 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1842 cmsg->cmsg_level, cmsg->cmsg_type);
30b8b68e 1843 memcpy(data, target_data, len);
7854b056
FB
1844 }
1845
1846 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
1847 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1848 target_cmsg_start);
7854b056 1849 }
5a4a898d
FB
1850 unlock_user(target_cmsg, target_cmsg_addr, 0);
1851 the_end:
7854b056 1852 msgh->msg_controllen = space;
5a4a898d 1853 return 0;
7854b056
FB
1854}
1855
5a4a898d
FB
1856static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1857 struct msghdr *msgh)
7854b056
FB
1858{
1859 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1860 abi_long msg_controllen;
1861 abi_ulong target_cmsg_addr;
ee104587 1862 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056
FB
1863 socklen_t space = 0;
1864
cbb21eed 1865 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1866 if (msg_controllen < sizeof (struct target_cmsghdr))
1867 goto the_end;
cbb21eed 1868 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1869 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
ee104587 1870 target_cmsg_start = target_cmsg;
5a4a898d
FB
1871 if (!target_cmsg)
1872 return -TARGET_EFAULT;
1873
7854b056
FB
1874 while (cmsg && target_cmsg) {
1875 void *data = CMSG_DATA(cmsg);
1876 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1877
ad762b99 1878 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
c2aeb258 1879 int tgt_len, tgt_space;
7854b056 1880
c2aeb258
PM
1881 /* We never copy a half-header but may copy half-data;
1882 * this is Linux's behaviour in put_cmsg(). Note that
1883 * truncation here is a guest problem (which we report
1884 * to the guest via the CTRUNC bit), unlike truncation
1885 * in target_to_host_cmsg, which is a QEMU bug.
1886 */
7174970a 1887 if (msg_controllen < sizeof(struct target_cmsghdr)) {
c2aeb258 1888 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7854b056
FB
1889 break;
1890 }
1891
dbf4f796
PJ
1892 if (cmsg->cmsg_level == SOL_SOCKET) {
1893 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1894 } else {
1895 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1896 }
7854b056 1897 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
7854b056 1898
c2aeb258
PM
1899 /* Payload types which need a different size of payload on
1900 * the target must adjust tgt_len here.
1901 */
309786cf 1902 tgt_len = len;
c2aeb258
PM
1903 switch (cmsg->cmsg_level) {
1904 case SOL_SOCKET:
1905 switch (cmsg->cmsg_type) {
1906 case SO_TIMESTAMP:
1907 tgt_len = sizeof(struct target_timeval);
1908 break;
1909 default:
1910 break;
1911 }
309786cf 1912 break;
c2aeb258
PM
1913 default:
1914 break;
1915 }
1916
7174970a 1917 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
c2aeb258 1918 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7174970a 1919 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
c2aeb258
PM
1920 }
1921
1922 /* We must now copy-and-convert len bytes of payload
1923 * into tgt_len bytes of destination space. Bear in mind
1924 * that in both source and destination we may be dealing
1925 * with a truncated value!
1926 */
52b65494
HD
1927 switch (cmsg->cmsg_level) {
1928 case SOL_SOCKET:
1929 switch (cmsg->cmsg_type) {
1930 case SCM_RIGHTS:
1931 {
1932 int *fd = (int *)data;
1933 int *target_fd = (int *)target_data;
c2aeb258 1934 int i, numfds = tgt_len / sizeof(int);
52b65494 1935
876e23cb
PM
1936 for (i = 0; i < numfds; i++) {
1937 __put_user(fd[i], target_fd + i);
1938 }
52b65494
HD
1939 break;
1940 }
1941 case SO_TIMESTAMP:
1942 {
1943 struct timeval *tv = (struct timeval *)data;
1944 struct target_timeval *target_tv =
1945 (struct target_timeval *)target_data;
1946
c2aeb258
PM
1947 if (len != sizeof(struct timeval) ||
1948 tgt_len != sizeof(struct target_timeval)) {
52b65494 1949 goto unimplemented;
c2aeb258 1950 }
52b65494
HD
1951
1952 /* copy struct timeval to target */
876e23cb
PM
1953 __put_user(tv->tv_sec, &target_tv->tv_sec);
1954 __put_user(tv->tv_usec, &target_tv->tv_usec);
52b65494
HD
1955 break;
1956 }
4bc29756
HD
1957 case SCM_CREDENTIALS:
1958 {
1959 struct ucred *cred = (struct ucred *)data;
1960 struct target_ucred *target_cred =
1961 (struct target_ucred *)target_data;
1962
1963 __put_user(cred->pid, &target_cred->pid);
1964 __put_user(cred->uid, &target_cred->uid);
1965 __put_user(cred->gid, &target_cred->gid);
1966 break;
1967 }
52b65494
HD
1968 default:
1969 goto unimplemented;
1970 }
1971 break;
7854b056 1972
ee1ac3a1
HD
1973 case SOL_IP:
1974 switch (cmsg->cmsg_type) {
1975 case IP_TTL:
1976 {
1977 uint32_t *v = (uint32_t *)data;
1978 uint32_t *t_int = (uint32_t *)target_data;
1979
7174970a
PM
1980 if (len != sizeof(uint32_t) ||
1981 tgt_len != sizeof(uint32_t)) {
1982 goto unimplemented;
1983 }
ee1ac3a1
HD
1984 __put_user(*v, t_int);
1985 break;
1986 }
1987 case IP_RECVERR:
1988 {
1989 struct errhdr_t {
1990 struct sock_extended_err ee;
1991 struct sockaddr_in offender;
1992 };
1993 struct errhdr_t *errh = (struct errhdr_t *)data;
1994 struct errhdr_t *target_errh =
1995 (struct errhdr_t *)target_data;
1996
7174970a
PM
1997 if (len != sizeof(struct errhdr_t) ||
1998 tgt_len != sizeof(struct errhdr_t)) {
1999 goto unimplemented;
2000 }
ee1ac3a1
HD
2001 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2002 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2003 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2004 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2005 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2006 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2007 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2008 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2009 (void *) &errh->offender, sizeof(errh->offender));
2010 break;
2011 }
2012 default:
2013 goto unimplemented;
2014 }
2015 break;
2016
2017 case SOL_IPV6:
2018 switch (cmsg->cmsg_type) {
2019 case IPV6_HOPLIMIT:
2020 {
2021 uint32_t *v = (uint32_t *)data;
2022 uint32_t *t_int = (uint32_t *)target_data;
2023
7174970a
PM
2024 if (len != sizeof(uint32_t) ||
2025 tgt_len != sizeof(uint32_t)) {
2026 goto unimplemented;
2027 }
ee1ac3a1
HD
2028 __put_user(*v, t_int);
2029 break;
2030 }
2031 case IPV6_RECVERR:
2032 {
2033 struct errhdr6_t {
2034 struct sock_extended_err ee;
2035 struct sockaddr_in6 offender;
2036 };
2037 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2038 struct errhdr6_t *target_errh =
2039 (struct errhdr6_t *)target_data;
2040
7174970a
PM
2041 if (len != sizeof(struct errhdr6_t) ||
2042 tgt_len != sizeof(struct errhdr6_t)) {
2043 goto unimplemented;
2044 }
ee1ac3a1
HD
2045 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2046 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2047 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2048 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2049 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2050 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2051 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2052 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2053 (void *) &errh->offender, sizeof(errh->offender));
2054 break;
2055 }
2056 default:
2057 goto unimplemented;
2058 }
2059 break;
2060
52b65494
HD
2061 default:
2062 unimplemented:
39be5350
JK
2063 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2064 cmsg->cmsg_level, cmsg->cmsg_type);
c2aeb258
PM
2065 memcpy(target_data, data, MIN(len, tgt_len));
2066 if (tgt_len > len) {
2067 memset(target_data + len, 0, tgt_len - len);
2068 }
7854b056
FB
2069 }
2070
7174970a
PM
2071 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2072 tgt_space = TARGET_CMSG_SPACE(tgt_len);
c2aeb258
PM
2073 if (msg_controllen < tgt_space) {
2074 tgt_space = msg_controllen;
2075 }
2076 msg_controllen -= tgt_space;
2077 space += tgt_space;
7854b056 2078 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
2079 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2080 target_cmsg_start);
7854b056 2081 }
5a4a898d
FB
2082 unlock_user(target_cmsg, target_cmsg_addr, space);
2083 the_end:
cbb21eed 2084 target_msgh->msg_controllen = tswapal(space);
5a4a898d 2085 return 0;
7854b056
FB
2086}
2087
0da46a6e 2088/* do_setsockopt() Must return target values and target errnos. */
992f48a0 2089static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 2090 abi_ulong optval_addr, socklen_t optlen)
7854b056 2091{
992f48a0 2092 abi_long ret;
32407103 2093 int val;
b975b83b 2094 struct ip_mreqn *ip_mreq;
6e3cb58f 2095 struct ip_mreq_source *ip_mreq_source;
3b46e624 2096
8853f86e
FB
2097 switch(level) {
2098 case SOL_TCP:
fe51b0a5
SCW
2099 case SOL_UDP:
2100 /* TCP and UDP options all take an 'int' value. */
7854b056 2101 if (optlen < sizeof(uint32_t))
0da46a6e 2102 return -TARGET_EINVAL;
3b46e624 2103
2f619698
FB
2104 if (get_user_u32(val, optval_addr))
2105 return -TARGET_EFAULT;
8853f86e
FB
2106 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2107 break;
2108 case SOL_IP:
2109 switch(optname) {
2efbe911
FB
2110 case IP_TOS:
2111 case IP_TTL:
8853f86e 2112 case IP_HDRINCL:
2efbe911
FB
2113 case IP_ROUTER_ALERT:
2114 case IP_RECVOPTS:
2115 case IP_RETOPTS:
2116 case IP_PKTINFO:
2117 case IP_MTU_DISCOVER:
2118 case IP_RECVERR:
ee1ac3a1 2119 case IP_RECVTTL:
2efbe911
FB
2120 case IP_RECVTOS:
2121#ifdef IP_FREEBIND
2122 case IP_FREEBIND:
2123#endif
2124 case IP_MULTICAST_TTL:
2125 case IP_MULTICAST_LOOP:
8853f86e
FB
2126 val = 0;
2127 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
2128 if (get_user_u32(val, optval_addr))
2129 return -TARGET_EFAULT;
8853f86e 2130 } else if (optlen >= 1) {
2f619698
FB
2131 if (get_user_u8(val, optval_addr))
2132 return -TARGET_EFAULT;
8853f86e
FB
2133 }
2134 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2135 break;
b975b83b
LL
2136 case IP_ADD_MEMBERSHIP:
2137 case IP_DROP_MEMBERSHIP:
2138 if (optlen < sizeof (struct target_ip_mreq) ||
2139 optlen > sizeof (struct target_ip_mreqn))
2140 return -TARGET_EINVAL;
2141
2142 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2143 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2144 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2145 break;
2146
6e3cb58f
LL
2147 case IP_BLOCK_SOURCE:
2148 case IP_UNBLOCK_SOURCE:
2149 case IP_ADD_SOURCE_MEMBERSHIP:
2150 case IP_DROP_SOURCE_MEMBERSHIP:
2151 if (optlen != sizeof (struct target_ip_mreq_source))
2152 return -TARGET_EINVAL;
2153
2154 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
74e43b04
PM
2155 if (!ip_mreq_source) {
2156 return -TARGET_EFAULT;
2157 }
6e3cb58f
LL
2158 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2159 unlock_user (ip_mreq_source, optval_addr, 0);
2160 break;
2161
920394db
JH
2162 default:
2163 goto unimplemented;
2164 }
2165 break;
0d78b3b5
LV
2166 case SOL_IPV6:
2167 switch (optname) {
2168 case IPV6_MTU_DISCOVER:
2169 case IPV6_MTU:
2170 case IPV6_V6ONLY:
2171 case IPV6_RECVPKTINFO:
ee1ac3a1 2172 case IPV6_UNICAST_HOPS:
21749c4c
LV
2173 case IPV6_MULTICAST_HOPS:
2174 case IPV6_MULTICAST_LOOP:
ee1ac3a1
HD
2175 case IPV6_RECVERR:
2176 case IPV6_RECVHOPLIMIT:
2177 case IPV6_2292HOPLIMIT:
2178 case IPV6_CHECKSUM:
b9cce6d7
HD
2179 case IPV6_ADDRFORM:
2180 case IPV6_2292PKTINFO:
2181 case IPV6_RECVTCLASS:
2182 case IPV6_RECVRTHDR:
2183 case IPV6_2292RTHDR:
2184 case IPV6_RECVHOPOPTS:
2185 case IPV6_2292HOPOPTS:
2186 case IPV6_RECVDSTOPTS:
2187 case IPV6_2292DSTOPTS:
2188 case IPV6_TCLASS:
22db1213 2189 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2190#ifdef IPV6_RECVPATHMTU
2191 case IPV6_RECVPATHMTU:
2192#endif
2193#ifdef IPV6_TRANSPARENT
2194 case IPV6_TRANSPARENT:
2195#endif
2196#ifdef IPV6_FREEBIND
2197 case IPV6_FREEBIND:
2198#endif
2199#ifdef IPV6_RECVORIGDSTADDR
2200 case IPV6_RECVORIGDSTADDR:
2201#endif
0d78b3b5
LV
2202 val = 0;
2203 if (optlen < sizeof(uint32_t)) {
2204 return -TARGET_EINVAL;
2205 }
2206 if (get_user_u32(val, optval_addr)) {
2207 return -TARGET_EFAULT;
2208 }
2209 ret = get_errno(setsockopt(sockfd, level, optname,
2210 &val, sizeof(val)));
2211 break;
ee1ac3a1
HD
2212 case IPV6_PKTINFO:
2213 {
2214 struct in6_pktinfo pki;
2215
2216 if (optlen < sizeof(pki)) {
2217 return -TARGET_EINVAL;
2218 }
2219
2220 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2221 return -TARGET_EFAULT;
2222 }
2223
2224 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2225
2226 ret = get_errno(setsockopt(sockfd, level, optname,
2227 &pki, sizeof(pki)));
2228 break;
2229 }
22bf4ee9
NC
2230 case IPV6_ADD_MEMBERSHIP:
2231 case IPV6_DROP_MEMBERSHIP:
2232 {
2233 struct ipv6_mreq ipv6mreq;
2234
2235 if (optlen < sizeof(ipv6mreq)) {
2236 return -TARGET_EINVAL;
2237 }
2238
2239 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2240 return -TARGET_EFAULT;
2241 }
2242
2243 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2244
2245 ret = get_errno(setsockopt(sockfd, level, optname,
2246 &ipv6mreq, sizeof(ipv6mreq)));
2247 break;
2248 }
ee1ac3a1
HD
2249 default:
2250 goto unimplemented;
2251 }
2252 break;
2253 case SOL_ICMPV6:
2254 switch (optname) {
2255 case ICMPV6_FILTER:
2256 {
2257 struct icmp6_filter icmp6f;
2258
2259 if (optlen > sizeof(icmp6f)) {
2260 optlen = sizeof(icmp6f);
2261 }
2262
2263 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2264 return -TARGET_EFAULT;
2265 }
2266
2267 for (val = 0; val < 8; val++) {
2268 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2269 }
2270
2271 ret = get_errno(setsockopt(sockfd, level, optname,
2272 &icmp6f, optlen));
2273 break;
2274 }
0d78b3b5
LV
2275 default:
2276 goto unimplemented;
2277 }
2278 break;
920394db
JH
2279 case SOL_RAW:
2280 switch (optname) {
2281 case ICMP_FILTER:
ee1ac3a1
HD
2282 case IPV6_CHECKSUM:
2283 /* those take an u32 value */
920394db
JH
2284 if (optlen < sizeof(uint32_t)) {
2285 return -TARGET_EINVAL;
2286 }
2287
2288 if (get_user_u32(val, optval_addr)) {
2289 return -TARGET_EFAULT;
2290 }
2291 ret = get_errno(setsockopt(sockfd, level, optname,
2292 &val, sizeof(val)));
2293 break;
2294
8853f86e
FB
2295 default:
2296 goto unimplemented;
2297 }
2298 break;
f31dddd2
YS
2299#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2300 case SOL_ALG:
2301 switch (optname) {
2302 case ALG_SET_KEY:
2303 {
2304 char *alg_key = g_malloc(optlen);
2305
2306 if (!alg_key) {
2307 return -TARGET_ENOMEM;
2308 }
2309 if (copy_from_user(alg_key, optval_addr, optlen)) {
2310 g_free(alg_key);
2311 return -TARGET_EFAULT;
2312 }
2313 ret = get_errno(setsockopt(sockfd, level, optname,
2314 alg_key, optlen));
2315 g_free(alg_key);
2316 break;
2317 }
2318 case ALG_SET_AEAD_AUTHSIZE:
2319 {
2320 ret = get_errno(setsockopt(sockfd, level, optname,
2321 NULL, optlen));
2322 break;
2323 }
2324 default:
2325 goto unimplemented;
2326 }
2327 break;
2328#endif
3532fa74 2329 case TARGET_SOL_SOCKET:
8853f86e 2330 switch (optname) {
1b09aeb9
LV
2331 case TARGET_SO_RCVTIMEO:
2332 {
2333 struct timeval tv;
2334
2335 optname = SO_RCVTIMEO;
2336
2337set_timeout:
2338 if (optlen != sizeof(struct target_timeval)) {
2339 return -TARGET_EINVAL;
2340 }
2341
2342 if (copy_from_user_timeval(&tv, optval_addr)) {
2343 return -TARGET_EFAULT;
2344 }
2345
2346 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2347 &tv, sizeof(tv)));
2348 return ret;
2349 }
2350 case TARGET_SO_SNDTIMEO:
2351 optname = SO_SNDTIMEO;
2352 goto set_timeout;
f57d4192
LV
2353 case TARGET_SO_ATTACH_FILTER:
2354 {
2355 struct target_sock_fprog *tfprog;
2356 struct target_sock_filter *tfilter;
2357 struct sock_fprog fprog;
2358 struct sock_filter *filter;
2359 int i;
2360
2361 if (optlen != sizeof(*tfprog)) {
2362 return -TARGET_EINVAL;
2363 }
2364 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2365 return -TARGET_EFAULT;
2366 }
2367 if (!lock_user_struct(VERIFY_READ, tfilter,
2368 tswapal(tfprog->filter), 0)) {
2369 unlock_user_struct(tfprog, optval_addr, 1);
2370 return -TARGET_EFAULT;
2371 }
2372
2373 fprog.len = tswap16(tfprog->len);
0e173b24 2374 filter = g_try_new(struct sock_filter, fprog.len);
f57d4192
LV
2375 if (filter == NULL) {
2376 unlock_user_struct(tfilter, tfprog->filter, 1);
2377 unlock_user_struct(tfprog, optval_addr, 1);
2378 return -TARGET_ENOMEM;
2379 }
2380 for (i = 0; i < fprog.len; i++) {
2381 filter[i].code = tswap16(tfilter[i].code);
2382 filter[i].jt = tfilter[i].jt;
2383 filter[i].jf = tfilter[i].jf;
2384 filter[i].k = tswap32(tfilter[i].k);
2385 }
2386 fprog.filter = filter;
2387
2388 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2389 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
0e173b24 2390 g_free(filter);
f57d4192
LV
2391
2392 unlock_user_struct(tfilter, tfprog->filter, 1);
2393 unlock_user_struct(tfprog, optval_addr, 1);
2394 return ret;
2395 }
451aaf68
JT
2396 case TARGET_SO_BINDTODEVICE:
2397 {
2398 char *dev_ifname, *addr_ifname;
2399
2400 if (optlen > IFNAMSIZ - 1) {
2401 optlen = IFNAMSIZ - 1;
2402 }
2403 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2404 if (!dev_ifname) {
2405 return -TARGET_EFAULT;
2406 }
2407 optname = SO_BINDTODEVICE;
2408 addr_ifname = alloca(IFNAMSIZ);
2409 memcpy(addr_ifname, dev_ifname, optlen);
2410 addr_ifname[optlen] = 0;
fad6c58a
CG
2411 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2412 addr_ifname, optlen));
451aaf68
JT
2413 unlock_user (dev_ifname, optval_addr, 0);
2414 return ret;
2415 }
83eb6e50
CMAB
2416 case TARGET_SO_LINGER:
2417 {
2418 struct linger lg;
2419 struct target_linger *tlg;
2420
2421 if (optlen != sizeof(struct target_linger)) {
2422 return -TARGET_EINVAL;
2423 }
2424 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2425 return -TARGET_EFAULT;
2426 }
2427 __get_user(lg.l_onoff, &tlg->l_onoff);
2428 __get_user(lg.l_linger, &tlg->l_linger);
2429 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2430 &lg, sizeof(lg)));
2431 unlock_user_struct(tlg, optval_addr, 0);
2432 return ret;
2433 }
8853f86e 2434 /* Options with 'int' argument. */
3532fa74
FB
2435 case TARGET_SO_DEBUG:
2436 optname = SO_DEBUG;
2437 break;
2438 case TARGET_SO_REUSEADDR:
2439 optname = SO_REUSEADDR;
2440 break;
113a9dd7
YS
2441#ifdef SO_REUSEPORT
2442 case TARGET_SO_REUSEPORT:
2443 optname = SO_REUSEPORT;
2444 break;
2445#endif
3532fa74
FB
2446 case TARGET_SO_TYPE:
2447 optname = SO_TYPE;
2448 break;
2449 case TARGET_SO_ERROR:
2450 optname = SO_ERROR;
2451 break;
2452 case TARGET_SO_DONTROUTE:
2453 optname = SO_DONTROUTE;
2454 break;
2455 case TARGET_SO_BROADCAST:
2456 optname = SO_BROADCAST;
2457 break;
2458 case TARGET_SO_SNDBUF:
2459 optname = SO_SNDBUF;
2460 break;
d79b6cc4
PB
2461 case TARGET_SO_SNDBUFFORCE:
2462 optname = SO_SNDBUFFORCE;
2463 break;
3532fa74
FB
2464 case TARGET_SO_RCVBUF:
2465 optname = SO_RCVBUF;
2466 break;
d79b6cc4
PB
2467 case TARGET_SO_RCVBUFFORCE:
2468 optname = SO_RCVBUFFORCE;
2469 break;
3532fa74
FB
2470 case TARGET_SO_KEEPALIVE:
2471 optname = SO_KEEPALIVE;
2472 break;
2473 case TARGET_SO_OOBINLINE:
2474 optname = SO_OOBINLINE;
2475 break;
2476 case TARGET_SO_NO_CHECK:
2477 optname = SO_NO_CHECK;
2478 break;
2479 case TARGET_SO_PRIORITY:
2480 optname = SO_PRIORITY;
2481 break;
5e83e8e3 2482#ifdef SO_BSDCOMPAT
3532fa74
FB
2483 case TARGET_SO_BSDCOMPAT:
2484 optname = SO_BSDCOMPAT;
2485 break;
5e83e8e3 2486#endif
3532fa74
FB
2487 case TARGET_SO_PASSCRED:
2488 optname = SO_PASSCRED;
2489 break;
82d0fe6b
PB
2490 case TARGET_SO_PASSSEC:
2491 optname = SO_PASSSEC;
2492 break;
3532fa74
FB
2493 case TARGET_SO_TIMESTAMP:
2494 optname = SO_TIMESTAMP;
2495 break;
2496 case TARGET_SO_RCVLOWAT:
2497 optname = SO_RCVLOWAT;
2498 break;
8853f86e
FB
2499 default:
2500 goto unimplemented;
2501 }
3532fa74 2502 if (optlen < sizeof(uint32_t))
2f619698 2503 return -TARGET_EINVAL;
3532fa74 2504
2f619698
FB
2505 if (get_user_u32(val, optval_addr))
2506 return -TARGET_EFAULT;
3532fa74 2507 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 2508 break;
a2d86682
JK
2509#ifdef SOL_NETLINK
2510 case SOL_NETLINK:
2511 switch (optname) {
2512 case NETLINK_PKTINFO:
2513 case NETLINK_ADD_MEMBERSHIP:
2514 case NETLINK_DROP_MEMBERSHIP:
2515 case NETLINK_BROADCAST_ERROR:
2516 case NETLINK_NO_ENOBUFS:
2517#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2518 case NETLINK_LISTEN_ALL_NSID:
2519 case NETLINK_CAP_ACK:
2520#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2521#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2522 case NETLINK_EXT_ACK:
2523#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2524#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2525 case NETLINK_GET_STRICT_CHK:
2526#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2527 break;
2528 default:
2529 goto unimplemented;
2530 }
2531 val = 0;
2532 if (optlen < sizeof(uint32_t)) {
2533 return -TARGET_EINVAL;
2534 }
2535 if (get_user_u32(val, optval_addr)) {
2536 return -TARGET_EFAULT;
2537 }
2538 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2539 sizeof(val)));
2540 break;
2541#endif /* SOL_NETLINK */
7854b056 2542 default:
8853f86e 2543 unimplemented:
39be5350
JK
2544 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2545 level, optname);
6fa13c17 2546 ret = -TARGET_ENOPROTOOPT;
7854b056 2547 }
8853f86e 2548 return ret;
7854b056
FB
2549}
2550
0da46a6e 2551/* do_getsockopt() Must return target values and target errnos. */
992f48a0 2552static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 2553 abi_ulong optval_addr, abi_ulong optlen)
7854b056 2554{
992f48a0 2555 abi_long ret;
b55266b5
BS
2556 int len, val;
2557 socklen_t lv;
8853f86e
FB
2558
2559 switch(level) {
3532fa74 2560 case TARGET_SOL_SOCKET:
f3b974cd
JL
2561 level = SOL_SOCKET;
2562 switch (optname) {
2563 /* These don't just return a single integer */
f3b974cd
JL
2564 case TARGET_SO_PEERNAME:
2565 goto unimplemented;
405dc4cf
AS
2566 case TARGET_SO_RCVTIMEO: {
2567 struct timeval tv;
2568 socklen_t tvlen;
2569
2570 optname = SO_RCVTIMEO;
2571
2572get_timeout:
2573 if (get_user_u32(len, optlen)) {
2574 return -TARGET_EFAULT;
2575 }
2576 if (len < 0) {
2577 return -TARGET_EINVAL;
2578 }
2579
2580 tvlen = sizeof(tv);
2581 ret = get_errno(getsockopt(sockfd, level, optname,
2582 &tv, &tvlen));
2583 if (ret < 0) {
2584 return ret;
2585 }
2586 if (len > sizeof(struct target_timeval)) {
2587 len = sizeof(struct target_timeval);
2588 }
2589 if (copy_to_user_timeval(optval_addr, &tv)) {
2590 return -TARGET_EFAULT;
2591 }
2592 if (put_user_u32(len, optlen)) {
2593 return -TARGET_EFAULT;
2594 }
2595 break;
2596 }
2597 case TARGET_SO_SNDTIMEO:
2598 optname = SO_SNDTIMEO;
2599 goto get_timeout;
583359a6
AP
2600 case TARGET_SO_PEERCRED: {
2601 struct ucred cr;
2602 socklen_t crlen;
2603 struct target_ucred *tcr;
2604
2605 if (get_user_u32(len, optlen)) {
2606 return -TARGET_EFAULT;
2607 }
2608 if (len < 0) {
2609 return -TARGET_EINVAL;
2610 }
2611
2612 crlen = sizeof(cr);
2613 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2614 &cr, &crlen));
2615 if (ret < 0) {
2616 return ret;
2617 }
2618 if (len > crlen) {
2619 len = crlen;
2620 }
2621 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2622 return -TARGET_EFAULT;
2623 }
2624 __put_user(cr.pid, &tcr->pid);
2625 __put_user(cr.uid, &tcr->uid);
2626 __put_user(cr.gid, &tcr->gid);
2627 unlock_user_struct(tcr, optval_addr, 1);
2628 if (put_user_u32(len, optlen)) {
83eb6e50
CMAB
2629 return -TARGET_EFAULT;
2630 }
2631 break;
2632 }
6d485a55
LV
2633 case TARGET_SO_PEERSEC: {
2634 char *name;
2635
2636 if (get_user_u32(len, optlen)) {
2637 return -TARGET_EFAULT;
2638 }
2639 if (len < 0) {
2640 return -TARGET_EINVAL;
2641 }
2642 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2643 if (!name) {
2644 return -TARGET_EFAULT;
2645 }
2646 lv = len;
2647 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2648 name, &lv));
2649 if (put_user_u32(lv, optlen)) {
2650 ret = -TARGET_EFAULT;
2651 }
2652 unlock_user(name, optval_addr, lv);
2653 break;
2654 }
83eb6e50
CMAB
2655 case TARGET_SO_LINGER:
2656 {
2657 struct linger lg;
2658 socklen_t lglen;
2659 struct target_linger *tlg;
2660
2661 if (get_user_u32(len, optlen)) {
2662 return -TARGET_EFAULT;
2663 }
2664 if (len < 0) {
2665 return -TARGET_EINVAL;
2666 }
2667
2668 lglen = sizeof(lg);
2669 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2670 &lg, &lglen));
2671 if (ret < 0) {
2672 return ret;
2673 }
2674 if (len > lglen) {
2675 len = lglen;
2676 }
2677 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2678 return -TARGET_EFAULT;
2679 }
2680 __put_user(lg.l_onoff, &tlg->l_onoff);
2681 __put_user(lg.l_linger, &tlg->l_linger);
2682 unlock_user_struct(tlg, optval_addr, 1);
2683 if (put_user_u32(len, optlen)) {
583359a6
AP
2684 return -TARGET_EFAULT;
2685 }
2686 break;
2687 }
f3b974cd
JL
2688 /* Options with 'int' argument. */
2689 case TARGET_SO_DEBUG:
2690 optname = SO_DEBUG;
2691 goto int_case;
2692 case TARGET_SO_REUSEADDR:
2693 optname = SO_REUSEADDR;
2694 goto int_case;
113a9dd7
YS
2695#ifdef SO_REUSEPORT
2696 case TARGET_SO_REUSEPORT:
2697 optname = SO_REUSEPORT;
2698 goto int_case;
2699#endif
f3b974cd
JL
2700 case TARGET_SO_TYPE:
2701 optname = SO_TYPE;
2702 goto int_case;
2703 case TARGET_SO_ERROR:
2704 optname = SO_ERROR;
2705 goto int_case;
2706 case TARGET_SO_DONTROUTE:
2707 optname = SO_DONTROUTE;
2708 goto int_case;
2709 case TARGET_SO_BROADCAST:
2710 optname = SO_BROADCAST;
2711 goto int_case;
2712 case TARGET_SO_SNDBUF:
2713 optname = SO_SNDBUF;
2714 goto int_case;
2715 case TARGET_SO_RCVBUF:
2716 optname = SO_RCVBUF;
2717 goto int_case;
2718 case TARGET_SO_KEEPALIVE:
2719 optname = SO_KEEPALIVE;
2720 goto int_case;
2721 case TARGET_SO_OOBINLINE:
2722 optname = SO_OOBINLINE;
2723 goto int_case;
2724 case TARGET_SO_NO_CHECK:
2725 optname = SO_NO_CHECK;
2726 goto int_case;
2727 case TARGET_SO_PRIORITY:
2728 optname = SO_PRIORITY;
2729 goto int_case;
2730#ifdef SO_BSDCOMPAT
2731 case TARGET_SO_BSDCOMPAT:
2732 optname = SO_BSDCOMPAT;
2733 goto int_case;
2734#endif
2735 case TARGET_SO_PASSCRED:
2736 optname = SO_PASSCRED;
2737 goto int_case;
2738 case TARGET_SO_TIMESTAMP:
2739 optname = SO_TIMESTAMP;
2740 goto int_case;
2741 case TARGET_SO_RCVLOWAT:
2742 optname = SO_RCVLOWAT;
2743 goto int_case;
aec1ca41
PB
2744 case TARGET_SO_ACCEPTCONN:
2745 optname = SO_ACCEPTCONN;
2746 goto int_case;
ec63e06e
JD
2747 case TARGET_SO_PROTOCOL:
2748 optname = SO_PROTOCOL;
2749 goto int_case;
2750 case TARGET_SO_DOMAIN:
2751 optname = SO_DOMAIN;
2752 goto int_case;
8853f86e 2753 default:
2efbe911
FB
2754 goto int_case;
2755 }
2756 break;
2757 case SOL_TCP:
fe51b0a5
SCW
2758 case SOL_UDP:
2759 /* TCP and UDP options all take an 'int' value. */
2efbe911 2760 int_case:
2f619698
FB
2761 if (get_user_u32(len, optlen))
2762 return -TARGET_EFAULT;
2efbe911 2763 if (len < 0)
0da46a6e 2764 return -TARGET_EINVAL;
73160d95 2765 lv = sizeof(lv);
2efbe911
FB
2766 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2767 if (ret < 0)
2768 return ret;
cb88b7c2
HD
2769 switch (optname) {
2770 case SO_TYPE:
8289d112 2771 val = host_to_target_sock_type(val);
cb88b7c2
HD
2772 break;
2773 case SO_ERROR:
2774 val = host_to_target_errno(val);
2775 break;
8289d112 2776 }
2efbe911
FB
2777 if (len > lv)
2778 len = lv;
2f619698
FB
2779 if (len == 4) {
2780 if (put_user_u32(val, optval_addr))
2781 return -TARGET_EFAULT;
2782 } else {
2783 if (put_user_u8(val, optval_addr))
2784 return -TARGET_EFAULT;
f3b974cd 2785 }
2f619698
FB
2786 if (put_user_u32(len, optlen))
2787 return -TARGET_EFAULT;
2efbe911
FB
2788 break;
2789 case SOL_IP:
2790 switch(optname) {
2791 case IP_TOS:
2792 case IP_TTL:
2793 case IP_HDRINCL:
2794 case IP_ROUTER_ALERT:
2795 case IP_RECVOPTS:
2796 case IP_RETOPTS:
2797 case IP_PKTINFO:
2798 case IP_MTU_DISCOVER:
2799 case IP_RECVERR:
2800 case IP_RECVTOS:
2801#ifdef IP_FREEBIND
2802 case IP_FREEBIND:
2803#endif
2804 case IP_MULTICAST_TTL:
2805 case IP_MULTICAST_LOOP:
2f619698
FB
2806 if (get_user_u32(len, optlen))
2807 return -TARGET_EFAULT;
8853f86e 2808 if (len < 0)
0da46a6e 2809 return -TARGET_EINVAL;
73160d95 2810 lv = sizeof(lv);
8853f86e
FB
2811 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2812 if (ret < 0)
2813 return ret;
2efbe911 2814 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 2815 len = 1;
2f619698
FB
2816 if (put_user_u32(len, optlen)
2817 || put_user_u8(val, optval_addr))
2818 return -TARGET_EFAULT;
2efbe911 2819 } else {
2efbe911
FB
2820 if (len > sizeof(int))
2821 len = sizeof(int);
2f619698
FB
2822 if (put_user_u32(len, optlen)
2823 || put_user_u32(val, optval_addr))
2824 return -TARGET_EFAULT;
2efbe911 2825 }
8853f86e 2826 break;
2efbe911 2827 default:
c02f499e
TS
2828 ret = -TARGET_ENOPROTOOPT;
2829 break;
8853f86e
FB
2830 }
2831 break;
bd8ed485
TD
2832 case SOL_IPV6:
2833 switch (optname) {
2834 case IPV6_MTU_DISCOVER:
2835 case IPV6_MTU:
2836 case IPV6_V6ONLY:
2837 case IPV6_RECVPKTINFO:
2838 case IPV6_UNICAST_HOPS:
2839 case IPV6_MULTICAST_HOPS:
2840 case IPV6_MULTICAST_LOOP:
2841 case IPV6_RECVERR:
2842 case IPV6_RECVHOPLIMIT:
2843 case IPV6_2292HOPLIMIT:
2844 case IPV6_CHECKSUM:
b9cce6d7
HD
2845 case IPV6_ADDRFORM:
2846 case IPV6_2292PKTINFO:
2847 case IPV6_RECVTCLASS:
2848 case IPV6_RECVRTHDR:
2849 case IPV6_2292RTHDR:
2850 case IPV6_RECVHOPOPTS:
2851 case IPV6_2292HOPOPTS:
2852 case IPV6_RECVDSTOPTS:
2853 case IPV6_2292DSTOPTS:
2854 case IPV6_TCLASS:
22db1213 2855 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2856#ifdef IPV6_RECVPATHMTU
2857 case IPV6_RECVPATHMTU:
2858#endif
2859#ifdef IPV6_TRANSPARENT
2860 case IPV6_TRANSPARENT:
2861#endif
2862#ifdef IPV6_FREEBIND
2863 case IPV6_FREEBIND:
2864#endif
2865#ifdef IPV6_RECVORIGDSTADDR
2866 case IPV6_RECVORIGDSTADDR:
2867#endif
bd8ed485
TD
2868 if (get_user_u32(len, optlen))
2869 return -TARGET_EFAULT;
2870 if (len < 0)
2871 return -TARGET_EINVAL;
2872 lv = sizeof(lv);
2873 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2874 if (ret < 0)
2875 return ret;
2876 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2877 len = 1;
2878 if (put_user_u32(len, optlen)
2879 || put_user_u8(val, optval_addr))
2880 return -TARGET_EFAULT;
2881 } else {
2882 if (len > sizeof(int))
2883 len = sizeof(int);
2884 if (put_user_u32(len, optlen)
2885 || put_user_u32(val, optval_addr))
2886 return -TARGET_EFAULT;
2887 }
2888 break;
2889 default:
2890 ret = -TARGET_ENOPROTOOPT;
2891 break;
2892 }
2893 break;
a2d86682
JK
2894#ifdef SOL_NETLINK
2895 case SOL_NETLINK:
2896 switch (optname) {
2897 case NETLINK_PKTINFO:
2898 case NETLINK_BROADCAST_ERROR:
2899 case NETLINK_NO_ENOBUFS:
2900#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2901 case NETLINK_LISTEN_ALL_NSID:
2902 case NETLINK_CAP_ACK:
2903#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2904#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2905 case NETLINK_EXT_ACK:
2906#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2907#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2908 case NETLINK_GET_STRICT_CHK:
2909#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2910 if (get_user_u32(len, optlen)) {
2911 return -TARGET_EFAULT;
2912 }
2913 if (len != sizeof(val)) {
2914 return -TARGET_EINVAL;
2915 }
2916 lv = len;
2917 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2918 if (ret < 0) {
2919 return ret;
2920 }
2921 if (put_user_u32(lv, optlen)
2922 || put_user_u32(val, optval_addr)) {
2923 return -TARGET_EFAULT;
2924 }
2925 break;
2926#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2927 case NETLINK_LIST_MEMBERSHIPS:
2928 {
2929 uint32_t *results;
2930 int i;
2931 if (get_user_u32(len, optlen)) {
2932 return -TARGET_EFAULT;
2933 }
2934 if (len < 0) {
2935 return -TARGET_EINVAL;
2936 }
2937 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
13e340c8 2938 if (!results && len > 0) {
a2d86682
JK
2939 return -TARGET_EFAULT;
2940 }
2941 lv = len;
2942 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2943 if (ret < 0) {
2944 unlock_user(results, optval_addr, 0);
2945 return ret;
2946 }
2947 /* swap host endianess to target endianess. */
2948 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2949 results[i] = tswap32(results[i]);
2950 }
2951 if (put_user_u32(lv, optlen)) {
2952 return -TARGET_EFAULT;
2953 }
2954 unlock_user(results, optval_addr, 0);
2955 break;
2956 }
2957#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2958 default:
2959 goto unimplemented;
2960 }
c0cb8801 2961 break;
a2d86682 2962#endif /* SOL_NETLINK */
8853f86e
FB
2963 default:
2964 unimplemented:
39be5350
JK
2965 qemu_log_mask(LOG_UNIMP,
2966 "getsockopt level=%d optname=%d not yet supported\n",
2967 level, optname);
c02f499e 2968 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
2969 break;
2970 }
2971 return ret;
7854b056
FB
2972}
2973
9ac22517
MF
2974/* Convert target low/high pair representing file offset into the host
2975 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2976 * as the kernel doesn't handle them either.
2977 */
2978static void target_to_host_low_high(abi_ulong tlow,
2979 abi_ulong thigh,
2980 unsigned long *hlow,
2981 unsigned long *hhigh)
2982{
2983 uint64_t off = tlow |
2984 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2985 TARGET_LONG_BITS / 2;
2986
2987 *hlow = off;
2988 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2989}
2990
f287b2c2 2991static struct iovec *lock_iovec(int type, abi_ulong target_addr,
dab32b32 2992 abi_ulong count, int copy)
53a5960a
PB
2993{
2994 struct target_iovec *target_vec;
f287b2c2
RH
2995 struct iovec *vec;
2996 abi_ulong total_len, max_len;
d732dcb4 2997 int i;
501bb4b0 2998 int err = 0;
29560a6c 2999 bool bad_address = false;
53a5960a 3000
f287b2c2
RH
3001 if (count == 0) {
3002 errno = 0;
3003 return NULL;
3004 }
dab32b32 3005 if (count > IOV_MAX) {
f287b2c2
RH
3006 errno = EINVAL;
3007 return NULL;
3008 }
3009
0e173b24 3010 vec = g_try_new0(struct iovec, count);
f287b2c2
RH
3011 if (vec == NULL) {
3012 errno = ENOMEM;
3013 return NULL;
3014 }
3015
3016 target_vec = lock_user(VERIFY_READ, target_addr,
3017 count * sizeof(struct target_iovec), 1);
3018 if (target_vec == NULL) {
501bb4b0 3019 err = EFAULT;
f287b2c2
RH
3020 goto fail2;
3021 }
3022
3023 /* ??? If host page size > target page size, this will result in a
3024 value larger than what we can actually support. */
3025 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3026 total_len = 0;
3027
3028 for (i = 0; i < count; i++) {
3029 abi_ulong base = tswapal(target_vec[i].iov_base);
3030 abi_long len = tswapal(target_vec[i].iov_len);
3031
3032 if (len < 0) {
501bb4b0 3033 err = EINVAL;
f287b2c2
RH
3034 goto fail;
3035 } else if (len == 0) {
3036 /* Zero length pointer is ignored. */
3037 vec[i].iov_base = 0;
41df8411 3038 } else {
f287b2c2 3039 vec[i].iov_base = lock_user(type, base, len, copy);
29560a6c
TM
3040 /* If the first buffer pointer is bad, this is a fault. But
3041 * subsequent bad buffers will result in a partial write; this
3042 * is realized by filling the vector with null pointers and
3043 * zero lengths. */
f287b2c2 3044 if (!vec[i].iov_base) {
29560a6c
TM
3045 if (i == 0) {
3046 err = EFAULT;
3047 goto fail;
3048 } else {
3049 bad_address = true;
3050 }
3051 }
3052 if (bad_address) {
3053 len = 0;
f287b2c2
RH
3054 }
3055 if (len > max_len - total_len) {
3056 len = max_len - total_len;
3057 }
41df8411 3058 }
f287b2c2
RH
3059 vec[i].iov_len = len;
3060 total_len += len;
579a97f7 3061 }
f287b2c2
RH
3062
3063 unlock_user(target_vec, target_addr, 0);
3064 return vec;
3065
3066 fail:
7eff518b
CG
3067 while (--i >= 0) {
3068 if (tswapal(target_vec[i].iov_len) > 0) {
3069 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3070 }
3071 }
f287b2c2 3072 unlock_user(target_vec, target_addr, 0);
501bb4b0 3073 fail2:
0e173b24 3074 g_free(vec);
501bb4b0 3075 errno = err;
f287b2c2 3076 return NULL;
53a5960a
PB
3077}
3078
f287b2c2 3079static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
dab32b32 3080 abi_ulong count, int copy)
53a5960a
PB
3081{
3082 struct target_iovec *target_vec;
53a5960a
PB
3083 int i;
3084
f287b2c2
RH
3085 target_vec = lock_user(VERIFY_READ, target_addr,
3086 count * sizeof(struct target_iovec), 1);
3087 if (target_vec) {
3088 for (i = 0; i < count; i++) {
3089 abi_ulong base = tswapal(target_vec[i].iov_base);
71ec7cef 3090 abi_long len = tswapal(target_vec[i].iov_len);
f287b2c2
RH
3091 if (len < 0) {
3092 break;
3093 }
d732dcb4
AZ
3094 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3095 }
f287b2c2 3096 unlock_user(target_vec, target_addr, 0);
53a5960a 3097 }
579a97f7 3098
0e173b24 3099 g_free(vec);
53a5960a
PB
3100}
3101
53d09b76 3102static inline int target_to_host_sock_type(int *type)
3532fa74 3103{
f651e6ae
PJ
3104 int host_type = 0;
3105 int target_type = *type;
3106
3107 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3532fa74 3108 case TARGET_SOCK_DGRAM:
f651e6ae 3109 host_type = SOCK_DGRAM;
3532fa74
FB
3110 break;
3111 case TARGET_SOCK_STREAM:
f651e6ae 3112 host_type = SOCK_STREAM;
3532fa74 3113 break;
f651e6ae
PJ
3114 default:
3115 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3532fa74
FB
3116 break;
3117 }
f651e6ae 3118 if (target_type & TARGET_SOCK_CLOEXEC) {
53d09b76 3119#if defined(SOCK_CLOEXEC)
f651e6ae 3120 host_type |= SOCK_CLOEXEC;
53d09b76
EI
3121#else
3122 return -TARGET_EINVAL;
3123#endif
f651e6ae
PJ
3124 }
3125 if (target_type & TARGET_SOCK_NONBLOCK) {
53d09b76 3126#if defined(SOCK_NONBLOCK)
f651e6ae 3127 host_type |= SOCK_NONBLOCK;
53d09b76
EI
3128#elif !defined(O_NONBLOCK)
3129 return -TARGET_EINVAL;
3130#endif
f651e6ae
PJ
3131 }
3132 *type = host_type;
53d09b76
EI
3133 return 0;
3134}
3135
3136/* Try to emulate socket type flags after socket creation. */
3137static int sock_flags_fixup(int fd, int target_type)
3138{
3139#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3140 if (target_type & TARGET_SOCK_NONBLOCK) {
3141 int flags = fcntl(fd, F_GETFL);
3142 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3143 close(fd);
3144 return -TARGET_EINVAL;
3145 }
3146 }
3147#endif
3148 return fd;
f651e6ae
PJ
3149}
3150
3151/* do_socket() Must return target values and target errnos. */
3152static abi_long do_socket(int domain, int type, int protocol)
3153{
53d09b76
EI
3154 int target_type = type;
3155 int ret;
3156
3157 ret = target_to_host_sock_type(&type);
3158 if (ret) {
3159 return ret;
3160 }
f651e6ae 3161
575b22b1
LV
3162 if (domain == PF_NETLINK && !(
3163#ifdef CONFIG_RTNETLINK
3164 protocol == NETLINK_ROUTE ||
3165#endif
3166 protocol == NETLINK_KOBJECT_UEVENT ||
3167 protocol == NETLINK_AUDIT)) {
71e2443e 3168 return -TARGET_EPROTONOSUPPORT;
6c5b5645 3169 }
ff626f2d
LV
3170
3171 if (domain == AF_PACKET ||
3172 (domain == AF_INET && type == SOCK_PACKET)) {
3173 protocol = tswap16(protocol);
3174 }
3175
53d09b76
EI
3176 ret = get_errno(socket(domain, type, protocol));
3177 if (ret >= 0) {
3178 ret = sock_flags_fixup(ret, target_type);
0cf22722
LV
3179 if (type == SOCK_PACKET) {
3180 /* Manage an obsolete case :
3181 * if socket type is SOCK_PACKET, bind by name
3182 */
3183 fd_trans_register(ret, &target_packet_trans);
6c5b5645
LV
3184 } else if (domain == PF_NETLINK) {
3185 switch (protocol) {
575b22b1 3186#ifdef CONFIG_RTNETLINK
6c5b5645
LV
3187 case NETLINK_ROUTE:
3188 fd_trans_register(ret, &target_netlink_route_trans);
3189 break;
575b22b1 3190#endif
b265620b
LV
3191 case NETLINK_KOBJECT_UEVENT:
3192 /* nothing to do: messages are strings */
3193 break;
5ce9bb59
LV
3194 case NETLINK_AUDIT:
3195 fd_trans_register(ret, &target_netlink_audit_trans);
3196 break;
6c5b5645
LV
3197 default:
3198 g_assert_not_reached();
3199 }
0cf22722 3200 }
53d09b76
EI
3201 }
3202 return ret;
3532fa74
FB
3203}
3204
0da46a6e 3205/* do_bind() Must return target values and target errnos. */
992f48a0
BS
3206static abi_long do_bind(int sockfd, abi_ulong target_addr,
3207 socklen_t addrlen)
3532fa74 3208{
8f7aeaf6 3209 void *addr;
917507b0 3210 abi_long ret;
8f7aeaf6 3211
38724253 3212 if ((int)addrlen < 0) {
8f7aeaf6 3213 return -TARGET_EINVAL;
38724253 3214 }
8f7aeaf6 3215
607175e0 3216 addr = alloca(addrlen+1);
3b46e624 3217
7b36f782 3218 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3219 if (ret)
3220 return ret;
3221
3532fa74
FB
3222 return get_errno(bind(sockfd, addr, addrlen));
3223}
3224
0da46a6e 3225/* do_connect() Must return target values and target errnos. */
992f48a0
BS
3226static abi_long do_connect(int sockfd, abi_ulong target_addr,
3227 socklen_t addrlen)
3532fa74 3228{
8f7aeaf6 3229 void *addr;
917507b0 3230 abi_long ret;
8f7aeaf6 3231
38724253 3232 if ((int)addrlen < 0) {
8f7aeaf6 3233 return -TARGET_EINVAL;
38724253 3234 }
8f7aeaf6 3235
2dd08dfd 3236 addr = alloca(addrlen+1);
3b46e624 3237
7b36f782 3238 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3239 if (ret)
3240 return ret;
3241
2a3c7619 3242 return get_errno(safe_connect(sockfd, addr, addrlen));
3532fa74
FB
3243}
3244
f19e00d7
AG
3245/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3246static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3247 int flags, int send)
3532fa74 3248{
6de645c7 3249 abi_long ret, len;
3532fa74 3250 struct msghdr msg;
dab32b32 3251 abi_ulong count;
3532fa74 3252 struct iovec *vec;
992f48a0 3253 abi_ulong target_vec;
3532fa74 3254
3532fa74
FB
3255 if (msgp->msg_name) {
3256 msg.msg_namelen = tswap32(msgp->msg_namelen);
2dd08dfd 3257 msg.msg_name = alloca(msg.msg_namelen+1);
7b36f782
LV
3258 ret = target_to_host_sockaddr(fd, msg.msg_name,
3259 tswapal(msgp->msg_name),
3260 msg.msg_namelen);
26a6fc96
PM
3261 if (ret == -TARGET_EFAULT) {
3262 /* For connected sockets msg_name and msg_namelen must
3263 * be ignored, so returning EFAULT immediately is wrong.
3264 * Instead, pass a bad msg_name to the host kernel, and
3265 * let it decide whether to return EFAULT or not.
3266 */
3267 msg.msg_name = (void *)-1;
3268 } else if (ret) {
f287b2c2 3269 goto out2;
917507b0 3270 }
3532fa74
FB
3271 } else {
3272 msg.msg_name = NULL;
3273 msg.msg_namelen = 0;
3274 }
cbb21eed 3275 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
3532fa74 3276 msg.msg_control = alloca(msg.msg_controllen);
1d3d1b23
JS
3277 memset(msg.msg_control, 0, msg.msg_controllen);
3278
3532fa74 3279 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 3280
cbb21eed 3281 count = tswapal(msgp->msg_iovlen);
cbb21eed 3282 target_vec = tswapal(msgp->msg_iov);
97b07970
PM
3283
3284 if (count > IOV_MAX) {
3285 /* sendrcvmsg returns a different errno for this condition than
3286 * readv/writev, so we must catch it here before lock_iovec() does.
3287 */
3288 ret = -TARGET_EMSGSIZE;
3289 goto out2;
3290 }
3291
f287b2c2
RH
3292 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3293 target_vec, count, send);
3294 if (vec == NULL) {
3295 ret = -host_to_target_errno(errno);
3f0744f9
HD
3296 /* allow sending packet without any iov, e.g. with MSG_MORE flag */
3297 if (!send || ret) {
3298 goto out2;
3299 }
f287b2c2 3300 }
3532fa74
FB
3301 msg.msg_iovlen = count;
3302 msg.msg_iov = vec;
3b46e624 3303
3532fa74 3304 if (send) {
6c5b5645 3305 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3306 void *host_msg;
3307
3308 host_msg = g_malloc(msg.msg_iov->iov_len);
3309 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3310 ret = fd_trans_target_to_host_data(fd)(host_msg,
6c5b5645 3311 msg.msg_iov->iov_len);
7d61d892
LV
3312 if (ret >= 0) {
3313 msg.msg_iov->iov_base = host_msg;
3314 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3315 }
3316 g_free(host_msg);
6c5b5645
LV
3317 } else {
3318 ret = target_to_host_cmsg(&msg, msgp);
7d61d892
LV
3319 if (ret == 0) {
3320 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3321 }
6c5b5645 3322 }
3532fa74 3323 } else {
66687530 3324 ret = get_errno(safe_recvmsg(fd, &msg, flags));
6de645c7
AZ
3325 if (!is_error(ret)) {
3326 len = ret;
6c5b5645
LV
3327 if (fd_trans_host_to_target_data(fd)) {
3328 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
2a03d3e6 3329 MIN(msg.msg_iov->iov_len, len));
16c81dd5
IZ
3330 }
3331 if (!is_error(ret)) {
6c5b5645
LV
3332 ret = host_to_target_cmsg(msgp, &msg);
3333 }
ca619067
JH
3334 if (!is_error(ret)) {
3335 msgp->msg_namelen = tswap32(msg.msg_namelen);
24894f39 3336 msgp->msg_flags = tswap32(msg.msg_flags);
26a6fc96 3337 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ca619067
JH
3338 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3339 msg.msg_name, msg.msg_namelen);
3340 if (ret) {
3341 goto out;
3342 }
3343 }
3344
6de645c7 3345 ret = len;
ca619067 3346 }
6de645c7 3347 }
3532fa74 3348 }
ca619067
JH
3349
3350out:
3f0744f9
HD
3351 if (vec) {
3352 unlock_iovec(vec, target_vec, count, !send);
3353 }
f287b2c2 3354out2:
f19e00d7
AG
3355 return ret;
3356}
3357
3358static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3359 int flags, int send)
3360{
3361 abi_long ret;
3362 struct target_msghdr *msgp;
3363
3364 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3365 msgp,
3366 target_msg,
3367 send ? 1 : 0)) {
3368 return -TARGET_EFAULT;
3369 }
3370 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
579a97f7 3371 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
3372 return ret;
3373}
3374
f19e00d7
AG
3375/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3376 * so it might not have this *mmsg-specific flag either.
3377 */
3378#ifndef MSG_WAITFORONE
3379#define MSG_WAITFORONE 0x10000
3380#endif
3381
3382static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3383 unsigned int vlen, unsigned int flags,
3384 int send)
3385{
3386 struct target_mmsghdr *mmsgp;
3387 abi_long ret = 0;
3388 int i;
3389
3390 if (vlen > UIO_MAXIOV) {
3391 vlen = UIO_MAXIOV;
3392 }
3393
3394 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3395 if (!mmsgp) {
3396 return -TARGET_EFAULT;
3397 }
3398
3399 for (i = 0; i < vlen; i++) {
3400 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3401 if (is_error(ret)) {
3402 break;
3403 }
3404 mmsgp[i].msg_len = tswap32(ret);
3405 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3406 if (flags & MSG_WAITFORONE) {
3407 flags |= MSG_DONTWAIT;
3408 }
3409 }
3410
3411 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3412
3413 /* Return number of datagrams sent if we sent any at all;
3414 * otherwise return the error.
3415 */
3416 if (i) {
3417 return i;
3418 }
3419 return ret;
3420}
f19e00d7 3421
a94b4987
PM
3422/* do_accept4() Must return target values and target errnos. */
3423static abi_long do_accept4(int fd, abi_ulong target_addr,
3424 abi_ulong target_addrlen_addr, int flags)
1be9e1dc 3425{
cd813367 3426 socklen_t addrlen, ret_addrlen;
2f619698 3427 void *addr;
992f48a0 3428 abi_long ret;
d25295d4
PJ
3429 int host_flags;
3430
3431 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
1be9e1dc 3432
a94b4987 3433 if (target_addr == 0) {
ff6dc130 3434 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
a94b4987 3435 }
917507b0 3436
e554eb4b 3437 /* linux returns EFAULT if addrlen pointer is invalid */
2f619698 3438 if (get_user_u32(addrlen, target_addrlen_addr))
e554eb4b 3439 return -TARGET_EFAULT;
2f619698 3440
38724253 3441 if ((int)addrlen < 0) {
8f7aeaf6 3442 return -TARGET_EINVAL;
38724253 3443 }
8f7aeaf6 3444
c7169b02 3445 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
e554eb4b 3446 return -TARGET_EFAULT;
c7169b02 3447 }
917507b0 3448
2f619698
FB
3449 addr = alloca(addrlen);
3450
cd813367
AS
3451 ret_addrlen = addrlen;
3452 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
1be9e1dc 3453 if (!is_error(ret)) {
cd813367
AS
3454 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3455 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3456 ret = -TARGET_EFAULT;
cd813367 3457 }
1be9e1dc
PB
3458 }
3459 return ret;
3460}
3461
0da46a6e 3462/* do_getpeername() Must return target values and target errnos. */
992f48a0 3463static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 3464 abi_ulong target_addrlen_addr)
1be9e1dc 3465{
cd813367 3466 socklen_t addrlen, ret_addrlen;
2f619698 3467 void *addr;
992f48a0 3468 abi_long ret;
1be9e1dc 3469
2f619698
FB
3470 if (get_user_u32(addrlen, target_addrlen_addr))
3471 return -TARGET_EFAULT;
3472
38724253 3473 if ((int)addrlen < 0) {
8f7aeaf6 3474 return -TARGET_EINVAL;
38724253 3475 }
8f7aeaf6 3476
c7169b02 3477 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3478 return -TARGET_EFAULT;
c7169b02 3479 }
917507b0 3480
2f619698
FB
3481 addr = alloca(addrlen);
3482
cd813367
AS
3483 ret_addrlen = addrlen;
3484 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
1be9e1dc 3485 if (!is_error(ret)) {
cd813367
AS
3486 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3487 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3488 ret = -TARGET_EFAULT;
cd813367 3489 }
1be9e1dc
PB
3490 }
3491 return ret;
3492}
3493
0da46a6e 3494/* do_getsockname() Must return target values and target errnos. */
992f48a0 3495static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 3496 abi_ulong target_addrlen_addr)
1be9e1dc 3497{
cd813367 3498 socklen_t addrlen, ret_addrlen;
2f619698 3499 void *addr;
992f48a0 3500 abi_long ret;
1be9e1dc 3501
2f619698
FB
3502 if (get_user_u32(addrlen, target_addrlen_addr))
3503 return -TARGET_EFAULT;
3504
38724253 3505 if ((int)addrlen < 0) {
8f7aeaf6 3506 return -TARGET_EINVAL;
38724253 3507 }
8f7aeaf6 3508
c7169b02 3509 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3510 return -TARGET_EFAULT;
c7169b02 3511 }
917507b0 3512
2f619698
FB
3513 addr = alloca(addrlen);
3514
cd813367
AS
3515 ret_addrlen = addrlen;
3516 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
1be9e1dc 3517 if (!is_error(ret)) {
cd813367
AS
3518 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3519 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3520 ret = -TARGET_EFAULT;
cd813367 3521 }
1be9e1dc
PB
3522 }
3523 return ret;
3524}
3525
0da46a6e 3526/* do_socketpair() Must return target values and target errnos. */
992f48a0 3527static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 3528 abi_ulong target_tab_addr)
1be9e1dc
PB
3529{
3530 int tab[2];
992f48a0 3531 abi_long ret;
1be9e1dc 3532
f651e6ae
PJ
3533 target_to_host_sock_type(&type);
3534
1be9e1dc
PB
3535 ret = get_errno(socketpair(domain, type, protocol, tab));
3536 if (!is_error(ret)) {
2f619698
FB
3537 if (put_user_s32(tab[0], target_tab_addr)
3538 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3539 ret = -TARGET_EFAULT;
1be9e1dc
PB
3540 }
3541 return ret;
3542}
3543
0da46a6e 3544/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
3545static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3546 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
3547{
3548 void *addr;
3549 void *host_msg;
7d61d892 3550 void *copy_msg = NULL;
992f48a0 3551 abi_long ret;
1be9e1dc 3552
38724253 3553 if ((int)addrlen < 0) {
8f7aeaf6 3554 return -TARGET_EINVAL;
38724253 3555 }
8f7aeaf6 3556
579a97f7
FB
3557 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3558 if (!host_msg)
3559 return -TARGET_EFAULT;
6c5b5645 3560 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3561 copy_msg = host_msg;
3562 host_msg = g_malloc(len);
3563 memcpy(host_msg, copy_msg, len);
6c5b5645
LV
3564 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3565 if (ret < 0) {
7d61d892 3566 goto fail;
6c5b5645
LV
3567 }
3568 }
1be9e1dc 3569 if (target_addr) {
2dd08dfd 3570 addr = alloca(addrlen+1);
7b36f782 3571 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
917507b0 3572 if (ret) {
7d61d892 3573 goto fail;
917507b0 3574 }
66687530 3575 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
1be9e1dc 3576 } else {
66687530 3577 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
1be9e1dc 3578 }
7d61d892
LV
3579fail:
3580 if (copy_msg) {
3581 g_free(host_msg);
3582 host_msg = copy_msg;
3583 }
1be9e1dc
PB
3584 unlock_user(host_msg, msg, 0);
3585 return ret;
3586}
3587
0da46a6e 3588/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
3589static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3590 abi_ulong target_addr,
3591 abi_ulong target_addrlen)
1be9e1dc 3592{
cd813367 3593 socklen_t addrlen, ret_addrlen;
1be9e1dc
PB
3594 void *addr;
3595 void *host_msg;
992f48a0 3596 abi_long ret;
1be9e1dc 3597
4a1e6bce
ZR
3598 if (!msg) {
3599 host_msg = NULL;
3600 } else {
3601 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3602 if (!host_msg) {
3603 return -TARGET_EFAULT;
3604 }
3605 }
1be9e1dc 3606 if (target_addr) {
2f619698
FB
3607 if (get_user_u32(addrlen, target_addrlen)) {
3608 ret = -TARGET_EFAULT;
3609 goto fail;
3610 }
38724253 3611 if ((int)addrlen < 0) {
8f7aeaf6
AJ
3612 ret = -TARGET_EINVAL;
3613 goto fail;
3614 }
1be9e1dc 3615 addr = alloca(addrlen);
cd813367 3616 ret_addrlen = addrlen;
66687530 3617 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
cd813367 3618 addr, &ret_addrlen));
1be9e1dc
PB
3619 } else {
3620 addr = NULL; /* To keep compiler quiet. */
cd813367 3621 addrlen = 0; /* To keep compiler quiet. */
66687530 3622 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
1be9e1dc
PB
3623 }
3624 if (!is_error(ret)) {
c35e1f9c 3625 if (fd_trans_host_to_target_data(fd)) {
2a03d3e6
LV
3626 abi_long trans;
3627 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3628 if (is_error(trans)) {
3629 ret = trans;
3630 goto fail;
3631 }
c35e1f9c 3632 }
1be9e1dc 3633 if (target_addr) {
cd813367
AS
3634 host_to_target_sockaddr(target_addr, addr,
3635 MIN(addrlen, ret_addrlen));
3636 if (put_user_u32(ret_addrlen, target_addrlen)) {
2f619698
FB
3637 ret = -TARGET_EFAULT;
3638 goto fail;
3639 }
1be9e1dc
PB
3640 }
3641 unlock_user(host_msg, msg, len);
3642 } else {
2f619698 3643fail:
1be9e1dc
PB
3644 unlock_user(host_msg, msg, 0);
3645 }
3646 return ret;
3647}
3648
32407103 3649#ifdef TARGET_NR_socketcall
ff71a454 3650/* do_socketcall() must return target values and target errnos. */
992f48a0 3651static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 3652{
ff71a454
AM
3653 static const unsigned nargs[] = { /* number of arguments per operation */
3654 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3655 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3656 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3657 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3658 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3659 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3660 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3661 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3662 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3663 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3664 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3665 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3666 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3667 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3668 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3669 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3670 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3671 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3672 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3673 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
62dc90c6
MT
3674 };
3675 abi_long a[6]; /* max 6 args */
ff71a454 3676 unsigned i;
62dc90c6 3677
ff71a454
AM
3678 /* check the range of the first argument num */
3679 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3680 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3681 return -TARGET_EINVAL;
3682 }
3683 /* ensure we have space for args */
3684 if (nargs[num] > ARRAY_SIZE(a)) {
3685 return -TARGET_EINVAL;
3686 }
3687 /* collect the arguments in a[] according to nargs[] */
3688 for (i = 0; i < nargs[num]; ++i) {
3689 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3690 return -TARGET_EFAULT;
31e31b8a 3691 }
62dc90c6 3692 }
ff71a454 3693 /* now when we have the args, invoke the appropriate underlying function */
62dc90c6 3694 switch (num) {
ff71a454 3695 case TARGET_SYS_SOCKET: /* domain, type, protocol */
62dc90c6 3696 return do_socket(a[0], a[1], a[2]);
ff71a454 3697 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
62dc90c6 3698 return do_bind(a[0], a[1], a[2]);
ff71a454 3699 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
62dc90c6 3700 return do_connect(a[0], a[1], a[2]);
ff71a454 3701 case TARGET_SYS_LISTEN: /* sockfd, backlog */
62dc90c6 3702 return get_errno(listen(a[0], a[1]));
ff71a454 3703 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
62dc90c6 3704 return do_accept4(a[0], a[1], a[2], 0);
ff71a454 3705 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
62dc90c6 3706 return do_getsockname(a[0], a[1], a[2]);
ff71a454 3707 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
62dc90c6 3708 return do_getpeername(a[0], a[1], a[2]);
ff71a454 3709 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
62dc90c6 3710 return do_socketpair(a[0], a[1], a[2], a[3]);
ff71a454 3711 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
62dc90c6 3712 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3713 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
62dc90c6 3714 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3715 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3716 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3717 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3718 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3719 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
62dc90c6 3720 return get_errno(shutdown(a[0], a[1]));
ff71a454
AM
3721 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3722 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
3723 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3724 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
3725 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
62dc90c6 3726 return do_sendrecvmsg(a[0], a[1], a[2], 1);
ff71a454 3727 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
62dc90c6 3728 return do_sendrecvmsg(a[0], a[1], a[2], 0);
ff71a454
AM
3729 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3730 return do_accept4(a[0], a[1], a[2], a[3]);
3731 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
5a53dc50 3732 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
ff71a454
AM
3733 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3734 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
31e31b8a 3735 default:
39be5350 3736 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
ff71a454 3737 return -TARGET_EINVAL;
31e31b8a 3738 }
31e31b8a 3739}
32407103 3740#endif
31e31b8a 3741
8853f86e
FB
3742#define N_SHM_REGIONS 32
3743
3744static struct shm_region {
b6e17875
PM
3745 abi_ulong start;
3746 abi_ulong size;
3747 bool in_use;
8853f86e
FB
3748} shm_regions[N_SHM_REGIONS];
3749
005eb2ae
PM
3750#ifndef TARGET_SEMID64_DS
3751/* asm-generic version of this struct */
3752struct target_semid64_ds
3eb6b044
TS
3753{
3754 struct target_ipc_perm sem_perm;
992f48a0 3755 abi_ulong sem_otime;
005eb2ae 3756#if TARGET_ABI_BITS == 32
992f48a0 3757 abi_ulong __unused1;
03527344 3758#endif
992f48a0 3759 abi_ulong sem_ctime;
005eb2ae 3760#if TARGET_ABI_BITS == 32
992f48a0 3761 abi_ulong __unused2;
03527344 3762#endif
992f48a0
BS
3763 abi_ulong sem_nsems;
3764 abi_ulong __unused3;
3765 abi_ulong __unused4;
3eb6b044 3766};
005eb2ae 3767#endif
3eb6b044 3768
579a97f7
FB
3769static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3770 abi_ulong target_addr)
3eb6b044
TS
3771{
3772 struct target_ipc_perm *target_ip;
005eb2ae 3773 struct target_semid64_ds *target_sd;
3eb6b044 3774
579a97f7
FB
3775 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3776 return -TARGET_EFAULT;
e8bbe36c 3777 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3778 host_ip->__key = tswap32(target_ip->__key);
3779 host_ip->uid = tswap32(target_ip->uid);
3780 host_ip->gid = tswap32(target_ip->gid);
3781 host_ip->cuid = tswap32(target_ip->cuid);
3782 host_ip->cgid = tswap32(target_ip->cgid);
3783#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3784 host_ip->mode = tswap32(target_ip->mode);
3785#else
cbb21eed 3786 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
3787#endif
3788#if defined(TARGET_PPC)
3789 host_ip->__seq = tswap32(target_ip->__seq);
3790#else
3791 host_ip->__seq = tswap16(target_ip->__seq);
3792#endif
3eb6b044 3793 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3794 return 0;
3eb6b044
TS
3795}
3796
579a97f7
FB
3797static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3798 struct ipc_perm *host_ip)
3eb6b044
TS
3799{
3800 struct target_ipc_perm *target_ip;
005eb2ae 3801 struct target_semid64_ds *target_sd;
3eb6b044 3802
579a97f7
FB
3803 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3804 return -TARGET_EFAULT;
3eb6b044 3805 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3806 target_ip->__key = tswap32(host_ip->__key);
3807 target_ip->uid = tswap32(host_ip->uid);
3808 target_ip->gid = tswap32(host_ip->gid);
3809 target_ip->cuid = tswap32(host_ip->cuid);
3810 target_ip->cgid = tswap32(host_ip->cgid);
3811#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3812 target_ip->mode = tswap32(host_ip->mode);
3813#else
cbb21eed 3814 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
3815#endif
3816#if defined(TARGET_PPC)
3817 target_ip->__seq = tswap32(host_ip->__seq);
3818#else
3819 target_ip->__seq = tswap16(host_ip->__seq);
3820#endif
3eb6b044 3821 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3822 return 0;
3eb6b044
TS
3823}
3824
579a97f7
FB
3825static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3826 abi_ulong target_addr)
3eb6b044 3827{
005eb2ae 3828 struct target_semid64_ds *target_sd;
3eb6b044 3829
579a97f7
FB
3830 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3831 return -TARGET_EFAULT;
e5289087
AJ
3832 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3833 return -TARGET_EFAULT;
cbb21eed
MB
3834 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3835 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3836 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 3837 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3838 return 0;
3eb6b044
TS
3839}
3840
579a97f7
FB
3841static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3842 struct semid_ds *host_sd)
3eb6b044 3843{
005eb2ae 3844 struct target_semid64_ds *target_sd;
3eb6b044 3845
579a97f7
FB
3846 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3847 return -TARGET_EFAULT;
e5289087 3848 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 3849 return -TARGET_EFAULT;
cbb21eed
MB
3850 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3851 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3852 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 3853 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3854 return 0;
3eb6b044
TS
3855}
3856
e5289087
AJ
3857struct target_seminfo {
3858 int semmap;
3859 int semmni;
3860 int semmns;
3861 int semmnu;
3862 int semmsl;
3863 int semopm;
3864 int semume;
3865 int semusz;
3866 int semvmx;
3867 int semaem;
3868};
3869
3870static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3871 struct seminfo *host_seminfo)
3872{
3873 struct target_seminfo *target_seminfo;
3874 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3875 return -TARGET_EFAULT;
3876 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3877 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3878 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3879 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3880 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3881 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3882 __put_user(host_seminfo->semume, &target_seminfo->semume);
3883 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3884 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3885 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3886 unlock_user_struct(target_seminfo, target_addr, 1);
3887 return 0;
3888}
3889
fa294816
TS
3890union semun {
3891 int val;
3eb6b044 3892 struct semid_ds *buf;
fa294816 3893 unsigned short *array;
e5289087 3894 struct seminfo *__buf;
fa294816
TS
3895};
3896
3eb6b044
TS
3897union target_semun {
3898 int val;
e5289087
AJ
3899 abi_ulong buf;
3900 abi_ulong array;
3901 abi_ulong __buf;
3eb6b044
TS
3902};
3903
e5289087
AJ
3904static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3905 abi_ulong target_addr)
3eb6b044 3906{
e5289087
AJ
3907 int nsems;
3908 unsigned short *array;
3909 union semun semun;
3910 struct semid_ds semid_ds;
3911 int i, ret;
3eb6b044 3912
e5289087
AJ
3913 semun.buf = &semid_ds;
3914
3915 ret = semctl(semid, 0, IPC_STAT, semun);
3916 if (ret == -1)
3917 return get_errno(ret);
3918
3919 nsems = semid_ds.sem_nsems;
3920
0e173b24 3921 *host_array = g_try_new(unsigned short, nsems);
69d4c703
PM
3922 if (!*host_array) {
3923 return -TARGET_ENOMEM;
3924 }
e5289087
AJ
3925 array = lock_user(VERIFY_READ, target_addr,
3926 nsems*sizeof(unsigned short), 1);
69d4c703 3927 if (!array) {
0e173b24 3928 g_free(*host_array);
e5289087 3929 return -TARGET_EFAULT;
69d4c703 3930 }
e5289087
AJ
3931
3932 for(i=0; i<nsems; i++) {
3933 __get_user((*host_array)[i], &array[i]);
3eb6b044 3934 }
e5289087
AJ
3935 unlock_user(array, target_addr, 0);
3936
579a97f7 3937 return 0;
3eb6b044
TS
3938}
3939
e5289087
AJ
3940static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3941 unsigned short **host_array)
3eb6b044 3942{
e5289087
AJ
3943 int nsems;
3944 unsigned short *array;
3945 union semun semun;
3946 struct semid_ds semid_ds;
3947 int i, ret;
3eb6b044 3948
e5289087
AJ
3949 semun.buf = &semid_ds;
3950
3951 ret = semctl(semid, 0, IPC_STAT, semun);
3952 if (ret == -1)
3953 return get_errno(ret);
3954
3955 nsems = semid_ds.sem_nsems;
3956
3957 array = lock_user(VERIFY_WRITE, target_addr,
3958 nsems*sizeof(unsigned short), 0);
3959 if (!array)
3960 return -TARGET_EFAULT;
3961
3962 for(i=0; i<nsems; i++) {
3963 __put_user((*host_array)[i], &array[i]);
3eb6b044 3964 }
0e173b24 3965 g_free(*host_array);
e5289087
AJ
3966 unlock_user(array, target_addr, 1);
3967
579a97f7 3968 return 0;
3eb6b044
TS
3969}
3970
e5289087 3971static inline abi_long do_semctl(int semid, int semnum, int cmd,
d1c002b6 3972 abi_ulong target_arg)
3eb6b044 3973{
d1c002b6 3974 union target_semun target_su = { .buf = target_arg };
3eb6b044
TS
3975 union semun arg;
3976 struct semid_ds dsarg;
7b8118e8 3977 unsigned short *array = NULL;
e5289087
AJ
3978 struct seminfo seminfo;
3979 abi_long ret = -TARGET_EINVAL;
3980 abi_long err;
3981 cmd &= 0xff;
3eb6b044
TS
3982
3983 switch( cmd ) {
3984 case GETVAL:
3eb6b044 3985 case SETVAL:
5464baec
TM
3986 /* In 64 bit cross-endian situations, we will erroneously pick up
3987 * the wrong half of the union for the "val" element. To rectify
3988 * this, the entire 8-byte structure is byteswapped, followed by
3989 * a swap of the 4 byte val field. In other cases, the data is
3990 * already in proper host byte order. */
3991 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3992 target_su.buf = tswapal(target_su.buf);
3993 arg.val = tswap32(target_su.val);
3994 } else {
3995 arg.val = target_su.val;
3996 }
e5289087 3997 ret = get_errno(semctl(semid, semnum, cmd, arg));
3eb6b044
TS
3998 break;
3999 case GETALL:
3eb6b044 4000 case SETALL:
e5289087
AJ
4001 err = target_to_host_semarray(semid, &array, target_su.array);
4002 if (err)
4003 return err;
4004 arg.array = array;
4005 ret = get_errno(semctl(semid, semnum, cmd, arg));
4006 err = host_to_target_semarray(semid, target_su.array, &array);
4007 if (err)
4008 return err;
3eb6b044
TS
4009 break;
4010 case IPC_STAT:
3eb6b044 4011 case IPC_SET:
e5289087
AJ
4012 case SEM_STAT:
4013 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4014 if (err)
4015 return err;
4016 arg.buf = &dsarg;
4017 ret = get_errno(semctl(semid, semnum, cmd, arg));
4018 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4019 if (err)
4020 return err;
4021 break;
4022 case IPC_INFO:
4023 case SEM_INFO:
4024 arg.__buf = &seminfo;
4025 ret = get_errno(semctl(semid, semnum, cmd, arg));
4026 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4027 if (err)
4028 return err;
4029 break;
4030 case IPC_RMID:
4031 case GETPID:
4032 case GETNCNT:
4033 case GETZCNT:
4034 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 4035 break;
3eb6b044
TS
4036 }
4037
4038 return ret;
4039}
4040
e5289087
AJ
4041struct target_sembuf {
4042 unsigned short sem_num;
4043 short sem_op;
4044 short sem_flg;
4045};
4046
4047static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4048 abi_ulong target_addr,
4049 unsigned nsops)
4050{
4051 struct target_sembuf *target_sembuf;
4052 int i;
4053
4054 target_sembuf = lock_user(VERIFY_READ, target_addr,
4055 nsops*sizeof(struct target_sembuf), 1);
4056 if (!target_sembuf)
4057 return -TARGET_EFAULT;
4058
4059 for(i=0; i<nsops; i++) {
4060 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4061 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4062 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4063 }
4064
4065 unlock_user(target_sembuf, target_addr, 0);
4066
4067 return 0;
4068}
4069
d8c08b1e 4070#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
cac46eb0 4071 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
d8c08b1e
MK
4072
4073/*
4074 * This macro is required to handle the s390 variants, which passes the
4075 * arguments in a different order than default.
4076 */
4077#ifdef __s390x__
4078#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4079 (__nsops), (__timeout), (__sops)
4080#else
4081#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4082 (__nsops), 0, (__sops), (__timeout)
4083#endif
4084
4085static inline abi_long do_semtimedop(int semid,
4086 abi_long ptr,
4087 unsigned nsops,
cac46eb0 4088 abi_long timeout, bool time64)
e5289087 4089{
0a7ec849 4090 struct sembuf *sops;
d8c08b1e 4091 struct timespec ts, *pts = NULL;
524fa340 4092 abi_long ret;
e5289087 4093
d8c08b1e
MK
4094 if (timeout) {
4095 pts = &ts;
cac46eb0
FB
4096 if (time64) {
4097 if (target_to_host_timespec64(pts, timeout)) {
4098 return -TARGET_EFAULT;
4099 }
4100 } else {
4101 if (target_to_host_timespec(pts, timeout)) {
4102 return -TARGET_EFAULT;
4103 }
d8c08b1e
MK
4104 }
4105 }
4106
0a7ec849
FB
4107 if (nsops > TARGET_SEMOPM) {
4108 return -TARGET_E2BIG;
4109 }
4110
4111 sops = g_new(struct sembuf, nsops);
4112
4113 if (target_to_host_sembuf(sops, ptr, nsops)) {
4114 g_free(sops);
e5289087 4115 return -TARGET_EFAULT;
0a7ec849 4116 }
e5289087 4117
524fa340
LV
4118 ret = -TARGET_ENOSYS;
4119#ifdef __NR_semtimedop
d8c08b1e 4120 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
524fa340
LV
4121#endif
4122#ifdef __NR_ipc
4123 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4124 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4125 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
524fa340
LV
4126 }
4127#endif
0a7ec849 4128 g_free(sops);
524fa340 4129 return ret;
e5289087 4130}
d8c08b1e 4131#endif
e5289087 4132
1bc012f6
TS
4133struct target_msqid_ds
4134{
1c54ff97
AJ
4135 struct target_ipc_perm msg_perm;
4136 abi_ulong msg_stime;
4137#if TARGET_ABI_BITS == 32
4138 abi_ulong __unused1;
4139#endif
4140 abi_ulong msg_rtime;
4141#if TARGET_ABI_BITS == 32
4142 abi_ulong __unused2;
4143#endif
4144 abi_ulong msg_ctime;
4145#if TARGET_ABI_BITS == 32
4146 abi_ulong __unused3;
4147#endif
4148 abi_ulong __msg_cbytes;
4149 abi_ulong msg_qnum;
4150 abi_ulong msg_qbytes;
4151 abi_ulong msg_lspid;
4152 abi_ulong msg_lrpid;
4153 abi_ulong __unused4;
4154 abi_ulong __unused5;
1bc012f6
TS
4155};
4156
579a97f7
FB
4157static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4158 abi_ulong target_addr)
1bc012f6
TS
4159{
4160 struct target_msqid_ds *target_md;
4161
579a97f7
FB
4162 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4163 return -TARGET_EFAULT;
1c54ff97
AJ
4164 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4165 return -TARGET_EFAULT;
cbb21eed
MB
4166 host_md->msg_stime = tswapal(target_md->msg_stime);
4167 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4168 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4169 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4170 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4171 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4172 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4173 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 4174 unlock_user_struct(target_md, target_addr, 0);
579a97f7 4175 return 0;
1bc012f6
TS
4176}
4177
579a97f7
FB
4178static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4179 struct msqid_ds *host_md)
1bc012f6
TS
4180{
4181 struct target_msqid_ds *target_md;
4182
579a97f7
FB
4183 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4184 return -TARGET_EFAULT;
1c54ff97
AJ
4185 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4186 return -TARGET_EFAULT;
cbb21eed
MB
4187 target_md->msg_stime = tswapal(host_md->msg_stime);
4188 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4189 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4190 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4191 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4192 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4193 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4194 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 4195 unlock_user_struct(target_md, target_addr, 1);
579a97f7 4196 return 0;
1bc012f6
TS
4197}
4198
1c54ff97
AJ
4199struct target_msginfo {
4200 int msgpool;
4201 int msgmap;
4202 int msgmax;
4203 int msgmnb;
4204 int msgmni;
4205 int msgssz;
4206 int msgtql;
4207 unsigned short int msgseg;
4208};
4209
4210static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4211 struct msginfo *host_msginfo)
4212{
4213 struct target_msginfo *target_msginfo;
4214 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4215 return -TARGET_EFAULT;
4216 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4217 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4218 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4219 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4220 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4221 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4222 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4223 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4224 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 4225 return 0;
1c54ff97
AJ
4226}
4227
4228static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
4229{
4230 struct msqid_ds dsarg;
1c54ff97
AJ
4231 struct msginfo msginfo;
4232 abi_long ret = -TARGET_EINVAL;
4233
4234 cmd &= 0xff;
4235
4236 switch (cmd) {
1bc012f6
TS
4237 case IPC_STAT:
4238 case IPC_SET:
1c54ff97
AJ
4239 case MSG_STAT:
4240 if (target_to_host_msqid_ds(&dsarg,ptr))
4241 return -TARGET_EFAULT;
4242 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4243 if (host_to_target_msqid_ds(ptr,&dsarg))
4244 return -TARGET_EFAULT;
4245 break;
4246 case IPC_RMID:
4247 ret = get_errno(msgctl(msgid, cmd, NULL));
4248 break;
4249 case IPC_INFO:
4250 case MSG_INFO:
4251 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4252 if (host_to_target_msginfo(ptr, &msginfo))
4253 return -TARGET_EFAULT;
4254 break;
1bc012f6 4255 }
1c54ff97 4256
1bc012f6
TS
4257 return ret;
4258}
4259
4260struct target_msgbuf {
1c54ff97
AJ
4261 abi_long mtype;
4262 char mtext[1];
1bc012f6
TS
4263};
4264
992f48a0 4265static inline abi_long do_msgsnd(int msqid, abi_long msgp,
edcc5f9d 4266 ssize_t msgsz, int msgflg)
1bc012f6
TS
4267{
4268 struct target_msgbuf *target_mb;
4269 struct msgbuf *host_mb;
992f48a0 4270 abi_long ret = 0;
1bc012f6 4271
edcc5f9d
TM
4272 if (msgsz < 0) {
4273 return -TARGET_EINVAL;
4274 }
4275
579a97f7
FB
4276 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4277 return -TARGET_EFAULT;
0e173b24 4278 host_mb = g_try_malloc(msgsz + sizeof(long));
29e03fcb
HZ
4279 if (!host_mb) {
4280 unlock_user_struct(target_mb, msgp, 0);
4281 return -TARGET_ENOMEM;
4282 }
cbb21eed 4283 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 4284 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
524fa340
LV
4285 ret = -TARGET_ENOSYS;
4286#ifdef __NR_msgsnd
89f9fe44 4287 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
524fa340
LV
4288#endif
4289#ifdef __NR_ipc
4290 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4291#ifdef __s390x__
4292 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4293 host_mb));
4294#else
524fa340
LV
4295 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4296 host_mb, 0));
d8c08b1e 4297#endif
524fa340
LV
4298 }
4299#endif
0e173b24 4300 g_free(host_mb);
1bc012f6
TS
4301 unlock_user_struct(target_mb, msgp, 0);
4302
4303 return ret;
4304}
4305
d8c08b1e
MK
4306#ifdef __NR_ipc
4307#if defined(__sparc__)
4308/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4309#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4310#elif defined(__s390x__)
4311/* The s390 sys_ipc variant has only five parameters. */
4312#define MSGRCV_ARGS(__msgp, __msgtyp) \
4313 ((long int[]){(long int)__msgp, __msgtyp})
4314#else
4315#define MSGRCV_ARGS(__msgp, __msgtyp) \
4316 ((long int[]){(long int)__msgp, __msgtyp}), 0
4317#endif
4318#endif
4319
992f48a0 4320static inline abi_long do_msgrcv(int msqid, abi_long msgp,
99874f65 4321 ssize_t msgsz, abi_long msgtyp,
992f48a0 4322 int msgflg)
1bc012f6
TS
4323{
4324 struct target_msgbuf *target_mb;
579a97f7 4325 char *target_mtext;
1bc012f6 4326 struct msgbuf *host_mb;
992f48a0 4327 abi_long ret = 0;
1bc012f6 4328
99874f65
PM
4329 if (msgsz < 0) {
4330 return -TARGET_EINVAL;
4331 }
4332
579a97f7
FB
4333 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4334 return -TARGET_EFAULT;
1c54ff97 4335
415d8471
PM
4336 host_mb = g_try_malloc(msgsz + sizeof(long));
4337 if (!host_mb) {
4338 ret = -TARGET_ENOMEM;
4339 goto end;
4340 }
524fa340
LV
4341 ret = -TARGET_ENOSYS;
4342#ifdef __NR_msgrcv
89f9fe44 4343 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
524fa340
LV
4344#endif
4345#ifdef __NR_ipc
4346 if (ret == -TARGET_ENOSYS) {
4347 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
d8c08b1e 4348 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
524fa340
LV
4349 }
4350#endif
1c54ff97 4351
579a97f7
FB
4352 if (ret > 0) {
4353 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4354 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4355 if (!target_mtext) {
4356 ret = -TARGET_EFAULT;
4357 goto end;
4358 }
1c54ff97 4359 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
4360 unlock_user(target_mtext, target_mtext_addr, ret);
4361 }
1c54ff97 4362
cbb21eed 4363 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 4364
579a97f7
FB
4365end:
4366 if (target_mb)
4367 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 4368 g_free(host_mb);
1bc012f6
TS
4369 return ret;
4370}
4371
88a8c984
RV
4372static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4373 abi_ulong target_addr)
4374{
4375 struct target_shmid_ds *target_sd;
4376
4377 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4378 return -TARGET_EFAULT;
4379 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4380 return -TARGET_EFAULT;
4381 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4382 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4383 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4384 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4385 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4386 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4387 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4388 unlock_user_struct(target_sd, target_addr, 0);
4389 return 0;
4390}
4391
4392static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4393 struct shmid_ds *host_sd)
4394{
4395 struct target_shmid_ds *target_sd;
4396
4397 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4398 return -TARGET_EFAULT;
4399 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4400 return -TARGET_EFAULT;
4401 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4402 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4403 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4404 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4405 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4406 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4407 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4408 unlock_user_struct(target_sd, target_addr, 1);
4409 return 0;
4410}
4411
4412struct target_shminfo {
4413 abi_ulong shmmax;
4414 abi_ulong shmmin;
4415 abi_ulong shmmni;
4416 abi_ulong shmseg;
4417 abi_ulong shmall;
4418};
4419
4420static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4421 struct shminfo *host_shminfo)
4422{
4423 struct target_shminfo *target_shminfo;
4424 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4425 return -TARGET_EFAULT;
4426 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4427 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4428 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4429 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4430 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4431 unlock_user_struct(target_shminfo, target_addr, 1);
4432 return 0;
4433}
4434
4435struct target_shm_info {
4436 int used_ids;
4437 abi_ulong shm_tot;
4438 abi_ulong shm_rss;
4439 abi_ulong shm_swp;
4440 abi_ulong swap_attempts;
4441 abi_ulong swap_successes;
4442};
4443
4444static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4445 struct shm_info *host_shm_info)
4446{
4447 struct target_shm_info *target_shm_info;
4448 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4449 return -TARGET_EFAULT;
4450 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4451 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4452 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4453 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4454 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4455 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4456 unlock_user_struct(target_shm_info, target_addr, 1);
4457 return 0;
4458}
4459
4460static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4461{
4462 struct shmid_ds dsarg;
4463 struct shminfo shminfo;
4464 struct shm_info shm_info;
4465 abi_long ret = -TARGET_EINVAL;
4466
4467 cmd &= 0xff;
4468
4469 switch(cmd) {
4470 case IPC_STAT:
4471 case IPC_SET:
4472 case SHM_STAT:
4473 if (target_to_host_shmid_ds(&dsarg, buf))
4474 return -TARGET_EFAULT;
4475 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4476 if (host_to_target_shmid_ds(buf, &dsarg))
4477 return -TARGET_EFAULT;
4478 break;
4479 case IPC_INFO:
4480 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4481 if (host_to_target_shminfo(buf, &shminfo))
4482 return -TARGET_EFAULT;
4483 break;
4484 case SHM_INFO:
4485 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4486 if (host_to_target_shm_info(buf, &shm_info))
4487 return -TARGET_EFAULT;
4488 break;
4489 case IPC_RMID:
4490 case SHM_LOCK:
4491 case SHM_UNLOCK:
4492 ret = get_errno(shmctl(shmid, cmd, NULL));
4493 break;
4494 }
4495
4496 return ret;
4497}
4498
ee8e7614
PM
4499#ifndef TARGET_FORCE_SHMLBA
4500/* For most architectures, SHMLBA is the same as the page size;
4501 * some architectures have larger values, in which case they should
4502 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4503 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4504 * and defining its own value for SHMLBA.
4505 *
4506 * The kernel also permits SHMLBA to be set by the architecture to a
4507 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4508 * this means that addresses are rounded to the large size if
4509 * SHM_RND is set but addresses not aligned to that size are not rejected
4510 * as long as they are at least page-aligned. Since the only architecture
4511 * which uses this is ia64 this code doesn't provide for that oddity.
4512 */
4513static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4514{
4515 return TARGET_PAGE_SIZE;
4516}
4517#endif
4518
4519static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4520 int shmid, abi_ulong shmaddr, int shmflg)
88a8c984 4521{
228168cb 4522 CPUState *cpu = env_cpu(cpu_env);
88a8c984
RV
4523 abi_long raddr;
4524 void *host_raddr;
4525 struct shmid_ds shm_info;
4526 int i,ret;
ee8e7614 4527 abi_ulong shmlba;
88a8c984 4528
ee1bf83d
RH
4529 /* shmat pointers are always untagged */
4530
88a8c984
RV
4531 /* find out the length of the shared memory segment */
4532 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4533 if (is_error(ret)) {
4534 /* can't get length, bail out */
4535 return ret;
4536 }
4537
ee8e7614
PM
4538 shmlba = target_shmlba(cpu_env);
4539
4540 if (shmaddr & (shmlba - 1)) {
4541 if (shmflg & SHM_RND) {
4542 shmaddr &= ~(shmlba - 1);
4543 } else {
4544 return -TARGET_EINVAL;
4545 }
4546 }
46b12f46 4547 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
ebf9a363
MF
4548 return -TARGET_EINVAL;
4549 }
ee8e7614 4550
88a8c984
RV
4551 mmap_lock();
4552
228168cb
RH
4553 /*
4554 * We're mapping shared memory, so ensure we generate code for parallel
4555 * execution and flush old translations. This will work up to the level
4556 * supported by the host -- anything that requires EXCP_ATOMIC will not
4557 * be atomic with respect to an external process.
4558 */
4559 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4560 cpu->tcg_cflags |= CF_PARALLEL;
4561 tb_flush(cpu);
4562 }
4563
88a8c984 4564 if (shmaddr)
3e8f1628 4565 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
88a8c984
RV
4566 else {
4567 abi_ulong mmap_start;
4568
30ab9ef2
RH
4569 /* In order to use the host shmat, we need to honor host SHMLBA. */
4570 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
88a8c984
RV
4571
4572 if (mmap_start == -1) {
4573 errno = ENOMEM;
4574 host_raddr = (void *)-1;
4575 } else
3e8f1628
RH
4576 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4577 shmflg | SHM_REMAP);
88a8c984
RV
4578 }
4579
4580 if (host_raddr == (void *)-1) {
4581 mmap_unlock();
4582 return get_errno((long)host_raddr);
4583 }
4584 raddr=h2g((unsigned long)host_raddr);
4585
4586 page_set_flags(raddr, raddr + shm_info.shm_segsz,
d9c58585
RH
4587 PAGE_VALID | PAGE_RESET | PAGE_READ |
4588 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
88a8c984
RV
4589
4590 for (i = 0; i < N_SHM_REGIONS; i++) {
b6e17875
PM
4591 if (!shm_regions[i].in_use) {
4592 shm_regions[i].in_use = true;
88a8c984
RV
4593 shm_regions[i].start = raddr;
4594 shm_regions[i].size = shm_info.shm_segsz;
4595 break;
4596 }
4597 }
4598
4599 mmap_unlock();
4600 return raddr;
4601
4602}
4603
4604static inline abi_long do_shmdt(abi_ulong shmaddr)
4605{
4606 int i;
3c5f6a5f
MF
4607 abi_long rv;
4608
ee1bf83d
RH
4609 /* shmdt pointers are always untagged */
4610
3c5f6a5f 4611 mmap_lock();
88a8c984
RV
4612
4613 for (i = 0; i < N_SHM_REGIONS; ++i) {
b6e17875
PM
4614 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4615 shm_regions[i].in_use = false;
e00ac249 4616 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
4617 break;
4618 }
4619 }
3e8f1628 4620 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
88a8c984 4621
3c5f6a5f 4622 mmap_unlock();
88a8c984 4623
3c5f6a5f 4624 return rv;
88a8c984
RV
4625}
4626
1c54ff97 4627#ifdef TARGET_NR_ipc
53a5960a 4628/* ??? This only works with linear mappings. */
0da46a6e 4629/* do_ipc() must return target values and target errnos. */
ee8e7614
PM
4630static abi_long do_ipc(CPUArchState *cpu_env,
4631 unsigned int call, abi_long first,
37ed0956 4632 abi_long second, abi_long third,
992f48a0 4633 abi_long ptr, abi_long fifth)
8853f86e
FB
4634{
4635 int version;
992f48a0 4636 abi_long ret = 0;
8853f86e
FB
4637
4638 version = call >> 16;
4639 call &= 0xffff;
4640
4641 switch (call) {
fa294816 4642 case IPCOP_semop:
cac46eb0 4643 ret = do_semtimedop(first, ptr, second, 0, false);
d8c08b1e
MK
4644 break;
4645 case IPCOP_semtimedop:
4646 /*
4647 * The s390 sys_ipc variant has only five parameters instead of six
4648 * (as for default variant) and the only difference is the handling of
4649 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4650 * to a struct timespec where the generic variant uses fifth parameter.
4651 */
4652#if defined(TARGET_S390X)
cac46eb0 4653 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
d8c08b1e 4654#else
cac46eb0 4655 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
d8c08b1e 4656#endif
fa294816
TS
4657 break;
4658
4659 case IPCOP_semget:
4660 ret = get_errno(semget(first, second, third));
4661 break;
4662
5d2fa8eb
TM
4663 case IPCOP_semctl: {
4664 /* The semun argument to semctl is passed by value, so dereference the
4665 * ptr argument. */
4666 abi_ulong atptr;
37ed0956 4667 get_user_ual(atptr, ptr);
d1c002b6 4668 ret = do_semctl(first, second, third, atptr);
fa294816 4669 break;
5d2fa8eb 4670 }
d96372ef 4671
1c54ff97
AJ
4672 case IPCOP_msgget:
4673 ret = get_errno(msgget(first, second));
4674 break;
d96372ef 4675
1c54ff97
AJ
4676 case IPCOP_msgsnd:
4677 ret = do_msgsnd(first, ptr, second, third);
4678 break;
d96372ef 4679
1c54ff97
AJ
4680 case IPCOP_msgctl:
4681 ret = do_msgctl(first, second, ptr);
4682 break;
d96372ef 4683
1c54ff97
AJ
4684 case IPCOP_msgrcv:
4685 switch (version) {
4686 case 0:
4687 {
4688 struct target_ipc_kludge {
4689 abi_long msgp;
4690 abi_long msgtyp;
4691 } *tmp;
4692
4693 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4694 ret = -TARGET_EFAULT;
4695 break;
4696 }
d96372ef 4697
79dd77de 4698 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 4699
1c54ff97
AJ
4700 unlock_user_struct(tmp, ptr, 0);
4701 break;
4702 }
4703 default:
4704 ret = do_msgrcv(first, ptr, second, fifth, third);
4705 }
4706 break;
d96372ef 4707
8853f86e 4708 case IPCOP_shmat:
88a8c984
RV
4709 switch (version) {
4710 default:
5a4a898d
FB
4711 {
4712 abi_ulong raddr;
ee8e7614 4713 raddr = do_shmat(cpu_env, first, ptr, second);
88a8c984
RV
4714 if (is_error(raddr))
4715 return get_errno(raddr);
2f619698 4716 if (put_user_ual(raddr, third))
5a4a898d 4717 return -TARGET_EFAULT;
88a8c984
RV
4718 break;
4719 }
4720 case 1:
4721 ret = -TARGET_EINVAL;
4722 break;
5a4a898d 4723 }
8853f86e
FB
4724 break;
4725 case IPCOP_shmdt:
88a8c984 4726 ret = do_shmdt(ptr);
8853f86e
FB
4727 break;
4728
4729 case IPCOP_shmget:
4730 /* IPC_* flag values are the same on all linux platforms */
4731 ret = get_errno(shmget(first, second, third));
4732 break;
4733
4734 /* IPC_* and SHM_* command values are the same on all linux platforms */
4735 case IPCOP_shmctl:
a2926784 4736 ret = do_shmctl(first, second, ptr);
8853f86e
FB
4737 break;
4738 default:
39be5350
JK
4739 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4740 call, version);
0da46a6e 4741 ret = -TARGET_ENOSYS;
8853f86e
FB
4742 break;
4743 }
4744 return ret;
4745}
32407103 4746#endif
8853f86e 4747
31e31b8a 4748/* kernel structure types definitions */
31e31b8a 4749
001faf32 4750#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
4751#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4752enum {
4753#include "syscall_types.h"
8be656b8 4754STRUCT_MAX
31e31b8a
FB
4755};
4756#undef STRUCT
4757#undef STRUCT_SPECIAL
4758
001faf32 4759#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
4760#define STRUCT_SPECIAL(name)
4761#include "syscall_types.h"
4762#undef STRUCT
4763#undef STRUCT_SPECIAL
4764
31e31b8a
FB
4765#define MAX_STRUCT_SIZE 4096
4766
dace20dc 4767#ifdef CONFIG_FIEMAP
285da2b9
PM
4768/* So fiemap access checks don't overflow on 32 bit systems.
4769 * This is very slightly smaller than the limit imposed by
4770 * the underlying kernel.
4771 */
4772#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4773 / sizeof(struct fiemap_extent))
4774
4775static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4776 int fd, int cmd, abi_long arg)
285da2b9
PM
4777{
4778 /* The parameter for this ioctl is a struct fiemap followed
4779 * by an array of struct fiemap_extent whose size is set
4780 * in fiemap->fm_extent_count. The array is filled in by the
4781 * ioctl.
4782 */
4783 int target_size_in, target_size_out;
4784 struct fiemap *fm;
4785 const argtype *arg_type = ie->arg_type;
4786 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4787 void *argptr, *p;
4788 abi_long ret;
4789 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4790 uint32_t outbufsz;
4791 int free_fm = 0;
4792
4793 assert(arg_type[0] == TYPE_PTR);
4794 assert(ie->access == IOC_RW);
4795 arg_type++;
4796 target_size_in = thunk_type_size(arg_type, 0);
4797 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4798 if (!argptr) {
4799 return -TARGET_EFAULT;
4800 }
4801 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4802 unlock_user(argptr, arg, 0);
4803 fm = (struct fiemap *)buf_temp;
4804 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4805 return -TARGET_EINVAL;
4806 }
4807
4808 outbufsz = sizeof (*fm) +
4809 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4810
4811 if (outbufsz > MAX_STRUCT_SIZE) {
4812 /* We can't fit all the extents into the fixed size buffer.
4813 * Allocate one that is large enough and use it instead.
4814 */
0e173b24 4815 fm = g_try_malloc(outbufsz);
285da2b9
PM
4816 if (!fm) {
4817 return -TARGET_ENOMEM;
4818 }
4819 memcpy(fm, buf_temp, sizeof(struct fiemap));
4820 free_fm = 1;
4821 }
49ca6f3e 4822 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
285da2b9
PM
4823 if (!is_error(ret)) {
4824 target_size_out = target_size_in;
4825 /* An extent_count of 0 means we were only counting the extents
4826 * so there are no structs to copy
4827 */
4828 if (fm->fm_extent_count != 0) {
4829 target_size_out += fm->fm_mapped_extents * extent_size;
4830 }
4831 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4832 if (!argptr) {
4833 ret = -TARGET_EFAULT;
4834 } else {
4835 /* Convert the struct fiemap */
4836 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4837 if (fm->fm_extent_count != 0) {
4838 p = argptr + target_size_in;
4839 /* ...and then all the struct fiemap_extents */
4840 for (i = 0; i < fm->fm_mapped_extents; i++) {
4841 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4842 THUNK_TARGET);
4843 p += extent_size;
4844 }
4845 }
4846 unlock_user(argptr, arg, target_size_out);
4847 }
4848 }
4849 if (free_fm) {
0e173b24 4850 g_free(fm);
285da2b9
PM
4851 }
4852 return ret;
4853}
dace20dc 4854#endif
285da2b9 4855
059c2f2c 4856static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4857 int fd, int cmd, abi_long arg)
059c2f2c
LV
4858{
4859 const argtype *arg_type = ie->arg_type;
4860 int target_size;
4861 void *argptr;
4862 int ret;
4863 struct ifconf *host_ifconf;
4864 uint32_t outbufsz;
4865 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
4df7b7fa 4866 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
059c2f2c
LV
4867 int target_ifreq_size;
4868 int nb_ifreq;
4869 int free_buf = 0;
4870 int i;
4871 int target_ifc_len;
4872 abi_long target_ifc_buf;
4873 int host_ifc_len;
4874 char *host_ifc_buf;
4875
4876 assert(arg_type[0] == TYPE_PTR);
4877 assert(ie->access == IOC_RW);
4878
4879 arg_type++;
4880 target_size = thunk_type_size(arg_type, 0);
4881
4882 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4883 if (!argptr)
4884 return -TARGET_EFAULT;
4885 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4886 unlock_user(argptr, arg, 0);
4887
4888 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
059c2f2c 4889 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
4df7b7fa 4890 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
059c2f2c 4891
22e4a267
KL
4892 if (target_ifc_buf != 0) {
4893 target_ifc_len = host_ifconf->ifc_len;
4894 nb_ifreq = target_ifc_len / target_ifreq_size;
4895 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4896
4897 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4898 if (outbufsz > MAX_STRUCT_SIZE) {
4899 /*
4900 * We can't fit all the extents into the fixed size buffer.
4901 * Allocate one that is large enough and use it instead.
4902 */
7a5626a1 4903 host_ifconf = g_try_malloc(outbufsz);
22e4a267
KL
4904 if (!host_ifconf) {
4905 return -TARGET_ENOMEM;
4906 }
4907 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4908 free_buf = 1;
059c2f2c 4909 }
22e4a267 4910 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
059c2f2c 4911
22e4a267
KL
4912 host_ifconf->ifc_len = host_ifc_len;
4913 } else {
4914 host_ifc_buf = NULL;
4915 }
059c2f2c
LV
4916 host_ifconf->ifc_buf = host_ifc_buf;
4917
49ca6f3e 4918 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
059c2f2c
LV
4919 if (!is_error(ret)) {
4920 /* convert host ifc_len to target ifc_len */
4921
4922 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4923 target_ifc_len = nb_ifreq * target_ifreq_size;
4924 host_ifconf->ifc_len = target_ifc_len;
4925
4926 /* restore target ifc_buf */
4927
4928 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4929
4930 /* copy struct ifconf to target user */
4931
4932 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4933 if (!argptr)
4934 return -TARGET_EFAULT;
4935 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4936 unlock_user(argptr, arg, target_size);
4937
22e4a267
KL
4938 if (target_ifc_buf != 0) {
4939 /* copy ifreq[] to target user */
4940 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4941 for (i = 0; i < nb_ifreq ; i++) {
4942 thunk_convert(argptr + i * target_ifreq_size,
4943 host_ifc_buf + i * sizeof(struct ifreq),
4944 ifreq_arg_type, THUNK_TARGET);
4945 }
4946 unlock_user(argptr, target_ifc_buf, target_ifc_len);
059c2f2c 4947 }
059c2f2c
LV
4948 }
4949
4950 if (free_buf) {
7a5626a1 4951 g_free(host_ifconf);
059c2f2c
LV
4952 }
4953
4954 return ret;
4955}
4956
a133367e
CT
4957#if defined(CONFIG_USBFS)
4958#if HOST_LONG_BITS > 64
4959#error USBDEVFS thunks do not support >64 bit hosts yet.
4960#endif
4961struct live_urb {
4962 uint64_t target_urb_adr;
4963 uint64_t target_buf_adr;
4964 char *target_buf_ptr;
4965 struct usbdevfs_urb host_urb;
4966};
4967
4968static GHashTable *usbdevfs_urb_hashtable(void)
4969{
4970 static GHashTable *urb_hashtable;
4971
4972 if (!urb_hashtable) {
4973 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4974 }
4975 return urb_hashtable;
4976}
4977
4978static void urb_hashtable_insert(struct live_urb *urb)
4979{
4980 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4981 g_hash_table_insert(urb_hashtable, urb, urb);
4982}
4983
4984static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4985{
4986 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4987 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4988}
4989
4990static void urb_hashtable_remove(struct live_urb *urb)
4991{
4992 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4993 g_hash_table_remove(urb_hashtable, urb);
4994}
4995
4996static abi_long
4997do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4998 int fd, int cmd, abi_long arg)
4999{
5000 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
5001 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
5002 struct live_urb *lurb;
5003 void *argptr;
5004 uint64_t hurb;
5005 int target_size;
5006 uintptr_t target_urb_adr;
5007 abi_long ret;
5008
5009 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
5010
5011 memset(buf_temp, 0, sizeof(uint64_t));
5012 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5013 if (is_error(ret)) {
5014 return ret;
5015 }
5016
5017 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5018 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5019 if (!lurb->target_urb_adr) {
5020 return -TARGET_EFAULT;
5021 }
5022 urb_hashtable_remove(lurb);
5023 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5024 lurb->host_urb.buffer_length);
5025 lurb->target_buf_ptr = NULL;
5026
5027 /* restore the guest buffer pointer */
5028 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5029
5030 /* update the guest urb struct */
5031 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5032 if (!argptr) {
5033 g_free(lurb);
5034 return -TARGET_EFAULT;
5035 }
5036 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5037 unlock_user(argptr, lurb->target_urb_adr, target_size);
5038
5039 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5040 /* write back the urb handle */
5041 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5042 if (!argptr) {
5043 g_free(lurb);
5044 return -TARGET_EFAULT;
5045 }
5046
5047 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5048 target_urb_adr = lurb->target_urb_adr;
5049 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5050 unlock_user(argptr, arg, target_size);
5051
5052 g_free(lurb);
5053 return ret;
5054}
5055
5056static abi_long
5057do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5058 uint8_t *buf_temp __attribute__((unused)),
5059 int fd, int cmd, abi_long arg)
5060{
5061 struct live_urb *lurb;
5062
5063 /* map target address back to host URB with metadata. */
5064 lurb = urb_hashtable_lookup(arg);
5065 if (!lurb) {
5066 return -TARGET_EFAULT;
5067 }
5068 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5069}
5070
5071static abi_long
5072do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5073 int fd, int cmd, abi_long arg)
5074{
5075 const argtype *arg_type = ie->arg_type;
5076 int target_size;
5077 abi_long ret;
5078 void *argptr;
5079 int rw_dir;
5080 struct live_urb *lurb;
5081
5082 /*
5083 * each submitted URB needs to map to a unique ID for the
5084 * kernel, and that unique ID needs to be a pointer to
5085 * host memory. hence, we need to malloc for each URB.
5086 * isochronous transfers have a variable length struct.
5087 */
5088 arg_type++;
5089 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5090
5091 /* construct host copy of urb and metadata */
b21e2380 5092 lurb = g_try_new0(struct live_urb, 1);
a133367e
CT
5093 if (!lurb) {
5094 return -TARGET_ENOMEM;
5095 }
5096
5097 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5098 if (!argptr) {
5099 g_free(lurb);
5100 return -TARGET_EFAULT;
5101 }
5102 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5103 unlock_user(argptr, arg, 0);
5104
5105 lurb->target_urb_adr = arg;
5106 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5107
5108 /* buffer space used depends on endpoint type so lock the entire buffer */
5109 /* control type urbs should check the buffer contents for true direction */
5110 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5111 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5112 lurb->host_urb.buffer_length, 1);
5113 if (lurb->target_buf_ptr == NULL) {
5114 g_free(lurb);
5115 return -TARGET_EFAULT;
5116 }
5117
5118 /* update buffer pointer in host copy */
5119 lurb->host_urb.buffer = lurb->target_buf_ptr;
5120
5121 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5122 if (is_error(ret)) {
5123 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5124 g_free(lurb);
5125 } else {
5126 urb_hashtable_insert(lurb);
5127 }
5128
5129 return ret;
5130}
5131#endif /* CONFIG_USBFS */
5132
56e904ec 5133static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5134 int cmd, abi_long arg)
56e904ec
AG
5135{
5136 void *argptr;
5137 struct dm_ioctl *host_dm;
5138 abi_long guest_data;
5139 uint32_t guest_data_size;
5140 int target_size;
5141 const argtype *arg_type = ie->arg_type;
5142 abi_long ret;
5143 void *big_buf = NULL;
5144 char *host_data;
5145
5146 arg_type++;
5147 target_size = thunk_type_size(arg_type, 0);
5148 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5149 if (!argptr) {
5150 ret = -TARGET_EFAULT;
5151 goto out;
5152 }
5153 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5154 unlock_user(argptr, arg, 0);
5155
5156 /* buf_temp is too small, so fetch things into a bigger buffer */
5157 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5158 memcpy(big_buf, buf_temp, target_size);
5159 buf_temp = big_buf;
5160 host_dm = big_buf;
5161
5162 guest_data = arg + host_dm->data_start;
5163 if ((guest_data - arg) < 0) {
f9757b1d 5164 ret = -TARGET_EINVAL;
56e904ec
AG
5165 goto out;
5166 }
5167 guest_data_size = host_dm->data_size - host_dm->data_start;
5168 host_data = (char*)host_dm + host_dm->data_start;
5169
5170 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3211215e
PM
5171 if (!argptr) {
5172 ret = -TARGET_EFAULT;
5173 goto out;
5174 }
5175
56e904ec
AG
5176 switch (ie->host_cmd) {
5177 case DM_REMOVE_ALL:
5178 case DM_LIST_DEVICES:
5179 case DM_DEV_CREATE:
5180 case DM_DEV_REMOVE:
5181 case DM_DEV_SUSPEND:
5182 case DM_DEV_STATUS:
5183 case DM_DEV_WAIT:
5184 case DM_TABLE_STATUS:
5185 case DM_TABLE_CLEAR:
5186 case DM_TABLE_DEPS:
5187 case DM_LIST_VERSIONS:
5188 /* no input data */
5189 break;
5190 case DM_DEV_RENAME:
5191 case DM_DEV_SET_GEOMETRY:
5192 /* data contains only strings */
5193 memcpy(host_data, argptr, guest_data_size);
5194 break;
5195 case DM_TARGET_MSG:
5196 memcpy(host_data, argptr, guest_data_size);
5197 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5198 break;
5199 case DM_TABLE_LOAD:
5200 {
5201 void *gspec = argptr;
5202 void *cur_data = host_data;
5203 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5204 int spec_size = thunk_type_size(arg_type, 0);
5205 int i;
5206
5207 for (i = 0; i < host_dm->target_count; i++) {
5208 struct dm_target_spec *spec = cur_data;
5209 uint32_t next;
5210 int slen;
5211
5212 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5213 slen = strlen((char*)gspec + spec_size) + 1;
5214 next = spec->next;
5215 spec->next = sizeof(*spec) + slen;
5216 strcpy((char*)&spec[1], gspec + spec_size);
5217 gspec += next;
5218 cur_data += spec->next;
5219 }
5220 break;
5221 }
5222 default:
5223 ret = -TARGET_EINVAL;
dec0473d 5224 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5225 goto out;
5226 }
5227 unlock_user(argptr, guest_data, 0);
5228
49ca6f3e 5229 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
56e904ec
AG
5230 if (!is_error(ret)) {
5231 guest_data = arg + host_dm->data_start;
5232 guest_data_size = host_dm->data_size - host_dm->data_start;
5233 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5234 switch (ie->host_cmd) {
5235 case DM_REMOVE_ALL:
5236 case DM_DEV_CREATE:
5237 case DM_DEV_REMOVE:
5238 case DM_DEV_RENAME:
5239 case DM_DEV_SUSPEND:
5240 case DM_DEV_STATUS:
5241 case DM_TABLE_LOAD:
5242 case DM_TABLE_CLEAR:
5243 case DM_TARGET_MSG:
5244 case DM_DEV_SET_GEOMETRY:
5245 /* no return data */
5246 break;
5247 case DM_LIST_DEVICES:
5248 {
5249 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5250 uint32_t remaining_data = guest_data_size;
5251 void *cur_data = argptr;
5252 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5253 int nl_size = 12; /* can't use thunk_size due to alignment */
5254
5255 while (1) {
5256 uint32_t next = nl->next;
5257 if (next) {
5258 nl->next = nl_size + (strlen(nl->name) + 1);
5259 }
5260 if (remaining_data < nl->next) {
5261 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5262 break;
5263 }
5264 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5265 strcpy(cur_data + nl_size, nl->name);
5266 cur_data += nl->next;
5267 remaining_data -= nl->next;
5268 if (!next) {
5269 break;
5270 }
5271 nl = (void*)nl + next;
5272 }
5273 break;
5274 }
5275 case DM_DEV_WAIT:
5276 case DM_TABLE_STATUS:
5277 {
5278 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5279 void *cur_data = argptr;
5280 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5281 int spec_size = thunk_type_size(arg_type, 0);
5282 int i;
5283
5284 for (i = 0; i < host_dm->target_count; i++) {
5285 uint32_t next = spec->next;
5286 int slen = strlen((char*)&spec[1]) + 1;
5287 spec->next = (cur_data - argptr) + spec_size + slen;
5288 if (guest_data_size < spec->next) {
5289 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5290 break;
5291 }
5292 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5293 strcpy(cur_data + spec_size, (char*)&spec[1]);
5294 cur_data = argptr + spec->next;
5295 spec = (void*)host_dm + host_dm->data_start + next;
5296 }
5297 break;
5298 }
5299 case DM_TABLE_DEPS:
5300 {
5301 void *hdata = (void*)host_dm + host_dm->data_start;
5302 int count = *(uint32_t*)hdata;
5303 uint64_t *hdev = hdata + 8;
5304 uint64_t *gdev = argptr + 8;
5305 int i;
5306
5307 *(uint32_t*)argptr = tswap32(count);
5308 for (i = 0; i < count; i++) {
5309 *gdev = tswap64(*hdev);
5310 gdev++;
5311 hdev++;
5312 }
5313 break;
5314 }
5315 case DM_LIST_VERSIONS:
5316 {
5317 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5318 uint32_t remaining_data = guest_data_size;
5319 void *cur_data = argptr;
5320 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5321 int vers_size = thunk_type_size(arg_type, 0);
5322
5323 while (1) {
5324 uint32_t next = vers->next;
5325 if (next) {
5326 vers->next = vers_size + (strlen(vers->name) + 1);
5327 }
5328 if (remaining_data < vers->next) {
5329 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5330 break;
5331 }
5332 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5333 strcpy(cur_data + vers_size, vers->name);
5334 cur_data += vers->next;
5335 remaining_data -= vers->next;
5336 if (!next) {
5337 break;
5338 }
5339 vers = (void*)vers + next;
5340 }
5341 break;
5342 }
5343 default:
dec0473d 5344 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5345 ret = -TARGET_EINVAL;
5346 goto out;
5347 }
5348 unlock_user(argptr, guest_data, guest_data_size);
5349
5350 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5351 if (!argptr) {
5352 ret = -TARGET_EFAULT;
5353 goto out;
5354 }
5355 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5356 unlock_user(argptr, arg, target_size);
5357 }
5358out:
ad11ad77 5359 g_free(big_buf);
56e904ec
AG
5360 return ret;
5361}
5362
a59b5e35 5363static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5364 int cmd, abi_long arg)
a59b5e35
AG
5365{
5366 void *argptr;
5367 int target_size;
5368 const argtype *arg_type = ie->arg_type;
5369 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5370 abi_long ret;
5371
5372 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5373 struct blkpg_partition host_part;
5374
5375 /* Read and convert blkpg */
5376 arg_type++;
5377 target_size = thunk_type_size(arg_type, 0);
5378 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5379 if (!argptr) {
5380 ret = -TARGET_EFAULT;
5381 goto out;
5382 }
5383 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5384 unlock_user(argptr, arg, 0);
5385
5386 switch (host_blkpg->op) {
5387 case BLKPG_ADD_PARTITION:
5388 case BLKPG_DEL_PARTITION:
5389 /* payload is struct blkpg_partition */
5390 break;
5391 default:
5392 /* Unknown opcode */
5393 ret = -TARGET_EINVAL;
5394 goto out;
5395 }
5396
5397 /* Read and convert blkpg->data */
5398 arg = (abi_long)(uintptr_t)host_blkpg->data;
5399 target_size = thunk_type_size(part_arg_type, 0);
5400 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5401 if (!argptr) {
5402 ret = -TARGET_EFAULT;
5403 goto out;
5404 }
5405 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5406 unlock_user(argptr, arg, 0);
5407
5408 /* Swizzle the data pointer to our local copy and call! */
5409 host_blkpg->data = &host_part;
49ca6f3e 5410 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
a59b5e35
AG
5411
5412out:
5413 return ret;
5414}
5415
7ff7b666 5416static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5417 int fd, int cmd, abi_long arg)
7ff7b666
LV
5418{
5419 const argtype *arg_type = ie->arg_type;
5420 const StructEntry *se;
5421 const argtype *field_types;
5422 const int *dst_offsets, *src_offsets;
5423 int target_size;
5424 void *argptr;
b78c522a
MAL
5425 abi_ulong *target_rt_dev_ptr = NULL;
5426 unsigned long *host_rt_dev_ptr = NULL;
7ff7b666
LV
5427 abi_long ret;
5428 int i;
5429
5430 assert(ie->access == IOC_W);
5431 assert(*arg_type == TYPE_PTR);
5432 arg_type++;
5433 assert(*arg_type == TYPE_STRUCT);
5434 target_size = thunk_type_size(arg_type, 0);
5435 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5436 if (!argptr) {
5437 return -TARGET_EFAULT;
5438 }
5439 arg_type++;
5440 assert(*arg_type == (int)STRUCT_rtentry);
5441 se = struct_entries + *arg_type++;
5442 assert(se->convert[0] == NULL);
5443 /* convert struct here to be able to catch rt_dev string */
5444 field_types = se->field_types;
5445 dst_offsets = se->field_offsets[THUNK_HOST];
5446 src_offsets = se->field_offsets[THUNK_TARGET];
5447 for (i = 0; i < se->nb_fields; i++) {
5448 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5449 assert(*field_types == TYPE_PTRVOID);
3d558330 5450 target_rt_dev_ptr = argptr + src_offsets[i];
7ff7b666
LV
5451 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5452 if (*target_rt_dev_ptr != 0) {
5453 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5454 tswapal(*target_rt_dev_ptr));
5455 if (!*host_rt_dev_ptr) {
5456 unlock_user(argptr, arg, 0);
5457 return -TARGET_EFAULT;
5458 }
5459 } else {
5460 *host_rt_dev_ptr = 0;
5461 }
5462 field_types++;
5463 continue;
5464 }
5465 field_types = thunk_convert(buf_temp + dst_offsets[i],
5466 argptr + src_offsets[i],
5467 field_types, THUNK_HOST);
5468 }
5469 unlock_user(argptr, arg, 0);
5470
49ca6f3e 5471 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
b78c522a
MAL
5472
5473 assert(host_rt_dev_ptr != NULL);
5474 assert(target_rt_dev_ptr != NULL);
7ff7b666
LV
5475 if (*host_rt_dev_ptr != 0) {
5476 unlock_user((void *)*host_rt_dev_ptr,
5477 *target_rt_dev_ptr, 0);
5478 }
5479 return ret;
5480}
5481
ca56f5b5 5482static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5483 int fd, int cmd, abi_long arg)
ca56f5b5
PB
5484{
5485 int sig = target_to_host_signal(arg);
49ca6f3e 5486 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
ca56f5b5
PB
5487}
5488
6d5d5dde
DB
5489static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5490 int fd, int cmd, abi_long arg)
5491{
5492 struct timeval tv;
5493 abi_long ret;
5494
5495 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5496 if (is_error(ret)) {
5497 return ret;
5498 }
5499
5500 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5501 if (copy_to_user_timeval(arg, &tv)) {
5502 return -TARGET_EFAULT;
5503 }
5504 } else {
5505 if (copy_to_user_timeval64(arg, &tv)) {
5506 return -TARGET_EFAULT;
5507 }
5508 }
5509
5510 return ret;
5511}
5512
5513static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5514 int fd, int cmd, abi_long arg)
5515{
5516 struct timespec ts;
5517 abi_long ret;
5518
5519 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5520 if (is_error(ret)) {
5521 return ret;
5522 }
5523
5524 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5525 if (host_to_target_timespec(arg, &ts)) {
5526 return -TARGET_EFAULT;
5527 }
5528 } else{
5529 if (host_to_target_timespec64(arg, &ts)) {
5530 return -TARGET_EFAULT;
5531 }
5532 }
5533
5534 return ret;
5535}
5536
2b74f621
AS
5537#ifdef TIOCGPTPEER
5538static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5539 int fd, int cmd, abi_long arg)
5540{
5541 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5542 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5543}
5544#endif
5545
e865b97f
CG
5546#ifdef HAVE_DRM_H
5547
5548static void unlock_drm_version(struct drm_version *host_ver,
5549 struct target_drm_version *target_ver,
5550 bool copy)
5551{
5552 unlock_user(host_ver->name, target_ver->name,
5553 copy ? host_ver->name_len : 0);
5554 unlock_user(host_ver->date, target_ver->date,
5555 copy ? host_ver->date_len : 0);
5556 unlock_user(host_ver->desc, target_ver->desc,
5557 copy ? host_ver->desc_len : 0);
5558}
5559
5560static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5561 struct target_drm_version *target_ver)
5562{
5563 memset(host_ver, 0, sizeof(*host_ver));
5564
5565 __get_user(host_ver->name_len, &target_ver->name_len);
5566 if (host_ver->name_len) {
5567 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5568 target_ver->name_len, 0);
5569 if (!host_ver->name) {
5570 return -EFAULT;
5571 }
5572 }
5573
5574 __get_user(host_ver->date_len, &target_ver->date_len);
5575 if (host_ver->date_len) {
5576 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5577 target_ver->date_len, 0);
5578 if (!host_ver->date) {
5579 goto err;
5580 }
5581 }
5582
5583 __get_user(host_ver->desc_len, &target_ver->desc_len);
5584 if (host_ver->desc_len) {
5585 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5586 target_ver->desc_len, 0);
5587 if (!host_ver->desc) {
5588 goto err;
5589 }
5590 }
5591
5592 return 0;
5593err:
5594 unlock_drm_version(host_ver, target_ver, false);
5595 return -EFAULT;
5596}
5597
5598static inline void host_to_target_drmversion(
5599 struct target_drm_version *target_ver,
5600 struct drm_version *host_ver)
5601{
5602 __put_user(host_ver->version_major, &target_ver->version_major);
5603 __put_user(host_ver->version_minor, &target_ver->version_minor);
5604 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5605 __put_user(host_ver->name_len, &target_ver->name_len);
5606 __put_user(host_ver->date_len, &target_ver->date_len);
5607 __put_user(host_ver->desc_len, &target_ver->desc_len);
5608 unlock_drm_version(host_ver, target_ver, true);
5609}
5610
5611static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5612 int fd, int cmd, abi_long arg)
5613{
5614 struct drm_version *ver;
5615 struct target_drm_version *target_ver;
5616 abi_long ret;
5617
5618 switch (ie->host_cmd) {
5619 case DRM_IOCTL_VERSION:
5620 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5621 return -TARGET_EFAULT;
5622 }
5623 ver = (struct drm_version *)buf_temp;
5624 ret = target_to_host_drmversion(ver, target_ver);
5625 if (!is_error(ret)) {
5626 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5627 if (is_error(ret)) {
5628 unlock_drm_version(ver, target_ver, false);
5629 } else {
5630 host_to_target_drmversion(target_ver, ver);
5631 }
5632 }
5633 unlock_user_struct(target_ver, arg, 0);
5634 return ret;
5635 }
5636 return -TARGET_ENOSYS;
5637}
5638
913b03c2
CG
5639static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5640 struct drm_i915_getparam *gparam,
5641 int fd, abi_long arg)
5642{
5643 abi_long ret;
5644 int value;
5645 struct target_drm_i915_getparam *target_gparam;
5646
5647 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5648 return -TARGET_EFAULT;
5649 }
5650
5651 __get_user(gparam->param, &target_gparam->param);
5652 gparam->value = &value;
5653 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5654 put_user_s32(value, target_gparam->value);
5655
5656 unlock_user_struct(target_gparam, arg, 0);
5657 return ret;
5658}
5659
5660static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5661 int fd, int cmd, abi_long arg)
5662{
5663 switch (ie->host_cmd) {
5664 case DRM_IOCTL_I915_GETPARAM:
5665 return do_ioctl_drm_i915_getparam(ie,
5666 (struct drm_i915_getparam *)buf_temp,
5667 fd, arg);
5668 default:
5669 return -TARGET_ENOSYS;
5670 }
5671}
5672
e865b97f
CG
5673#endif
5674
6addf06a
SCW
5675static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5676 int fd, int cmd, abi_long arg)
5677{
5678 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5679 struct tun_filter *target_filter;
5680 char *target_addr;
5681
5682 assert(ie->access == IOC_W);
5683
5684 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5685 if (!target_filter) {
5686 return -TARGET_EFAULT;
5687 }
5688 filter->flags = tswap16(target_filter->flags);
5689 filter->count = tswap16(target_filter->count);
5690 unlock_user(target_filter, arg, 0);
5691
5692 if (filter->count) {
5693 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5694 MAX_STRUCT_SIZE) {
5695 return -TARGET_EFAULT;
5696 }
5697
5698 target_addr = lock_user(VERIFY_READ,
5699 arg + offsetof(struct tun_filter, addr),
5700 filter->count * ETH_ALEN, 1);
5701 if (!target_addr) {
5702 return -TARGET_EFAULT;
5703 }
5704 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5705 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5706 }
5707
5708 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5709}
5710
79482e59 5711IOCTLEntry ioctl_entries[] = {
001faf32 5712#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
5713 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5714#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5715 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
8cb762fe
HD
5716#define IOCTL_IGNORE(cmd) \
5717 { TARGET_ ## cmd, 0, #cmd },
31e31b8a
FB
5718#include "ioctls.h"
5719 { 0, 0, },
5720};
5721
53a5960a 5722/* ??? Implement proper locking for ioctls. */
0da46a6e 5723/* do_ioctl() Must return target values and target errnos. */
45c874eb 5724static abi_long do_ioctl(int fd, int cmd, abi_long arg)
31e31b8a
FB
5725{
5726 const IOCTLEntry *ie;
5727 const argtype *arg_type;
992f48a0 5728 abi_long ret;
31e31b8a 5729 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
5730 int target_size;
5731 void *argptr;
31e31b8a
FB
5732
5733 ie = ioctl_entries;
5734 for(;;) {
5735 if (ie->target_cmd == 0) {
39be5350
JK
5736 qemu_log_mask(
5737 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 5738 return -TARGET_ENOSYS;
31e31b8a
FB
5739 }
5740 if (ie->target_cmd == cmd)
5741 break;
5742 ie++;
5743 }
5744 arg_type = ie->arg_type;
d2ef05bb
PM
5745 if (ie->do_ioctl) {
5746 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
8cb762fe
HD
5747 } else if (!ie->host_cmd) {
5748 /* Some architectures define BSD ioctls in their headers
5749 that are not implemented in Linux. */
5750 return -TARGET_ENOSYS;
d2ef05bb
PM
5751 }
5752
31e31b8a
FB
5753 switch(arg_type[0]) {
5754 case TYPE_NULL:
5755 /* no argument */
49ca6f3e 5756 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
31e31b8a
FB
5757 break;
5758 case TYPE_PTRVOID:
5759 case TYPE_INT:
c858e537
FB
5760 case TYPE_LONG:
5761 case TYPE_ULONG:
49ca6f3e 5762 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
31e31b8a
FB
5763 break;
5764 case TYPE_PTR:
5765 arg_type++;
53a5960a 5766 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
5767 switch(ie->access) {
5768 case IOC_R:
49ca6f3e 5769 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5770 if (!is_error(ret)) {
579a97f7
FB
5771 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5772 if (!argptr)
5773 return -TARGET_EFAULT;
53a5960a
PB
5774 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5775 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5776 }
5777 break;
5778 case IOC_W:
579a97f7
FB
5779 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5780 if (!argptr)
5781 return -TARGET_EFAULT;
53a5960a
PB
5782 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5783 unlock_user(argptr, arg, 0);
49ca6f3e 5784 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a
FB
5785 break;
5786 default:
5787 case IOC_RW:
579a97f7
FB
5788 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5789 if (!argptr)
5790 return -TARGET_EFAULT;
53a5960a
PB
5791 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5792 unlock_user(argptr, arg, 0);
49ca6f3e 5793 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5794 if (!is_error(ret)) {
579a97f7
FB
5795 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5796 if (!argptr)
5797 return -TARGET_EFAULT;
53a5960a
PB
5798 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5799 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5800 }
5801 break;
5802 }
5803 break;
5804 default:
39be5350
JK
5805 qemu_log_mask(LOG_UNIMP,
5806 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5807 (long)cmd, arg_type[0]);
0da46a6e 5808 ret = -TARGET_ENOSYS;
31e31b8a
FB
5809 break;
5810 }
5811 return ret;
5812}
5813
b39bc503 5814static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
5815 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5816 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5817 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5818 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5819 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5820 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5821 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5822 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5823 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5824 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5825 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5826 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5827 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5828 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
c218b4ed 5829 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
31e31b8a
FB
5830 { 0, 0, 0, 0 }
5831};
5832
b39bc503 5833static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
5834 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5835 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5836 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5837 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5838 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5839 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5840 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5841 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5842 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5843 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5844 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5845 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5846 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5847 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5848 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5849 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5850 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5851 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5852 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5853 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5854 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5855 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5856 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5857 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5858 { 0, 0, 0, 0 }
5859};
5860
b39bc503 5861static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
5862 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5863 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5864 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5865 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5866 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5867 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5868 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5869 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5870 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5871 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5872 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5873 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5874 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5875 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5876 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5877 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5878 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5879 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5880 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5881 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5882 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5883 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5884 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5885 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5886 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5887 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5888 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5889 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5890 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5891 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5892 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5893 { 0, 0, 0, 0 }
5894};
5895
b39bc503 5896static const bitmask_transtbl lflag_tbl[] = {
c218b4ed
FB
5897 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5898 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5899 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5900 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5901 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5902 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5903 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5904 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5905 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5906 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5907 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5908 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5909 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5910 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5911 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5912 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5913 { 0, 0, 0, 0 }
31e31b8a
FB
5914};
5915
5916static void target_to_host_termios (void *dst, const void *src)
5917{
5918 struct host_termios *host = dst;
5919 const struct target_termios *target = src;
3b46e624 5920
5fafdf24 5921 host->c_iflag =
31e31b8a 5922 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 5923 host->c_oflag =
31e31b8a 5924 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 5925 host->c_cflag =
31e31b8a 5926 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 5927 host->c_lflag =
31e31b8a
FB
5928 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5929 host->c_line = target->c_line;
3b46e624 5930
44607123 5931 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
5932 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5933 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 5934 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 5935 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 5936 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 5937 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 5938 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 5939 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 5940 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
5941 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5942 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
5943 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5944 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5945 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5946 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5947 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 5948 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 5949}
3b46e624 5950
31e31b8a
FB
5951static void host_to_target_termios (void *dst, const void *src)
5952{
5953 struct target_termios *target = dst;
5954 const struct host_termios *host = src;
5955
5fafdf24 5956 target->c_iflag =
31e31b8a 5957 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 5958 target->c_oflag =
31e31b8a 5959 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 5960 target->c_cflag =
31e31b8a 5961 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 5962 target->c_lflag =
31e31b8a
FB
5963 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5964 target->c_line = host->c_line;
3b46e624 5965
44607123 5966 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
5967 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5968 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5969 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5970 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5971 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5972 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5973 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5974 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5975 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5976 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5977 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5978 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5979 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5980 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5981 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5982 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5983 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5984}
5985
8e853dc7 5986static const StructEntry struct_termios_def = {
31e31b8a
FB
5987 .convert = { host_to_target_termios, target_to_host_termios },
5988 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5989 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
888468db 5990 .print = print_termios,
31e31b8a
FB
5991};
5992
180d4ef3 5993static const bitmask_transtbl mmap_flags_tbl[] = {
541e1690
HD
5994 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5995 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5996 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5997 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5998 MAP_ANONYMOUS, MAP_ANONYMOUS },
5999 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
6000 MAP_GROWSDOWN, MAP_GROWSDOWN },
6001 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
6002 MAP_DENYWRITE, MAP_DENYWRITE },
6003 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
6004 MAP_EXECUTABLE, MAP_EXECUTABLE },
6005 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
6006 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
6007 MAP_NORESERVE, MAP_NORESERVE },
6008 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
6009 /* MAP_STACK had been ignored by the kernel for quite some time.
6010 Recognize it for the target insofar as we do not want to pass
6011 it through to the host. */
6012 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6013 { 0, 0, 0, 0 }
5286db75
FB
6014};
6015
9d12f79d
LV
6016/*
6017 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6018 * TARGET_I386 is defined if TARGET_X86_64 is defined
6019 */
2ab83ea7 6020#if defined(TARGET_I386)
6dbad63e
FB
6021
6022/* NOTE: there is really one LDT for all the threads */
b1d8e52e 6023static uint8_t *ldt_table;
6dbad63e 6024
03acab66 6025static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
6026{
6027 int size;
53a5960a 6028 void *p;
6dbad63e
FB
6029
6030 if (!ldt_table)
6031 return 0;
6032 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6033 if (size > bytecount)
6034 size = bytecount;
579a97f7
FB
6035 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6036 if (!p)
03acab66 6037 return -TARGET_EFAULT;
579a97f7 6038 /* ??? Should this by byteswapped? */
53a5960a
PB
6039 memcpy(p, ldt_table, size);
6040 unlock_user(p, ptr, size);
6dbad63e
FB
6041 return size;
6042}
6043
6044/* XXX: add locking support */
03acab66
FB
6045static abi_long write_ldt(CPUX86State *env,
6046 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
6047{
6048 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 6049 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 6050 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 6051 int seg_not_present, useable, lm;
6dbad63e
FB
6052 uint32_t *lp, entry_1, entry_2;
6053
6054 if (bytecount != sizeof(ldt_info))
03acab66 6055 return -TARGET_EINVAL;
579a97f7 6056 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 6057 return -TARGET_EFAULT;
53a5960a 6058 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6059 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
6060 ldt_info.limit = tswap32(target_ldt_info->limit);
6061 ldt_info.flags = tswap32(target_ldt_info->flags);
6062 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 6063
6dbad63e 6064 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 6065 return -TARGET_EINVAL;
6dbad63e
FB
6066 seg_32bit = ldt_info.flags & 1;
6067 contents = (ldt_info.flags >> 1) & 3;
6068 read_exec_only = (ldt_info.flags >> 3) & 1;
6069 limit_in_pages = (ldt_info.flags >> 4) & 1;
6070 seg_not_present = (ldt_info.flags >> 5) & 1;
6071 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
6072#ifdef TARGET_ABI32
6073 lm = 0;
6074#else
6075 lm = (ldt_info.flags >> 7) & 1;
6076#endif
6dbad63e
FB
6077 if (contents == 3) {
6078 if (oldmode)
03acab66 6079 return -TARGET_EINVAL;
6dbad63e 6080 if (seg_not_present == 0)
03acab66 6081 return -TARGET_EINVAL;
6dbad63e
FB
6082 }
6083 /* allocate the LDT */
6084 if (!ldt_table) {
e441570f
AZ
6085 env->ldt.base = target_mmap(0,
6086 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6087 PROT_READ|PROT_WRITE,
6088 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6089 if (env->ldt.base == -1)
03acab66 6090 return -TARGET_ENOMEM;
3e8f1628 6091 memset(g2h_untagged(env->ldt.base), 0,
e441570f 6092 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 6093 env->ldt.limit = 0xffff;
3e8f1628 6094 ldt_table = g2h_untagged(env->ldt.base);
6dbad63e
FB
6095 }
6096
6097 /* NOTE: same code as Linux kernel */
6098 /* Allow LDTs to be cleared by the user. */
6099 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6100 if (oldmode ||
6101 (contents == 0 &&
6102 read_exec_only == 1 &&
6103 seg_32bit == 0 &&
6104 limit_in_pages == 0 &&
6105 seg_not_present == 1 &&
6106 useable == 0 )) {
6107 entry_1 = 0;
6108 entry_2 = 0;
6109 goto install;
6110 }
6111 }
3b46e624 6112
6dbad63e
FB
6113 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6114 (ldt_info.limit & 0x0ffff);
6115 entry_2 = (ldt_info.base_addr & 0xff000000) |
6116 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6117 (ldt_info.limit & 0xf0000) |
6118 ((read_exec_only ^ 1) << 9) |
6119 (contents << 10) |
6120 ((seg_not_present ^ 1) << 15) |
6121 (seg_32bit << 22) |
6122 (limit_in_pages << 23) |
8d18e893 6123 (lm << 21) |
6dbad63e
FB
6124 0x7000;
6125 if (!oldmode)
6126 entry_2 |= (useable << 20);
14ae3ba7 6127
6dbad63e
FB
6128 /* Install the new entry ... */
6129install:
6130 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6131 lp[0] = tswap32(entry_1);
6132 lp[1] = tswap32(entry_2);
6133 return 0;
6134}
6135
6136/* specific and weird i386 syscalls */
8fcd3692
BS
6137static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6138 unsigned long bytecount)
6dbad63e 6139{
03acab66 6140 abi_long ret;
3b46e624 6141
6dbad63e
FB
6142 switch (func) {
6143 case 0:
6144 ret = read_ldt(ptr, bytecount);
6145 break;
6146 case 1:
6147 ret = write_ldt(env, ptr, bytecount, 1);
6148 break;
6149 case 0x11:
6150 ret = write_ldt(env, ptr, bytecount, 0);
6151 break;
03acab66
FB
6152 default:
6153 ret = -TARGET_ENOSYS;
6154 break;
6dbad63e
FB
6155 }
6156 return ret;
6157}
1b6b029e 6158
9d12f79d 6159#if defined(TARGET_ABI32)
bc22eb44 6160abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893 6161{
3e8f1628 6162 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6163 struct target_modify_ldt_ldt_s ldt_info;
6164 struct target_modify_ldt_ldt_s *target_ldt_info;
6165 int seg_32bit, contents, read_exec_only, limit_in_pages;
6166 int seg_not_present, useable, lm;
6167 uint32_t *lp, entry_1, entry_2;
6168 int i;
6169
6170 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6171 if (!target_ldt_info)
6172 return -TARGET_EFAULT;
6173 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6174 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
6175 ldt_info.limit = tswap32(target_ldt_info->limit);
6176 ldt_info.flags = tswap32(target_ldt_info->flags);
6177 if (ldt_info.entry_number == -1) {
6178 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6179 if (gdt_table[i] == 0) {
6180 ldt_info.entry_number = i;
6181 target_ldt_info->entry_number = tswap32(i);
6182 break;
6183 }
6184 }
6185 }
6186 unlock_user_struct(target_ldt_info, ptr, 1);
6187
6188 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6189 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6190 return -TARGET_EINVAL;
6191 seg_32bit = ldt_info.flags & 1;
6192 contents = (ldt_info.flags >> 1) & 3;
6193 read_exec_only = (ldt_info.flags >> 3) & 1;
6194 limit_in_pages = (ldt_info.flags >> 4) & 1;
6195 seg_not_present = (ldt_info.flags >> 5) & 1;
6196 useable = (ldt_info.flags >> 6) & 1;
6197#ifdef TARGET_ABI32
6198 lm = 0;
6199#else
6200 lm = (ldt_info.flags >> 7) & 1;
6201#endif
6202
6203 if (contents == 3) {
6204 if (seg_not_present == 0)
6205 return -TARGET_EINVAL;
6206 }
6207
6208 /* NOTE: same code as Linux kernel */
6209 /* Allow LDTs to be cleared by the user. */
6210 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6211 if ((contents == 0 &&
6212 read_exec_only == 1 &&
6213 seg_32bit == 0 &&
6214 limit_in_pages == 0 &&
6215 seg_not_present == 1 &&
6216 useable == 0 )) {
6217 entry_1 = 0;
6218 entry_2 = 0;
6219 goto install;
6220 }
6221 }
6222
6223 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6224 (ldt_info.limit & 0x0ffff);
6225 entry_2 = (ldt_info.base_addr & 0xff000000) |
6226 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6227 (ldt_info.limit & 0xf0000) |
6228 ((read_exec_only ^ 1) << 9) |
6229 (contents << 10) |
6230 ((seg_not_present ^ 1) << 15) |
6231 (seg_32bit << 22) |
6232 (limit_in_pages << 23) |
6233 (useable << 20) |
6234 (lm << 21) |
6235 0x7000;
6236
6237 /* Install the new entry ... */
6238install:
6239 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6240 lp[0] = tswap32(entry_1);
6241 lp[1] = tswap32(entry_2);
6242 return 0;
6243}
6244
8fcd3692 6245static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
6246{
6247 struct target_modify_ldt_ldt_s *target_ldt_info;
3e8f1628 6248 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6249 uint32_t base_addr, limit, flags;
6250 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6251 int seg_not_present, useable, lm;
6252 uint32_t *lp, entry_1, entry_2;
6253
6254 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6255 if (!target_ldt_info)
6256 return -TARGET_EFAULT;
6257 idx = tswap32(target_ldt_info->entry_number);
6258 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6259 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6260 unlock_user_struct(target_ldt_info, ptr, 1);
6261 return -TARGET_EINVAL;
6262 }
6263 lp = (uint32_t *)(gdt_table + idx);
6264 entry_1 = tswap32(lp[0]);
6265 entry_2 = tswap32(lp[1]);
6266
6267 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6268 contents = (entry_2 >> 10) & 3;
6269 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6270 seg_32bit = (entry_2 >> 22) & 1;
6271 limit_in_pages = (entry_2 >> 23) & 1;
6272 useable = (entry_2 >> 20) & 1;
6273#ifdef TARGET_ABI32
6274 lm = 0;
6275#else
6276 lm = (entry_2 >> 21) & 1;
6277#endif
6278 flags = (seg_32bit << 0) | (contents << 1) |
6279 (read_exec_only << 3) | (limit_in_pages << 4) |
6280 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6281 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6282 base_addr = (entry_1 >> 16) |
6283 (entry_2 & 0xff000000) |
6284 ((entry_2 & 0xff) << 16);
cbb21eed 6285 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
6286 target_ldt_info->limit = tswap32(limit);
6287 target_ldt_info->flags = tswap32(flags);
6288 unlock_user_struct(target_ldt_info, ptr, 1);
6289 return 0;
6290}
6291
9d12f79d
LV
6292abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6293{
538fabcb 6294 return -TARGET_ENOSYS;
9d12f79d
LV
6295}
6296#else
2667e71c 6297abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 6298{
1add8698 6299 abi_long ret = 0;
d2fd1af7
FB
6300 abi_ulong val;
6301 int idx;
1add8698 6302
d2fd1af7
FB
6303 switch(code) {
6304 case TARGET_ARCH_SET_GS:
6305 case TARGET_ARCH_SET_FS:
6306 if (code == TARGET_ARCH_SET_GS)
6307 idx = R_GS;
6308 else
6309 idx = R_FS;
6310 cpu_x86_load_seg(env, idx, 0);
6311 env->segs[idx].base = addr;
6312 break;
6313 case TARGET_ARCH_GET_GS:
6314 case TARGET_ARCH_GET_FS:
6315 if (code == TARGET_ARCH_GET_GS)
6316 idx = R_GS;
6317 else
6318 idx = R_FS;
6319 val = env->segs[idx].base;
6320 if (put_user(val, addr, abi_ulong))
1add8698 6321 ret = -TARGET_EFAULT;
d2fd1af7
FB
6322 break;
6323 default:
6324 ret = -TARGET_EINVAL;
6325 break;
6326 }
1add8698 6327 return ret;
d2fd1af7 6328}
9d12f79d 6329#endif /* defined(TARGET_ABI32 */
2ab83ea7
FB
6330#endif /* defined(TARGET_I386) */
6331
87e9bf23
RH
6332/*
6333 * These constants are generic. Supply any that are missing from the host.
6334 */
6335#ifndef PR_SET_NAME
6336# define PR_SET_NAME 15
6337# define PR_GET_NAME 16
6338#endif
6339#ifndef PR_SET_FP_MODE
6340# define PR_SET_FP_MODE 45
6341# define PR_GET_FP_MODE 46
6342# define PR_FP_MODE_FR (1 << 0)
6343# define PR_FP_MODE_FRE (1 << 1)
6344#endif
6345#ifndef PR_SVE_SET_VL
6346# define PR_SVE_SET_VL 50
6347# define PR_SVE_GET_VL 51
6348# define PR_SVE_VL_LEN_MASK 0xffff
6349# define PR_SVE_VL_INHERIT (1 << 17)
6350#endif
6351#ifndef PR_PAC_RESET_KEYS
6352# define PR_PAC_RESET_KEYS 54
6353# define PR_PAC_APIAKEY (1 << 0)
6354# define PR_PAC_APIBKEY (1 << 1)
6355# define PR_PAC_APDAKEY (1 << 2)
6356# define PR_PAC_APDBKEY (1 << 3)
6357# define PR_PAC_APGAKEY (1 << 4)
6358#endif
6359#ifndef PR_SET_TAGGED_ADDR_CTRL
6360# define PR_SET_TAGGED_ADDR_CTRL 55
6361# define PR_GET_TAGGED_ADDR_CTRL 56
6362# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6363#endif
6364#ifndef PR_MTE_TCF_SHIFT
6365# define PR_MTE_TCF_SHIFT 1
6366# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6367# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6368# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6369# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6370# define PR_MTE_TAG_SHIFT 3
6371# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6372#endif
220717a6
RH
6373#ifndef PR_SET_IO_FLUSHER
6374# define PR_SET_IO_FLUSHER 57
6375# define PR_GET_IO_FLUSHER 58
6376#endif
6377#ifndef PR_SET_SYSCALL_USER_DISPATCH
6378# define PR_SET_SYSCALL_USER_DISPATCH 59
6379#endif
24d87c18
RH
6380#ifndef PR_SME_SET_VL
6381# define PR_SME_SET_VL 63
6382# define PR_SME_GET_VL 64
6383# define PR_SME_VL_LEN_MASK 0xffff
6384# define PR_SME_VL_INHERIT (1 << 17)
6385#endif
87e9bf23
RH
6386
6387#include "target_prctl.h"
6388
6389static abi_long do_prctl_inval0(CPUArchState *env)
6390{
6391 return -TARGET_EINVAL;
6392}
6393
6394static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6395{
6396 return -TARGET_EINVAL;
6397}
6398
6399#ifndef do_prctl_get_fp_mode
6400#define do_prctl_get_fp_mode do_prctl_inval0
6401#endif
6402#ifndef do_prctl_set_fp_mode
6403#define do_prctl_set_fp_mode do_prctl_inval1
6404#endif
fd72f5d0
RH
6405#ifndef do_prctl_sve_get_vl
6406#define do_prctl_sve_get_vl do_prctl_inval0
87e9bf23 6407#endif
fd72f5d0
RH
6408#ifndef do_prctl_sve_set_vl
6409#define do_prctl_sve_set_vl do_prctl_inval1
87e9bf23
RH
6410#endif
6411#ifndef do_prctl_reset_keys
6412#define do_prctl_reset_keys do_prctl_inval1
6413#endif
6414#ifndef do_prctl_set_tagged_addr_ctrl
6415#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6416#endif
6417#ifndef do_prctl_get_tagged_addr_ctrl
6418#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6419#endif
6e8dcacd
RH
6420#ifndef do_prctl_get_unalign
6421#define do_prctl_get_unalign do_prctl_inval1
6422#endif
6423#ifndef do_prctl_set_unalign
6424#define do_prctl_set_unalign do_prctl_inval1
6425#endif
24d87c18
RH
6426#ifndef do_prctl_sme_get_vl
6427#define do_prctl_sme_get_vl do_prctl_inval0
6428#endif
6429#ifndef do_prctl_sme_set_vl
6430#define do_prctl_sme_set_vl do_prctl_inval1
6431#endif
87e9bf23
RH
6432
6433static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6434 abi_long arg3, abi_long arg4, abi_long arg5)
6435{
6436 abi_long ret;
6437
6438 switch (option) {
6439 case PR_GET_PDEATHSIG:
6440 {
6441 int deathsig;
6442 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6443 arg3, arg4, arg5));
1edebb36
RH
6444 if (!is_error(ret) &&
6445 put_user_s32(host_to_target_signal(deathsig), arg2)) {
87e9bf23
RH
6446 return -TARGET_EFAULT;
6447 }
6448 return ret;
6449 }
f746c659
RH
6450 case PR_SET_PDEATHSIG:
6451 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6452 arg3, arg4, arg5));
87e9bf23
RH
6453 case PR_GET_NAME:
6454 {
6455 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6456 if (!name) {
6457 return -TARGET_EFAULT;
6458 }
6459 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6460 arg3, arg4, arg5));
6461 unlock_user(name, arg2, 16);
6462 return ret;
6463 }
6464 case PR_SET_NAME:
6465 {
6466 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6467 if (!name) {
6468 return -TARGET_EFAULT;
6469 }
6470 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6471 arg3, arg4, arg5));
6472 unlock_user(name, arg2, 0);
6473 return ret;
6474 }
6475 case PR_GET_FP_MODE:
6476 return do_prctl_get_fp_mode(env);
6477 case PR_SET_FP_MODE:
6478 return do_prctl_set_fp_mode(env, arg2);
6479 case PR_SVE_GET_VL:
fd72f5d0 6480 return do_prctl_sve_get_vl(env);
87e9bf23 6481 case PR_SVE_SET_VL:
fd72f5d0 6482 return do_prctl_sve_set_vl(env, arg2);
24d87c18
RH
6483 case PR_SME_GET_VL:
6484 return do_prctl_sme_get_vl(env);
6485 case PR_SME_SET_VL:
6486 return do_prctl_sme_set_vl(env, arg2);
87e9bf23
RH
6487 case PR_PAC_RESET_KEYS:
6488 if (arg3 || arg4 || arg5) {
6489 return -TARGET_EINVAL;
6490 }
6491 return do_prctl_reset_keys(env, arg2);
6492 case PR_SET_TAGGED_ADDR_CTRL:
6493 if (arg3 || arg4 || arg5) {
6494 return -TARGET_EINVAL;
6495 }
6496 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6497 case PR_GET_TAGGED_ADDR_CTRL:
6498 if (arg2 || arg3 || arg4 || arg5) {
6499 return -TARGET_EINVAL;
6500 }
6501 return do_prctl_get_tagged_addr_ctrl(env);
220717a6 6502
6e8dcacd
RH
6503 case PR_GET_UNALIGN:
6504 return do_prctl_get_unalign(env, arg2);
6505 case PR_SET_UNALIGN:
6506 return do_prctl_set_unalign(env, arg2);
6507
4f4e5567
RH
6508 case PR_CAP_AMBIENT:
6509 case PR_CAPBSET_READ:
6510 case PR_CAPBSET_DROP:
220717a6
RH
6511 case PR_GET_DUMPABLE:
6512 case PR_SET_DUMPABLE:
6513 case PR_GET_KEEPCAPS:
6514 case PR_SET_KEEPCAPS:
4f4e5567
RH
6515 case PR_GET_SECUREBITS:
6516 case PR_SET_SECUREBITS:
220717a6
RH
6517 case PR_GET_TIMING:
6518 case PR_SET_TIMING:
6519 case PR_GET_TIMERSLACK:
6520 case PR_SET_TIMERSLACK:
6521 case PR_MCE_KILL:
6522 case PR_MCE_KILL_GET:
6523 case PR_GET_NO_NEW_PRIVS:
6524 case PR_SET_NO_NEW_PRIVS:
6525 case PR_GET_IO_FLUSHER:
6526 case PR_SET_IO_FLUSHER:
6527 /* Some prctl options have no pointer arguments and we can pass on. */
6528 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6529
6530 case PR_GET_CHILD_SUBREAPER:
6531 case PR_SET_CHILD_SUBREAPER:
6532 case PR_GET_SPECULATION_CTRL:
6533 case PR_SET_SPECULATION_CTRL:
6534 case PR_GET_TID_ADDRESS:
6535 /* TODO */
6536 return -TARGET_EINVAL;
6537
6538 case PR_GET_FPEXC:
6539 case PR_SET_FPEXC:
6540 /* Was used for SPE on PowerPC. */
6541 return -TARGET_EINVAL;
6542
6543 case PR_GET_ENDIAN:
6544 case PR_SET_ENDIAN:
6545 case PR_GET_FPEMU:
6546 case PR_SET_FPEMU:
6547 case PR_SET_MM:
87e9bf23
RH
6548 case PR_GET_SECCOMP:
6549 case PR_SET_SECCOMP:
220717a6
RH
6550 case PR_SET_SYSCALL_USER_DISPATCH:
6551 case PR_GET_THP_DISABLE:
6552 case PR_SET_THP_DISABLE:
6553 case PR_GET_TSC:
6554 case PR_SET_TSC:
220717a6 6555 /* Disable to prevent the target disabling stuff we need. */
87e9bf23 6556 return -TARGET_EINVAL;
220717a6 6557
87e9bf23 6558 default:
220717a6
RH
6559 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6560 option);
6561 return -TARGET_EINVAL;
87e9bf23
RH
6562 }
6563}
6564
05098a93 6565#define NEW_STACK_SIZE 0x40000
d865bab5 6566
d865bab5
PB
6567
6568static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6569typedef struct {
9349b4f9 6570 CPUArchState *env;
d865bab5
PB
6571 pthread_mutex_t mutex;
6572 pthread_cond_t cond;
6573 pthread_t thread;
6574 uint32_t tid;
6575 abi_ulong child_tidptr;
6576 abi_ulong parent_tidptr;
6577 sigset_t sigmask;
6578} new_thread_info;
6579
6580static void *clone_func(void *arg)
6581{
6582 new_thread_info *info = arg;
9349b4f9 6583 CPUArchState *env;
0d34282f 6584 CPUState *cpu;
edf8e2af 6585 TaskState *ts;
d865bab5 6586
70903763 6587 rcu_register_thread();
3468b59e 6588 tcg_register_thread();
d865bab5 6589 env = info->env;
29a0af61 6590 cpu = env_cpu(env);
a2247f8e 6591 thread_cpu = cpu;
0429a971 6592 ts = (TaskState *)cpu->opaque;
71ba74f6 6593 info->tid = sys_gettid();
edf8e2af 6594 task_settid(ts);
d865bab5
PB
6595 if (info->child_tidptr)
6596 put_user_u32(info->tid, info->child_tidptr);
6597 if (info->parent_tidptr)
6598 put_user_u32(info->tid, info->parent_tidptr);
5ebdd774 6599 qemu_guest_random_seed_thread_part2(cpu->random_seed);
d865bab5
PB
6600 /* Enable signals. */
6601 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6602 /* Signal to the parent that we're ready. */
6603 pthread_mutex_lock(&info->mutex);
6604 pthread_cond_broadcast(&info->cond);
6605 pthread_mutex_unlock(&info->mutex);
a4dd3d51 6606 /* Wait until the parent has finished initializing the tls state. */
d865bab5
PB
6607 pthread_mutex_lock(&clone_lock);
6608 pthread_mutex_unlock(&clone_lock);
6609 cpu_loop(env);
6610 /* never exits */
6611 return NULL;
6612}
1b6b029e 6613
0da46a6e
TS
6614/* do_fork() Must return host values and target errnos (unlike most
6615 do_*() functions). */
9349b4f9 6616static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
6617 abi_ulong parent_tidptr, target_ulong newtls,
6618 abi_ulong child_tidptr)
1b6b029e 6619{
29a0af61 6620 CPUState *cpu = env_cpu(env);
1b6b029e 6621 int ret;
5cd4393b 6622 TaskState *ts;
0429a971 6623 CPUState *new_cpu;
9349b4f9 6624 CPUArchState *new_env;
d865bab5 6625 sigset_t sigmask;
3b46e624 6626
5ea2fc84
PM
6627 flags &= ~CLONE_IGNORED_FLAGS;
6628
436d124b
AZ
6629 /* Emulate vfork() with fork() */
6630 if (flags & CLONE_VFORK)
6631 flags &= ~(CLONE_VFORK | CLONE_VM);
6632
1b6b029e 6633 if (flags & CLONE_VM) {
0429a971 6634 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
6635 new_thread_info info;
6636 pthread_attr_t attr;
24cb36a6 6637
5ea2fc84
PM
6638 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6639 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6640 return -TARGET_EINVAL;
6641 }
6642
c78d65e8 6643 ts = g_new0(TaskState, 1);
624f7979 6644 init_task_state(ts);
73a988d9
MF
6645
6646 /* Grab a mutex so that thread setup appears atomic. */
6647 pthread_mutex_lock(&clone_lock);
6648
6cc9d67c
RH
6649 /*
6650 * If this is our first additional thread, we need to ensure we
6651 * generate code for parallel execution and flush old translations.
6652 * Do this now so that the copy gets CF_PARALLEL too.
6653 */
6654 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6655 cpu->tcg_cflags |= CF_PARALLEL;
6656 tb_flush(cpu);
6657 }
6658
1b6b029e 6659 /* we create a new CPU instance. */
c5be9f08 6660 new_env = cpu_copy(env);
6e68e076 6661 /* Init regs that differ from the parent. */
608999d1 6662 cpu_clone_regs_child(new_env, newsp, flags);
07a6ecf4 6663 cpu_clone_regs_parent(env, flags);
29a0af61 6664 new_cpu = env_cpu(new_env);
0429a971 6665 new_cpu->opaque = ts;
edf8e2af
MW
6666 ts->bprm = parent_ts->bprm;
6667 ts->info = parent_ts->info;
3d3efba0 6668 ts->signal_mask = parent_ts->signal_mask;
d865bab5 6669
7cfbd386 6670 if (flags & CLONE_CHILD_CLEARTID) {
c2764719
PB
6671 ts->child_tidptr = child_tidptr;
6672 }
6673
7cfbd386 6674 if (flags & CLONE_SETTLS) {
d865bab5 6675 cpu_set_tls (new_env, newtls);
7cfbd386 6676 }
d865bab5 6677
d865bab5
PB
6678 memset(&info, 0, sizeof(info));
6679 pthread_mutex_init(&info.mutex, NULL);
6680 pthread_mutex_lock(&info.mutex);
6681 pthread_cond_init(&info.cond, NULL);
6682 info.env = new_env;
7cfbd386 6683 if (flags & CLONE_CHILD_SETTID) {
d865bab5 6684 info.child_tidptr = child_tidptr;
7cfbd386
PM
6685 }
6686 if (flags & CLONE_PARENT_SETTID) {
d865bab5 6687 info.parent_tidptr = parent_tidptr;
7cfbd386 6688 }
d865bab5
PB
6689
6690 ret = pthread_attr_init(&attr);
48e15fc2
NF
6691 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6692 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
6693 /* It is not safe to deliver signals until the child has finished
6694 initializing, so temporarily block all signals. */
6695 sigfillset(&sigmask);
6696 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
5ebdd774 6697 cpu->random_seed = qemu_guest_random_seed_thread_part1();
d865bab5
PB
6698
6699 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 6700 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
6701
6702 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6703 pthread_attr_destroy(&attr);
6704 if (ret == 0) {
6705 /* Wait for the child to initialize. */
6706 pthread_cond_wait(&info.cond, &info.mutex);
6707 ret = info.tid;
d865bab5
PB
6708 } else {
6709 ret = -1;
6710 }
6711 pthread_mutex_unlock(&info.mutex);
6712 pthread_cond_destroy(&info.cond);
6713 pthread_mutex_destroy(&info.mutex);
6714 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
6715 } else {
6716 /* if no CLONE_VM, we consider it is a fork */
5ea2fc84
PM
6717 if (flags & CLONE_INVALID_FORK_FLAGS) {
6718 return -TARGET_EINVAL;
6719 }
6720
6721 /* We can't support custom termination signals */
6722 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
93b4eff8
TB
6723 return -TARGET_EINVAL;
6724 }
7d92d34e
TB
6725
6726 if (block_signals()) {
af254a27 6727 return -QEMU_ERESTARTSYS;
7d92d34e
TB
6728 }
6729
d865bab5 6730 fork_start();
1b6b029e 6731 ret = fork();
d865bab5 6732 if (ret == 0) {
2b1319c8 6733 /* Child Process. */
608999d1 6734 cpu_clone_regs_child(env, newsp, flags);
d865bab5 6735 fork_end(1);
2b1319c8
AJ
6736 /* There is a race condition here. The parent process could
6737 theoretically read the TID in the child process before the child
6738 tid is set. This would require using either ptrace
6739 (not implemented) or having *_tidptr to point at a shared memory
6740 mapping. We can't repeat the spinlock hack used above because
6741 the child process gets its own copy of the lock. */
d865bab5 6742 if (flags & CLONE_CHILD_SETTID)
71ba74f6 6743 put_user_u32(sys_gettid(), child_tidptr);
d865bab5 6744 if (flags & CLONE_PARENT_SETTID)
71ba74f6 6745 put_user_u32(sys_gettid(), parent_tidptr);
0429a971 6746 ts = (TaskState *)cpu->opaque;
d865bab5
PB
6747 if (flags & CLONE_SETTLS)
6748 cpu_set_tls (env, newtls);
c2764719
PB
6749 if (flags & CLONE_CHILD_CLEARTID)
6750 ts->child_tidptr = child_tidptr;
d865bab5 6751 } else {
07a6ecf4 6752 cpu_clone_regs_parent(env, flags);
d865bab5
PB
6753 fork_end(0);
6754 }
1b6b029e
FB
6755 }
6756 return ret;
6757}
6758
5f106811
APR
6759/* warning : doesn't handle linux specific flags... */
6760static int target_to_host_fcntl_cmd(int cmd)
6761{
4a545761
SB
6762 int ret;
6763
5f106811 6764 switch(cmd) {
4a545761
SB
6765 case TARGET_F_DUPFD:
6766 case TARGET_F_GETFD:
6767 case TARGET_F_SETFD:
6768 case TARGET_F_GETFL:
6769 case TARGET_F_SETFL:
2d92c682
AS
6770 case TARGET_F_OFD_GETLK:
6771 case TARGET_F_OFD_SETLK:
6772 case TARGET_F_OFD_SETLKW:
4a545761
SB
6773 ret = cmd;
6774 break;
6775 case TARGET_F_GETLK:
6776 ret = F_GETLK64;
6777 break;
6778 case TARGET_F_SETLK:
6779 ret = F_SETLK64;
6780 break;
6781 case TARGET_F_SETLKW:
6782 ret = F_SETLKW64;
6783 break;
6784 case TARGET_F_GETOWN:
6785 ret = F_GETOWN;
6786 break;
6787 case TARGET_F_SETOWN:
6788 ret = F_SETOWN;
6789 break;
6790 case TARGET_F_GETSIG:
6791 ret = F_GETSIG;
6792 break;
6793 case TARGET_F_SETSIG:
6794 ret = F_SETSIG;
6795 break;
5f106811 6796#if TARGET_ABI_BITS == 32
4a545761
SB
6797 case TARGET_F_GETLK64:
6798 ret = F_GETLK64;
6799 break;
6800 case TARGET_F_SETLK64:
6801 ret = F_SETLK64;
6802 break;
6803 case TARGET_F_SETLKW64:
6804 ret = F_SETLKW64;
6805 break;
5f106811 6806#endif
4a545761
SB
6807 case TARGET_F_SETLEASE:
6808 ret = F_SETLEASE;
6809 break;
6810 case TARGET_F_GETLEASE:
6811 ret = F_GETLEASE;
6812 break;
fbd5de9b 6813#ifdef F_DUPFD_CLOEXEC
4a545761
SB
6814 case TARGET_F_DUPFD_CLOEXEC:
6815 ret = F_DUPFD_CLOEXEC;
6816 break;
fbd5de9b 6817#endif
4a545761
SB
6818 case TARGET_F_NOTIFY:
6819 ret = F_NOTIFY;
6820 break;
8d5d3004 6821#ifdef F_GETOWN_EX
4a545761
SB
6822 case TARGET_F_GETOWN_EX:
6823 ret = F_GETOWN_EX;
6824 break;
8d5d3004
AS
6825#endif
6826#ifdef F_SETOWN_EX
4a545761
SB
6827 case TARGET_F_SETOWN_EX:
6828 ret = F_SETOWN_EX;
6829 break;
8d5d3004 6830#endif
ddf31aa8 6831#ifdef F_SETPIPE_SZ
4a545761
SB
6832 case TARGET_F_SETPIPE_SZ:
6833 ret = F_SETPIPE_SZ;
6834 break;
6835 case TARGET_F_GETPIPE_SZ:
6836 ret = F_GETPIPE_SZ;
6837 break;
2bb963ff
SCW
6838#endif
6839#ifdef F_ADD_SEALS
6840 case TARGET_F_ADD_SEALS:
6841 ret = F_ADD_SEALS;
6842 break;
6843 case TARGET_F_GET_SEALS:
6844 ret = F_GET_SEALS;
6845 break;
ddf31aa8 6846#endif
4a545761
SB
6847 default:
6848 ret = -TARGET_EINVAL;
6849 break;
6850 }
6851
6852#if defined(__powerpc64__)
6853 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6854 * is not supported by kernel. The glibc fcntl call actually adjusts
6855 * them to 5, 6 and 7 before making the syscall(). Since we make the
6856 * syscall directly, adjust to what is supported by the kernel.
6857 */
6858 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6859 ret -= F_GETLK64 - 5;
5f106811 6860 }
4a545761
SB
6861#endif
6862
6863 return ret;
5f106811
APR
6864}
6865
ae68ad9f
LV
6866#define FLOCK_TRANSTBL \
6867 switch (type) { \
6868 TRANSTBL_CONVERT(F_RDLCK); \
6869 TRANSTBL_CONVERT(F_WRLCK); \
6870 TRANSTBL_CONVERT(F_UNLCK); \
ae68ad9f
LV
6871 }
6872
6873static int target_to_host_flock(int type)
6874{
6875#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6876 FLOCK_TRANSTBL
6877#undef TRANSTBL_CONVERT
6878 return -TARGET_EINVAL;
6879}
6880
6881static int host_to_target_flock(int type)
6882{
6883#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6884 FLOCK_TRANSTBL
6885#undef TRANSTBL_CONVERT
6886 /* if we don't know how to convert the value coming
6887 * from the host we copy to the target field as-is
6888 */
6889 return type;
6890}
2ba7f730 6891
213d3e9e
PM
6892static inline abi_long copy_from_user_flock(struct flock64 *fl,
6893 abi_ulong target_flock_addr)
7775e9ec 6894{
53a5960a 6895 struct target_flock *target_fl;
ae68ad9f 6896 int l_type;
213d3e9e
PM
6897
6898 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6899 return -TARGET_EFAULT;
6900 }
6901
6902 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6903 l_type = target_to_host_flock(l_type);
6904 if (l_type < 0) {
6905 return l_type;
6906 }
6907 fl->l_type = l_type;
213d3e9e
PM
6908 __get_user(fl->l_whence, &target_fl->l_whence);
6909 __get_user(fl->l_start, &target_fl->l_start);
6910 __get_user(fl->l_len, &target_fl->l_len);
6911 __get_user(fl->l_pid, &target_fl->l_pid);
6912 unlock_user_struct(target_fl, target_flock_addr, 0);
6913 return 0;
6914}
6915
6916static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6917 const struct flock64 *fl)
6918{
6919 struct target_flock *target_fl;
6920 short l_type;
6921
6922 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6923 return -TARGET_EFAULT;
6924 }
6925
ae68ad9f 6926 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6927 __put_user(l_type, &target_fl->l_type);
6928 __put_user(fl->l_whence, &target_fl->l_whence);
6929 __put_user(fl->l_start, &target_fl->l_start);
6930 __put_user(fl->l_len, &target_fl->l_len);
6931 __put_user(fl->l_pid, &target_fl->l_pid);
6932 unlock_user_struct(target_fl, target_flock_addr, 1);
6933 return 0;
6934}
6935
6936typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6937typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6938
6939#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
ffe81d43
RH
6940struct target_oabi_flock64 {
6941 abi_short l_type;
6942 abi_short l_whence;
6943 abi_llong l_start;
6944 abi_llong l_len;
6945 abi_int l_pid;
6946} QEMU_PACKED;
6947
7f254c5c 6948static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
213d3e9e
PM
6949 abi_ulong target_flock_addr)
6950{
7f254c5c 6951 struct target_oabi_flock64 *target_fl;
ae68ad9f 6952 int l_type;
213d3e9e
PM
6953
6954 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6955 return -TARGET_EFAULT;
6956 }
6957
6958 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6959 l_type = target_to_host_flock(l_type);
6960 if (l_type < 0) {
6961 return l_type;
6962 }
6963 fl->l_type = l_type;
213d3e9e
PM
6964 __get_user(fl->l_whence, &target_fl->l_whence);
6965 __get_user(fl->l_start, &target_fl->l_start);
6966 __get_user(fl->l_len, &target_fl->l_len);
6967 __get_user(fl->l_pid, &target_fl->l_pid);
6968 unlock_user_struct(target_fl, target_flock_addr, 0);
6969 return 0;
6970}
6971
7f254c5c 6972static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
213d3e9e
PM
6973 const struct flock64 *fl)
6974{
7f254c5c 6975 struct target_oabi_flock64 *target_fl;
213d3e9e
PM
6976 short l_type;
6977
6978 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6979 return -TARGET_EFAULT;
6980 }
6981
ae68ad9f 6982 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6983 __put_user(l_type, &target_fl->l_type);
6984 __put_user(fl->l_whence, &target_fl->l_whence);
6985 __put_user(fl->l_start, &target_fl->l_start);
6986 __put_user(fl->l_len, &target_fl->l_len);
6987 __put_user(fl->l_pid, &target_fl->l_pid);
6988 unlock_user_struct(target_fl, target_flock_addr, 1);
6989 return 0;
6990}
6991#endif
6992
6993static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6994 abi_ulong target_flock_addr)
6995{
6996 struct target_flock64 *target_fl;
ae68ad9f 6997 int l_type;
213d3e9e
PM
6998
6999 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
7000 return -TARGET_EFAULT;
7001 }
7002
7003 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
7004 l_type = target_to_host_flock(l_type);
7005 if (l_type < 0) {
7006 return l_type;
7007 }
7008 fl->l_type = l_type;
213d3e9e
PM
7009 __get_user(fl->l_whence, &target_fl->l_whence);
7010 __get_user(fl->l_start, &target_fl->l_start);
7011 __get_user(fl->l_len, &target_fl->l_len);
7012 __get_user(fl->l_pid, &target_fl->l_pid);
7013 unlock_user_struct(target_fl, target_flock_addr, 0);
7014 return 0;
7015}
7016
7017static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
7018 const struct flock64 *fl)
7019{
7020 struct target_flock64 *target_fl;
7021 short l_type;
7022
7023 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
7024 return -TARGET_EFAULT;
7025 }
7026
ae68ad9f 7027 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
7028 __put_user(l_type, &target_fl->l_type);
7029 __put_user(fl->l_whence, &target_fl->l_whence);
7030 __put_user(fl->l_start, &target_fl->l_start);
7031 __put_user(fl->l_len, &target_fl->l_len);
7032 __put_user(fl->l_pid, &target_fl->l_pid);
7033 unlock_user_struct(target_fl, target_flock_addr, 1);
7034 return 0;
7035}
7036
7037static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7038{
43f238d7 7039 struct flock64 fl64;
8d5d3004
AS
7040#ifdef F_GETOWN_EX
7041 struct f_owner_ex fox;
7042 struct target_f_owner_ex *target_fox;
7043#endif
992f48a0 7044 abi_long ret;
5f106811
APR
7045 int host_cmd = target_to_host_fcntl_cmd(cmd);
7046
7047 if (host_cmd == -TARGET_EINVAL)
7048 return host_cmd;
53a5960a 7049
7775e9ec
FB
7050 switch(cmd) {
7051 case TARGET_F_GETLK:
213d3e9e
PM
7052 ret = copy_from_user_flock(&fl64, arg);
7053 if (ret) {
7054 return ret;
7055 }
435da5e7 7056 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7057 if (ret == 0) {
213d3e9e 7058 ret = copy_to_user_flock(arg, &fl64);
7775e9ec
FB
7059 }
7060 break;
3b46e624 7061
7775e9ec
FB
7062 case TARGET_F_SETLK:
7063 case TARGET_F_SETLKW:
213d3e9e
PM
7064 ret = copy_from_user_flock(&fl64, arg);
7065 if (ret) {
7066 return ret;
7067 }
435da5e7 7068 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7069 break;
3b46e624 7070
7775e9ec 7071 case TARGET_F_GETLK64:
2d92c682 7072 case TARGET_F_OFD_GETLK:
213d3e9e
PM
7073 ret = copy_from_user_flock64(&fl64, arg);
7074 if (ret) {
7075 return ret;
7076 }
435da5e7 7077 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
43f238d7 7078 if (ret == 0) {
213d3e9e 7079 ret = copy_to_user_flock64(arg, &fl64);
43f238d7 7080 }
9ee1fa2c 7081 break;
7775e9ec
FB
7082 case TARGET_F_SETLK64:
7083 case TARGET_F_SETLKW64:
2d92c682
AS
7084 case TARGET_F_OFD_SETLK:
7085 case TARGET_F_OFD_SETLKW:
213d3e9e
PM
7086 ret = copy_from_user_flock64(&fl64, arg);
7087 if (ret) {
7088 return ret;
7089 }
435da5e7 7090 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
7091 break;
7092
5f106811 7093 case TARGET_F_GETFL:
435da5e7 7094 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
7095 if (ret >= 0) {
7096 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7097 }
ffa65c3b
FB
7098 break;
7099
5f106811 7100 case TARGET_F_SETFL:
435da5e7
PM
7101 ret = get_errno(safe_fcntl(fd, host_cmd,
7102 target_to_host_bitmask(arg,
7103 fcntl_flags_tbl)));
5f106811
APR
7104 break;
7105
8d5d3004
AS
7106#ifdef F_GETOWN_EX
7107 case TARGET_F_GETOWN_EX:
435da5e7 7108 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7109 if (ret >= 0) {
7110 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7111 return -TARGET_EFAULT;
7112 target_fox->type = tswap32(fox.type);
7113 target_fox->pid = tswap32(fox.pid);
7114 unlock_user_struct(target_fox, arg, 1);
7115 }
7116 break;
7117#endif
7118
7119#ifdef F_SETOWN_EX
7120 case TARGET_F_SETOWN_EX:
7121 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7122 return -TARGET_EFAULT;
7123 fox.type = tswap32(target_fox->type);
7124 fox.pid = tswap32(target_fox->pid);
7125 unlock_user_struct(target_fox, arg, 0);
435da5e7 7126 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7127 break;
7128#endif
7129
5f106811 7130 case TARGET_F_SETSIG:
a7b4c9b1
TB
7131 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7132 break;
7133
5f106811 7134 case TARGET_F_GETSIG:
a7b4c9b1
TB
7135 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7136 break;
7137
7138 case TARGET_F_SETOWN:
7139 case TARGET_F_GETOWN:
7e22e546
UH
7140 case TARGET_F_SETLEASE:
7141 case TARGET_F_GETLEASE:
7e3b92ec
PM
7142 case TARGET_F_SETPIPE_SZ:
7143 case TARGET_F_GETPIPE_SZ:
2bb963ff
SCW
7144 case TARGET_F_ADD_SEALS:
7145 case TARGET_F_GET_SEALS:
435da5e7 7146 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
ffa65c3b
FB
7147 break;
7148
7775e9ec 7149 default:
435da5e7 7150 ret = get_errno(safe_fcntl(fd, cmd, arg));
7775e9ec
FB
7151 break;
7152 }
7153 return ret;
7154}
7155
67867308 7156#ifdef USE_UID16
7775e9ec 7157
67867308
FB
7158static inline int high2lowuid(int uid)
7159{
7160 if (uid > 65535)
7161 return 65534;
7162 else
7163 return uid;
7164}
7165
7166static inline int high2lowgid(int gid)
7167{
7168 if (gid > 65535)
7169 return 65534;
7170 else
7171 return gid;
7172}
7173
7174static inline int low2highuid(int uid)
7175{
7176 if ((int16_t)uid == -1)
7177 return -1;
7178 else
7179 return uid;
7180}
7181
7182static inline int low2highgid(int gid)
7183{
7184 if ((int16_t)gid == -1)
7185 return -1;
7186 else
7187 return gid;
7188}
0c866a7e
RV
7189static inline int tswapid(int id)
7190{
7191 return tswap16(id);
7192}
76ca310a
PM
7193
7194#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7195
0c866a7e
RV
7196#else /* !USE_UID16 */
7197static inline int high2lowuid(int uid)
7198{
7199 return uid;
7200}
7201static inline int high2lowgid(int gid)
7202{
7203 return gid;
7204}
7205static inline int low2highuid(int uid)
7206{
7207 return uid;
7208}
7209static inline int low2highgid(int gid)
7210{
7211 return gid;
7212}
7213static inline int tswapid(int id)
7214{
7215 return tswap32(id);
7216}
76ca310a
PM
7217
7218#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7219
67867308 7220#endif /* USE_UID16 */
1b6b029e 7221
fd6f7798
PM
7222/* We must do direct syscalls for setting UID/GID, because we want to
7223 * implement the Linux system call semantics of "change only for this thread",
7224 * not the libc/POSIX semantics of "change for all threads in process".
7225 * (See http://ewontfix.com/17/ for more details.)
7226 * We use the 32-bit version of the syscalls if present; if it is not
7227 * then either the host architecture supports 32-bit UIDs natively with
7228 * the standard syscall, or the 16-bit UID is the best we can do.
7229 */
7230#ifdef __NR_setuid32
7231#define __NR_sys_setuid __NR_setuid32
7232#else
7233#define __NR_sys_setuid __NR_setuid
7234#endif
7235#ifdef __NR_setgid32
7236#define __NR_sys_setgid __NR_setgid32
7237#else
7238#define __NR_sys_setgid __NR_setgid
7239#endif
7240#ifdef __NR_setresuid32
7241#define __NR_sys_setresuid __NR_setresuid32
7242#else
7243#define __NR_sys_setresuid __NR_setresuid
7244#endif
7245#ifdef __NR_setresgid32
7246#define __NR_sys_setresgid __NR_setresgid32
7247#else
7248#define __NR_sys_setresgid __NR_setresgid
7249#endif
7250
7251_syscall1(int, sys_setuid, uid_t, uid)
7252_syscall1(int, sys_setgid, gid_t, gid)
7253_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7254_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7255
31e31b8a
FB
7256void syscall_init(void)
7257{
2ab83ea7
FB
7258 IOCTLEntry *ie;
7259 const argtype *arg_type;
7260 int size;
7261
8be656b8
AG
7262 thunk_init(STRUCT_MAX);
7263
001faf32 7264#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 7265#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
7266#include "syscall_types.h"
7267#undef STRUCT
7268#undef STRUCT_SPECIAL
2ab83ea7
FB
7269
7270 /* we patch the ioctl size if necessary. We rely on the fact that
7271 no ioctl has all the bits at '1' in the size field */
7272 ie = ioctl_entries;
7273 while (ie->target_cmd != 0) {
7274 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7275 TARGET_IOC_SIZEMASK) {
7276 arg_type = ie->arg_type;
7277 if (arg_type[0] != TYPE_PTR) {
5fafdf24 7278 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
7279 ie->target_cmd);
7280 exit(1);
7281 }
7282 arg_type++;
7283 size = thunk_type_size(arg_type, 0);
5fafdf24 7284 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
7285 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7286 (size << TARGET_IOC_SIZESHIFT);
7287 }
b92c47c1 7288
2ab83ea7 7289 /* automatic consistency check if same arch */
872ea0c0
AZ
7290#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7291 (defined(__x86_64__) && defined(TARGET_X86_64))
7292 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7293 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7294 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
7295 }
7296#endif
7297 ie++;
7298 }
31e31b8a 7299}
c573ff67 7300
ce4defa0 7301#ifdef TARGET_NR_truncate64
a0939b89 7302static inline abi_long target_truncate64(CPUArchState *cpu_env, const char *arg1,
992f48a0
BS
7303 abi_long arg2,
7304 abi_long arg3,
7305 abi_long arg4)
ce4defa0 7306{
8bf8e9df 7307 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
ce4defa0
PB
7308 arg2 = arg3;
7309 arg3 = arg4;
48e515d4 7310 }
ce4defa0
PB
7311 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7312}
7313#endif
7314
7315#ifdef TARGET_NR_ftruncate64
a0939b89 7316static inline abi_long target_ftruncate64(CPUArchState *cpu_env, abi_long arg1,
992f48a0
BS
7317 abi_long arg2,
7318 abi_long arg3,
7319 abi_long arg4)
ce4defa0 7320{
8bf8e9df 7321 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
ce4defa0
PB
7322 arg2 = arg3;
7323 arg3 = arg4;
48e515d4 7324 }
ce4defa0
PB
7325 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7326}
7327#endif
7328
859e8a89
AF
7329#if defined(TARGET_NR_timer_settime) || \
7330 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
2c86c90f 7331static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
f4f1e10a
ECL
7332 abi_ulong target_addr)
7333{
2c86c90f
FB
7334 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7335 offsetof(struct target_itimerspec,
7336 it_interval)) ||
7337 target_to_host_timespec(&host_its->it_value, target_addr +
7338 offsetof(struct target_itimerspec,
7339 it_value))) {
f4f1e10a
ECL
7340 return -TARGET_EFAULT;
7341 }
7342
f4f1e10a
ECL
7343 return 0;
7344}
859e8a89 7345#endif
f4f1e10a 7346
828cb3a1
FB
7347#if defined(TARGET_NR_timer_settime64) || \
7348 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7349static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7350 abi_ulong target_addr)
7351{
7352 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7353 offsetof(struct target__kernel_itimerspec,
7354 it_interval)) ||
7355 target_to_host_timespec64(&host_its->it_value, target_addr +
7356 offsetof(struct target__kernel_itimerspec,
7357 it_value))) {
7358 return -TARGET_EFAULT;
7359 }
7360
7361 return 0;
7362}
7363#endif
7364
859e8a89
AF
7365#if ((defined(TARGET_NR_timerfd_gettime) || \
7366 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
2c86c90f 7367 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
f4f1e10a 7368static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
2c86c90f
FB
7369 struct itimerspec *host_its)
7370{
7371 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7372 it_interval),
7373 &host_its->it_interval) ||
7374 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7375 it_value),
7376 &host_its->it_value)) {
f4f1e10a
ECL
7377 return -TARGET_EFAULT;
7378 }
f4f1e10a
ECL
7379 return 0;
7380}
859e8a89 7381#endif
f4f1e10a 7382
828cb3a1
FB
7383#if ((defined(TARGET_NR_timerfd_gettime64) || \
7384 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7385 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7386static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7387 struct itimerspec *host_its)
7388{
7389 if (host_to_target_timespec64(target_addr +
7390 offsetof(struct target__kernel_itimerspec,
7391 it_interval),
7392 &host_its->it_interval) ||
7393 host_to_target_timespec64(target_addr +
7394 offsetof(struct target__kernel_itimerspec,
7395 it_value),
7396 &host_its->it_value)) {
7397 return -TARGET_EFAULT;
7398 }
7399 return 0;
7400}
7401#endif
7402
859e8a89
AF
7403#if defined(TARGET_NR_adjtimex) || \
7404 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
19f59bce
AM
7405static inline abi_long target_to_host_timex(struct timex *host_tx,
7406 abi_long target_addr)
7407{
7408 struct target_timex *target_tx;
7409
7410 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7411 return -TARGET_EFAULT;
7412 }
7413
7414 __get_user(host_tx->modes, &target_tx->modes);
7415 __get_user(host_tx->offset, &target_tx->offset);
7416 __get_user(host_tx->freq, &target_tx->freq);
7417 __get_user(host_tx->maxerror, &target_tx->maxerror);
7418 __get_user(host_tx->esterror, &target_tx->esterror);
7419 __get_user(host_tx->status, &target_tx->status);
7420 __get_user(host_tx->constant, &target_tx->constant);
7421 __get_user(host_tx->precision, &target_tx->precision);
7422 __get_user(host_tx->tolerance, &target_tx->tolerance);
7423 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7424 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7425 __get_user(host_tx->tick, &target_tx->tick);
7426 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7427 __get_user(host_tx->jitter, &target_tx->jitter);
7428 __get_user(host_tx->shift, &target_tx->shift);
7429 __get_user(host_tx->stabil, &target_tx->stabil);
7430 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7431 __get_user(host_tx->calcnt, &target_tx->calcnt);
7432 __get_user(host_tx->errcnt, &target_tx->errcnt);
7433 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7434 __get_user(host_tx->tai, &target_tx->tai);
7435
7436 unlock_user_struct(target_tx, target_addr, 0);
7437 return 0;
7438}
7439
7440static inline abi_long host_to_target_timex(abi_long target_addr,
7441 struct timex *host_tx)
7442{
7443 struct target_timex *target_tx;
7444
7445 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7446 return -TARGET_EFAULT;
7447 }
7448
7449 __put_user(host_tx->modes, &target_tx->modes);
7450 __put_user(host_tx->offset, &target_tx->offset);
7451 __put_user(host_tx->freq, &target_tx->freq);
7452 __put_user(host_tx->maxerror, &target_tx->maxerror);
7453 __put_user(host_tx->esterror, &target_tx->esterror);
7454 __put_user(host_tx->status, &target_tx->status);
7455 __put_user(host_tx->constant, &target_tx->constant);
7456 __put_user(host_tx->precision, &target_tx->precision);
7457 __put_user(host_tx->tolerance, &target_tx->tolerance);
7458 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7459 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7460 __put_user(host_tx->tick, &target_tx->tick);
7461 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7462 __put_user(host_tx->jitter, &target_tx->jitter);
7463 __put_user(host_tx->shift, &target_tx->shift);
7464 __put_user(host_tx->stabil, &target_tx->stabil);
7465 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7466 __put_user(host_tx->calcnt, &target_tx->calcnt);
7467 __put_user(host_tx->errcnt, &target_tx->errcnt);
7468 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7469 __put_user(host_tx->tai, &target_tx->tai);
7470
7471 unlock_user_struct(target_tx, target_addr, 1);
7472 return 0;
7473}
859e8a89 7474#endif
19f59bce 7475
6ac03b2c
FB
7476
7477#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7478static inline abi_long target_to_host_timex64(struct timex *host_tx,
7479 abi_long target_addr)
7480{
7481 struct target__kernel_timex *target_tx;
7482
7483 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7484 offsetof(struct target__kernel_timex,
7485 time))) {
7486 return -TARGET_EFAULT;
7487 }
7488
7489 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7490 return -TARGET_EFAULT;
7491 }
7492
7493 __get_user(host_tx->modes, &target_tx->modes);
7494 __get_user(host_tx->offset, &target_tx->offset);
7495 __get_user(host_tx->freq, &target_tx->freq);
7496 __get_user(host_tx->maxerror, &target_tx->maxerror);
7497 __get_user(host_tx->esterror, &target_tx->esterror);
7498 __get_user(host_tx->status, &target_tx->status);
7499 __get_user(host_tx->constant, &target_tx->constant);
7500 __get_user(host_tx->precision, &target_tx->precision);
7501 __get_user(host_tx->tolerance, &target_tx->tolerance);
7502 __get_user(host_tx->tick, &target_tx->tick);
7503 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7504 __get_user(host_tx->jitter, &target_tx->jitter);
7505 __get_user(host_tx->shift, &target_tx->shift);
7506 __get_user(host_tx->stabil, &target_tx->stabil);
7507 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7508 __get_user(host_tx->calcnt, &target_tx->calcnt);
7509 __get_user(host_tx->errcnt, &target_tx->errcnt);
7510 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7511 __get_user(host_tx->tai, &target_tx->tai);
7512
7513 unlock_user_struct(target_tx, target_addr, 0);
7514 return 0;
7515}
7516
7517static inline abi_long host_to_target_timex64(abi_long target_addr,
7518 struct timex *host_tx)
7519{
7520 struct target__kernel_timex *target_tx;
7521
7522 if (copy_to_user_timeval64(target_addr +
7523 offsetof(struct target__kernel_timex, time),
7524 &host_tx->time)) {
7525 return -TARGET_EFAULT;
7526 }
7527
7528 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7529 return -TARGET_EFAULT;
7530 }
7531
7532 __put_user(host_tx->modes, &target_tx->modes);
7533 __put_user(host_tx->offset, &target_tx->offset);
7534 __put_user(host_tx->freq, &target_tx->freq);
7535 __put_user(host_tx->maxerror, &target_tx->maxerror);
7536 __put_user(host_tx->esterror, &target_tx->esterror);
7537 __put_user(host_tx->status, &target_tx->status);
7538 __put_user(host_tx->constant, &target_tx->constant);
7539 __put_user(host_tx->precision, &target_tx->precision);
7540 __put_user(host_tx->tolerance, &target_tx->tolerance);
7541 __put_user(host_tx->tick, &target_tx->tick);
7542 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7543 __put_user(host_tx->jitter, &target_tx->jitter);
7544 __put_user(host_tx->shift, &target_tx->shift);
7545 __put_user(host_tx->stabil, &target_tx->stabil);
7546 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7547 __put_user(host_tx->calcnt, &target_tx->calcnt);
7548 __put_user(host_tx->errcnt, &target_tx->errcnt);
7549 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7550 __put_user(host_tx->tai, &target_tx->tai);
7551
7552 unlock_user_struct(target_tx, target_addr, 1);
7553 return 0;
7554}
7555#endif
7556
96ff758c
MF
7557#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7558#define sigev_notify_thread_id _sigev_un._tid
7559#endif
7560
c065976f
PM
7561static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7562 abi_ulong target_addr)
7563{
7564 struct target_sigevent *target_sevp;
7565
7566 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7567 return -TARGET_EFAULT;
7568 }
7569
7570 /* This union is awkward on 64 bit systems because it has a 32 bit
7571 * integer and a pointer in it; we follow the conversion approach
7572 * used for handling sigval types in signal.c so the guest should get
7573 * the correct value back even if we did a 64 bit byteswap and it's
7574 * using the 32 bit integer.
7575 */
7576 host_sevp->sigev_value.sival_ptr =
7577 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7578 host_sevp->sigev_signo =
7579 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7580 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
96ff758c 7581 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
c065976f
PM
7582
7583 unlock_user_struct(target_sevp, target_addr, 1);
7584 return 0;
7585}
7586
6f6a4032
TM
7587#if defined(TARGET_NR_mlockall)
7588static inline int target_to_host_mlockall_arg(int arg)
7589{
7590 int result = 0;
7591
02e5d7d7 7592 if (arg & TARGET_MCL_CURRENT) {
6f6a4032
TM
7593 result |= MCL_CURRENT;
7594 }
02e5d7d7 7595 if (arg & TARGET_MCL_FUTURE) {
6f6a4032
TM
7596 result |= MCL_FUTURE;
7597 }
02e5d7d7
FB
7598#ifdef MCL_ONFAULT
7599 if (arg & TARGET_MCL_ONFAULT) {
7600 result |= MCL_ONFAULT;
7601 }
7602#endif
7603
6f6a4032
TM
7604 return result;
7605}
7606#endif
7607
4f7f8924
AR
7608#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7609 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7610 defined(TARGET_NR_newfstatat))
a0939b89 7611static inline abi_long host_to_target_stat64(CPUArchState *cpu_env,
6a24a778
AZ
7612 abi_ulong target_addr,
7613 struct stat *host_st)
7614{
09701199 7615#if defined(TARGET_ARM) && defined(TARGET_ABI32)
0effdc29 7616 if (cpu_env->eabi) {
6a24a778
AZ
7617 struct target_eabi_stat64 *target_st;
7618
7619 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7620 return -TARGET_EFAULT;
7621 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7622 __put_user(host_st->st_dev, &target_st->st_dev);
7623 __put_user(host_st->st_ino, &target_st->st_ino);
7624#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7625 __put_user(host_st->st_ino, &target_st->__st_ino);
7626#endif
7627 __put_user(host_st->st_mode, &target_st->st_mode);
7628 __put_user(host_st->st_nlink, &target_st->st_nlink);
7629 __put_user(host_st->st_uid, &target_st->st_uid);
7630 __put_user(host_st->st_gid, &target_st->st_gid);
7631 __put_user(host_st->st_rdev, &target_st->st_rdev);
7632 __put_user(host_st->st_size, &target_st->st_size);
7633 __put_user(host_st->st_blksize, &target_st->st_blksize);
7634 __put_user(host_st->st_blocks, &target_st->st_blocks);
7635 __put_user(host_st->st_atime, &target_st->target_st_atime);
7636 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7637 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7638#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7639 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7640 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7641 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7642#endif
6a24a778
AZ
7643 unlock_user_struct(target_st, target_addr, 1);
7644 } else
7645#endif
7646 {
20d155bc 7647#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 7648 struct target_stat64 *target_st;
20d155bc
SW
7649#else
7650 struct target_stat *target_st;
9d33b76b 7651#endif
6a24a778
AZ
7652
7653 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7654 return -TARGET_EFAULT;
9d33b76b 7655 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
7656 __put_user(host_st->st_dev, &target_st->st_dev);
7657 __put_user(host_st->st_ino, &target_st->st_ino);
7658#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7659 __put_user(host_st->st_ino, &target_st->__st_ino);
7660#endif
7661 __put_user(host_st->st_mode, &target_st->st_mode);
7662 __put_user(host_st->st_nlink, &target_st->st_nlink);
7663 __put_user(host_st->st_uid, &target_st->st_uid);
7664 __put_user(host_st->st_gid, &target_st->st_gid);
7665 __put_user(host_st->st_rdev, &target_st->st_rdev);
7666 /* XXX: better use of kernel struct */
7667 __put_user(host_st->st_size, &target_st->st_size);
7668 __put_user(host_st->st_blksize, &target_st->st_blksize);
7669 __put_user(host_st->st_blocks, &target_st->st_blocks);
7670 __put_user(host_st->st_atime, &target_st->target_st_atime);
7671 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7672 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7673#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7674 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7675 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7676 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7677#endif
6a24a778
AZ
7678 unlock_user_struct(target_st, target_addr, 1);
7679 }
7680
7681 return 0;
7682}
4f7f8924 7683#endif
6a24a778 7684
efa92184
AR
7685#if defined(TARGET_NR_statx) && defined(__NR_statx)
7686static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7687 abi_ulong target_addr)
7688{
7689 struct target_statx *target_stx;
7690
7691 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7692 return -TARGET_EFAULT;
7693 }
7694 memset(target_stx, 0, sizeof(*target_stx));
7695
7696 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7697 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7698 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7699 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7700 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7701 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7702 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7703 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7704 __put_user(host_stx->stx_size, &target_stx->stx_size);
7705 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7706 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7707 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7708 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
d1e26707
AC
7709 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7710 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7711 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7712 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7713 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7714 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
efa92184
AR
7715 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7716 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7717 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7718 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7719
7720 unlock_user_struct(target_stx, target_addr, 1);
7721
7722 return 0;
7723}
7724#endif
7725
14690296
AF
7726static int do_sys_futex(int *uaddr, int op, int val,
7727 const struct timespec *timeout, int *uaddr2,
7728 int val3)
7729{
7730#if HOST_LONG_BITS == 64
7731#if defined(__NR_futex)
7732 /* always a 64-bit time_t, it doesn't define _time64 version */
7733 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7734
7735#endif
7736#else /* HOST_LONG_BITS == 64 */
7737#if defined(__NR_futex_time64)
7738 if (sizeof(timeout->tv_sec) == 8) {
7739 /* _time64 function on 32bit arch */
7740 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7741 }
7742#endif
7743#if defined(__NR_futex)
7744 /* old function on 32bit arch */
7745 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7746#endif
7747#endif /* HOST_LONG_BITS == 64 */
7748 g_assert_not_reached();
7749}
7750
7751static int do_safe_futex(int *uaddr, int op, int val,
7752 const struct timespec *timeout, int *uaddr2,
7753 int val3)
7754{
7755#if HOST_LONG_BITS == 64
7756#if defined(__NR_futex)
7757 /* always a 64-bit time_t, it doesn't define _time64 version */
7758 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7759#endif
7760#else /* HOST_LONG_BITS == 64 */
7761#if defined(__NR_futex_time64)
7762 if (sizeof(timeout->tv_sec) == 8) {
7763 /* _time64 function on 32bit arch */
7764 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7765 val3));
7766 }
7767#endif
7768#if defined(__NR_futex)
7769 /* old function on 32bit arch */
7770 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7771#endif
7772#endif /* HOST_LONG_BITS == 64 */
7773 return -TARGET_ENOSYS;
7774}
efa92184 7775
bd0c5661
PB
7776/* ??? Using host futex calls even when target atomic operations
7777 are not really atomic probably breaks things. However implementing
7778 futexes locally would make futexes shared between multiple processes
7779 tricky. However they're probably useless because guest atomic
7780 operations won't work either. */
0fbc0f8d
RH
7781#if defined(TARGET_NR_futex) || defined(TARGET_NR_futex_time64)
7782static int do_futex(CPUState *cpu, bool time64, target_ulong uaddr,
7783 int op, int val, target_ulong timeout,
7784 target_ulong uaddr2, int val3)
bd0c5661 7785{
57b9ccd4
RH
7786 struct timespec ts, *pts = NULL;
7787 void *haddr2 = NULL;
a16aae0c 7788 int base_op;
bd0c5661 7789
57b9ccd4 7790 /* We assume FUTEX_* constants are the same on both host and target. */
a29ccd63 7791#ifdef FUTEX_CMD_MASK
a16aae0c 7792 base_op = op & FUTEX_CMD_MASK;
a29ccd63 7793#else
a16aae0c 7794 base_op = op;
a29ccd63 7795#endif
a16aae0c 7796 switch (base_op) {
bd0c5661 7797 case FUTEX_WAIT:
cce246e0 7798 case FUTEX_WAIT_BITSET:
57b9ccd4
RH
7799 val = tswap32(val);
7800 break;
c72a90df
RH
7801 case FUTEX_WAIT_REQUEUE_PI:
7802 val = tswap32(val);
7803 haddr2 = g2h(cpu, uaddr2);
7804 break;
7805 case FUTEX_LOCK_PI:
7806 case FUTEX_LOCK_PI2:
7807 break;
bd0c5661 7808 case FUTEX_WAKE:
a6180f8a 7809 case FUTEX_WAKE_BITSET:
c72a90df
RH
7810 case FUTEX_TRYLOCK_PI:
7811 case FUTEX_UNLOCK_PI:
57b9ccd4
RH
7812 timeout = 0;
7813 break;
bd0c5661 7814 case FUTEX_FD:
0f946731 7815 val = target_to_host_signal(val);
57b9ccd4
RH
7816 timeout = 0;
7817 break;
bd0c5661 7818 case FUTEX_CMP_REQUEUE:
c72a90df 7819 case FUTEX_CMP_REQUEUE_PI:
57b9ccd4
RH
7820 val3 = tswap32(val3);
7821 /* fall through */
7822 case FUTEX_REQUEUE:
a16aae0c 7823 case FUTEX_WAKE_OP:
57b9ccd4
RH
7824 /*
7825 * For these, the 4th argument is not TIMEOUT, but VAL2.
7826 * But the prototype of do_safe_futex takes a pointer, so
7827 * insert casts to satisfy the compiler. We do not need
7828 * to tswap VAL2 since it's not compared to guest memory.
7829 */
7830 pts = (struct timespec *)(uintptr_t)timeout;
7831 timeout = 0;
7832 haddr2 = g2h(cpu, uaddr2);
7833 break;
bd0c5661
PB
7834 default:
7835 return -TARGET_ENOSYS;
7836 }
57b9ccd4
RH
7837 if (timeout) {
7838 pts = &ts;
7839 if (time64
7840 ? target_to_host_timespec64(pts, timeout)
7841 : target_to_host_timespec(pts, timeout)) {
7842 return -TARGET_EFAULT;
7843 }
7844 }
7845 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, haddr2, val3);
bd0c5661 7846}
859e8a89 7847#endif
14690296 7848
0f0426f3
LV
7849#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7850static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7851 abi_long handle, abi_long mount_id,
7852 abi_long flags)
7853{
7854 struct file_handle *target_fh;
7855 struct file_handle *fh;
7856 int mid = 0;
7857 abi_long ret;
7858 char *name;
7859 unsigned int size, total_size;
7860
7861 if (get_user_s32(size, handle)) {
7862 return -TARGET_EFAULT;
7863 }
7864
7865 name = lock_user_string(pathname);
7866 if (!name) {
7867 return -TARGET_EFAULT;
7868 }
7869
7870 total_size = sizeof(struct file_handle) + size;
7871 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7872 if (!target_fh) {
7873 unlock_user(name, pathname, 0);
7874 return -TARGET_EFAULT;
7875 }
7876
7877 fh = g_malloc0(total_size);
7878 fh->handle_bytes = size;
7879
7880 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7881 unlock_user(name, pathname, 0);
7882
7883 /* man name_to_handle_at(2):
7884 * Other than the use of the handle_bytes field, the caller should treat
7885 * the file_handle structure as an opaque data type
7886 */
7887
7888 memcpy(target_fh, fh, total_size);
7889 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7890 target_fh->handle_type = tswap32(fh->handle_type);
7891 g_free(fh);
7892 unlock_user(target_fh, handle, total_size);
7893
7894 if (put_user_s32(mid, mount_id)) {
7895 return -TARGET_EFAULT;
7896 }
7897
7898 return ret;
7899
7900}
7901#endif
7902
7903#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7904static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7905 abi_long flags)
7906{
7907 struct file_handle *target_fh;
7908 struct file_handle *fh;
7909 unsigned int size, total_size;
7910 abi_long ret;
7911
7912 if (get_user_s32(size, handle)) {
7913 return -TARGET_EFAULT;
7914 }
7915
7916 total_size = sizeof(struct file_handle) + size;
7917 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7918 if (!target_fh) {
7919 return -TARGET_EFAULT;
7920 }
7921
e9d49d51 7922 fh = g_memdup(target_fh, total_size);
0f0426f3
LV
7923 fh->handle_bytes = size;
7924 fh->handle_type = tswap32(target_fh->handle_type);
7925
7926 ret = get_errno(open_by_handle_at(mount_fd, fh,
7927 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7928
7929 g_free(fh);
7930
7931 unlock_user(target_fh, handle, total_size);
7932
7933 return ret;
7934}
7935#endif
bd0c5661 7936
e36800c9
LV
7937#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7938
e36800c9
LV
7939static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7940{
7941 int host_flags;
7942 target_sigset_t *target_mask;
7943 sigset_t host_mask;
7944 abi_long ret;
7945
78721301 7946 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
e36800c9
LV
7947 return -TARGET_EINVAL;
7948 }
7949 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7950 return -TARGET_EFAULT;
7951 }
7952
7953 target_to_host_sigset(&host_mask, target_mask);
7954
7955 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7956
7957 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7958 if (ret >= 0) {
7959 fd_trans_register(ret, &target_signalfd_trans);
7960 }
7961
7962 unlock_user_struct(target_mask, mask, 0);
7963
7964 return ret;
7965}
7966#endif
7967
1d9d8b55
PB
7968/* Map host to target signal numbers for the wait family of syscalls.
7969 Assume all other status bits are the same. */
a05c6409 7970int host_to_target_waitstatus(int status)
1d9d8b55
PB
7971{
7972 if (WIFSIGNALED(status)) {
7973 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7974 }
7975 if (WIFSTOPPED(status)) {
7976 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7977 | (status & 0xff);
7978 }
7979 return status;
7980}
7981
a0939b89 7982static int open_self_cmdline(CPUArchState *cpu_env, int fd)
76b94245 7983{
0effdc29 7984 CPUState *cpu = env_cpu(cpu_env);
58de8b96
AS
7985 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
7986 int i;
76b94245 7987
58de8b96
AS
7988 for (i = 0; i < bprm->argc; i++) {
7989 size_t len = strlen(bprm->argv[i]) + 1;
76b94245 7990
58de8b96 7991 if (write(fd, bprm->argv[i], len) != len) {
76b94245 7992 return -1;
76b94245
WVS
7993 }
7994 }
7995
58de8b96 7996 return 0;
76b94245
WVS
7997}
7998
a0939b89 7999static int open_self_maps(CPUArchState *cpu_env, int fd)
36c08d49 8000{
0effdc29 8001 CPUState *cpu = env_cpu(cpu_env);
0429a971 8002 TaskState *ts = cpu->opaque;
01ef6b9e
AB
8003 GSList *map_info = read_self_maps();
8004 GSList *s;
bb55173c 8005 int count;
1a49ef2a 8006
01ef6b9e
AB
8007 for (s = map_info; s; s = g_slist_next(s)) {
8008 MapInfo *e = (MapInfo *) s->data;
1a49ef2a 8009
01ef6b9e
AB
8010 if (h2g_valid(e->start)) {
8011 unsigned long min = e->start;
8012 unsigned long max = e->end;
d67f4aaa 8013 int flags = page_get_flags(h2g(min));
01ef6b9e
AB
8014 const char *path;
8015
8016 max = h2g_valid(max - 1) ?
3e8f1628 8017 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
01ef6b9e 8018
d67f4aaa
MI
8019 if (page_check_range(h2g(min), max - min, flags) == -1) {
8020 continue;
8021 }
01ef6b9e 8022
0a3346b5
HD
8023#ifdef TARGET_HPPA
8024 if (h2g(max) == ts->info->stack_limit) {
8025#else
d67f4aaa 8026 if (h2g(min) == ts->info->stack_limit) {
0a3346b5 8027#endif
bb55173c 8028 path = "[stack]";
01ef6b9e
AB
8029 } else {
8030 path = e->path;
d67f4aaa 8031 }
01ef6b9e 8032
bb55173c
AB
8033 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8034 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8035 h2g(min), h2g(max - 1) + 1,
08f3a96b
NS
8036 (flags & PAGE_READ) ? 'r' : '-',
8037 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8038 (flags & PAGE_EXEC) ? 'x' : '-',
e13685a6 8039 e->is_priv ? 'p' : 's',
bb55173c
AB
8040 (uint64_t) e->offset, e->dev, e->inode);
8041 if (path) {
8042 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8043 } else {
8044 dprintf(fd, "\n");
8045 }
1a49ef2a
AG
8046 }
8047 }
8048
01ef6b9e
AB
8049 free_self_maps(map_info);
8050
bf02adcd
RH
8051#ifdef TARGET_VSYSCALL_PAGE
8052 /*
8053 * We only support execution from the vsyscall page.
8054 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8055 */
bb55173c
AB
8056 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8057 " --xp 00000000 00:00 0",
8058 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8059 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
bf02adcd
RH
8060#endif
8061
36c08d49
AG
8062 return 0;
8063}
8064
a0939b89 8065static int open_self_stat(CPUArchState *cpu_env, int fd)
480b8e7d 8066{
0effdc29 8067 CPUState *cpu = env_cpu(cpu_env);
0429a971 8068 TaskState *ts = cpu->opaque;
7ad4d5a4 8069 g_autoptr(GString) buf = g_string_new(NULL);
480b8e7d
AG
8070 int i;
8071
8072 for (i = 0; i < 44; i++) {
7ad4d5a4
AB
8073 if (i == 0) {
8074 /* pid */
8075 g_string_printf(buf, FMT_pid " ", getpid());
8076 } else if (i == 1) {
8077 /* app name */
8078 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8079 bin = bin ? bin + 1 : ts->bprm->argv[0];
8080 g_string_printf(buf, "(%.15s) ", bin);
7aa9fe3a
AS
8081 } else if (i == 3) {
8082 /* ppid */
8083 g_string_printf(buf, FMT_pid " ", getppid());
eb33cdae
CE
8084 } else if (i == 21) {
8085 /* starttime */
8086 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
7ad4d5a4
AB
8087 } else if (i == 27) {
8088 /* stack bottom */
8089 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8090 } else {
8091 /* for the rest, there is MasterCard */
8092 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8093 }
8094
8095 if (write(fd, buf->str, buf->len) != buf->len) {
8096 return -1;
8097 }
480b8e7d
AG
8098 }
8099
8100 return 0;
8101}
8102
a0939b89 8103static int open_self_auxv(CPUArchState *cpu_env, int fd)
257450ee 8104{
0effdc29 8105 CPUState *cpu = env_cpu(cpu_env);
0429a971 8106 TaskState *ts = cpu->opaque;
257450ee
AG
8107 abi_ulong auxv = ts->info->saved_auxv;
8108 abi_ulong len = ts->info->auxv_len;
8109 char *ptr;
8110
8111 /*
8112 * Auxiliary vector is stored in target process stack.
8113 * read in whole auxv vector and copy it to file
8114 */
8115 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8116 if (ptr != NULL) {
8117 while (len > 0) {
8118 ssize_t r;
8119 r = write(fd, ptr, len);
8120 if (r <= 0) {
8121 break;
8122 }
8123 len -= r;
8124 ptr += r;
8125 }
8126 lseek(fd, 0, SEEK_SET);
8127 unlock_user(ptr, auxv, len);
8128 }
8129
8130 return 0;
8131}
8132
463d8e73
AS
8133static int is_proc_myself(const char *filename, const char *entry)
8134{
8135 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8136 filename += strlen("/proc/");
8137 if (!strncmp(filename, "self/", strlen("self/"))) {
8138 filename += strlen("self/");
8139 } else if (*filename >= '1' && *filename <= '9') {
8140 char myself[80];
8141 snprintf(myself, sizeof(myself), "%d/", getpid());
8142 if (!strncmp(filename, myself, strlen(myself))) {
8143 filename += strlen(myself);
8144 } else {
8145 return 0;
8146 }
8147 } else {
8148 return 0;
8149 }
8150 if (!strcmp(filename, entry)) {
8151 return 1;
8152 }
8153 }
8154 return 0;
8155}
8156
bd5ccd61
HD
8157static void excp_dump_file(FILE *logfile, CPUArchState *env,
8158 const char *fmt, int code)
8159{
8160 if (logfile) {
8161 CPUState *cs = env_cpu(env);
8162
8163 fprintf(logfile, fmt, code);
8164 fprintf(logfile, "Failing executable: %s\n", exec_path);
8165 cpu_dump_state(cs, logfile, 0);
8166 open_self_maps(env, fileno(logfile));
8167 }
8168}
8169
8170void target_exception_dump(CPUArchState *env, const char *fmt, int code)
8171{
8172 /* dump to console */
8173 excp_dump_file(stderr, env, fmt, code);
8174
8175 /* dump to log file */
8176 if (qemu_log_separate()) {
8177 FILE *logfile = qemu_log_trylock();
8178
8179 excp_dump_file(logfile, env, fmt, code);
8180 qemu_log_unlock(logfile);
8181 }
8182}
8183
ee3eb3a7 8184#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN || \
93a5661d 8185 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
de6b9933
LV
8186static int is_proc(const char *filename, const char *entry)
8187{
8188 return strcmp(filename, entry) == 0;
8189}
fff69382 8190#endif
de6b9933 8191
ee3eb3a7 8192#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
a0939b89 8193static int open_net_route(CPUArchState *cpu_env, int fd)
de6b9933
LV
8194{
8195 FILE *fp;
8196 char *line = NULL;
8197 size_t len = 0;
8198 ssize_t read;
8199
8200 fp = fopen("/proc/net/route", "r");
8201 if (fp == NULL) {
a3ca7bb2 8202 return -1;
de6b9933
LV
8203 }
8204
8205 /* read header */
8206
8207 read = getline(&line, &len, fp);
8208 dprintf(fd, "%s", line);
8209
8210 /* read routes */
8211
8212 while ((read = getline(&line, &len, fp)) != -1) {
8213 char iface[16];
8214 uint32_t dest, gw, mask;
8215 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
9d0bd0cd
PM
8216 int fields;
8217
8218 fields = sscanf(line,
8219 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8220 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8221 &mask, &mtu, &window, &irtt);
8222 if (fields != 11) {
8223 continue;
8224 }
de6b9933
LV
8225 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8226 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8227 metric, tswap32(mask), mtu, window, irtt);
8228 }
8229
8230 free(line);
8231 fclose(fp);
8232
8233 return 0;
8234}
8235#endif
8236
fff69382 8237#if defined(TARGET_SPARC)
a0939b89 8238static int open_cpuinfo(CPUArchState *cpu_env, int fd)
fff69382
LV
8239{
8240 dprintf(fd, "type\t\t: sun4u\n");
8241 return 0;
8242}
8243#endif
8244
93a5661d 8245#if defined(TARGET_HPPA)
a0939b89 8246static int open_cpuinfo(CPUArchState *cpu_env, int fd)
93a5661d 8247{
e0174afe
HD
8248 int i, num_cpus;
8249
8250 num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
8251 for (i = 0; i < num_cpus; i++) {
8252 dprintf(fd, "processor\t: %d\n", i);
8253 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8254 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8255 dprintf(fd, "capabilities\t: os32\n");
8256 dprintf(fd, "model\t\t: 9000/778/B160L - "
8257 "Merlin L2 160 QEMU (9000/778/B160L)\n\n");
8258 }
93a5661d
HD
8259 return 0;
8260}
8261#endif
8262
4ab6713e 8263#if defined(TARGET_M68K)
a0939b89 8264static int open_hardware(CPUArchState *cpu_env, int fd)
4ab6713e
LV
8265{
8266 dprintf(fd, "Model:\t\tqemu-m68k\n");
8267 return 0;
8268}
8269#endif
8270
a0939b89 8271static int do_openat(CPUArchState *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
3be14d05
AG
8272{
8273 struct fake_open {
8274 const char *filename;
a0939b89 8275 int (*fill)(CPUArchState *cpu_env, int fd);
de6b9933 8276 int (*cmp)(const char *s1, const char *s2);
3be14d05
AG
8277 };
8278 const struct fake_open *fake_open;
8279 static const struct fake_open fakes[] = {
de6b9933
LV
8280 { "maps", open_self_maps, is_proc_myself },
8281 { "stat", open_self_stat, is_proc_myself },
8282 { "auxv", open_self_auxv, is_proc_myself },
76b94245 8283 { "cmdline", open_self_cmdline, is_proc_myself },
ee3eb3a7 8284#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
de6b9933 8285 { "/proc/net/route", open_net_route, is_proc },
fff69382 8286#endif
93a5661d 8287#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
fff69382 8288 { "/proc/cpuinfo", open_cpuinfo, is_proc },
4ab6713e
LV
8289#endif
8290#if defined(TARGET_M68K)
8291 { "/proc/hardware", open_hardware, is_proc },
de6b9933
LV
8292#endif
8293 { NULL, NULL, NULL }
3be14d05
AG
8294 };
8295
aa07f5ec 8296 if (is_proc_myself(pathname, "exe")) {
00ed8a34 8297 return safe_openat(dirfd, exec_path, flags, mode);
aa07f5ec
MO
8298 }
8299
3be14d05 8300 for (fake_open = fakes; fake_open->filename; fake_open++) {
de6b9933 8301 if (fake_open->cmp(pathname, fake_open->filename)) {
3be14d05
AG
8302 break;
8303 }
8304 }
8305
8306 if (fake_open->filename) {
8307 const char *tmpdir;
8308 char filename[PATH_MAX];
8309 int fd, r;
8310
5b63de6b 8311 fd = memfd_create("qemu-open", 0);
3be14d05 8312 if (fd < 0) {
5b63de6b
RM
8313 if (errno != ENOSYS) {
8314 return fd;
8315 }
8316 /* create temporary file to map stat to */
8317 tmpdir = getenv("TMPDIR");
8318 if (!tmpdir)
8319 tmpdir = "/tmp";
8320 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8321 fd = mkstemp(filename);
8322 if (fd < 0) {
8323 return fd;
8324 }
8325 unlink(filename);
3be14d05 8326 }
3be14d05
AG
8327
8328 if ((r = fake_open->fill(cpu_env, fd))) {
a3ca7bb2 8329 int e = errno;
3be14d05 8330 close(fd);
a3ca7bb2 8331 errno = e;
3be14d05
AG
8332 return r;
8333 }
8334 lseek(fd, 0, SEEK_SET);
8335
8336 return fd;
8337 }
8338
c10a0738 8339 return safe_openat(dirfd, path(pathname), flags, mode);
3be14d05
AG
8340}
8341
55bbe4d5 8342static int do_execveat(CPUArchState *cpu_env, int dirfd,
156e1f67 8343 abi_long pathname, abi_long guest_argp,
55bbe4d5 8344 abi_long guest_envp, int flags)
156e1f67
DD
8345{
8346 int ret;
8347 char **argp, **envp;
8348 int argc, envc;
8349 abi_ulong gp;
8350 abi_ulong addr;
8351 char **q;
8352 void *p;
8353
8354 argc = 0;
8355
8356 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
8357 if (get_user_ual(addr, gp)) {
8358 return -TARGET_EFAULT;
8359 }
8360 if (!addr) {
8361 break;
8362 }
8363 argc++;
8364 }
8365 envc = 0;
8366 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
8367 if (get_user_ual(addr, gp)) {
8368 return -TARGET_EFAULT;
8369 }
8370 if (!addr) {
8371 break;
8372 }
8373 envc++;
8374 }
8375
8376 argp = g_new0(char *, argc + 1);
8377 envp = g_new0(char *, envc + 1);
8378
8379 for (gp = guest_argp, q = argp; gp; gp += sizeof(abi_ulong), q++) {
8380 if (get_user_ual(addr, gp)) {
8381 goto execve_efault;
8382 }
8383 if (!addr) {
8384 break;
8385 }
8386 *q = lock_user_string(addr);
8387 if (!*q) {
8388 goto execve_efault;
8389 }
8390 }
8391 *q = NULL;
8392
8393 for (gp = guest_envp, q = envp; gp; gp += sizeof(abi_ulong), q++) {
8394 if (get_user_ual(addr, gp)) {
8395 goto execve_efault;
8396 }
8397 if (!addr) {
8398 break;
8399 }
8400 *q = lock_user_string(addr);
8401 if (!*q) {
8402 goto execve_efault;
8403 }
8404 }
8405 *q = NULL;
8406
8407 /*
8408 * Although execve() is not an interruptible syscall it is
8409 * a special case where we must use the safe_syscall wrapper:
8410 * if we allow a signal to happen before we make the host
8411 * syscall then we will 'lose' it, because at the point of
8412 * execve the process leaves QEMU's control. So we use the
8413 * safe syscall wrapper to ensure that we either take the
8414 * signal as a guest signal, or else it does not happen
8415 * before the execve completes and makes it the other
8416 * program's problem.
8417 */
8418 p = lock_user_string(pathname);
8419 if (!p) {
8420 goto execve_efault;
8421 }
8422
8423 if (is_proc_myself(p, "exe")) {
55bbe4d5 8424 ret = get_errno(safe_execveat(dirfd, exec_path, argp, envp, flags));
156e1f67 8425 } else {
55bbe4d5 8426 ret = get_errno(safe_execveat(dirfd, p, argp, envp, flags));
156e1f67
DD
8427 }
8428
8429 unlock_user(p, pathname, 0);
8430
8431 goto execve_end;
8432
8433execve_efault:
8434 ret = -TARGET_EFAULT;
8435
8436execve_end:
8437 for (gp = guest_argp, q = argp; *q; gp += sizeof(abi_ulong), q++) {
8438 if (get_user_ual(addr, gp) || !addr) {
8439 break;
8440 }
8441 unlock_user(*q, addr, 0);
8442 }
8443 for (gp = guest_envp, q = envp; *q; gp += sizeof(abi_ulong), q++) {
8444 if (get_user_ual(addr, gp) || !addr) {
8445 break;
8446 }
8447 unlock_user(*q, addr, 0);
8448 }
8449
8450 g_free(argp);
8451 g_free(envp);
8452 return ret;
8453}
8454
aecc8861
AG
8455#define TIMER_MAGIC 0x0caf0000
8456#define TIMER_MAGIC_MASK 0xffff0000
8457
8458/* Convert QEMU provided timer ID back to internal 16bit index format */
8459static target_timer_t get_timer_id(abi_long arg)
8460{
8461 target_timer_t timerid = arg;
8462
8463 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8464 return -TARGET_EINVAL;
8465 }
8466
8467 timerid &= 0xffff;
8468
8469 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8470 return -TARGET_EINVAL;
8471 }
8472
8473 return timerid;
8474}
8475
2e0a8713
ST
8476static int target_to_host_cpu_mask(unsigned long *host_mask,
8477 size_t host_size,
8478 abi_ulong target_addr,
8479 size_t target_size)
8480{
8481 unsigned target_bits = sizeof(abi_ulong) * 8;
8482 unsigned host_bits = sizeof(*host_mask) * 8;
8483 abi_ulong *target_mask;
8484 unsigned i, j;
8485
8486 assert(host_size >= target_size);
8487
8488 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8489 if (!target_mask) {
8490 return -TARGET_EFAULT;
8491 }
8492 memset(host_mask, 0, host_size);
8493
8494 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8495 unsigned bit = i * target_bits;
8496 abi_ulong val;
8497
8498 __get_user(val, &target_mask[i]);
8499 for (j = 0; j < target_bits; j++, bit++) {
8500 if (val & (1UL << j)) {
8501 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8502 }
8503 }
8504 }
8505
8506 unlock_user(target_mask, target_addr, 0);
8507 return 0;
8508}
8509
8510static int host_to_target_cpu_mask(const unsigned long *host_mask,
8511 size_t host_size,
8512 abi_ulong target_addr,
8513 size_t target_size)
8514{
8515 unsigned target_bits = sizeof(abi_ulong) * 8;
8516 unsigned host_bits = sizeof(*host_mask) * 8;
8517 abi_ulong *target_mask;
8518 unsigned i, j;
8519
8520 assert(host_size >= target_size);
8521
8522 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8523 if (!target_mask) {
8524 return -TARGET_EFAULT;
8525 }
8526
8527 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8528 unsigned bit = i * target_bits;
8529 abi_ulong val = 0;
8530
8531 for (j = 0; j < target_bits; j++, bit++) {
8532 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8533 val |= 1UL << j;
8534 }
8535 }
8536 __put_user(val, &target_mask[i]);
8537 }
8538
8539 unlock_user(target_mask, target_addr, target_size);
8540 return 0;
8541}
8542
fd08ddb9 8543#ifdef TARGET_NR_getdents
aee14c77 8544static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8545{
aee14c77
RH
8546 g_autofree void *hdirp = NULL;
8547 void *tdirp;
8548 int hlen, hoff, toff;
8549 int hreclen, treclen;
8550 off64_t prev_diroff = 0;
8551
8552 hdirp = g_try_malloc(count);
8553 if (!hdirp) {
8554 return -TARGET_ENOMEM;
8555 }
fd08ddb9
RH
8556
8557#ifdef EMULATE_GETDENTS_WITH_GETDENTS
aee14c77
RH
8558 hlen = sys_getdents(dirfd, hdirp, count);
8559#else
8560 hlen = sys_getdents64(dirfd, hdirp, count);
8561#endif
fd08ddb9 8562
aee14c77
RH
8563 hlen = get_errno(hlen);
8564 if (is_error(hlen)) {
8565 return hlen;
fd08ddb9
RH
8566 }
8567
aee14c77
RH
8568 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8569 if (!tdirp) {
fd08ddb9
RH
8570 return -TARGET_EFAULT;
8571 }
aee14c77
RH
8572
8573 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8574#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8575 struct linux_dirent *hde = hdirp + hoff;
fd08ddb9 8576#else
aee14c77
RH
8577 struct linux_dirent64 *hde = hdirp + hoff;
8578#endif
8579 struct target_dirent *tde = tdirp + toff;
8580 int namelen;
8581 uint8_t type;
fd08ddb9 8582
aee14c77
RH
8583 namelen = strlen(hde->d_name);
8584 hreclen = hde->d_reclen;
8585 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8586 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
fd08ddb9 8587
aee14c77 8588 if (toff + treclen > count) {
fd08ddb9 8589 /*
aee14c77
RH
8590 * If the host struct is smaller than the target struct, or
8591 * requires less alignment and thus packs into less space,
8592 * then the host can return more entries than we can pass
8593 * on to the guest.
fd08ddb9 8594 */
aee14c77
RH
8595 if (toff == 0) {
8596 toff = -TARGET_EINVAL; /* result buffer is too small */
8597 break;
8598 }
8599 /*
8600 * Return what we have, resetting the file pointer to the
8601 * location of the first record not returned.
8602 */
8603 lseek64(dirfd, prev_diroff, SEEK_SET);
8604 break;
fd08ddb9 8605 }
aee14c77
RH
8606
8607 prev_diroff = hde->d_off;
8608 tde->d_ino = tswapal(hde->d_ino);
8609 tde->d_off = tswapal(hde->d_off);
8610 tde->d_reclen = tswap16(treclen);
8611 memcpy(tde->d_name, hde->d_name, namelen + 1);
8612
8613 /*
8614 * The getdents type is in what was formerly a padding byte at the
8615 * end of the structure.
8616 */
8617#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8618 type = *((uint8_t *)hde + hreclen - 1);
8619#else
8620 type = hde->d_type;
fd08ddb9 8621#endif
aee14c77
RH
8622 *((uint8_t *)tde + treclen - 1) = type;
8623 }
8624
8625 unlock_user(tdirp, arg2, toff);
8626 return toff;
fd08ddb9
RH
8627}
8628#endif /* TARGET_NR_getdents */
8629
8630#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
aee14c77 8631static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8632{
aee14c77
RH
8633 g_autofree void *hdirp = NULL;
8634 void *tdirp;
8635 int hlen, hoff, toff;
8636 int hreclen, treclen;
8637 off64_t prev_diroff = 0;
8638
8639 hdirp = g_try_malloc(count);
8640 if (!hdirp) {
8641 return -TARGET_ENOMEM;
8642 }
fd08ddb9 8643
aee14c77
RH
8644 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8645 if (is_error(hlen)) {
8646 return hlen;
8647 }
8648
8649 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8650 if (!tdirp) {
fd08ddb9
RH
8651 return -TARGET_EFAULT;
8652 }
aee14c77
RH
8653
8654 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8655 struct linux_dirent64 *hde = hdirp + hoff;
8656 struct target_dirent64 *tde = tdirp + toff;
8657 int namelen;
8658
8659 namelen = strlen(hde->d_name) + 1;
8660 hreclen = hde->d_reclen;
8661 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8662 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8663
8664 if (toff + treclen > count) {
8665 /*
8666 * If the host struct is smaller than the target struct, or
8667 * requires less alignment and thus packs into less space,
8668 * then the host can return more entries than we can pass
8669 * on to the guest.
8670 */
8671 if (toff == 0) {
8672 toff = -TARGET_EINVAL; /* result buffer is too small */
fd08ddb9
RH
8673 break;
8674 }
aee14c77
RH
8675 /*
8676 * Return what we have, resetting the file pointer to the
8677 * location of the first record not returned.
8678 */
8679 lseek64(dirfd, prev_diroff, SEEK_SET);
8680 break;
fd08ddb9 8681 }
aee14c77
RH
8682
8683 prev_diroff = hde->d_off;
8684 tde->d_ino = tswap64(hde->d_ino);
8685 tde->d_off = tswap64(hde->d_off);
8686 tde->d_reclen = tswap16(treclen);
8687 tde->d_type = hde->d_type;
8688 memcpy(tde->d_name, hde->d_name, namelen);
fd08ddb9 8689 }
aee14c77
RH
8690
8691 unlock_user(tdirp, arg2, toff);
8692 return toff;
fd08ddb9
RH
8693}
8694#endif /* TARGET_NR_getdents64 */
8695
e10fbe8f
YT
8696#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8697_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8698#endif
8699
dc1ce18b
RH
8700/* This is an internal helper for do_syscall so that it is easier
8701 * to have a single return point, so that actions, such as logging
8702 * of syscall results, can be performed.
8703 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8704 */
a0939b89 8705static abi_long do_syscall1(CPUArchState *cpu_env, int num, abi_long arg1,
dc1ce18b
RH
8706 abi_long arg2, abi_long arg3, abi_long arg4,
8707 abi_long arg5, abi_long arg6, abi_long arg7,
8708 abi_long arg8)
31e31b8a 8709{
29a0af61 8710 CPUState *cpu = env_cpu(cpu_env);
992f48a0 8711 abi_long ret;
4f7f8924
AR
8712#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8713 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
efa92184
AR
8714 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8715 || defined(TARGET_NR_statx)
31e31b8a 8716 struct stat st;
4f7f8924
AR
8717#endif
8718#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8719 || defined(TARGET_NR_fstatfs)
56c8f68f 8720 struct statfs stfs;
4f7f8924 8721#endif
53a5960a 8722 void *p;
3b46e624 8723
31e31b8a
FB
8724 switch(num) {
8725 case TARGET_NR_exit:
9b056fcc 8726 /* In old applications this may be used to implement _exit(2).
6f9ff551 8727 However in threaded applications it is used for thread termination,
9b056fcc
AF
8728 and _exit_group is used for application termination.
8729 Do thread termination if we have more then one thread. */
a0995886
TB
8730
8731 if (block_signals()) {
af254a27 8732 return -QEMU_ERESTARTSYS;
a0995886
TB
8733 }
8734
1f81ce90 8735 pthread_mutex_lock(&clone_lock);
dd1f6349 8736
bdc44640 8737 if (CPU_NEXT(first_cpu)) {
1f81ce90 8738 TaskState *ts = cpu->opaque;
9b056fcc 8739
6490d9aa
RH
8740 if (ts->child_tidptr) {
8741 put_user_u32(0, ts->child_tidptr);
8742 do_sys_futex(g2h(cpu, ts->child_tidptr),
8743 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
8744 }
8745
8746 object_unparent(OBJECT(cpu));
1f81ce90
AB
8747 object_unref(OBJECT(cpu));
8748 /*
8749 * At this point the CPU should be unrealized and removed
8750 * from cpu lists. We can clean-up the rest of the thread
8751 * data without the lock held.
8752 */
dd1f6349 8753
1f81ce90 8754 pthread_mutex_unlock(&clone_lock);
dd1f6349 8755
a2247f8e 8756 thread_cpu = NULL;
9b056fcc 8757 g_free(ts);
70903763 8758 rcu_unregister_thread();
9b056fcc
AF
8759 pthread_exit(NULL);
8760 }
dd1f6349 8761
1f81ce90 8762 pthread_mutex_unlock(&clone_lock);
708b6a64 8763 preexit_cleanup(cpu_env, arg1);
c2764719 8764 _exit(arg1);
72eb7ea8 8765 return 0; /* avoid warning */
31e31b8a 8766 case TARGET_NR_read:
ba584f1d
AS
8767 if (arg2 == 0 && arg3 == 0) {
8768 return get_errno(safe_read(arg1, 0, 0));
72eb7ea8 8769 } else {
38d840e6 8770 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
2852aafd 8771 return -TARGET_EFAULT;
50afd02b 8772 ret = get_errno(safe_read(arg1, p, arg3));
e36800c9 8773 if (ret >= 0 &&
5d4d3665
LV
8774 fd_trans_host_to_target_data(arg1)) {
8775 ret = fd_trans_host_to_target_data(arg1)(p, ret);
e36800c9 8776 }
38d840e6
AJ
8777 unlock_user(p, arg2, ret);
8778 }
72eb7ea8 8779 return ret;
31e31b8a 8780 case TARGET_NR_write:
58cfa6c2
TGJ
8781 if (arg2 == 0 && arg3 == 0) {
8782 return get_errno(safe_write(arg1, 0, 0));
8783 }
579a97f7 8784 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
2852aafd 8785 return -TARGET_EFAULT;
04b9bcf9
LV
8786 if (fd_trans_target_to_host_data(arg1)) {
8787 void *copy = g_malloc(arg3);
8788 memcpy(copy, p, arg3);
8789 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8790 if (ret >= 0) {
8791 ret = get_errno(safe_write(arg1, copy, ret));
8792 }
8793 g_free(copy);
8794 } else {
8795 ret = get_errno(safe_write(arg1, p, arg3));
8796 }
53a5960a 8797 unlock_user(p, arg2, 0);
72eb7ea8
RH
8798 return ret;
8799
704eff6c 8800#ifdef TARGET_NR_open
31e31b8a 8801 case TARGET_NR_open:
2f619698 8802 if (!(p = lock_user_string(arg1)))
2852aafd 8803 return -TARGET_EFAULT;
0b2effd7
RV
8804 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8805 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8806 arg3));
e36800c9 8807 fd_trans_unregister(ret);
53a5960a 8808 unlock_user(p, arg1, 0);
72eb7ea8 8809 return ret;
704eff6c 8810#endif
82424832 8811 case TARGET_NR_openat:
579a97f7 8812 if (!(p = lock_user_string(arg2)))
2852aafd 8813 return -TARGET_EFAULT;
0b2effd7
RV
8814 ret = get_errno(do_openat(cpu_env, arg1, p,
8815 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8816 arg4));
e36800c9 8817 fd_trans_unregister(ret);
579a97f7 8818 unlock_user(p, arg2, 0);
72eb7ea8 8819 return ret;
0f0426f3
LV
8820#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8821 case TARGET_NR_name_to_handle_at:
8822 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
72eb7ea8 8823 return ret;
0f0426f3
LV
8824#endif
8825#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8826 case TARGET_NR_open_by_handle_at:
8827 ret = do_open_by_handle_at(arg1, arg2, arg3);
e36800c9 8828 fd_trans_unregister(ret);
72eb7ea8 8829 return ret;
cc054c6f
HD
8830#endif
8831#if defined(__NR_pidfd_open) && defined(TARGET_NR_pidfd_open)
8832 case TARGET_NR_pidfd_open:
8833 return get_errno(pidfd_open(arg1, arg2));
8834#endif
8835#if defined(__NR_pidfd_send_signal) && defined(TARGET_NR_pidfd_send_signal)
8836 case TARGET_NR_pidfd_send_signal:
8837 {
46187d70 8838 siginfo_t uinfo, *puinfo;
cc054c6f 8839
46187d70
LV
8840 if (arg3) {
8841 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8842 if (!p) {
8843 return -TARGET_EFAULT;
8844 }
8845 target_to_host_siginfo(&uinfo, p);
8846 unlock_user(p, arg3, 0);
8847 puinfo = &uinfo;
8848 } else {
8849 puinfo = NULL;
cc054c6f 8850 }
cc054c6f 8851 ret = get_errno(pidfd_send_signal(arg1, target_to_host_signal(arg2),
46187d70 8852 puinfo, arg4));
cc054c6f
HD
8853 }
8854 return ret;
8855#endif
8856#if defined(__NR_pidfd_getfd) && defined(TARGET_NR_pidfd_getfd)
8857 case TARGET_NR_pidfd_getfd:
8858 return get_errno(pidfd_getfd(arg1, arg2, arg3));
0f0426f3 8859#endif
31e31b8a 8860 case TARGET_NR_close:
e36800c9 8861 fd_trans_unregister(arg1);
72eb7ea8 8862 return get_errno(close(arg1));
af804f39
HD
8863#if defined(__NR_close_range) && defined(TARGET_NR_close_range)
8864 case TARGET_NR_close_range:
8865 ret = get_errno(sys_close_range(arg1, arg2, arg3));
8866 if (ret == 0 && !(arg3 & CLOSE_RANGE_CLOEXEC)) {
8867 abi_long fd, maxfd;
8868 maxfd = MIN(arg2, target_fd_max);
8869 for (fd = arg1; fd < maxfd; fd++) {
8870 fd_trans_unregister(fd);
8871 }
8872 }
8873 return ret;
8874#endif
72eb7ea8 8875
31e31b8a 8876 case TARGET_NR_brk:
72eb7ea8 8877 return do_brk(arg1);
704eff6c 8878#ifdef TARGET_NR_fork
31e31b8a 8879 case TARGET_NR_fork:
72eb7ea8 8880 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
704eff6c 8881#endif
e5febef5 8882#ifdef TARGET_NR_waitpid
31e31b8a
FB
8883 case TARGET_NR_waitpid:
8884 {
53a5960a 8885 int status;
4af80a37 8886 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
5379557b 8887 if (!is_error(ret) && arg2 && ret
1d9d8b55 8888 && put_user_s32(host_to_target_waitstatus(status), arg2))
2852aafd 8889 return -TARGET_EFAULT;
31e31b8a 8890 }
72eb7ea8 8891 return ret;
e5febef5 8892#endif
f0cbb613
PB
8893#ifdef TARGET_NR_waitid
8894 case TARGET_NR_waitid:
8895 {
8896 siginfo_t info;
8897 info.si_pid = 0;
4af80a37 8898 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
f0cbb613 8899 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 8900 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
2852aafd 8901 return -TARGET_EFAULT;
f0cbb613 8902 host_to_target_siginfo(p, &info);
c227f099 8903 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
8904 }
8905 }
72eb7ea8 8906 return ret;
f0cbb613 8907#endif
7a3148a9 8908#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 8909 case TARGET_NR_creat:
579a97f7 8910 if (!(p = lock_user_string(arg1)))
2852aafd 8911 return -TARGET_EFAULT;
53a5960a 8912 ret = get_errno(creat(p, arg2));
e36800c9 8913 fd_trans_unregister(ret);
53a5960a 8914 unlock_user(p, arg1, 0);
72eb7ea8 8915 return ret;
7a3148a9 8916#endif
704eff6c 8917#ifdef TARGET_NR_link
31e31b8a 8918 case TARGET_NR_link:
53a5960a
PB
8919 {
8920 void * p2;
8921 p = lock_user_string(arg1);
8922 p2 = lock_user_string(arg2);
579a97f7
FB
8923 if (!p || !p2)
8924 ret = -TARGET_EFAULT;
8925 else
8926 ret = get_errno(link(p, p2));
53a5960a
PB
8927 unlock_user(p2, arg2, 0);
8928 unlock_user(p, arg1, 0);
8929 }
72eb7ea8 8930 return ret;
704eff6c 8931#endif
c0d472b1 8932#if defined(TARGET_NR_linkat)
64f0ce4c 8933 case TARGET_NR_linkat:
64f0ce4c
TS
8934 {
8935 void * p2 = NULL;
579a97f7 8936 if (!arg2 || !arg4)
2852aafd 8937 return -TARGET_EFAULT;
64f0ce4c
TS
8938 p = lock_user_string(arg2);
8939 p2 = lock_user_string(arg4);
579a97f7 8940 if (!p || !p2)
0da46a6e 8941 ret = -TARGET_EFAULT;
64f0ce4c 8942 else
c0d472b1 8943 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
8944 unlock_user(p, arg2, 0);
8945 unlock_user(p2, arg4, 0);
64f0ce4c 8946 }
72eb7ea8 8947 return ret;
64f0ce4c 8948#endif
704eff6c 8949#ifdef TARGET_NR_unlink
31e31b8a 8950 case TARGET_NR_unlink:
579a97f7 8951 if (!(p = lock_user_string(arg1)))
2852aafd 8952 return -TARGET_EFAULT;
53a5960a
PB
8953 ret = get_errno(unlink(p));
8954 unlock_user(p, arg1, 0);
72eb7ea8 8955 return ret;
704eff6c 8956#endif
c0d472b1 8957#if defined(TARGET_NR_unlinkat)
8170f56b 8958 case TARGET_NR_unlinkat:
579a97f7 8959 if (!(p = lock_user_string(arg2)))
2852aafd 8960 return -TARGET_EFAULT;
c0d472b1 8961 ret = get_errno(unlinkat(arg1, p, arg3));
579a97f7 8962 unlock_user(p, arg2, 0);
72eb7ea8 8963 return ret;
b7d35e65 8964#endif
55bbe4d5
DD
8965 case TARGET_NR_execveat:
8966 return do_execveat(cpu_env, arg1, arg2, arg3, arg4, arg5);
31e31b8a 8967 case TARGET_NR_execve:
55bbe4d5 8968 return do_execveat(cpu_env, AT_FDCWD, arg1, arg2, arg3, 0);
31e31b8a 8969 case TARGET_NR_chdir:
579a97f7 8970 if (!(p = lock_user_string(arg1)))
2852aafd 8971 return -TARGET_EFAULT;
53a5960a
PB
8972 ret = get_errno(chdir(p));
8973 unlock_user(p, arg1, 0);
72eb7ea8 8974 return ret;
a315a145 8975#ifdef TARGET_NR_time
31e31b8a
FB
8976 case TARGET_NR_time:
8977 {
53a5960a
PB
8978 time_t host_time;
8979 ret = get_errno(time(&host_time));
2f619698
FB
8980 if (!is_error(ret)
8981 && arg1
8982 && put_user_sal(host_time, arg1))
2852aafd 8983 return -TARGET_EFAULT;
31e31b8a 8984 }
72eb7ea8 8985 return ret;
a315a145 8986#endif
704eff6c 8987#ifdef TARGET_NR_mknod
31e31b8a 8988 case TARGET_NR_mknod:
579a97f7 8989 if (!(p = lock_user_string(arg1)))
2852aafd 8990 return -TARGET_EFAULT;
53a5960a
PB
8991 ret = get_errno(mknod(p, arg2, arg3));
8992 unlock_user(p, arg1, 0);
72eb7ea8 8993 return ret;
704eff6c 8994#endif
c0d472b1 8995#if defined(TARGET_NR_mknodat)
75ac37a0 8996 case TARGET_NR_mknodat:
579a97f7 8997 if (!(p = lock_user_string(arg2)))
2852aafd 8998 return -TARGET_EFAULT;
c0d472b1 8999 ret = get_errno(mknodat(arg1, p, arg3, arg4));
579a97f7 9000 unlock_user(p, arg2, 0);
72eb7ea8 9001 return ret;
75ac37a0 9002#endif
704eff6c 9003#ifdef TARGET_NR_chmod
31e31b8a 9004 case TARGET_NR_chmod:
579a97f7 9005 if (!(p = lock_user_string(arg1)))
2852aafd 9006 return -TARGET_EFAULT;
53a5960a
PB
9007 ret = get_errno(chmod(p, arg2));
9008 unlock_user(p, arg1, 0);
72eb7ea8 9009 return ret;
704eff6c 9010#endif
4f7f8924 9011#ifdef TARGET_NR_lseek
31e31b8a 9012 case TARGET_NR_lseek:
72eb7ea8 9013 return get_errno(lseek(arg1, arg2, arg3));
4f7f8924 9014#endif
9231733a
RH
9015#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
9016 /* Alpha specific */
7a3148a9 9017 case TARGET_NR_getxpid:
0effdc29 9018 cpu_env->ir[IR_A4] = getppid();
72eb7ea8 9019 return get_errno(getpid());
7a3148a9 9020#endif
9231733a
RH
9021#ifdef TARGET_NR_getpid
9022 case TARGET_NR_getpid:
72eb7ea8 9023 return get_errno(getpid());
9231733a 9024#endif
31e31b8a 9025 case TARGET_NR_mount:
356d771b
PB
9026 {
9027 /* need to look at the data field */
9028 void *p2, *p3;
9029
9030 if (arg1) {
9031 p = lock_user_string(arg1);
9032 if (!p) {
2852aafd 9033 return -TARGET_EFAULT;
356d771b
PB
9034 }
9035 } else {
9036 p = NULL;
9037 }
9038
9039 p2 = lock_user_string(arg2);
9040 if (!p2) {
9041 if (arg1) {
9042 unlock_user(p, arg1, 0);
9043 }
2852aafd 9044 return -TARGET_EFAULT;
356d771b
PB
9045 }
9046
9047 if (arg3) {
9048 p3 = lock_user_string(arg3);
9049 if (!p3) {
9050 if (arg1) {
579a97f7 9051 unlock_user(p, arg1, 0);
356d771b
PB
9052 }
9053 unlock_user(p2, arg2, 0);
2852aafd 9054 return -TARGET_EFAULT;
356d771b
PB
9055 }
9056 } else {
9057 p3 = NULL;
9058 }
9059
9060 /* FIXME - arg5 should be locked, but it isn't clear how to
9061 * do that since it's not guaranteed to be a NULL-terminated
9062 * string.
9063 */
9064 if (!arg5) {
9065 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
9066 } else {
3e8f1628 9067 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
356d771b
PB
9068 }
9069 ret = get_errno(ret);
9070
9071 if (arg1) {
9072 unlock_user(p, arg1, 0);
9073 }
9074 unlock_user(p2, arg2, 0);
9075 if (arg3) {
9076 unlock_user(p3, arg3, 0);
9077 }
9078 }
72eb7ea8 9079 return ret;
6eb9dbf6
LV
9080#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
9081#if defined(TARGET_NR_umount)
31e31b8a 9082 case TARGET_NR_umount:
6eb9dbf6
LV
9083#endif
9084#if defined(TARGET_NR_oldumount)
9085 case TARGET_NR_oldumount:
9086#endif
579a97f7 9087 if (!(p = lock_user_string(arg1)))
2852aafd 9088 return -TARGET_EFAULT;
53a5960a
PB
9089 ret = get_errno(umount(p));
9090 unlock_user(p, arg1, 0);
72eb7ea8 9091 return ret;
e5febef5 9092#endif
7a3148a9 9093#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
9094 case TARGET_NR_stime:
9095 {
0f1f2d45
LV
9096 struct timespec ts;
9097 ts.tv_nsec = 0;
9098 if (get_user_sal(ts.tv_sec, arg1)) {
2852aafd 9099 return -TARGET_EFAULT;
0f1f2d45
LV
9100 }
9101 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
31e31b8a 9102 }
7a3148a9 9103#endif
7a3148a9 9104#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a 9105 case TARGET_NR_alarm:
72eb7ea8 9106 return alarm(arg1);
7a3148a9 9107#endif
7a3148a9 9108#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a 9109 case TARGET_NR_pause:
f59ec606
TB
9110 if (!block_signals()) {
9111 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9112 }
72eb7ea8 9113 return -TARGET_EINTR;
7a3148a9 9114#endif
e5febef5 9115#ifdef TARGET_NR_utime
31e31b8a 9116 case TARGET_NR_utime:
ebc05488 9117 {
53a5960a
PB
9118 struct utimbuf tbuf, *host_tbuf;
9119 struct target_utimbuf *target_tbuf;
9120 if (arg2) {
579a97f7 9121 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
2852aafd 9122 return -TARGET_EFAULT;
cbb21eed
MB
9123 tbuf.actime = tswapal(target_tbuf->actime);
9124 tbuf.modtime = tswapal(target_tbuf->modtime);
53a5960a
PB
9125 unlock_user_struct(target_tbuf, arg2, 0);
9126 host_tbuf = &tbuf;
f72e8ff4 9127 } else {
53a5960a 9128 host_tbuf = NULL;
f72e8ff4 9129 }
579a97f7 9130 if (!(p = lock_user_string(arg1)))
2852aafd 9131 return -TARGET_EFAULT;
53a5960a
PB
9132 ret = get_errno(utime(p, host_tbuf));
9133 unlock_user(p, arg1, 0);
ebc05488 9134 }
72eb7ea8 9135 return ret;
e5febef5 9136#endif
704eff6c 9137#ifdef TARGET_NR_utimes
978a66ff
FB
9138 case TARGET_NR_utimes:
9139 {
978a66ff 9140 struct timeval *tvp, tv[2];
53a5960a 9141 if (arg2) {
788f5ec4
TS
9142 if (copy_from_user_timeval(&tv[0], arg2)
9143 || copy_from_user_timeval(&tv[1],
9144 arg2 + sizeof(struct target_timeval)))
2852aafd 9145 return -TARGET_EFAULT;
978a66ff
FB
9146 tvp = tv;
9147 } else {
9148 tvp = NULL;
9149 }
579a97f7 9150 if (!(p = lock_user_string(arg1)))
2852aafd 9151 return -TARGET_EFAULT;
53a5960a
PB
9152 ret = get_errno(utimes(p, tvp));
9153 unlock_user(p, arg1, 0);
978a66ff 9154 }
72eb7ea8 9155 return ret;
704eff6c 9156#endif
c0d472b1 9157#if defined(TARGET_NR_futimesat)
ac8a6556
AZ
9158 case TARGET_NR_futimesat:
9159 {
9160 struct timeval *tvp, tv[2];
9161 if (arg3) {
9162 if (copy_from_user_timeval(&tv[0], arg3)
9163 || copy_from_user_timeval(&tv[1],
9164 arg3 + sizeof(struct target_timeval)))
2852aafd 9165 return -TARGET_EFAULT;
ac8a6556
AZ
9166 tvp = tv;
9167 } else {
9168 tvp = NULL;
9169 }
2852aafd
RH
9170 if (!(p = lock_user_string(arg2))) {
9171 return -TARGET_EFAULT;
9172 }
c0d472b1 9173 ret = get_errno(futimesat(arg1, path(p), tvp));
ac8a6556
AZ
9174 unlock_user(p, arg2, 0);
9175 }
72eb7ea8 9176 return ret;
ac8a6556 9177#endif
704eff6c 9178#ifdef TARGET_NR_access
31e31b8a 9179 case TARGET_NR_access:
2852aafd
RH
9180 if (!(p = lock_user_string(arg1))) {
9181 return -TARGET_EFAULT;
9182 }
719f908e 9183 ret = get_errno(access(path(p), arg2));
53a5960a 9184 unlock_user(p, arg1, 0);
72eb7ea8 9185 return ret;
704eff6c 9186#endif
92a34c10
TS
9187#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9188 case TARGET_NR_faccessat:
2852aafd
RH
9189 if (!(p = lock_user_string(arg2))) {
9190 return -TARGET_EFAULT;
9191 }
c0d472b1 9192 ret = get_errno(faccessat(arg1, p, arg3, 0));
579a97f7 9193 unlock_user(p, arg2, 0);
72eb7ea8 9194 return ret;
92a34c10 9195#endif
35a2c85f
WX
9196#if defined(TARGET_NR_faccessat2)
9197 case TARGET_NR_faccessat2:
9198 if (!(p = lock_user_string(arg2))) {
9199 return -TARGET_EFAULT;
9200 }
9201 ret = get_errno(faccessat(arg1, p, arg3, arg4));
9202 unlock_user(p, arg2, 0);
9203 return ret;
9204#endif
7a3148a9 9205#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a 9206 case TARGET_NR_nice:
72eb7ea8 9207 return get_errno(nice(arg1));
ebc05488 9208#endif
31e31b8a 9209 case TARGET_NR_sync:
04369ff2 9210 sync();
72eb7ea8 9211 return 0;
5a03cd00
AM
9212#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9213 case TARGET_NR_syncfs:
72eb7ea8 9214 return get_errno(syncfs(arg1));
5a03cd00 9215#endif
31e31b8a 9216 case TARGET_NR_kill:
72eb7ea8 9217 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
704eff6c 9218#ifdef TARGET_NR_rename
31e31b8a 9219 case TARGET_NR_rename:
53a5960a
PB
9220 {
9221 void *p2;
9222 p = lock_user_string(arg1);
9223 p2 = lock_user_string(arg2);
579a97f7
FB
9224 if (!p || !p2)
9225 ret = -TARGET_EFAULT;
9226 else
9227 ret = get_errno(rename(p, p2));
53a5960a
PB
9228 unlock_user(p2, arg2, 0);
9229 unlock_user(p, arg1, 0);
9230 }
72eb7ea8 9231 return ret;
704eff6c 9232#endif
c0d472b1 9233#if defined(TARGET_NR_renameat)
722183f6 9234 case TARGET_NR_renameat:
722183f6 9235 {
579a97f7 9236 void *p2;
722183f6
TS
9237 p = lock_user_string(arg2);
9238 p2 = lock_user_string(arg4);
579a97f7 9239 if (!p || !p2)
0da46a6e 9240 ret = -TARGET_EFAULT;
722183f6 9241 else
c0d472b1 9242 ret = get_errno(renameat(arg1, p, arg3, p2));
579a97f7
FB
9243 unlock_user(p2, arg4, 0);
9244 unlock_user(p, arg2, 0);
722183f6 9245 }
72eb7ea8 9246 return ret;
95d0307c
AS
9247#endif
9248#if defined(TARGET_NR_renameat2)
9249 case TARGET_NR_renameat2:
9250 {
9251 void *p2;
9252 p = lock_user_string(arg2);
9253 p2 = lock_user_string(arg4);
9254 if (!p || !p2) {
9255 ret = -TARGET_EFAULT;
9256 } else {
9257 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9258 }
9259 unlock_user(p2, arg4, 0);
9260 unlock_user(p, arg2, 0);
9261 }
72eb7ea8 9262 return ret;
722183f6 9263#endif
704eff6c 9264#ifdef TARGET_NR_mkdir
31e31b8a 9265 case TARGET_NR_mkdir:
579a97f7 9266 if (!(p = lock_user_string(arg1)))
2852aafd 9267 return -TARGET_EFAULT;
53a5960a
PB
9268 ret = get_errno(mkdir(p, arg2));
9269 unlock_user(p, arg1, 0);
72eb7ea8 9270 return ret;
704eff6c 9271#endif
c0d472b1 9272#if defined(TARGET_NR_mkdirat)
4472ad0d 9273 case TARGET_NR_mkdirat:
579a97f7 9274 if (!(p = lock_user_string(arg2)))
2852aafd 9275 return -TARGET_EFAULT;
c0d472b1 9276 ret = get_errno(mkdirat(arg1, p, arg3));
579a97f7 9277 unlock_user(p, arg2, 0);
72eb7ea8 9278 return ret;
4472ad0d 9279#endif
704eff6c 9280#ifdef TARGET_NR_rmdir
31e31b8a 9281 case TARGET_NR_rmdir:
579a97f7 9282 if (!(p = lock_user_string(arg1)))
2852aafd 9283 return -TARGET_EFAULT;
53a5960a
PB
9284 ret = get_errno(rmdir(p));
9285 unlock_user(p, arg1, 0);
72eb7ea8 9286 return ret;
704eff6c 9287#endif
31e31b8a
FB
9288 case TARGET_NR_dup:
9289 ret = get_errno(dup(arg1));
e36800c9
LV
9290 if (ret >= 0) {
9291 fd_trans_dup(arg1, ret);
9292 }
72eb7ea8 9293 return ret;
704eff6c 9294#ifdef TARGET_NR_pipe
31e31b8a 9295 case TARGET_NR_pipe:
72eb7ea8 9296 return do_pipe(cpu_env, arg1, 0, 0);
704eff6c 9297#endif
099d6b0f
RV
9298#ifdef TARGET_NR_pipe2
9299 case TARGET_NR_pipe2:
72eb7ea8
RH
9300 return do_pipe(cpu_env, arg1,
9301 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
099d6b0f 9302#endif
31e31b8a 9303 case TARGET_NR_times:
32f36bce 9304 {
53a5960a 9305 struct target_tms *tmsp;
32f36bce
FB
9306 struct tms tms;
9307 ret = get_errno(times(&tms));
53a5960a 9308 if (arg1) {
579a97f7
FB
9309 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9310 if (!tmsp)
2852aafd 9311 return -TARGET_EFAULT;
cbb21eed
MB
9312 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9313 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9314 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9315 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
32f36bce 9316 }
c596ed17
FB
9317 if (!is_error(ret))
9318 ret = host_to_target_clock_t(ret);
32f36bce 9319 }
72eb7ea8 9320 return ret;
31e31b8a 9321 case TARGET_NR_acct:
38d840e6
AJ
9322 if (arg1 == 0) {
9323 ret = get_errno(acct(NULL));
9324 } else {
2852aafd
RH
9325 if (!(p = lock_user_string(arg1))) {
9326 return -TARGET_EFAULT;
9327 }
38d840e6
AJ
9328 ret = get_errno(acct(path(p)));
9329 unlock_user(p, arg1, 0);
9330 }
72eb7ea8 9331 return ret;
8070e7be 9332#ifdef TARGET_NR_umount2
31e31b8a 9333 case TARGET_NR_umount2:
579a97f7 9334 if (!(p = lock_user_string(arg1)))
2852aafd 9335 return -TARGET_EFAULT;
53a5960a
PB
9336 ret = get_errno(umount2(p, arg2));
9337 unlock_user(p, arg1, 0);
72eb7ea8 9338 return ret;
ebc05488 9339#endif
31e31b8a 9340 case TARGET_NR_ioctl:
72eb7ea8 9341 return do_ioctl(arg1, arg2, arg3);
47ae93cd 9342#ifdef TARGET_NR_fcntl
31e31b8a 9343 case TARGET_NR_fcntl:
72eb7ea8 9344 return do_fcntl(arg1, arg2, arg3);
ebc05488 9345#endif
31e31b8a 9346 case TARGET_NR_setpgid:
72eb7ea8 9347 return get_errno(setpgid(arg1, arg2));
31e31b8a 9348 case TARGET_NR_umask:
72eb7ea8 9349 return get_errno(umask(arg1));
31e31b8a 9350 case TARGET_NR_chroot:
579a97f7 9351 if (!(p = lock_user_string(arg1)))
2852aafd 9352 return -TARGET_EFAULT;
53a5960a
PB
9353 ret = get_errno(chroot(p));
9354 unlock_user(p, arg1, 0);
72eb7ea8 9355 return ret;
704eff6c 9356#ifdef TARGET_NR_dup2
31e31b8a
FB
9357 case TARGET_NR_dup2:
9358 ret = get_errno(dup2(arg1, arg2));
e36800c9
LV
9359 if (ret >= 0) {
9360 fd_trans_dup(arg1, arg2);
9361 }
72eb7ea8 9362 return ret;
704eff6c 9363#endif
d0927938
UH
9364#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9365 case TARGET_NR_dup3:
10fa993a
PM
9366 {
9367 int host_flags;
9368
9369 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9370 return -EINVAL;
9371 }
9372 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9373 ret = get_errno(dup3(arg1, arg2, host_flags));
e36800c9
LV
9374 if (ret >= 0) {
9375 fd_trans_dup(arg1, arg2);
9376 }
72eb7ea8 9377 return ret;
10fa993a 9378 }
d0927938 9379#endif
7a3148a9 9380#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a 9381 case TARGET_NR_getppid:
72eb7ea8 9382 return get_errno(getppid());
7a3148a9 9383#endif
704eff6c 9384#ifdef TARGET_NR_getpgrp
31e31b8a 9385 case TARGET_NR_getpgrp:
72eb7ea8 9386 return get_errno(getpgrp());
704eff6c 9387#endif
31e31b8a 9388 case TARGET_NR_setsid:
72eb7ea8 9389 return get_errno(setsid());
e5febef5 9390#ifdef TARGET_NR_sigaction
31e31b8a 9391 case TARGET_NR_sigaction:
31e31b8a 9392 {
02d0de10 9393#if defined(TARGET_MIPS)
106ec879
FB
9394 struct target_sigaction act, oact, *pact, *old_act;
9395
9396 if (arg2) {
579a97f7 9397 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9398 return -TARGET_EFAULT;
106ec879
FB
9399 act._sa_handler = old_act->_sa_handler;
9400 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9401 act.sa_flags = old_act->sa_flags;
9402 unlock_user_struct(old_act, arg2, 0);
9403 pact = &act;
9404 } else {
9405 pact = NULL;
9406 }
9407
02fb28e8 9408 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
106ec879
FB
9409
9410 if (!is_error(ret) && arg3) {
579a97f7 9411 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9412 return -TARGET_EFAULT;
106ec879
FB
9413 old_act->_sa_handler = oact._sa_handler;
9414 old_act->sa_flags = oact.sa_flags;
9415 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9416 old_act->sa_mask.sig[1] = 0;
9417 old_act->sa_mask.sig[2] = 0;
9418 old_act->sa_mask.sig[3] = 0;
9419 unlock_user_struct(old_act, arg3, 1);
9420 }
6049f4f8
RH
9421#else
9422 struct target_old_sigaction *old_act;
9423 struct target_sigaction act, oact, *pact;
9424 if (arg2) {
9425 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9426 return -TARGET_EFAULT;
6049f4f8
RH
9427 act._sa_handler = old_act->_sa_handler;
9428 target_siginitset(&act.sa_mask, old_act->sa_mask);
9429 act.sa_flags = old_act->sa_flags;
ca192277 9430#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9431 act.sa_restorer = old_act->sa_restorer;
ca192277 9432#endif
6049f4f8
RH
9433 unlock_user_struct(old_act, arg2, 0);
9434 pact = &act;
9435 } else {
9436 pact = NULL;
9437 }
02fb28e8 9438 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
6049f4f8
RH
9439 if (!is_error(ret) && arg3) {
9440 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9441 return -TARGET_EFAULT;
6049f4f8
RH
9442 old_act->_sa_handler = oact._sa_handler;
9443 old_act->sa_mask = oact.sa_mask.sig[0];
9444 old_act->sa_flags = oact.sa_flags;
ca192277 9445#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9446 old_act->sa_restorer = oact.sa_restorer;
ca192277 9447#endif
6049f4f8
RH
9448 unlock_user_struct(old_act, arg3, 1);
9449 }
388bb21a 9450#endif
31e31b8a 9451 }
72eb7ea8 9452 return ret;
e5febef5 9453#endif
66fb9763 9454 case TARGET_NR_rt_sigaction:
53a5960a 9455 {
0f6f9903
RH
9456 /*
9457 * For Alpha and SPARC this is a 5 argument syscall, with
78bfef72
PM
9458 * a 'restorer' parameter which must be copied into the
9459 * sa_restorer field of the sigaction struct.
9460 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9461 * and arg5 is the sigsetsize.
78bfef72 9462 */
0f6f9903
RH
9463#if defined(TARGET_ALPHA)
9464 target_ulong sigsetsize = arg4;
9465 target_ulong restorer = arg5;
9466#elif defined(TARGET_SPARC)
78bfef72
PM
9467 target_ulong restorer = arg4;
9468 target_ulong sigsetsize = arg5;
9469#else
9470 target_ulong sigsetsize = arg4;
02fb28e8 9471 target_ulong restorer = 0;
78bfef72 9472#endif
fb80439b
RH
9473 struct target_sigaction *act = NULL;
9474 struct target_sigaction *oact = NULL;
53a5960a 9475
78bfef72 9476 if (sigsetsize != sizeof(target_sigset_t)) {
72eb7ea8 9477 return -TARGET_EINVAL;
c815701e 9478 }
fb80439b
RH
9479 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9480 return -TARGET_EFAULT;
78bfef72 9481 }
fb80439b
RH
9482 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9483 ret = -TARGET_EFAULT;
9484 } else {
9485 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9486 if (oact) {
9487 unlock_user_struct(oact, arg3, 1);
579a97f7 9488 }
fb80439b
RH
9489 }
9490 if (act) {
53a5960a 9491 unlock_user_struct(act, arg2, 0);
fb80439b 9492 }
53a5960a 9493 }
72eb7ea8 9494 return ret;
7a3148a9 9495#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 9496 case TARGET_NR_sgetmask:
66fb9763
FB
9497 {
9498 sigset_t cur_set;
992f48a0 9499 abi_ulong target_set;
3d3efba0
PM
9500 ret = do_sigprocmask(0, NULL, &cur_set);
9501 if (!ret) {
9502 host_to_target_old_sigset(&target_set, &cur_set);
9503 ret = target_set;
9504 }
66fb9763 9505 }
72eb7ea8 9506 return ret;
7a3148a9
JM
9507#endif
9508#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 9509 case TARGET_NR_ssetmask:
66fb9763 9510 {
a8617d8c 9511 sigset_t set, oset;
992f48a0 9512 abi_ulong target_set = arg1;
66fb9763 9513 target_to_host_old_sigset(&set, &target_set);
3d3efba0
PM
9514 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9515 if (!ret) {
9516 host_to_target_old_sigset(&target_set, &oset);
9517 ret = target_set;
9518 }
66fb9763 9519 }
72eb7ea8 9520 return ret;
7a3148a9 9521#endif
e5febef5 9522#ifdef TARGET_NR_sigprocmask
66fb9763
FB
9523 case TARGET_NR_sigprocmask:
9524 {
a5b3b13b
RH
9525#if defined(TARGET_ALPHA)
9526 sigset_t set, oldset;
9527 abi_ulong mask;
9528 int how;
9529
9530 switch (arg1) {
9531 case TARGET_SIG_BLOCK:
9532 how = SIG_BLOCK;
9533 break;
9534 case TARGET_SIG_UNBLOCK:
9535 how = SIG_UNBLOCK;
9536 break;
9537 case TARGET_SIG_SETMASK:
9538 how = SIG_SETMASK;
9539 break;
9540 default:
259841c1 9541 return -TARGET_EINVAL;
a5b3b13b
RH
9542 }
9543 mask = arg2;
9544 target_to_host_old_sigset(&set, &mask);
9545
3d3efba0 9546 ret = do_sigprocmask(how, &set, &oldset);
a5b3b13b
RH
9547 if (!is_error(ret)) {
9548 host_to_target_old_sigset(&mask, &oldset);
9549 ret = mask;
0effdc29 9550 cpu_env->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
9551 }
9552#else
66fb9763 9553 sigset_t set, oldset, *set_ptr;
a5b3b13b 9554 int how;
3b46e624 9555
53a5960a 9556 if (arg2) {
ebce1719
PV
9557 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9558 if (!p) {
9559 return -TARGET_EFAULT;
9560 }
9561 target_to_host_old_sigset(&set, p);
9562 unlock_user(p, arg2, 0);
9563 set_ptr = &set;
a5b3b13b 9564 switch (arg1) {
66fb9763
FB
9565 case TARGET_SIG_BLOCK:
9566 how = SIG_BLOCK;
9567 break;
9568 case TARGET_SIG_UNBLOCK:
9569 how = SIG_UNBLOCK;
9570 break;
9571 case TARGET_SIG_SETMASK:
9572 how = SIG_SETMASK;
9573 break;
9574 default:
259841c1 9575 return -TARGET_EINVAL;
66fb9763 9576 }
66fb9763
FB
9577 } else {
9578 how = 0;
9579 set_ptr = NULL;
9580 }
3d3efba0 9581 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9582 if (!is_error(ret) && arg3) {
c227f099 9583 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9584 return -TARGET_EFAULT;
53a5960a 9585 host_to_target_old_sigset(p, &oldset);
c227f099 9586 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 9587 }
a5b3b13b 9588#endif
66fb9763 9589 }
72eb7ea8 9590 return ret;
e5febef5 9591#endif
66fb9763
FB
9592 case TARGET_NR_rt_sigprocmask:
9593 {
9594 int how = arg1;
9595 sigset_t set, oldset, *set_ptr;
3b46e624 9596
c815701e 9597 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9598 return -TARGET_EINVAL;
c815701e
PM
9599 }
9600
53a5960a 9601 if (arg2) {
d3ced2a5
SCW
9602 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9603 if (!p) {
9604 return -TARGET_EFAULT;
9605 }
9606 target_to_host_sigset(&set, p);
9607 unlock_user(p, arg2, 0);
9608 set_ptr = &set;
66fb9763
FB
9609 switch(how) {
9610 case TARGET_SIG_BLOCK:
9611 how = SIG_BLOCK;
9612 break;
9613 case TARGET_SIG_UNBLOCK:
9614 how = SIG_UNBLOCK;
9615 break;
9616 case TARGET_SIG_SETMASK:
9617 how = SIG_SETMASK;
9618 break;
9619 default:
259841c1 9620 return -TARGET_EINVAL;
66fb9763 9621 }
66fb9763
FB
9622 } else {
9623 how = 0;
9624 set_ptr = NULL;
9625 }
3d3efba0 9626 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9627 if (!is_error(ret) && arg3) {
c227f099 9628 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9629 return -TARGET_EFAULT;
53a5960a 9630 host_to_target_sigset(p, &oldset);
c227f099 9631 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
9632 }
9633 }
72eb7ea8 9634 return ret;
e5febef5 9635#ifdef TARGET_NR_sigpending
66fb9763
FB
9636 case TARGET_NR_sigpending:
9637 {
9638 sigset_t set;
9639 ret = get_errno(sigpending(&set));
9640 if (!is_error(ret)) {
c227f099 9641 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9642 return -TARGET_EFAULT;
53a5960a 9643 host_to_target_old_sigset(p, &set);
c227f099 9644 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9645 }
9646 }
72eb7ea8 9647 return ret;
e5febef5 9648#endif
66fb9763
FB
9649 case TARGET_NR_rt_sigpending:
9650 {
9651 sigset_t set;
c815701e
PM
9652
9653 /* Yes, this check is >, not != like most. We follow the kernel's
9654 * logic and it does it like this because it implements
9655 * NR_sigpending through the same code path, and in that case
9656 * the old_sigset_t is smaller in size.
9657 */
9658 if (arg2 > sizeof(target_sigset_t)) {
72eb7ea8 9659 return -TARGET_EINVAL;
c815701e
PM
9660 }
9661
66fb9763
FB
9662 ret = get_errno(sigpending(&set));
9663 if (!is_error(ret)) {
c227f099 9664 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9665 return -TARGET_EFAULT;
53a5960a 9666 host_to_target_sigset(p, &set);
c227f099 9667 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9668 }
9669 }
72eb7ea8 9670 return ret;
e5febef5 9671#ifdef TARGET_NR_sigsuspend
66fb9763
FB
9672 case TARGET_NR_sigsuspend:
9673 {
0a99f093
RH
9674 sigset_t *set;
9675
f43ce12b 9676#if defined(TARGET_ALPHA)
0a99f093 9677 TaskState *ts = cpu->opaque;
7fb5ef35
RH
9678 /* target_to_host_old_sigset will bswap back */
9679 abi_ulong mask = tswapal(arg1);
0a99f093
RH
9680 set = &ts->sigsuspend_mask;
9681 target_to_host_old_sigset(set, &mask);
f43ce12b 9682#else
0a99f093
RH
9683 ret = process_sigsuspend_mask(&set, arg1, sizeof(target_sigset_t));
9684 if (ret != 0) {
9685 return ret;
3d3efba0 9686 }
0a99f093
RH
9687#endif
9688 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9689 finish_sigsuspend_mask(ret);
66fb9763 9690 }
72eb7ea8 9691 return ret;
e5febef5 9692#endif
66fb9763
FB
9693 case TARGET_NR_rt_sigsuspend:
9694 {
0a99f093 9695 sigset_t *set;
c815701e 9696
0a99f093
RH
9697 ret = process_sigsuspend_mask(&set, arg1, arg2);
9698 if (ret != 0) {
9699 return ret;
3d3efba0 9700 }
0a99f093
RH
9701 ret = get_errno(safe_rt_sigsuspend(set, SIGSET_T_SIZE));
9702 finish_sigsuspend_mask(ret);
66fb9763 9703 }
72eb7ea8 9704 return ret;
859e8a89 9705#ifdef TARGET_NR_rt_sigtimedwait
66fb9763
FB
9706 case TARGET_NR_rt_sigtimedwait:
9707 {
66fb9763
FB
9708 sigset_t set;
9709 struct timespec uts, *puts;
9710 siginfo_t uinfo;
3b46e624 9711
c815701e 9712 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9713 return -TARGET_EINVAL;
c815701e
PM
9714 }
9715
c227f099 9716 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
2852aafd 9717 return -TARGET_EFAULT;
53a5960a
PB
9718 target_to_host_sigset(&set, p);
9719 unlock_user(p, arg1, 0);
9720 if (arg3) {
66fb9763 9721 puts = &uts;
4d213001
FB
9722 if (target_to_host_timespec(puts, arg3)) {
9723 return -TARGET_EFAULT;
9724 }
66fb9763
FB
9725 } else {
9726 puts = NULL;
9727 }
b3f82330
PM
9728 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9729 SIGSET_T_SIZE));
974a196d
PJ
9730 if (!is_error(ret)) {
9731 if (arg2) {
9732 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9733 0);
9734 if (!p) {
2852aafd 9735 return -TARGET_EFAULT;
974a196d
PJ
9736 }
9737 host_to_target_siginfo(p, &uinfo);
9738 unlock_user(p, arg2, sizeof(target_siginfo_t));
9739 }
9740 ret = host_to_target_signal(ret);
66fb9763
FB
9741 }
9742 }
72eb7ea8 9743 return ret;
ddcbde15
FB
9744#endif
9745#ifdef TARGET_NR_rt_sigtimedwait_time64
9746 case TARGET_NR_rt_sigtimedwait_time64:
9747 {
9748 sigset_t set;
9749 struct timespec uts, *puts;
9750 siginfo_t uinfo;
9751
9752 if (arg4 != sizeof(target_sigset_t)) {
9753 return -TARGET_EINVAL;
9754 }
9755
9756 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9757 if (!p) {
9758 return -TARGET_EFAULT;
9759 }
9760 target_to_host_sigset(&set, p);
9761 unlock_user(p, arg1, 0);
9762 if (arg3) {
9763 puts = &uts;
9764 if (target_to_host_timespec64(puts, arg3)) {
9765 return -TARGET_EFAULT;
9766 }
9767 } else {
9768 puts = NULL;
9769 }
9770 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9771 SIGSET_T_SIZE));
9772 if (!is_error(ret)) {
9773 if (arg2) {
9774 p = lock_user(VERIFY_WRITE, arg2,
9775 sizeof(target_siginfo_t), 0);
9776 if (!p) {
9777 return -TARGET_EFAULT;
9778 }
9779 host_to_target_siginfo(p, &uinfo);
9780 unlock_user(p, arg2, sizeof(target_siginfo_t));
9781 }
9782 ret = host_to_target_signal(ret);
9783 }
9784 }
9785 return ret;
859e8a89 9786#endif
66fb9763
FB
9787 case TARGET_NR_rt_sigqueueinfo:
9788 {
9789 siginfo_t uinfo;
4debae6f
PM
9790
9791 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9792 if (!p) {
2852aafd 9793 return -TARGET_EFAULT;
4debae6f 9794 }
53a5960a 9795 target_to_host_siginfo(&uinfo, p);
d8b6d892 9796 unlock_user(p, arg3, 0);
9b9145f0 9797 ret = get_errno(sys_rt_sigqueueinfo(arg1, target_to_host_signal(arg2), &uinfo));
66fb9763 9798 }
72eb7ea8 9799 return ret;
cf8b8bfc
MS
9800 case TARGET_NR_rt_tgsigqueueinfo:
9801 {
9802 siginfo_t uinfo;
9803
9804 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9805 if (!p) {
2852aafd 9806 return -TARGET_EFAULT;
cf8b8bfc
MS
9807 }
9808 target_to_host_siginfo(&uinfo, p);
9809 unlock_user(p, arg4, 0);
9b9145f0 9810 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, target_to_host_signal(arg3), &uinfo));
cf8b8bfc 9811 }
72eb7ea8 9812 return ret;
e5febef5 9813#ifdef TARGET_NR_sigreturn
66fb9763 9814 case TARGET_NR_sigreturn:
3d3efba0 9815 if (block_signals()) {
af254a27 9816 return -QEMU_ERESTARTSYS;
3d3efba0 9817 }
72eb7ea8 9818 return do_sigreturn(cpu_env);
e5febef5 9819#endif
66fb9763 9820 case TARGET_NR_rt_sigreturn:
3d3efba0 9821 if (block_signals()) {
af254a27 9822 return -QEMU_ERESTARTSYS;
3d3efba0 9823 }
72eb7ea8 9824 return do_rt_sigreturn(cpu_env);
31e31b8a 9825 case TARGET_NR_sethostname:
579a97f7 9826 if (!(p = lock_user_string(arg1)))
2852aafd 9827 return -TARGET_EFAULT;
53a5960a
PB
9828 ret = get_errno(sethostname(p, arg2));
9829 unlock_user(p, arg1, 0);
72eb7ea8 9830 return ret;
4f7f8924 9831#ifdef TARGET_NR_setrlimit
31e31b8a 9832 case TARGET_NR_setrlimit:
9de5e440 9833 {
e22b7015 9834 int resource = target_to_host_resource(arg1);
53a5960a 9835 struct target_rlimit *target_rlim;
9de5e440 9836 struct rlimit rlim;
579a97f7 9837 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
2852aafd 9838 return -TARGET_EFAULT;
81bbe906
TY
9839 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9840 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 9841 unlock_user_struct(target_rlim, arg2, 0);
5dfa88f7
MF
9842 /*
9843 * If we just passed through resource limit settings for memory then
9844 * they would also apply to QEMU's own allocations, and QEMU will
9845 * crash or hang or die if its allocations fail. Ideally we would
9846 * track the guest allocations in QEMU and apply the limits ourselves.
9847 * For now, just tell the guest the call succeeded but don't actually
9848 * limit anything.
9849 */
9850 if (resource != RLIMIT_AS &&
9851 resource != RLIMIT_DATA &&
9852 resource != RLIMIT_STACK) {
9853 return get_errno(setrlimit(resource, &rlim));
9854 } else {
9855 return 0;
9856 }
9de5e440 9857 }
4f7f8924
AR
9858#endif
9859#ifdef TARGET_NR_getrlimit
31e31b8a 9860 case TARGET_NR_getrlimit:
9de5e440 9861 {
e22b7015 9862 int resource = target_to_host_resource(arg1);
53a5960a 9863 struct target_rlimit *target_rlim;
9de5e440 9864 struct rlimit rlim;
3b46e624 9865
9de5e440
FB
9866 ret = get_errno(getrlimit(resource, &rlim));
9867 if (!is_error(ret)) {
579a97f7 9868 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 9869 return -TARGET_EFAULT;
81bbe906
TY
9870 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9871 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 9872 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
9873 }
9874 }
72eb7ea8 9875 return ret;
4f7f8924 9876#endif
31e31b8a 9877 case TARGET_NR_getrusage:
b409186b
FB
9878 {
9879 struct rusage rusage;
b409186b
FB
9880 ret = get_errno(getrusage(arg1, &rusage));
9881 if (!is_error(ret)) {
a39fb273 9882 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
9883 }
9884 }
72eb7ea8 9885 return ret;
859e8a89 9886#if defined(TARGET_NR_gettimeofday)
31e31b8a
FB
9887 case TARGET_NR_gettimeofday:
9888 {
31e31b8a 9889 struct timeval tv;
a52f5f87
RH
9890 struct timezone tz;
9891
9892 ret = get_errno(gettimeofday(&tv, &tz));
31e31b8a 9893 if (!is_error(ret)) {
a52f5f87
RH
9894 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
9895 return -TARGET_EFAULT;
9896 }
9897 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
2852aafd 9898 return -TARGET_EFAULT;
a52f5f87 9899 }
31e31b8a
FB
9900 }
9901 }
72eb7ea8 9902 return ret;
859e8a89
AF
9903#endif
9904#if defined(TARGET_NR_settimeofday)
31e31b8a
FB
9905 case TARGET_NR_settimeofday:
9906 {
b67d8031 9907 struct timeval tv, *ptv = NULL;
ef4467e9
PB
9908 struct timezone tz, *ptz = NULL;
9909
b67d8031
PB
9910 if (arg1) {
9911 if (copy_from_user_timeval(&tv, arg1)) {
2852aafd 9912 return -TARGET_EFAULT;
b67d8031
PB
9913 }
9914 ptv = &tv;
9915 }
ef4467e9
PB
9916
9917 if (arg2) {
9918 if (copy_from_user_timezone(&tz, arg2)) {
2852aafd 9919 return -TARGET_EFAULT;
ef4467e9
PB
9920 }
9921 ptz = &tz;
9922 }
9923
72eb7ea8 9924 return get_errno(settimeofday(ptv, ptz));
31e31b8a 9925 }
859e8a89 9926#endif
9468a5d4 9927#if defined(TARGET_NR_select)
31e31b8a 9928 case TARGET_NR_select:
5457dc9e
LV
9929#if defined(TARGET_WANT_NI_OLD_SELECT)
9930 /* some architectures used to have old_select here
9931 * but now ENOSYS it.
9932 */
9933 ret = -TARGET_ENOSYS;
9934#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9935 ret = do_old_select(arg1);
9468a5d4 9936#else
5457dc9e 9937 ret = do_select(arg1, arg2, arg3, arg4, arg5);
9468a5d4 9938#endif
72eb7ea8 9939 return ret;
9e42382f
RV
9940#endif
9941#ifdef TARGET_NR_pselect6
9942 case TARGET_NR_pselect6:
e5ce9688
FB
9943 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9944#endif
9945#ifdef TARGET_NR_pselect6_time64
9946 case TARGET_NR_pselect6_time64:
9947 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
048f6b4d 9948#endif
704eff6c 9949#ifdef TARGET_NR_symlink
31e31b8a 9950 case TARGET_NR_symlink:
53a5960a
PB
9951 {
9952 void *p2;
9953 p = lock_user_string(arg1);
9954 p2 = lock_user_string(arg2);
579a97f7
FB
9955 if (!p || !p2)
9956 ret = -TARGET_EFAULT;
9957 else
9958 ret = get_errno(symlink(p, p2));
53a5960a
PB
9959 unlock_user(p2, arg2, 0);
9960 unlock_user(p, arg1, 0);
9961 }
72eb7ea8 9962 return ret;
704eff6c 9963#endif
c0d472b1 9964#if defined(TARGET_NR_symlinkat)
f0b6243d 9965 case TARGET_NR_symlinkat:
f0b6243d 9966 {
579a97f7 9967 void *p2;
f0b6243d
TS
9968 p = lock_user_string(arg1);
9969 p2 = lock_user_string(arg3);
579a97f7 9970 if (!p || !p2)
0da46a6e 9971 ret = -TARGET_EFAULT;
f0b6243d 9972 else
c0d472b1 9973 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
9974 unlock_user(p2, arg3, 0);
9975 unlock_user(p, arg1, 0);
f0b6243d 9976 }
72eb7ea8 9977 return ret;
f0b6243d 9978#endif
704eff6c 9979#ifdef TARGET_NR_readlink
31e31b8a 9980 case TARGET_NR_readlink:
53a5960a 9981 {
463d8e73 9982 void *p2;
53a5960a 9983 p = lock_user_string(arg1);
579a97f7 9984 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 9985 if (!p || !p2) {
579a97f7 9986 ret = -TARGET_EFAULT;
f17f4989
MF
9987 } else if (!arg3) {
9988 /* Short circuit this for the magic exe check. */
9989 ret = -TARGET_EINVAL;
463d8e73
AS
9990 } else if (is_proc_myself((const char *)p, "exe")) {
9991 char real[PATH_MAX], *temp;
9992 temp = realpath(exec_path, real);
f17f4989
MF
9993 /* Return value is # of bytes that we wrote to the buffer. */
9994 if (temp == NULL) {
9995 ret = get_errno(-1);
9996 } else {
9997 /* Don't worry about sign mismatch as earlier mapping
9998 * logic would have thrown a bad address error. */
9999 ret = MIN(strlen(real), arg3);
10000 /* We cannot NUL terminate the string. */
10001 memcpy(p2, real, ret);
10002 }
463d8e73
AS
10003 } else {
10004 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 10005 }
53a5960a
PB
10006 unlock_user(p2, arg2, ret);
10007 unlock_user(p, arg1, 0);
10008 }
72eb7ea8 10009 return ret;
704eff6c 10010#endif
c0d472b1 10011#if defined(TARGET_NR_readlinkat)
5e0ccb18 10012 case TARGET_NR_readlinkat:
5e0ccb18 10013 {
579a97f7 10014 void *p2;
5e0ccb18 10015 p = lock_user_string(arg2);
579a97f7 10016 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
10017 if (!p || !p2) {
10018 ret = -TARGET_EFAULT;
65d4830d
JN
10019 } else if (!arg4) {
10020 /* Short circuit this for the magic exe check. */
10021 ret = -TARGET_EINVAL;
463d8e73
AS
10022 } else if (is_proc_myself((const char *)p, "exe")) {
10023 char real[PATH_MAX], *temp;
10024 temp = realpath(exec_path, real);
65d4830d
JN
10025 /* Return value is # of bytes that we wrote to the buffer. */
10026 if (temp == NULL) {
10027 ret = get_errno(-1);
10028 } else {
10029 /* Don't worry about sign mismatch as earlier mapping
10030 * logic would have thrown a bad address error. */
10031 ret = MIN(strlen(real), arg4);
10032 /* We cannot NUL terminate the string. */
10033 memcpy(p2, real, ret);
10034 }
463d8e73 10035 } else {
c0d472b1 10036 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 10037 }
579a97f7
FB
10038 unlock_user(p2, arg3, ret);
10039 unlock_user(p, arg2, 0);
5e0ccb18 10040 }
72eb7ea8 10041 return ret;
5e0ccb18 10042#endif
e5febef5 10043#ifdef TARGET_NR_swapon
31e31b8a 10044 case TARGET_NR_swapon:
579a97f7 10045 if (!(p = lock_user_string(arg1)))
2852aafd 10046 return -TARGET_EFAULT;
53a5960a
PB
10047 ret = get_errno(swapon(p, arg2));
10048 unlock_user(p, arg1, 0);
72eb7ea8 10049 return ret;
e5febef5 10050#endif
31e31b8a 10051 case TARGET_NR_reboot:
c07ecc68
LV
10052 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
10053 /* arg4 must be ignored in all other cases */
10054 p = lock_user_string(arg4);
10055 if (!p) {
2852aafd 10056 return -TARGET_EFAULT;
c07ecc68
LV
10057 }
10058 ret = get_errno(reboot(arg1, arg2, arg3, p));
10059 unlock_user(p, arg4, 0);
10060 } else {
10061 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
10062 }
72eb7ea8 10063 return ret;
e5febef5 10064#ifdef TARGET_NR_mmap
31e31b8a 10065 case TARGET_NR_mmap:
09701199
AG
10066#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
10067 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
10068 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
10069 || defined(TARGET_S390X)
31e31b8a 10070 {
992f48a0
BS
10071 abi_ulong *v;
10072 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7 10073 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
2852aafd 10074 return -TARGET_EFAULT;
cbb21eed
MB
10075 v1 = tswapal(v[0]);
10076 v2 = tswapal(v[1]);
10077 v3 = tswapal(v[2]);
10078 v4 = tswapal(v[3]);
10079 v5 = tswapal(v[4]);
10080 v6 = tswapal(v[5]);
53a5960a 10081 unlock_user(v, arg1, 0);
5fafdf24 10082 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
10083 target_to_host_bitmask(v4, mmap_flags_tbl),
10084 v5, v6));
31e31b8a 10085 }
31e31b8a 10086#else
ee1bf83d 10087 /* mmap pointers are always untagged */
5fafdf24
TS
10088 ret = get_errno(target_mmap(arg1, arg2, arg3,
10089 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
10090 arg5,
10091 arg6));
31e31b8a 10092#endif
72eb7ea8 10093 return ret;
e5febef5 10094#endif
a315a145 10095#ifdef TARGET_NR_mmap2
6fb883e8 10096 case TARGET_NR_mmap2:
bb7ec043 10097#ifndef MMAP_SHIFT
c573ff67 10098#define MMAP_SHIFT 12
c573ff67 10099#endif
72eb7ea8
RH
10100 ret = target_mmap(arg1, arg2, arg3,
10101 target_to_host_bitmask(arg4, mmap_flags_tbl),
10102 arg5, arg6 << MMAP_SHIFT);
10103 return get_errno(ret);
a315a145 10104#endif
31e31b8a 10105 case TARGET_NR_munmap:
ee1bf83d 10106 arg1 = cpu_untagged_addr(cpu, arg1);
72eb7ea8 10107 return get_errno(target_munmap(arg1, arg2));
9de5e440 10108 case TARGET_NR_mprotect:
ee1bf83d 10109 arg1 = cpu_untagged_addr(cpu, arg1);
97374d38 10110 {
0429a971 10111 TaskState *ts = cpu->opaque;
97374d38
PB
10112 /* Special hack to detect libc making the stack executable. */
10113 if ((arg3 & PROT_GROWSDOWN)
10114 && arg1 >= ts->info->stack_limit
10115 && arg1 <= ts->info->start_stack) {
10116 arg3 &= ~PROT_GROWSDOWN;
10117 arg2 = arg2 + arg1 - ts->info->stack_limit;
10118 arg1 = ts->info->stack_limit;
10119 }
10120 }
72eb7ea8 10121 return get_errno(target_mprotect(arg1, arg2, arg3));
e5febef5 10122#ifdef TARGET_NR_mremap
9de5e440 10123 case TARGET_NR_mremap:
ee1bf83d
RH
10124 arg1 = cpu_untagged_addr(cpu, arg1);
10125 /* mremap new_addr (arg5) is always untagged */
72eb7ea8 10126 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
e5febef5 10127#endif
53a5960a 10128 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 10129#ifdef TARGET_NR_msync
9de5e440 10130 case TARGET_NR_msync:
3e8f1628 10131 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
e5febef5
TS
10132#endif
10133#ifdef TARGET_NR_mlock
9de5e440 10134 case TARGET_NR_mlock:
3e8f1628 10135 return get_errno(mlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10136#endif
10137#ifdef TARGET_NR_munlock
9de5e440 10138 case TARGET_NR_munlock:
3e8f1628 10139 return get_errno(munlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10140#endif
10141#ifdef TARGET_NR_mlockall
9de5e440 10142 case TARGET_NR_mlockall:
72eb7ea8 10143 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
e5febef5
TS
10144#endif
10145#ifdef TARGET_NR_munlockall
9de5e440 10146 case TARGET_NR_munlockall:
72eb7ea8 10147 return get_errno(munlockall());
e5febef5 10148#endif
4f7f8924 10149#ifdef TARGET_NR_truncate
31e31b8a 10150 case TARGET_NR_truncate:
579a97f7 10151 if (!(p = lock_user_string(arg1)))
2852aafd 10152 return -TARGET_EFAULT;
53a5960a
PB
10153 ret = get_errno(truncate(p, arg2));
10154 unlock_user(p, arg1, 0);
72eb7ea8 10155 return ret;
4f7f8924
AR
10156#endif
10157#ifdef TARGET_NR_ftruncate
31e31b8a 10158 case TARGET_NR_ftruncate:
72eb7ea8 10159 return get_errno(ftruncate(arg1, arg2));
4f7f8924 10160#endif
31e31b8a 10161 case TARGET_NR_fchmod:
72eb7ea8 10162 return get_errno(fchmod(arg1, arg2));
c0d472b1 10163#if defined(TARGET_NR_fchmodat)
814d7977 10164 case TARGET_NR_fchmodat:
579a97f7 10165 if (!(p = lock_user_string(arg2)))
2852aafd 10166 return -TARGET_EFAULT;
c0d472b1 10167 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 10168 unlock_user(p, arg2, 0);
72eb7ea8 10169 return ret;
814d7977 10170#endif
31e31b8a 10171 case TARGET_NR_getpriority:
95c09828
RH
10172 /* Note that negative values are valid for getpriority, so we must
10173 differentiate based on errno settings. */
10174 errno = 0;
10175 ret = getpriority(arg1, arg2);
10176 if (ret == -1 && errno != 0) {
72eb7ea8 10177 return -host_to_target_errno(errno);
95c09828
RH
10178 }
10179#ifdef TARGET_ALPHA
10180 /* Return value is the unbiased priority. Signal no error. */
0effdc29 10181 cpu_env->ir[IR_V0] = 0;
95c09828
RH
10182#else
10183 /* Return value is a biased priority to avoid negative numbers. */
10184 ret = 20 - ret;
10185#endif
72eb7ea8 10186 return ret;
31e31b8a 10187 case TARGET_NR_setpriority:
72eb7ea8 10188 return get_errno(setpriority(arg1, arg2, arg3));
4f7f8924 10189#ifdef TARGET_NR_statfs
31e31b8a 10190 case TARGET_NR_statfs:
2852aafd
RH
10191 if (!(p = lock_user_string(arg1))) {
10192 return -TARGET_EFAULT;
10193 }
53a5960a
PB
10194 ret = get_errno(statfs(path(p), &stfs));
10195 unlock_user(p, arg1, 0);
31e31b8a
FB
10196 convert_statfs:
10197 if (!is_error(ret)) {
53a5960a 10198 struct target_statfs *target_stfs;
3b46e624 10199
579a97f7 10200 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
2852aafd 10201 return -TARGET_EFAULT;
579a97f7
FB
10202 __put_user(stfs.f_type, &target_stfs->f_type);
10203 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10204 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10205 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10206 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10207 __put_user(stfs.f_files, &target_stfs->f_files);
10208 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10209 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10210 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10211 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10212 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
d4247ec2
SL
10213#ifdef _STATFS_F_FLAGS
10214 __put_user(stfs.f_flags, &target_stfs->f_flags);
10215#else
10216 __put_user(0, &target_stfs->f_flags);
10217#endif
229d3376 10218 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 10219 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a 10220 }
72eb7ea8 10221 return ret;
4f7f8924
AR
10222#endif
10223#ifdef TARGET_NR_fstatfs
31e31b8a 10224 case TARGET_NR_fstatfs:
56c8f68f 10225 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 10226 goto convert_statfs;
4f7f8924 10227#endif
56c8f68f
FB
10228#ifdef TARGET_NR_statfs64
10229 case TARGET_NR_statfs64:
2852aafd
RH
10230 if (!(p = lock_user_string(arg1))) {
10231 return -TARGET_EFAULT;
10232 }
53a5960a
PB
10233 ret = get_errno(statfs(path(p), &stfs));
10234 unlock_user(p, arg1, 0);
56c8f68f
FB
10235 convert_statfs64:
10236 if (!is_error(ret)) {
53a5960a 10237 struct target_statfs64 *target_stfs;
3b46e624 10238
579a97f7 10239 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
2852aafd 10240 return -TARGET_EFAULT;
579a97f7
FB
10241 __put_user(stfs.f_type, &target_stfs->f_type);
10242 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10243 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10244 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10245 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10246 __put_user(stfs.f_files, &target_stfs->f_files);
10247 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10248 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10249 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10250 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10251 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
b94e2b4e
F
10252#ifdef _STATFS_F_FLAGS
10253 __put_user(stfs.f_flags, &target_stfs->f_flags);
10254#else
10255 __put_user(0, &target_stfs->f_flags);
10256#endif
229d3376 10257 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 10258 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f 10259 }
72eb7ea8 10260 return ret;
56c8f68f
FB
10261 case TARGET_NR_fstatfs64:
10262 ret = get_errno(fstatfs(arg1, &stfs));
10263 goto convert_statfs64;
10264#endif
e5febef5 10265#ifdef TARGET_NR_socketcall
31e31b8a 10266 case TARGET_NR_socketcall:
72eb7ea8 10267 return do_socketcall(arg1, arg2);
e5febef5 10268#endif
3532fa74
FB
10269#ifdef TARGET_NR_accept
10270 case TARGET_NR_accept:
72eb7ea8 10271 return do_accept4(arg1, arg2, arg3, 0);
a94b4987
PM
10272#endif
10273#ifdef TARGET_NR_accept4
10274 case TARGET_NR_accept4:
72eb7ea8 10275 return do_accept4(arg1, arg2, arg3, arg4);
3532fa74
FB
10276#endif
10277#ifdef TARGET_NR_bind
10278 case TARGET_NR_bind:
72eb7ea8 10279 return do_bind(arg1, arg2, arg3);
3532fa74
FB
10280#endif
10281#ifdef TARGET_NR_connect
10282 case TARGET_NR_connect:
72eb7ea8 10283 return do_connect(arg1, arg2, arg3);
3532fa74
FB
10284#endif
10285#ifdef TARGET_NR_getpeername
10286 case TARGET_NR_getpeername:
72eb7ea8 10287 return do_getpeername(arg1, arg2, arg3);
3532fa74
FB
10288#endif
10289#ifdef TARGET_NR_getsockname
10290 case TARGET_NR_getsockname:
72eb7ea8 10291 return do_getsockname(arg1, arg2, arg3);
3532fa74
FB
10292#endif
10293#ifdef TARGET_NR_getsockopt
10294 case TARGET_NR_getsockopt:
72eb7ea8 10295 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
3532fa74
FB
10296#endif
10297#ifdef TARGET_NR_listen
10298 case TARGET_NR_listen:
72eb7ea8 10299 return get_errno(listen(arg1, arg2));
3532fa74
FB
10300#endif
10301#ifdef TARGET_NR_recv
10302 case TARGET_NR_recv:
72eb7ea8 10303 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10304#endif
10305#ifdef TARGET_NR_recvfrom
10306 case TARGET_NR_recvfrom:
72eb7ea8 10307 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10308#endif
10309#ifdef TARGET_NR_recvmsg
10310 case TARGET_NR_recvmsg:
72eb7ea8 10311 return do_sendrecvmsg(arg1, arg2, arg3, 0);
3532fa74
FB
10312#endif
10313#ifdef TARGET_NR_send
10314 case TARGET_NR_send:
72eb7ea8 10315 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10316#endif
10317#ifdef TARGET_NR_sendmsg
10318 case TARGET_NR_sendmsg:
72eb7ea8 10319 return do_sendrecvmsg(arg1, arg2, arg3, 1);
3532fa74 10320#endif
f19e00d7
AG
10321#ifdef TARGET_NR_sendmmsg
10322 case TARGET_NR_sendmmsg:
72eb7ea8 10323 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
859e8a89
AF
10324#endif
10325#ifdef TARGET_NR_recvmmsg
f19e00d7 10326 case TARGET_NR_recvmmsg:
72eb7ea8 10327 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
f19e00d7 10328#endif
3532fa74
FB
10329#ifdef TARGET_NR_sendto
10330 case TARGET_NR_sendto:
72eb7ea8 10331 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10332#endif
10333#ifdef TARGET_NR_shutdown
10334 case TARGET_NR_shutdown:
72eb7ea8 10335 return get_errno(shutdown(arg1, arg2));
3532fa74 10336#endif
f894efd1
LV
10337#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10338 case TARGET_NR_getrandom:
10339 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10340 if (!p) {
2852aafd 10341 return -TARGET_EFAULT;
f894efd1
LV
10342 }
10343 ret = get_errno(getrandom(p, arg2, arg3));
10344 unlock_user(p, arg1, ret);
72eb7ea8 10345 return ret;
f894efd1 10346#endif
3532fa74
FB
10347#ifdef TARGET_NR_socket
10348 case TARGET_NR_socket:
72eb7ea8 10349 return do_socket(arg1, arg2, arg3);
3532fa74
FB
10350#endif
10351#ifdef TARGET_NR_socketpair
10352 case TARGET_NR_socketpair:
72eb7ea8 10353 return do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
10354#endif
10355#ifdef TARGET_NR_setsockopt
10356 case TARGET_NR_setsockopt:
72eb7ea8 10357 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
3532fa74 10358#endif
da2c8ad7 10359#if defined(TARGET_NR_syslog)
31e31b8a 10360 case TARGET_NR_syslog:
da2c8ad7
AM
10361 {
10362 int len = arg2;
7494b0f9 10363
da2c8ad7
AM
10364 switch (arg1) {
10365 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10366 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10367 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10368 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10369 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10370 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10371 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10372 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
72eb7ea8 10373 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
da2c8ad7
AM
10374 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10375 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10376 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10377 {
da2c8ad7 10378 if (len < 0) {
259841c1 10379 return -TARGET_EINVAL;
da2c8ad7 10380 }
da2c8ad7 10381 if (len == 0) {
72eb7ea8 10382 return 0;
da2c8ad7
AM
10383 }
10384 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10385 if (!p) {
259841c1 10386 return -TARGET_EFAULT;
da2c8ad7
AM
10387 }
10388 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10389 unlock_user(p, arg2, arg3);
10390 }
72eb7ea8 10391 return ret;
da2c8ad7 10392 default:
72eb7ea8 10393 return -TARGET_EINVAL;
da2c8ad7
AM
10394 }
10395 }
10396 break;
10397#endif
31e31b8a 10398 case TARGET_NR_setitimer:
66fb9763 10399 {
66fb9763
FB
10400 struct itimerval value, ovalue, *pvalue;
10401
53a5960a 10402 if (arg2) {
66fb9763 10403 pvalue = &value;
788f5ec4
TS
10404 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10405 || copy_from_user_timeval(&pvalue->it_value,
10406 arg2 + sizeof(struct target_timeval)))
2852aafd 10407 return -TARGET_EFAULT;
66fb9763
FB
10408 } else {
10409 pvalue = NULL;
10410 }
10411 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 10412 if (!is_error(ret) && arg3) {
788f5ec4
TS
10413 if (copy_to_user_timeval(arg3,
10414 &ovalue.it_interval)
10415 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10416 &ovalue.it_value))
2852aafd 10417 return -TARGET_EFAULT;
66fb9763
FB
10418 }
10419 }
72eb7ea8 10420 return ret;
31e31b8a 10421 case TARGET_NR_getitimer:
66fb9763 10422 {
66fb9763 10423 struct itimerval value;
3b46e624 10424
66fb9763 10425 ret = get_errno(getitimer(arg1, &value));
53a5960a 10426 if (!is_error(ret) && arg2) {
788f5ec4
TS
10427 if (copy_to_user_timeval(arg2,
10428 &value.it_interval)
10429 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10430 &value.it_value))
2852aafd 10431 return -TARGET_EFAULT;
66fb9763
FB
10432 }
10433 }
72eb7ea8 10434 return ret;
704eff6c 10435#ifdef TARGET_NR_stat
31e31b8a 10436 case TARGET_NR_stat:
2852aafd
RH
10437 if (!(p = lock_user_string(arg1))) {
10438 return -TARGET_EFAULT;
10439 }
53a5960a
PB
10440 ret = get_errno(stat(path(p), &st));
10441 unlock_user(p, arg1, 0);
31e31b8a 10442 goto do_stat;
704eff6c
CG
10443#endif
10444#ifdef TARGET_NR_lstat
31e31b8a 10445 case TARGET_NR_lstat:
2852aafd
RH
10446 if (!(p = lock_user_string(arg1))) {
10447 return -TARGET_EFAULT;
10448 }
53a5960a
PB
10449 ret = get_errno(lstat(path(p), &st));
10450 unlock_user(p, arg1, 0);
31e31b8a 10451 goto do_stat;
704eff6c 10452#endif
4f7f8924 10453#ifdef TARGET_NR_fstat
31e31b8a
FB
10454 case TARGET_NR_fstat:
10455 {
10456 ret = get_errno(fstat(arg1, &st));
704eff6c 10457#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
31e31b8a 10458 do_stat:
704eff6c 10459#endif
31e31b8a 10460 if (!is_error(ret)) {
53a5960a 10461 struct target_stat *target_st;
e3584658 10462
579a97f7 10463 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
2852aafd 10464 return -TARGET_EFAULT;
12727917 10465 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
10466 __put_user(st.st_dev, &target_st->st_dev);
10467 __put_user(st.st_ino, &target_st->st_ino);
10468 __put_user(st.st_mode, &target_st->st_mode);
10469 __put_user(st.st_uid, &target_st->st_uid);
10470 __put_user(st.st_gid, &target_st->st_gid);
10471 __put_user(st.st_nlink, &target_st->st_nlink);
10472 __put_user(st.st_rdev, &target_st->st_rdev);
10473 __put_user(st.st_size, &target_st->st_size);
10474 __put_user(st.st_blksize, &target_st->st_blksize);
10475 __put_user(st.st_blocks, &target_st->st_blocks);
10476 __put_user(st.st_atime, &target_st->target_st_atime);
10477 __put_user(st.st_mtime, &target_st->target_st_mtime);
10478 __put_user(st.st_ctime, &target_st->target_st_ctime);
febf6fad 10479#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
5f992db6
CYT
10480 __put_user(st.st_atim.tv_nsec,
10481 &target_st->target_st_atime_nsec);
10482 __put_user(st.st_mtim.tv_nsec,
10483 &target_st->target_st_mtime_nsec);
10484 __put_user(st.st_ctim.tv_nsec,
10485 &target_st->target_st_ctime_nsec);
10486#endif
53a5960a 10487 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
10488 }
10489 }
72eb7ea8 10490 return ret;
ebc05488 10491#endif
31e31b8a 10492 case TARGET_NR_vhangup:
72eb7ea8 10493 return get_errno(vhangup());
42ad6ae9
FB
10494#ifdef TARGET_NR_syscall
10495 case TARGET_NR_syscall:
72eb7ea8
RH
10496 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10497 arg6, arg7, arg8, 0);
ebc05488 10498#endif
859e8a89 10499#if defined(TARGET_NR_wait4)
31e31b8a
FB
10500 case TARGET_NR_wait4:
10501 {
10502 int status;
992f48a0 10503 abi_long status_ptr = arg2;
31e31b8a 10504 struct rusage rusage, *rusage_ptr;
992f48a0 10505 abi_ulong target_rusage = arg4;
a39fb273 10506 abi_long rusage_err;
31e31b8a
FB
10507 if (target_rusage)
10508 rusage_ptr = &rusage;
10509 else
10510 rusage_ptr = NULL;
4af80a37 10511 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
31e31b8a 10512 if (!is_error(ret)) {
5379557b 10513 if (status_ptr && ret) {
1d9d8b55 10514 status = host_to_target_waitstatus(status);
2f619698 10515 if (put_user_s32(status, status_ptr))
2852aafd 10516 return -TARGET_EFAULT;
31e31b8a 10517 }
a39fb273
PJ
10518 if (target_rusage) {
10519 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10520 if (rusage_err) {
10521 ret = rusage_err;
10522 }
10523 }
31e31b8a
FB
10524 }
10525 }
72eb7ea8 10526 return ret;
859e8a89 10527#endif
e5febef5 10528#ifdef TARGET_NR_swapoff
31e31b8a 10529 case TARGET_NR_swapoff:
579a97f7 10530 if (!(p = lock_user_string(arg1)))
2852aafd 10531 return -TARGET_EFAULT;
53a5960a
PB
10532 ret = get_errno(swapoff(p));
10533 unlock_user(p, arg1, 0);
72eb7ea8 10534 return ret;
e5febef5 10535#endif
31e31b8a 10536 case TARGET_NR_sysinfo:
a5448a7d 10537 {
53a5960a 10538 struct target_sysinfo *target_value;
a5448a7d
FB
10539 struct sysinfo value;
10540 ret = get_errno(sysinfo(&value));
53a5960a 10541 if (!is_error(ret) && arg1)
a5448a7d 10542 {
579a97f7 10543 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
2852aafd 10544 return -TARGET_EFAULT;
a5448a7d
FB
10545 __put_user(value.uptime, &target_value->uptime);
10546 __put_user(value.loads[0], &target_value->loads[0]);
10547 __put_user(value.loads[1], &target_value->loads[1]);
10548 __put_user(value.loads[2], &target_value->loads[2]);
10549 __put_user(value.totalram, &target_value->totalram);
10550 __put_user(value.freeram, &target_value->freeram);
10551 __put_user(value.sharedram, &target_value->sharedram);
10552 __put_user(value.bufferram, &target_value->bufferram);
10553 __put_user(value.totalswap, &target_value->totalswap);
10554 __put_user(value.freeswap, &target_value->freeswap);
10555 __put_user(value.procs, &target_value->procs);
10556 __put_user(value.totalhigh, &target_value->totalhigh);
10557 __put_user(value.freehigh, &target_value->freehigh);
10558 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 10559 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
10560 }
10561 }
72eb7ea8 10562 return ret;
e5febef5 10563#ifdef TARGET_NR_ipc
31e31b8a 10564 case TARGET_NR_ipc:
72eb7ea8 10565 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
e5febef5 10566#endif
e5289087
AJ
10567#ifdef TARGET_NR_semget
10568 case TARGET_NR_semget:
72eb7ea8 10569 return get_errno(semget(arg1, arg2, arg3));
e5289087
AJ
10570#endif
10571#ifdef TARGET_NR_semop
10572 case TARGET_NR_semop:
cac46eb0 10573 return do_semtimedop(arg1, arg2, arg3, 0, false);
d8c08b1e
MK
10574#endif
10575#ifdef TARGET_NR_semtimedop
10576 case TARGET_NR_semtimedop:
cac46eb0
FB
10577 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10578#endif
10579#ifdef TARGET_NR_semtimedop_time64
10580 case TARGET_NR_semtimedop_time64:
10581 return do_semtimedop(arg1, arg2, arg3, arg4, true);
e5289087
AJ
10582#endif
10583#ifdef TARGET_NR_semctl
10584 case TARGET_NR_semctl:
72eb7ea8 10585 return do_semctl(arg1, arg2, arg3, arg4);
e5289087 10586#endif
eeb438c1
AJ
10587#ifdef TARGET_NR_msgctl
10588 case TARGET_NR_msgctl:
72eb7ea8 10589 return do_msgctl(arg1, arg2, arg3);
eeb438c1
AJ
10590#endif
10591#ifdef TARGET_NR_msgget
10592 case TARGET_NR_msgget:
72eb7ea8 10593 return get_errno(msgget(arg1, arg2));
eeb438c1
AJ
10594#endif
10595#ifdef TARGET_NR_msgrcv
10596 case TARGET_NR_msgrcv:
72eb7ea8 10597 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
eeb438c1
AJ
10598#endif
10599#ifdef TARGET_NR_msgsnd
10600 case TARGET_NR_msgsnd:
72eb7ea8 10601 return do_msgsnd(arg1, arg2, arg3, arg4);
88a8c984
RV
10602#endif
10603#ifdef TARGET_NR_shmget
10604 case TARGET_NR_shmget:
72eb7ea8 10605 return get_errno(shmget(arg1, arg2, arg3));
88a8c984
RV
10606#endif
10607#ifdef TARGET_NR_shmctl
10608 case TARGET_NR_shmctl:
72eb7ea8 10609 return do_shmctl(arg1, arg2, arg3);
88a8c984
RV
10610#endif
10611#ifdef TARGET_NR_shmat
10612 case TARGET_NR_shmat:
72eb7ea8 10613 return do_shmat(cpu_env, arg1, arg2, arg3);
88a8c984
RV
10614#endif
10615#ifdef TARGET_NR_shmdt
10616 case TARGET_NR_shmdt:
72eb7ea8 10617 return do_shmdt(arg1);
eeb438c1 10618#endif
31e31b8a 10619 case TARGET_NR_fsync:
72eb7ea8 10620 return get_errno(fsync(arg1));
31e31b8a 10621 case TARGET_NR_clone:
4ce6243d
PM
10622 /* Linux manages to have three different orderings for its
10623 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10624 * match the kernel's CONFIG_CLONE_* settings.
10625 * Microblaze is further special in that it uses a sixth
10626 * implicit argument to clone for the TLS pointer.
10627 */
10628#if defined(TARGET_MICROBLAZE)
a5b3bdcb 10629 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
10630#elif defined(TARGET_CLONE_BACKWARDS)
10631 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10632#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 10633 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 10634#else
4ce6243d 10635 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 10636#endif
72eb7ea8 10637 return ret;
ec86b0fb
FB
10638#ifdef __NR_exit_group
10639 /* new thread calls */
10640 case TARGET_NR_exit_group:
708b6a64 10641 preexit_cleanup(cpu_env, arg1);
72eb7ea8 10642 return get_errno(exit_group(arg1));
ec86b0fb 10643#endif
31e31b8a 10644 case TARGET_NR_setdomainname:
579a97f7 10645 if (!(p = lock_user_string(arg1)))
2852aafd 10646 return -TARGET_EFAULT;
53a5960a
PB
10647 ret = get_errno(setdomainname(p, arg2));
10648 unlock_user(p, arg1, 0);
72eb7ea8 10649 return ret;
31e31b8a
FB
10650 case TARGET_NR_uname:
10651 /* no need to transcode because we use the linux syscall */
29e619b1
FB
10652 {
10653 struct new_utsname * buf;
3b46e624 10654
579a97f7 10655 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
2852aafd 10656 return -TARGET_EFAULT;
29e619b1
FB
10657 ret = get_errno(sys_uname(buf));
10658 if (!is_error(ret)) {
332c9781 10659 /* Overwrite the native machine name with whatever is being
29e619b1 10660 emulated. */
871f95c6
PMD
10661 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10662 sizeof(buf->machine));
c5937220 10663 /* Allow the user to override the reported release. */
332c9781
PM
10664 if (qemu_uname_release && *qemu_uname_release) {
10665 g_strlcpy(buf->release, qemu_uname_release,
10666 sizeof(buf->release));
10667 }
29e619b1 10668 }
53a5960a 10669 unlock_user_struct(buf, arg1, 1);
29e619b1 10670 }
72eb7ea8 10671 return ret;
6dbad63e 10672#ifdef TARGET_I386
31e31b8a 10673 case TARGET_NR_modify_ldt:
72eb7ea8 10674 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
84409ddb 10675#if !defined(TARGET_X86_64)
5cd4393b 10676 case TARGET_NR_vm86:
72eb7ea8 10677 return do_vm86(cpu_env, arg1, arg2);
84409ddb 10678#endif
6dbad63e 10679#endif
859e8a89 10680#if defined(TARGET_NR_adjtimex)
31e31b8a 10681 case TARGET_NR_adjtimex:
19f59bce
AM
10682 {
10683 struct timex host_buf;
10684
10685 if (target_to_host_timex(&host_buf, arg1) != 0) {
2852aafd 10686 return -TARGET_EFAULT;
19f59bce
AM
10687 }
10688 ret = get_errno(adjtimex(&host_buf));
10689 if (!is_error(ret)) {
10690 if (host_to_target_timex(arg1, &host_buf) != 0) {
2852aafd 10691 return -TARGET_EFAULT;
19f59bce
AM
10692 }
10693 }
10694 }
72eb7ea8 10695 return ret;
859e8a89 10696#endif
38860a03
AM
10697#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10698 case TARGET_NR_clock_adjtime:
10699 {
10700 struct timex htx, *phtx = &htx;
10701
10702 if (target_to_host_timex(phtx, arg2) != 0) {
2852aafd 10703 return -TARGET_EFAULT;
38860a03
AM
10704 }
10705 ret = get_errno(clock_adjtime(arg1, phtx));
10706 if (!is_error(ret) && phtx) {
10707 if (host_to_target_timex(arg2, phtx) != 0) {
2852aafd 10708 return -TARGET_EFAULT;
38860a03
AM
10709 }
10710 }
10711 }
72eb7ea8 10712 return ret;
6ac03b2c
FB
10713#endif
10714#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10715 case TARGET_NR_clock_adjtime64:
10716 {
10717 struct timex htx;
10718
10719 if (target_to_host_timex64(&htx, arg2) != 0) {
10720 return -TARGET_EFAULT;
10721 }
10722 ret = get_errno(clock_adjtime(arg1, &htx));
10723 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10724 return -TARGET_EFAULT;
10725 }
10726 }
10727 return ret;
38860a03 10728#endif
31e31b8a 10729 case TARGET_NR_getpgid:
72eb7ea8 10730 return get_errno(getpgid(arg1));
31e31b8a 10731 case TARGET_NR_fchdir:
72eb7ea8 10732 return get_errno(fchdir(arg1));
31e31b8a 10733 case TARGET_NR_personality:
72eb7ea8 10734 return get_errno(personality(arg1));
7a3148a9 10735#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
10736 case TARGET_NR__llseek:
10737 {
0c1592d9 10738 int64_t res;
d35b261c 10739#if !defined(__NR_llseek)
9fea273c 10740 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
0c1592d9
PM
10741 if (res == -1) {
10742 ret = get_errno(res);
10743 } else {
10744 ret = 0;
10745 }
4f2ac237 10746#else
31e31b8a 10747 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 10748#endif
0c1592d9 10749 if ((ret == 0) && put_user_s64(res, arg4)) {
2852aafd 10750 return -TARGET_EFAULT;
0c1592d9 10751 }
31e31b8a 10752 }
72eb7ea8 10753 return ret;
7a3148a9 10754#endif
704eff6c 10755#ifdef TARGET_NR_getdents
31e31b8a 10756 case TARGET_NR_getdents:
fd08ddb9 10757 return do_getdents(arg1, arg2, arg3);
704eff6c 10758#endif /* TARGET_NR_getdents */
3ae43202 10759#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99 10760 case TARGET_NR_getdents64:
fd08ddb9 10761 return do_getdents64(arg1, arg2, arg3);
a541f297 10762#endif /* TARGET_NR_getdents64 */
9468a5d4 10763#if defined(TARGET_NR__newselect)
31e31b8a 10764 case TARGET_NR__newselect:
72eb7ea8 10765 return do_select(arg1, arg2, arg3, arg4, arg5);
e5febef5 10766#endif
e5ce9688 10767#ifdef TARGET_NR_poll
9de5e440 10768 case TARGET_NR_poll:
e5ce9688
FB
10769 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10770#endif
10771#ifdef TARGET_NR_ppoll
d8035d4c 10772 case TARGET_NR_ppoll:
e5ce9688
FB
10773 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10774#endif
10775#ifdef TARGET_NR_ppoll_time64
10776 case TARGET_NR_ppoll_time64:
10777 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
e5febef5 10778#endif
31e31b8a 10779 case TARGET_NR_flock:
9de5e440
FB
10780 /* NOTE: the flock constant seems to be the same for every
10781 Linux platform */
72eb7ea8 10782 return get_errno(safe_flock(arg1, arg2));
31e31b8a
FB
10783 case TARGET_NR_readv:
10784 {
f287b2c2
RH
10785 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10786 if (vec != NULL) {
918c03ed 10787 ret = get_errno(safe_readv(arg1, vec, arg3));
f287b2c2
RH
10788 unlock_iovec(vec, arg2, arg3, 1);
10789 } else {
10790 ret = -host_to_target_errno(errno);
10791 }
31e31b8a 10792 }
72eb7ea8 10793 return ret;
31e31b8a
FB
10794 case TARGET_NR_writev:
10795 {
f287b2c2
RH
10796 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10797 if (vec != NULL) {
918c03ed 10798 ret = get_errno(safe_writev(arg1, vec, arg3));
f287b2c2
RH
10799 unlock_iovec(vec, arg2, arg3, 0);
10800 } else {
10801 ret = -host_to_target_errno(errno);
10802 }
31e31b8a 10803 }
72eb7ea8 10804 return ret;
0f26386c
DJ
10805#if defined(TARGET_NR_preadv)
10806 case TARGET_NR_preadv:
10807 {
10808 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10809 if (vec != NULL) {
9ac22517
MF
10810 unsigned long low, high;
10811
10812 target_to_host_low_high(arg4, arg5, &low, &high);
10813 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
0f26386c
DJ
10814 unlock_iovec(vec, arg2, arg3, 1);
10815 } else {
10816 ret = -host_to_target_errno(errno);
f8d00fba
DJ
10817 }
10818 }
72eb7ea8 10819 return ret;
f8d00fba
DJ
10820#endif
10821#if defined(TARGET_NR_pwritev)
10822 case TARGET_NR_pwritev:
10823 {
10824 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10825 if (vec != NULL) {
9ac22517
MF
10826 unsigned long low, high;
10827
10828 target_to_host_low_high(arg4, arg5, &low, &high);
10829 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
f8d00fba
DJ
10830 unlock_iovec(vec, arg2, arg3, 0);
10831 } else {
10832 ret = -host_to_target_errno(errno);
0f26386c
DJ
10833 }
10834 }
72eb7ea8 10835 return ret;
0f26386c 10836#endif
31e31b8a 10837 case TARGET_NR_getsid:
72eb7ea8 10838 return get_errno(getsid(arg1));
7a3148a9 10839#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 10840 case TARGET_NR_fdatasync:
72eb7ea8 10841 return get_errno(fdatasync(arg1));
704eff6c 10842#endif
737de1d1
MF
10843 case TARGET_NR_sched_getaffinity:
10844 {
10845 unsigned int mask_size;
10846 unsigned long *mask;
10847
10848 /*
10849 * sched_getaffinity needs multiples of ulong, so need to take
10850 * care of mismatches between target ulong and host ulong sizes.
10851 */
10852 if (arg2 & (sizeof(abi_ulong) - 1)) {
72eb7ea8 10853 return -TARGET_EINVAL;
737de1d1
MF
10854 }
10855 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10856
10857 mask = alloca(mask_size);
2e0a8713 10858 memset(mask, 0, mask_size);
737de1d1
MF
10859 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10860
10861 if (!is_error(ret)) {
be3bd286
PM
10862 if (ret > arg2) {
10863 /* More data returned than the caller's buffer will fit.
10864 * This only happens if sizeof(abi_long) < sizeof(long)
10865 * and the caller passed us a buffer holding an odd number
10866 * of abi_longs. If the host kernel is actually using the
10867 * extra 4 bytes then fail EINVAL; otherwise we can just
10868 * ignore them and only copy the interesting part.
10869 */
10870 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10871 if (numcpus > arg2 * 8) {
72eb7ea8 10872 return -TARGET_EINVAL;
be3bd286
PM
10873 }
10874 ret = arg2;
10875 }
10876
5fdefcf8 10877 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
2852aafd 10878 return -TARGET_EFAULT;
5fdefcf8 10879 }
737de1d1
MF
10880 }
10881 }
72eb7ea8 10882 return ret;
737de1d1
MF
10883 case TARGET_NR_sched_setaffinity:
10884 {
10885 unsigned int mask_size;
10886 unsigned long *mask;
10887
10888 /*
10889 * sched_setaffinity 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);
737de1d1 10896 mask = alloca(mask_size);
2e0a8713
ST
10897
10898 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10899 if (ret) {
72eb7ea8 10900 return ret;
737de1d1 10901 }
737de1d1 10902
72eb7ea8 10903 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
737de1d1 10904 }
b827c3ed
ST
10905 case TARGET_NR_getcpu:
10906 {
10907 unsigned cpu, node;
10908 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10909 arg2 ? &node : NULL,
10910 NULL));
10911 if (is_error(ret)) {
259841c1 10912 return ret;
b827c3ed
ST
10913 }
10914 if (arg1 && put_user_u32(cpu, arg1)) {
2852aafd 10915 return -TARGET_EFAULT;
b827c3ed
ST
10916 }
10917 if (arg2 && put_user_u32(node, arg2)) {
2852aafd 10918 return -TARGET_EFAULT;
b827c3ed
ST
10919 }
10920 }
72eb7ea8 10921 return ret;
31e31b8a 10922 case TARGET_NR_sched_setparam:
5cd4393b 10923 {
407a119b 10924 struct target_sched_param *target_schp;
5cd4393b 10925 struct sched_param schp;
53a5960a 10926
a1d5c5b2
TM
10927 if (arg2 == 0) {
10928 return -TARGET_EINVAL;
10929 }
407a119b 10930 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
2852aafd 10931 return -TARGET_EFAULT;
407a119b 10932 }
5cd4393b 10933 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10934 unlock_user_struct(target_schp, arg2, 0);
407a119b 10935 return get_errno(sys_sched_setparam(arg1, &schp));
5cd4393b 10936 }
31e31b8a 10937 case TARGET_NR_sched_getparam:
5cd4393b 10938 {
407a119b 10939 struct target_sched_param *target_schp;
5cd4393b 10940 struct sched_param schp;
a1d5c5b2
TM
10941
10942 if (arg2 == 0) {
10943 return -TARGET_EINVAL;
10944 }
407a119b 10945 ret = get_errno(sys_sched_getparam(arg1, &schp));
5cd4393b 10946 if (!is_error(ret)) {
407a119b 10947 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
2852aafd 10948 return -TARGET_EFAULT;
407a119b 10949 }
5cd4393b 10950 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 10951 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
10952 }
10953 }
72eb7ea8 10954 return ret;
31e31b8a 10955 case TARGET_NR_sched_setscheduler:
5cd4393b 10956 {
407a119b 10957 struct target_sched_param *target_schp;
5cd4393b 10958 struct sched_param schp;
a1d5c5b2
TM
10959 if (arg3 == 0) {
10960 return -TARGET_EINVAL;
10961 }
407a119b 10962 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
2852aafd 10963 return -TARGET_EFAULT;
407a119b 10964 }
5cd4393b 10965 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10966 unlock_user_struct(target_schp, arg3, 0);
407a119b 10967 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
5cd4393b 10968 }
31e31b8a 10969 case TARGET_NR_sched_getscheduler:
407a119b 10970 return get_errno(sys_sched_getscheduler(arg1));
45ad761c
TT
10971 case TARGET_NR_sched_getattr:
10972 {
10973 struct target_sched_attr *target_scha;
10974 struct sched_attr scha;
10975 if (arg2 == 0) {
10976 return -TARGET_EINVAL;
10977 }
10978 if (arg3 > sizeof(scha)) {
10979 arg3 = sizeof(scha);
10980 }
10981 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
10982 if (!is_error(ret)) {
10983 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10984 if (!target_scha) {
10985 return -TARGET_EFAULT;
10986 }
10987 target_scha->size = tswap32(scha.size);
10988 target_scha->sched_policy = tswap32(scha.sched_policy);
10989 target_scha->sched_flags = tswap64(scha.sched_flags);
10990 target_scha->sched_nice = tswap32(scha.sched_nice);
10991 target_scha->sched_priority = tswap32(scha.sched_priority);
10992 target_scha->sched_runtime = tswap64(scha.sched_runtime);
10993 target_scha->sched_deadline = tswap64(scha.sched_deadline);
10994 target_scha->sched_period = tswap64(scha.sched_period);
10995 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
10996 target_scha->sched_util_min = tswap32(scha.sched_util_min);
10997 target_scha->sched_util_max = tswap32(scha.sched_util_max);
10998 }
10999 unlock_user(target_scha, arg2, arg3);
11000 }
11001 return ret;
11002 }
11003 case TARGET_NR_sched_setattr:
11004 {
11005 struct target_sched_attr *target_scha;
11006 struct sched_attr scha;
11007 uint32_t size;
11008 int zeroed;
11009 if (arg2 == 0) {
11010 return -TARGET_EINVAL;
11011 }
11012 if (get_user_u32(size, arg2)) {
11013 return -TARGET_EFAULT;
11014 }
11015 if (!size) {
11016 size = offsetof(struct target_sched_attr, sched_util_min);
11017 }
11018 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
11019 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11020 return -TARGET_EFAULT;
11021 }
11022 return -TARGET_E2BIG;
11023 }
11024
11025 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
11026 if (zeroed < 0) {
11027 return zeroed;
11028 } else if (zeroed == 0) {
11029 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
11030 return -TARGET_EFAULT;
11031 }
11032 return -TARGET_E2BIG;
11033 }
11034 if (size > sizeof(struct target_sched_attr)) {
11035 size = sizeof(struct target_sched_attr);
11036 }
11037
11038 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
11039 if (!target_scha) {
11040 return -TARGET_EFAULT;
11041 }
11042 scha.size = size;
11043 scha.sched_policy = tswap32(target_scha->sched_policy);
11044 scha.sched_flags = tswap64(target_scha->sched_flags);
11045 scha.sched_nice = tswap32(target_scha->sched_nice);
11046 scha.sched_priority = tswap32(target_scha->sched_priority);
11047 scha.sched_runtime = tswap64(target_scha->sched_runtime);
11048 scha.sched_deadline = tswap64(target_scha->sched_deadline);
11049 scha.sched_period = tswap64(target_scha->sched_period);
11050 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
11051 scha.sched_util_min = tswap32(target_scha->sched_util_min);
11052 scha.sched_util_max = tswap32(target_scha->sched_util_max);
11053 }
11054 unlock_user(target_scha, arg2, 0);
11055 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
11056 }
31e31b8a 11057 case TARGET_NR_sched_yield:
72eb7ea8 11058 return get_errno(sched_yield());
31e31b8a 11059 case TARGET_NR_sched_get_priority_max:
72eb7ea8 11060 return get_errno(sched_get_priority_max(arg1));
31e31b8a 11061 case TARGET_NR_sched_get_priority_min:
72eb7ea8 11062 return get_errno(sched_get_priority_min(arg1));
859e8a89 11063#ifdef TARGET_NR_sched_rr_get_interval
31e31b8a 11064 case TARGET_NR_sched_rr_get_interval:
5cd4393b 11065 {
5cd4393b
FB
11066 struct timespec ts;
11067 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11068 if (!is_error(ret)) {
d4290c40 11069 ret = host_to_target_timespec(arg2, &ts);
5cd4393b
FB
11070 }
11071 }
72eb7ea8 11072 return ret;
859e8a89 11073#endif
ddcbde15
FB
11074#ifdef TARGET_NR_sched_rr_get_interval_time64
11075 case TARGET_NR_sched_rr_get_interval_time64:
11076 {
11077 struct timespec ts;
11078 ret = get_errno(sched_rr_get_interval(arg1, &ts));
11079 if (!is_error(ret)) {
11080 ret = host_to_target_timespec64(arg2, &ts);
11081 }
11082 }
11083 return ret;
11084#endif
859e8a89 11085#if defined(TARGET_NR_nanosleep)
31e31b8a 11086 case TARGET_NR_nanosleep:
1b6b029e 11087 {
1b6b029e 11088 struct timespec req, rem;
53a5960a 11089 target_to_host_timespec(&req, arg1);
9e518226 11090 ret = get_errno(safe_nanosleep(&req, &rem));
53a5960a
PB
11091 if (is_error(ret) && arg2) {
11092 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
11093 }
11094 }
72eb7ea8 11095 return ret;
859e8a89 11096#endif
31e31b8a 11097 case TARGET_NR_prctl:
87e9bf23 11098 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
39b9aae1 11099 break;
d2fd1af7
FB
11100#ifdef TARGET_NR_arch_prctl
11101 case TARGET_NR_arch_prctl:
72eb7ea8 11102 return do_arch_prctl(cpu_env, arg1, arg2);
d2fd1af7 11103#endif
f2c7ba15
AJ
11104#ifdef TARGET_NR_pread64
11105 case TARGET_NR_pread64:
8bf8e9df 11106 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
11107 arg4 = arg5;
11108 arg5 = arg6;
11109 }
2bd3f899
PM
11110 if (arg2 == 0 && arg3 == 0) {
11111 /* Special-case NULL buffer and zero length, which should succeed */
11112 p = 0;
11113 } else {
11114 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11115 if (!p) {
11116 return -TARGET_EFAULT;
11117 }
11118 }
f2c7ba15
AJ
11119 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11120 unlock_user(p, arg2, ret);
72eb7ea8 11121 return ret;
f2c7ba15 11122 case TARGET_NR_pwrite64:
8bf8e9df 11123 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
11124 arg4 = arg5;
11125 arg5 = arg6;
11126 }
2bd3f899
PM
11127 if (arg2 == 0 && arg3 == 0) {
11128 /* Special-case NULL buffer and zero length, which should succeed */
11129 p = 0;
11130 } else {
11131 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11132 if (!p) {
11133 return -TARGET_EFAULT;
11134 }
11135 }
f2c7ba15
AJ
11136 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11137 unlock_user(p, arg2, 0);
72eb7ea8 11138 return ret;
67867308 11139#endif
31e31b8a 11140 case TARGET_NR_getcwd:
579a97f7 11141 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
2852aafd 11142 return -TARGET_EFAULT;
53a5960a
PB
11143 ret = get_errno(sys_getcwd1(p, arg2));
11144 unlock_user(p, arg1, ret);
72eb7ea8 11145 return ret;
31e31b8a
FB
11146 case TARGET_NR_capget:
11147 case TARGET_NR_capset:
e0eb210e
PM
11148 {
11149 struct target_user_cap_header *target_header;
11150 struct target_user_cap_data *target_data = NULL;
11151 struct __user_cap_header_struct header;
11152 struct __user_cap_data_struct data[2];
11153 struct __user_cap_data_struct *dataptr = NULL;
11154 int i, target_datalen;
11155 int data_items = 1;
11156
11157 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
2852aafd 11158 return -TARGET_EFAULT;
e0eb210e
PM
11159 }
11160 header.version = tswap32(target_header->version);
11161 header.pid = tswap32(target_header->pid);
11162
ec864874 11163 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
11164 /* Version 2 and up takes pointer to two user_data structs */
11165 data_items = 2;
11166 }
11167
11168 target_datalen = sizeof(*target_data) * data_items;
11169
11170 if (arg2) {
11171 if (num == TARGET_NR_capget) {
11172 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11173 } else {
11174 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11175 }
11176 if (!target_data) {
11177 unlock_user_struct(target_header, arg1, 0);
2852aafd 11178 return -TARGET_EFAULT;
e0eb210e
PM
11179 }
11180
11181 if (num == TARGET_NR_capset) {
11182 for (i = 0; i < data_items; i++) {
11183 data[i].effective = tswap32(target_data[i].effective);
11184 data[i].permitted = tswap32(target_data[i].permitted);
11185 data[i].inheritable = tswap32(target_data[i].inheritable);
11186 }
11187 }
11188
11189 dataptr = data;
11190 }
11191
11192 if (num == TARGET_NR_capget) {
11193 ret = get_errno(capget(&header, dataptr));
11194 } else {
11195 ret = get_errno(capset(&header, dataptr));
11196 }
11197
11198 /* The kernel always updates version for both capget and capset */
11199 target_header->version = tswap32(header.version);
11200 unlock_user_struct(target_header, arg1, 1);
11201
11202 if (arg2) {
11203 if (num == TARGET_NR_capget) {
11204 for (i = 0; i < data_items; i++) {
11205 target_data[i].effective = tswap32(data[i].effective);
11206 target_data[i].permitted = tswap32(data[i].permitted);
11207 target_data[i].inheritable = tswap32(data[i].inheritable);
11208 }
11209 unlock_user(target_data, arg2, target_datalen);
11210 } else {
11211 unlock_user(target_data, arg2, 0);
11212 }
11213 }
72eb7ea8 11214 return ret;
e0eb210e 11215 }
31e31b8a 11216 case TARGET_NR_sigaltstack:
6b208755 11217 return do_sigaltstack(arg1, arg2, cpu_env);
a8fd1aba
PM
11218
11219#ifdef CONFIG_SENDFILE
4f7f8924 11220#ifdef TARGET_NR_sendfile
a8fd1aba
PM
11221 case TARGET_NR_sendfile:
11222 {
11223 off_t *offp = NULL;
11224 off_t off;
11225 if (arg3) {
11226 ret = get_user_sal(off, arg3);
11227 if (is_error(ret)) {
72eb7ea8 11228 return ret;
a8fd1aba
PM
11229 }
11230 offp = &off;
11231 }
11232 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11233 if (!is_error(ret) && arg3) {
11234 abi_long ret2 = put_user_sal(off, arg3);
11235 if (is_error(ret2)) {
11236 ret = ret2;
11237 }
11238 }
72eb7ea8 11239 return ret;
a8fd1aba 11240 }
4f7f8924 11241#endif
a8fd1aba
PM
11242#ifdef TARGET_NR_sendfile64
11243 case TARGET_NR_sendfile64:
11244 {
11245 off_t *offp = NULL;
11246 off_t off;
11247 if (arg3) {
11248 ret = get_user_s64(off, arg3);
11249 if (is_error(ret)) {
72eb7ea8 11250 return ret;
a8fd1aba
PM
11251 }
11252 offp = &off;
11253 }
11254 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11255 if (!is_error(ret) && arg3) {
11256 abi_long ret2 = put_user_s64(off, arg3);
11257 if (is_error(ret2)) {
11258 ret = ret2;
11259 }
11260 }
72eb7ea8 11261 return ret;
a8fd1aba
PM
11262 }
11263#endif
ebc05488 11264#endif
048f6b4d 11265#ifdef TARGET_NR_vfork
31e31b8a 11266 case TARGET_NR_vfork:
72eb7ea8
RH
11267 return get_errno(do_fork(cpu_env,
11268 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11269 0, 0, 0, 0));
048f6b4d 11270#endif
ebc05488 11271#ifdef TARGET_NR_ugetrlimit
31e31b8a 11272 case TARGET_NR_ugetrlimit:
728584be
FB
11273 {
11274 struct rlimit rlim;
e22b7015
WT
11275 int resource = target_to_host_resource(arg1);
11276 ret = get_errno(getrlimit(resource, &rlim));
728584be 11277 if (!is_error(ret)) {
53a5960a 11278 struct target_rlimit *target_rlim;
579a97f7 11279 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 11280 return -TARGET_EFAULT;
81bbe906
TY
11281 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11282 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 11283 unlock_user_struct(target_rlim, arg2, 1);
728584be 11284 }
72eb7ea8 11285 return ret;
728584be 11286 }
ebc05488 11287#endif
a315a145 11288#ifdef TARGET_NR_truncate64
31e31b8a 11289 case TARGET_NR_truncate64:
579a97f7 11290 if (!(p = lock_user_string(arg1)))
2852aafd 11291 return -TARGET_EFAULT;
53a5960a
PB
11292 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11293 unlock_user(p, arg1, 0);
72eb7ea8 11294 return ret;
a315a145
FB
11295#endif
11296#ifdef TARGET_NR_ftruncate64
31e31b8a 11297 case TARGET_NR_ftruncate64:
72eb7ea8 11298 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
a315a145
FB
11299#endif
11300#ifdef TARGET_NR_stat64
31e31b8a 11301 case TARGET_NR_stat64:
2852aafd
RH
11302 if (!(p = lock_user_string(arg1))) {
11303 return -TARGET_EFAULT;
11304 }
53a5960a
PB
11305 ret = get_errno(stat(path(p), &st));
11306 unlock_user(p, arg1, 0);
6a24a778
AZ
11307 if (!is_error(ret))
11308 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11309 return ret;
a315a145
FB
11310#endif
11311#ifdef TARGET_NR_lstat64
31e31b8a 11312 case TARGET_NR_lstat64:
2852aafd
RH
11313 if (!(p = lock_user_string(arg1))) {
11314 return -TARGET_EFAULT;
11315 }
53a5960a
PB
11316 ret = get_errno(lstat(path(p), &st));
11317 unlock_user(p, arg1, 0);
6a24a778
AZ
11318 if (!is_error(ret))
11319 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11320 return ret;
a315a145
FB
11321#endif
11322#ifdef TARGET_NR_fstat64
31e31b8a 11323 case TARGET_NR_fstat64:
6a24a778
AZ
11324 ret = get_errno(fstat(arg1, &st));
11325 if (!is_error(ret))
11326 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11327 return ret;
ce4defa0 11328#endif
c0d472b1 11329#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 11330#ifdef TARGET_NR_fstatat64
6a24a778 11331 case TARGET_NR_fstatat64:
9d33b76b
AJ
11332#endif
11333#ifdef TARGET_NR_newfstatat
11334 case TARGET_NR_newfstatat:
11335#endif
2852aafd
RH
11336 if (!(p = lock_user_string(arg2))) {
11337 return -TARGET_EFAULT;
11338 }
c0d472b1 11339 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
2852aafd 11340 unlock_user(p, arg2, 0);
6a24a778
AZ
11341 if (!is_error(ret))
11342 ret = host_to_target_stat64(cpu_env, arg3, &st);
72eb7ea8 11343 return ret;
a315a145 11344#endif
efa92184
AR
11345#if defined(TARGET_NR_statx)
11346 case TARGET_NR_statx:
11347 {
11348 struct target_statx *target_stx;
11349 int dirfd = arg1;
11350 int flags = arg3;
11351
11352 p = lock_user_string(arg2);
11353 if (p == NULL) {
11354 return -TARGET_EFAULT;
11355 }
11356#if defined(__NR_statx)
11357 {
11358 /*
11359 * It is assumed that struct statx is architecture independent.
11360 */
11361 struct target_statx host_stx;
11362 int mask = arg4;
11363
11364 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11365 if (!is_error(ret)) {
11366 if (host_to_target_statx(&host_stx, arg5) != 0) {
11367 unlock_user(p, arg2, 0);
11368 return -TARGET_EFAULT;
11369 }
11370 }
11371
11372 if (ret != -TARGET_ENOSYS) {
11373 unlock_user(p, arg2, 0);
11374 return ret;
11375 }
11376 }
11377#endif
11378 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11379 unlock_user(p, arg2, 0);
11380
11381 if (!is_error(ret)) {
11382 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11383 return -TARGET_EFAULT;
11384 }
11385 memset(target_stx, 0, sizeof(*target_stx));
11386 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11387 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11388 __put_user(st.st_ino, &target_stx->stx_ino);
11389 __put_user(st.st_mode, &target_stx->stx_mode);
11390 __put_user(st.st_uid, &target_stx->stx_uid);
11391 __put_user(st.st_gid, &target_stx->stx_gid);
11392 __put_user(st.st_nlink, &target_stx->stx_nlink);
11393 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11394 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11395 __put_user(st.st_size, &target_stx->stx_size);
11396 __put_user(st.st_blksize, &target_stx->stx_blksize);
11397 __put_user(st.st_blocks, &target_stx->stx_blocks);
11398 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11399 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11400 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11401 unlock_user_struct(target_stx, arg5, 1);
11402 }
11403 }
11404 return ret;
11405#endif
704eff6c 11406#ifdef TARGET_NR_lchown
67867308 11407 case TARGET_NR_lchown:
579a97f7 11408 if (!(p = lock_user_string(arg1)))
2852aafd 11409 return -TARGET_EFAULT;
53a5960a
PB
11410 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11411 unlock_user(p, arg1, 0);
72eb7ea8 11412 return ret;
704eff6c 11413#endif
0c866a7e 11414#ifdef TARGET_NR_getuid
67867308 11415 case TARGET_NR_getuid:
72eb7ea8 11416 return get_errno(high2lowuid(getuid()));
0c866a7e
RV
11417#endif
11418#ifdef TARGET_NR_getgid
67867308 11419 case TARGET_NR_getgid:
72eb7ea8 11420 return get_errno(high2lowgid(getgid()));
0c866a7e
RV
11421#endif
11422#ifdef TARGET_NR_geteuid
67867308 11423 case TARGET_NR_geteuid:
72eb7ea8 11424 return get_errno(high2lowuid(geteuid()));
0c866a7e
RV
11425#endif
11426#ifdef TARGET_NR_getegid
67867308 11427 case TARGET_NR_getegid:
72eb7ea8 11428 return get_errno(high2lowgid(getegid()));
0c866a7e 11429#endif
67867308 11430 case TARGET_NR_setreuid:
72eb7ea8 11431 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
67867308 11432 case TARGET_NR_setregid:
72eb7ea8 11433 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
67867308
FB
11434 case TARGET_NR_getgroups:
11435 {
11436 int gidsetsize = arg1;
0c866a7e 11437 target_id *target_grouplist;
67867308
FB
11438 gid_t *grouplist;
11439 int i;
11440
11441 grouplist = alloca(gidsetsize * sizeof(gid_t));
11442 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11443 if (gidsetsize == 0)
72eb7ea8 11444 return ret;
67867308 11445 if (!is_error(ret)) {
03903ffc 11446 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7 11447 if (!target_grouplist)
2852aafd 11448 return -TARGET_EFAULT;
a2155fcc 11449 for(i = 0;i < ret; i++)
0c866a7e 11450 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 11451 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
11452 }
11453 }
72eb7ea8 11454 return ret;
67867308
FB
11455 case TARGET_NR_setgroups:
11456 {
11457 int gidsetsize = arg1;
0c866a7e 11458 target_id *target_grouplist;
f2b79ce9 11459 gid_t *grouplist = NULL;
67867308 11460 int i;
f2b79ce9
DA
11461 if (gidsetsize) {
11462 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 11463 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9 11464 if (!target_grouplist) {
259841c1 11465 return -TARGET_EFAULT;
f2b79ce9
DA
11466 }
11467 for (i = 0; i < gidsetsize; i++) {
11468 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11469 }
11470 unlock_user(target_grouplist, arg2, 0);
579a97f7 11471 }
72eb7ea8 11472 return get_errno(setgroups(gidsetsize, grouplist));
67867308 11473 }
67867308 11474 case TARGET_NR_fchown:
72eb7ea8 11475 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
c0d472b1 11476#if defined(TARGET_NR_fchownat)
ccfa72b7 11477 case TARGET_NR_fchownat:
579a97f7 11478 if (!(p = lock_user_string(arg2)))
2852aafd 11479 return -TARGET_EFAULT;
c0d472b1
PM
11480 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11481 low2highgid(arg4), arg5));
579a97f7 11482 unlock_user(p, arg2, 0);
72eb7ea8 11483 return ret;
ccfa72b7 11484#endif
67867308
FB
11485#ifdef TARGET_NR_setresuid
11486 case TARGET_NR_setresuid:
72eb7ea8
RH
11487 return get_errno(sys_setresuid(low2highuid(arg1),
11488 low2highuid(arg2),
11489 low2highuid(arg3)));
67867308
FB
11490#endif
11491#ifdef TARGET_NR_getresuid
11492 case TARGET_NR_getresuid:
11493 {
53a5960a 11494 uid_t ruid, euid, suid;
67867308
FB
11495 ret = get_errno(getresuid(&ruid, &euid, &suid));
11496 if (!is_error(ret)) {
76ca310a
PM
11497 if (put_user_id(high2lowuid(ruid), arg1)
11498 || put_user_id(high2lowuid(euid), arg2)
11499 || put_user_id(high2lowuid(suid), arg3))
2852aafd 11500 return -TARGET_EFAULT;
67867308
FB
11501 }
11502 }
72eb7ea8 11503 return ret;
67867308
FB
11504#endif
11505#ifdef TARGET_NR_getresgid
11506 case TARGET_NR_setresgid:
72eb7ea8
RH
11507 return get_errno(sys_setresgid(low2highgid(arg1),
11508 low2highgid(arg2),
11509 low2highgid(arg3)));
67867308
FB
11510#endif
11511#ifdef TARGET_NR_getresgid
11512 case TARGET_NR_getresgid:
11513 {
53a5960a 11514 gid_t rgid, egid, sgid;
67867308
FB
11515 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11516 if (!is_error(ret)) {
76ca310a
PM
11517 if (put_user_id(high2lowgid(rgid), arg1)
11518 || put_user_id(high2lowgid(egid), arg2)
11519 || put_user_id(high2lowgid(sgid), arg3))
2852aafd 11520 return -TARGET_EFAULT;
67867308
FB
11521 }
11522 }
72eb7ea8 11523 return ret;
67867308 11524#endif
704eff6c 11525#ifdef TARGET_NR_chown
67867308 11526 case TARGET_NR_chown:
579a97f7 11527 if (!(p = lock_user_string(arg1)))
2852aafd 11528 return -TARGET_EFAULT;
53a5960a
PB
11529 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11530 unlock_user(p, arg1, 0);
72eb7ea8 11531 return ret;
704eff6c 11532#endif
67867308 11533 case TARGET_NR_setuid:
72eb7ea8 11534 return get_errno(sys_setuid(low2highuid(arg1)));
67867308 11535 case TARGET_NR_setgid:
72eb7ea8 11536 return get_errno(sys_setgid(low2highgid(arg1)));
67867308 11537 case TARGET_NR_setfsuid:
72eb7ea8 11538 return get_errno(setfsuid(arg1));
67867308 11539 case TARGET_NR_setfsgid:
72eb7ea8 11540 return get_errno(setfsgid(arg1));
67867308 11541
a315a145 11542#ifdef TARGET_NR_lchown32
31e31b8a 11543 case TARGET_NR_lchown32:
579a97f7 11544 if (!(p = lock_user_string(arg1)))
2852aafd 11545 return -TARGET_EFAULT;
53a5960a
PB
11546 ret = get_errno(lchown(p, arg2, arg3));
11547 unlock_user(p, arg1, 0);
72eb7ea8 11548 return ret;
a315a145
FB
11549#endif
11550#ifdef TARGET_NR_getuid32
31e31b8a 11551 case TARGET_NR_getuid32:
72eb7ea8 11552 return get_errno(getuid());
a315a145 11553#endif
64b4d28c
AJ
11554
11555#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11556 /* Alpha specific */
11557 case TARGET_NR_getxuid:
ba0e276d
RH
11558 {
11559 uid_t euid;
11560 euid=geteuid();
0effdc29 11561 cpu_env->ir[IR_A4]=euid;
ba0e276d 11562 }
72eb7ea8 11563 return get_errno(getuid());
64b4d28c
AJ
11564#endif
11565#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11566 /* Alpha specific */
11567 case TARGET_NR_getxgid:
ba0e276d
RH
11568 {
11569 uid_t egid;
11570 egid=getegid();
0effdc29 11571 cpu_env->ir[IR_A4]=egid;
ba0e276d 11572 }
72eb7ea8 11573 return get_errno(getgid());
64b4d28c 11574#endif
ba0e276d
RH
11575#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11576 /* Alpha specific */
11577 case TARGET_NR_osf_getsysinfo:
11578 ret = -TARGET_EOPNOTSUPP;
11579 switch (arg1) {
11580 case TARGET_GSI_IEEE_FP_CONTROL:
11581 {
21ba8564 11582 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
0effdc29 11583 uint64_t swcr = cpu_env->swcr;
21ba8564
RH
11584
11585 swcr &= ~SWCR_STATUS_MASK;
11586 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
ba0e276d
RH
11587
11588 if (put_user_u64 (swcr, arg2))
2852aafd 11589 return -TARGET_EFAULT;
ba0e276d
RH
11590 ret = 0;
11591 }
11592 break;
11593
11594 /* case GSI_IEEE_STATE_AT_SIGNAL:
11595 -- Not implemented in linux kernel.
11596 case GSI_UACPROC:
11597 -- Retrieves current unaligned access state; not much used.
11598 case GSI_PROC_TYPE:
11599 -- Retrieves implver information; surely not used.
11600 case GSI_GET_HWRPB:
11601 -- Grabs a copy of the HWRPB; surely not used.
11602 */
11603 }
72eb7ea8 11604 return ret;
ba0e276d
RH
11605#endif
11606#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11607 /* Alpha specific */
11608 case TARGET_NR_osf_setsysinfo:
11609 ret = -TARGET_EOPNOTSUPP;
11610 switch (arg1) {
11611 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d 11612 {
21ba8564 11613 uint64_t swcr, fpcr;
ba0e276d 11614
6e06d515 11615 if (get_user_u64 (swcr, arg2)) {
2852aafd 11616 return -TARGET_EFAULT;
6e06d515 11617 }
ba0e276d 11618
21ba8564
RH
11619 /*
11620 * The kernel calls swcr_update_status to update the
11621 * status bits from the fpcr at every point that it
11622 * could be queried. Therefore, we store the status
11623 * bits only in FPCR.
11624 */
0effdc29 11625 cpu_env->swcr = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
21ba8564
RH
11626
11627 fpcr = cpu_alpha_load_fpcr(cpu_env);
11628 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11629 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
6e06d515 11630 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 11631 ret = 0;
6e06d515
RH
11632 }
11633 break;
11634
11635 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11636 {
21ba8564 11637 uint64_t exc, fpcr, fex;
6e06d515
RH
11638
11639 if (get_user_u64(exc, arg2)) {
2852aafd 11640 return -TARGET_EFAULT;
6e06d515 11641 }
21ba8564
RH
11642 exc &= SWCR_STATUS_MASK;
11643 fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 11644
21ba8564
RH
11645 /* Old exceptions are not signaled. */
11646 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11647 fex = exc & ~fex;
11648 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
0effdc29 11649 fex &= (cpu_env)->swcr;
6e06d515 11650
21ba8564
RH
11651 /* Update the hardware fpcr. */
11652 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
6e06d515 11653 cpu_alpha_store_fpcr(cpu_env, fpcr);
6e06d515 11654
21ba8564
RH
11655 if (fex) {
11656 int si_code = TARGET_FPE_FLTUNK;
6e06d515 11657 target_siginfo_t info;
21ba8564
RH
11658
11659 if (fex & SWCR_TRAP_ENABLE_DNO) {
11660 si_code = TARGET_FPE_FLTUND;
11661 }
11662 if (fex & SWCR_TRAP_ENABLE_INE) {
11663 si_code = TARGET_FPE_FLTRES;
11664 }
11665 if (fex & SWCR_TRAP_ENABLE_UNF) {
11666 si_code = TARGET_FPE_FLTUND;
11667 }
11668 if (fex & SWCR_TRAP_ENABLE_OVF) {
11669 si_code = TARGET_FPE_FLTOVF;
11670 }
11671 if (fex & SWCR_TRAP_ENABLE_DZE) {
11672 si_code = TARGET_FPE_FLTDIV;
11673 }
11674 if (fex & SWCR_TRAP_ENABLE_INV) {
11675 si_code = TARGET_FPE_FLTINV;
11676 }
11677
6e06d515
RH
11678 info.si_signo = SIGFPE;
11679 info.si_errno = 0;
11680 info.si_code = si_code;
0effdc29
PMD
11681 info._sifields._sigfault._addr = (cpu_env)->pc;
11682 queue_signal(cpu_env, info.si_signo,
9d2803f7 11683 QEMU_SI_FAULT, &info);
ba0e276d 11684 }
21ba8564 11685 ret = 0;
ba0e276d
RH
11686 }
11687 break;
11688
11689 /* case SSI_NVPAIRS:
11690 -- Used with SSIN_UACPROC to enable unaligned accesses.
11691 case SSI_IEEE_STATE_AT_SIGNAL:
11692 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11693 -- Not implemented in linux kernel
11694 */
11695 }
72eb7ea8 11696 return ret;
ba0e276d
RH
11697#endif
11698#ifdef TARGET_NR_osf_sigprocmask
11699 /* Alpha specific. */
11700 case TARGET_NR_osf_sigprocmask:
11701 {
11702 abi_ulong mask;
bc088ba1 11703 int how;
ba0e276d
RH
11704 sigset_t set, oldset;
11705
11706 switch(arg1) {
11707 case TARGET_SIG_BLOCK:
11708 how = SIG_BLOCK;
11709 break;
11710 case TARGET_SIG_UNBLOCK:
11711 how = SIG_UNBLOCK;
11712 break;
11713 case TARGET_SIG_SETMASK:
11714 how = SIG_SETMASK;
11715 break;
11716 default:
259841c1 11717 return -TARGET_EINVAL;
ba0e276d
RH
11718 }
11719 mask = arg2;
11720 target_to_host_old_sigset(&set, &mask);
3d3efba0
PM
11721 ret = do_sigprocmask(how, &set, &oldset);
11722 if (!ret) {
11723 host_to_target_old_sigset(&mask, &oldset);
11724 ret = mask;
11725 }
ba0e276d 11726 }
72eb7ea8 11727 return ret;
ba0e276d 11728#endif
64b4d28c 11729
a315a145 11730#ifdef TARGET_NR_getgid32
31e31b8a 11731 case TARGET_NR_getgid32:
72eb7ea8 11732 return get_errno(getgid());
a315a145
FB
11733#endif
11734#ifdef TARGET_NR_geteuid32
31e31b8a 11735 case TARGET_NR_geteuid32:
72eb7ea8 11736 return get_errno(geteuid());
a315a145
FB
11737#endif
11738#ifdef TARGET_NR_getegid32
31e31b8a 11739 case TARGET_NR_getegid32:
72eb7ea8 11740 return get_errno(getegid());
a315a145
FB
11741#endif
11742#ifdef TARGET_NR_setreuid32
31e31b8a 11743 case TARGET_NR_setreuid32:
72eb7ea8 11744 return get_errno(setreuid(arg1, arg2));
a315a145
FB
11745#endif
11746#ifdef TARGET_NR_setregid32
31e31b8a 11747 case TARGET_NR_setregid32:
72eb7ea8 11748 return get_errno(setregid(arg1, arg2));
a315a145
FB
11749#endif
11750#ifdef TARGET_NR_getgroups32
31e31b8a 11751 case TARGET_NR_getgroups32:
99c475ab
FB
11752 {
11753 int gidsetsize = arg1;
53a5960a 11754 uint32_t *target_grouplist;
99c475ab
FB
11755 gid_t *grouplist;
11756 int i;
11757
11758 grouplist = alloca(gidsetsize * sizeof(gid_t));
11759 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11760 if (gidsetsize == 0)
72eb7ea8 11761 return ret;
99c475ab 11762 if (!is_error(ret)) {
579a97f7
FB
11763 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11764 if (!target_grouplist) {
259841c1 11765 return -TARGET_EFAULT;
579a97f7 11766 }
a2155fcc 11767 for(i = 0;i < ret; i++)
53a5960a
PB
11768 target_grouplist[i] = tswap32(grouplist[i]);
11769 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
11770 }
11771 }
72eb7ea8 11772 return ret;
a315a145
FB
11773#endif
11774#ifdef TARGET_NR_setgroups32
31e31b8a 11775 case TARGET_NR_setgroups32:
99c475ab
FB
11776 {
11777 int gidsetsize = arg1;
53a5960a 11778 uint32_t *target_grouplist;
99c475ab
FB
11779 gid_t *grouplist;
11780 int i;
3b46e624 11781
99c475ab 11782 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
11783 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11784 if (!target_grouplist) {
259841c1 11785 return -TARGET_EFAULT;
579a97f7 11786 }
99c475ab 11787 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
11788 grouplist[i] = tswap32(target_grouplist[i]);
11789 unlock_user(target_grouplist, arg2, 0);
72eb7ea8 11790 return get_errno(setgroups(gidsetsize, grouplist));
99c475ab 11791 }
a315a145
FB
11792#endif
11793#ifdef TARGET_NR_fchown32
31e31b8a 11794 case TARGET_NR_fchown32:
72eb7ea8 11795 return get_errno(fchown(arg1, arg2, arg3));
a315a145
FB
11796#endif
11797#ifdef TARGET_NR_setresuid32
31e31b8a 11798 case TARGET_NR_setresuid32:
72eb7ea8 11799 return get_errno(sys_setresuid(arg1, arg2, arg3));
a315a145
FB
11800#endif
11801#ifdef TARGET_NR_getresuid32
31e31b8a 11802 case TARGET_NR_getresuid32:
b03c60f3 11803 {
53a5960a 11804 uid_t ruid, euid, suid;
b03c60f3
FB
11805 ret = get_errno(getresuid(&ruid, &euid, &suid));
11806 if (!is_error(ret)) {
2f619698
FB
11807 if (put_user_u32(ruid, arg1)
11808 || put_user_u32(euid, arg2)
11809 || put_user_u32(suid, arg3))
2852aafd 11810 return -TARGET_EFAULT;
b03c60f3
FB
11811 }
11812 }
72eb7ea8 11813 return ret;
a315a145
FB
11814#endif
11815#ifdef TARGET_NR_setresgid32
31e31b8a 11816 case TARGET_NR_setresgid32:
72eb7ea8 11817 return get_errno(sys_setresgid(arg1, arg2, arg3));
a315a145
FB
11818#endif
11819#ifdef TARGET_NR_getresgid32
31e31b8a 11820 case TARGET_NR_getresgid32:
b03c60f3 11821 {
53a5960a 11822 gid_t rgid, egid, sgid;
b03c60f3
FB
11823 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11824 if (!is_error(ret)) {
2f619698
FB
11825 if (put_user_u32(rgid, arg1)
11826 || put_user_u32(egid, arg2)
11827 || put_user_u32(sgid, arg3))
2852aafd 11828 return -TARGET_EFAULT;
b03c60f3
FB
11829 }
11830 }
72eb7ea8 11831 return ret;
a315a145
FB
11832#endif
11833#ifdef TARGET_NR_chown32
31e31b8a 11834 case TARGET_NR_chown32:
579a97f7 11835 if (!(p = lock_user_string(arg1)))
2852aafd 11836 return -TARGET_EFAULT;
53a5960a
PB
11837 ret = get_errno(chown(p, arg2, arg3));
11838 unlock_user(p, arg1, 0);
72eb7ea8 11839 return ret;
a315a145
FB
11840#endif
11841#ifdef TARGET_NR_setuid32
31e31b8a 11842 case TARGET_NR_setuid32:
72eb7ea8 11843 return get_errno(sys_setuid(arg1));
a315a145
FB
11844#endif
11845#ifdef TARGET_NR_setgid32
31e31b8a 11846 case TARGET_NR_setgid32:
72eb7ea8 11847 return get_errno(sys_setgid(arg1));
a315a145
FB
11848#endif
11849#ifdef TARGET_NR_setfsuid32
31e31b8a 11850 case TARGET_NR_setfsuid32:
72eb7ea8 11851 return get_errno(setfsuid(arg1));
a315a145
FB
11852#endif
11853#ifdef TARGET_NR_setfsgid32
31e31b8a 11854 case TARGET_NR_setfsgid32:
72eb7ea8 11855 return get_errno(setfsgid(arg1));
a315a145 11856#endif
ffa65c3b 11857#ifdef TARGET_NR_mincore
31e31b8a 11858 case TARGET_NR_mincore:
04bb9ace 11859 {
259841c1 11860 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
98a3331a 11861 if (!a) {
259841c1 11862 return -TARGET_ENOMEM;
98a3331a 11863 }
98a3331a
FSM
11864 p = lock_user_string(arg3);
11865 if (!p) {
259841c1
RH
11866 ret = -TARGET_EFAULT;
11867 } else {
11868 ret = get_errno(mincore(a, arg2, p));
11869 unlock_user(p, arg3, ret);
98a3331a 11870 }
04bb9ace
AJ
11871 unlock_user(a, arg1, 0);
11872 }
72eb7ea8 11873 return ret;
ffa65c3b 11874#endif
408321b6
AJ
11875#ifdef TARGET_NR_arm_fadvise64_64
11876 case TARGET_NR_arm_fadvise64_64:
e0156a9d
PM
11877 /* arm_fadvise64_64 looks like fadvise64_64 but
11878 * with different argument order: fd, advice, offset, len
11879 * rather than the usual fd, offset, len, advice.
11880 * Note that offset and len are both 64-bit so appear as
11881 * pairs of 32-bit registers.
11882 */
11883 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11884 target_offset64(arg5, arg6), arg2);
72eb7ea8 11885 return -host_to_target_errno(ret);
408321b6 11886#endif
badd3cd8 11887
eeed2291 11888#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
badd3cd8
PM
11889
11890#ifdef TARGET_NR_fadvise64_64
11891 case TARGET_NR_fadvise64_64:
64a563dd 11892#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
43046b5a
LV
11893 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11894 ret = arg2;
11895 arg2 = arg3;
11896 arg3 = arg4;
11897 arg4 = arg5;
11898 arg5 = arg6;
11899 arg6 = ret;
11900#else
badd3cd8 11901 /* 6 args: fd, offset (high, low), len (high, low), advice */
8bf8e9df 11902 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11903 /* offset is in (3,4), len in (5,6) and advice in 7 */
11904 arg2 = arg3;
11905 arg3 = arg4;
11906 arg4 = arg5;
11907 arg5 = arg6;
11908 arg6 = arg7;
11909 }
43046b5a 11910#endif
72eb7ea8
RH
11911 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11912 target_offset64(arg4, arg5), arg6);
11913 return -host_to_target_errno(ret);
badd3cd8
PM
11914#endif
11915
11916#ifdef TARGET_NR_fadvise64
11917 case TARGET_NR_fadvise64:
11918 /* 5 args: fd, offset (high, low), len, advice */
8bf8e9df 11919 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11920 /* offset is in (3,4), len in 5 and advice in 6 */
11921 arg2 = arg3;
11922 arg3 = arg4;
11923 arg4 = arg5;
11924 arg5 = arg6;
11925 }
72eb7ea8
RH
11926 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11927 return -host_to_target_errno(ret);
408321b6 11928#endif
badd3cd8
PM
11929
11930#else /* not a 32-bit ABI */
e0156a9d 11931#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
11932#ifdef TARGET_NR_fadvise64_64
11933 case TARGET_NR_fadvise64_64:
11934#endif
e72d2cc7
UH
11935#ifdef TARGET_NR_fadvise64
11936 case TARGET_NR_fadvise64:
11937#endif
11938#ifdef TARGET_S390X
11939 switch (arg4) {
11940 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11941 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11942 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11943 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11944 default: break;
11945 }
11946#endif
72eb7ea8 11947 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
408321b6 11948#endif
badd3cd8
PM
11949#endif /* end of 64-bit ABI fadvise handling */
11950
ffa65c3b 11951#ifdef TARGET_NR_madvise
31e31b8a 11952 case TARGET_NR_madvise:
892a4f6a 11953 return target_madvise(arg1, arg2, arg3);
ffa65c3b 11954#endif
bbf5f2a1 11955#ifdef TARGET_NR_fcntl64
31e31b8a 11956 case TARGET_NR_fcntl64:
77e4672d 11957 {
bbf5f2a1
AB
11958 int cmd;
11959 struct flock64 fl;
213d3e9e
PM
11960 from_flock64_fn *copyfrom = copy_from_user_flock64;
11961 to_flock64_fn *copyto = copy_to_user_flock64;
11962
ce4defa0 11963#ifdef TARGET_ARM
0effdc29 11964 if (!cpu_env->eabi) {
7f254c5c
LV
11965 copyfrom = copy_from_user_oabi_flock64;
11966 copyto = copy_to_user_oabi_flock64;
213d3e9e 11967 }
ce4defa0 11968#endif
77e4672d 11969
bbf5f2a1 11970 cmd = target_to_host_fcntl_cmd(arg2);
31b63193 11971 if (cmd == -TARGET_EINVAL) {
72eb7ea8 11972 return cmd;
31b63193 11973 }
b1e341eb 11974
60cd49d5 11975 switch(arg2) {
b1e341eb 11976 case TARGET_F_GETLK64:
213d3e9e
PM
11977 ret = copyfrom(&fl, arg3);
11978 if (ret) {
11979 break;
5813427b 11980 }
af8ab2bf 11981 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
213d3e9e
PM
11982 if (ret == 0) {
11983 ret = copyto(arg3, &fl);
11984 }
77e4672d
FB
11985 break;
11986
b1e341eb
TS
11987 case TARGET_F_SETLK64:
11988 case TARGET_F_SETLKW64:
213d3e9e
PM
11989 ret = copyfrom(&fl, arg3);
11990 if (ret) {
11991 break;
ce4defa0 11992 }
435da5e7 11993 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
77e4672d 11994 break;
60cd49d5 11995 default:
5f106811 11996 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
11997 break;
11998 }
72eb7ea8 11999 return ret;
77e4672d 12000 }
60cd49d5 12001#endif
7d600c80
TS
12002#ifdef TARGET_NR_cacheflush
12003 case TARGET_NR_cacheflush:
12004 /* self-modifying code is handled automatically, so nothing needed */
72eb7ea8 12005 return 0;
7d600c80 12006#endif
c573ff67
FB
12007#ifdef TARGET_NR_getpagesize
12008 case TARGET_NR_getpagesize:
72eb7ea8 12009 return TARGET_PAGE_SIZE;
ebc05488 12010#endif
31e31b8a 12011 case TARGET_NR_gettid:
71ba74f6 12012 return get_errno(sys_gettid());
e5febef5 12013#ifdef TARGET_NR_readahead
31e31b8a 12014 case TARGET_NR_readahead:
eeed2291 12015#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
8bf8e9df 12016 if (regpairs_aligned(cpu_env, num)) {
2054ac9b
AJ
12017 arg2 = arg3;
12018 arg3 = arg4;
12019 arg4 = arg5;
12020 }
77c6850f 12021 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
2054ac9b
AJ
12022#else
12023 ret = get_errno(readahead(arg1, arg2, arg3));
12024#endif
72eb7ea8 12025 return ret;
e5febef5 12026#endif
a790ae38 12027#ifdef CONFIG_ATTR
ebc05488 12028#ifdef TARGET_NR_setxattr
31e31b8a
FB
12029 case TARGET_NR_listxattr:
12030 case TARGET_NR_llistxattr:
fb5590f7
PM
12031 {
12032 void *p, *b = 0;
12033 if (arg2) {
12034 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12035 if (!b) {
72eb7ea8 12036 return -TARGET_EFAULT;
fb5590f7
PM
12037 }
12038 }
12039 p = lock_user_string(arg1);
12040 if (p) {
12041 if (num == TARGET_NR_listxattr) {
12042 ret = get_errno(listxattr(p, b, arg3));
12043 } else {
12044 ret = get_errno(llistxattr(p, b, arg3));
12045 }
12046 } else {
12047 ret = -TARGET_EFAULT;
12048 }
12049 unlock_user(p, arg1, 0);
12050 unlock_user(b, arg2, arg3);
72eb7ea8 12051 return ret;
fb5590f7 12052 }
31e31b8a 12053 case TARGET_NR_flistxattr:
fb5590f7
PM
12054 {
12055 void *b = 0;
12056 if (arg2) {
12057 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
12058 if (!b) {
72eb7ea8 12059 return -TARGET_EFAULT;
fb5590f7
PM
12060 }
12061 }
12062 ret = get_errno(flistxattr(arg1, b, arg3));
12063 unlock_user(b, arg2, arg3);
72eb7ea8 12064 return ret;
fb5590f7 12065 }
a790ae38 12066 case TARGET_NR_setxattr:
30297b55 12067 case TARGET_NR_lsetxattr:
a790ae38 12068 {
e3c33ec6
PM
12069 void *p, *n, *v = 0;
12070 if (arg3) {
12071 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12072 if (!v) {
72eb7ea8 12073 return -TARGET_EFAULT;
e3c33ec6
PM
12074 }
12075 }
a790ae38
ACH
12076 p = lock_user_string(arg1);
12077 n = lock_user_string(arg2);
e3c33ec6 12078 if (p && n) {
30297b55
PM
12079 if (num == TARGET_NR_setxattr) {
12080 ret = get_errno(setxattr(p, n, v, arg4, arg5));
12081 } else {
12082 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
12083 }
a790ae38
ACH
12084 } else {
12085 ret = -TARGET_EFAULT;
12086 }
12087 unlock_user(p, arg1, 0);
12088 unlock_user(n, arg2, 0);
12089 unlock_user(v, arg3, 0);
12090 }
72eb7ea8 12091 return ret;
30297b55
PM
12092 case TARGET_NR_fsetxattr:
12093 {
12094 void *n, *v = 0;
12095 if (arg3) {
12096 v = lock_user(VERIFY_READ, arg3, arg4, 1);
12097 if (!v) {
72eb7ea8 12098 return -TARGET_EFAULT;
30297b55
PM
12099 }
12100 }
12101 n = lock_user_string(arg2);
12102 if (n) {
12103 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
12104 } else {
12105 ret = -TARGET_EFAULT;
12106 }
12107 unlock_user(n, arg2, 0);
12108 unlock_user(v, arg3, 0);
12109 }
72eb7ea8 12110 return ret;
a790ae38 12111 case TARGET_NR_getxattr:
30297b55 12112 case TARGET_NR_lgetxattr:
a790ae38 12113 {
e3c33ec6
PM
12114 void *p, *n, *v = 0;
12115 if (arg3) {
12116 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12117 if (!v) {
72eb7ea8 12118 return -TARGET_EFAULT;
e3c33ec6
PM
12119 }
12120 }
a790ae38
ACH
12121 p = lock_user_string(arg1);
12122 n = lock_user_string(arg2);
e3c33ec6 12123 if (p && n) {
30297b55
PM
12124 if (num == TARGET_NR_getxattr) {
12125 ret = get_errno(getxattr(p, n, v, arg4));
12126 } else {
12127 ret = get_errno(lgetxattr(p, n, v, arg4));
12128 }
a790ae38
ACH
12129 } else {
12130 ret = -TARGET_EFAULT;
12131 }
12132 unlock_user(p, arg1, 0);
12133 unlock_user(n, arg2, 0);
12134 unlock_user(v, arg3, arg4);
12135 }
72eb7ea8 12136 return ret;
30297b55
PM
12137 case TARGET_NR_fgetxattr:
12138 {
12139 void *n, *v = 0;
12140 if (arg3) {
12141 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12142 if (!v) {
72eb7ea8 12143 return -TARGET_EFAULT;
30297b55
PM
12144 }
12145 }
12146 n = lock_user_string(arg2);
12147 if (n) {
12148 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12149 } else {
12150 ret = -TARGET_EFAULT;
12151 }
12152 unlock_user(n, arg2, 0);
12153 unlock_user(v, arg3, arg4);
12154 }
72eb7ea8 12155 return ret;
a790ae38 12156 case TARGET_NR_removexattr:
30297b55 12157 case TARGET_NR_lremovexattr:
a790ae38
ACH
12158 {
12159 void *p, *n;
12160 p = lock_user_string(arg1);
12161 n = lock_user_string(arg2);
12162 if (p && n) {
30297b55
PM
12163 if (num == TARGET_NR_removexattr) {
12164 ret = get_errno(removexattr(p, n));
12165 } else {
12166 ret = get_errno(lremovexattr(p, n));
12167 }
a790ae38
ACH
12168 } else {
12169 ret = -TARGET_EFAULT;
12170 }
12171 unlock_user(p, arg1, 0);
12172 unlock_user(n, arg2, 0);
12173 }
72eb7ea8 12174 return ret;
30297b55
PM
12175 case TARGET_NR_fremovexattr:
12176 {
12177 void *n;
12178 n = lock_user_string(arg2);
12179 if (n) {
12180 ret = get_errno(fremovexattr(arg1, n));
12181 } else {
12182 ret = -TARGET_EFAULT;
12183 }
12184 unlock_user(n, arg2, 0);
12185 }
72eb7ea8 12186 return ret;
ebc05488 12187#endif
a790ae38 12188#endif /* CONFIG_ATTR */
ebc05488 12189#ifdef TARGET_NR_set_thread_area
5cd4393b 12190 case TARGET_NR_set_thread_area:
8d18e893 12191#if defined(TARGET_MIPS)
0effdc29 12192 cpu_env->active_tc.CP0_UserLocal = arg1;
72eb7ea8 12193 return 0;
ef96779b
EI
12194#elif defined(TARGET_CRIS)
12195 if (arg1 & 0xff)
12196 ret = -TARGET_EINVAL;
12197 else {
0effdc29 12198 cpu_env->pregs[PR_PID] = arg1;
ef96779b
EI
12199 ret = 0;
12200 }
72eb7ea8 12201 return ret;
8d18e893 12202#elif defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12203 return do_set_thread_area(cpu_env, arg1);
1ccd9374
PM
12204#elif defined(TARGET_M68K)
12205 {
0429a971 12206 TaskState *ts = cpu->opaque;
1ccd9374 12207 ts->tp_value = arg1;
72eb7ea8 12208 return 0;
1ccd9374 12209 }
6f5b89a0 12210#else
10f45d98 12211 return -TARGET_ENOSYS;
6f5b89a0
TS
12212#endif
12213#endif
12214#ifdef TARGET_NR_get_thread_area
5cd4393b 12215 case TARGET_NR_get_thread_area:
8d18e893 12216#if defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12217 return do_get_thread_area(cpu_env, arg1);
1ccd9374
PM
12218#elif defined(TARGET_M68K)
12219 {
0429a971 12220 TaskState *ts = cpu->opaque;
72eb7ea8 12221 return ts->tp_value;
1ccd9374 12222 }
8d18e893 12223#else
10f45d98 12224 return -TARGET_ENOSYS;
48dc41eb 12225#endif
8d18e893 12226#endif
48dc41eb
FB
12227#ifdef TARGET_NR_getdomainname
12228 case TARGET_NR_getdomainname:
10f45d98 12229 return -TARGET_ENOSYS;
ebc05488 12230#endif
6f5b89a0 12231
12e3340c
MF
12232#ifdef TARGET_NR_clock_settime
12233 case TARGET_NR_clock_settime:
12234 {
12235 struct timespec ts;
12236
12237 ret = target_to_host_timespec(&ts, arg2);
12238 if (!is_error(ret)) {
12239 ret = get_errno(clock_settime(arg1, &ts));
12240 }
72eb7ea8 12241 return ret;
12e3340c
MF
12242 }
12243#endif
c6c8d102
AF
12244#ifdef TARGET_NR_clock_settime64
12245 case TARGET_NR_clock_settime64:
12246 {
12247 struct timespec ts;
12248
12249 ret = target_to_host_timespec64(&ts, arg2);
12250 if (!is_error(ret)) {
12251 ret = get_errno(clock_settime(arg1, &ts));
12252 }
12253 return ret;
12254 }
12255#endif
b5906f95
TS
12256#ifdef TARGET_NR_clock_gettime
12257 case TARGET_NR_clock_gettime:
12258 {
12259 struct timespec ts;
12260 ret = get_errno(clock_gettime(arg1, &ts));
12261 if (!is_error(ret)) {
b9f9908e 12262 ret = host_to_target_timespec(arg2, &ts);
b5906f95 12263 }
72eb7ea8 12264 return ret;
b5906f95
TS
12265 }
12266#endif
c6c8d102
AF
12267#ifdef TARGET_NR_clock_gettime64
12268 case TARGET_NR_clock_gettime64:
12269 {
12270 struct timespec ts;
12271 ret = get_errno(clock_gettime(arg1, &ts));
12272 if (!is_error(ret)) {
12273 ret = host_to_target_timespec64(arg2, &ts);
12274 }
12275 return ret;
12276 }
12277#endif
b5906f95
TS
12278#ifdef TARGET_NR_clock_getres
12279 case TARGET_NR_clock_getres:
12280 {
12281 struct timespec ts;
12282 ret = get_errno(clock_getres(arg1, &ts));
12283 if (!is_error(ret)) {
12284 host_to_target_timespec(arg2, &ts);
12285 }
72eb7ea8 12286 return ret;
b5906f95
TS
12287 }
12288#endif
828cb3a1
FB
12289#ifdef TARGET_NR_clock_getres_time64
12290 case TARGET_NR_clock_getres_time64:
12291 {
12292 struct timespec ts;
12293 ret = get_errno(clock_getres(arg1, &ts));
12294 if (!is_error(ret)) {
12295 host_to_target_timespec64(arg2, &ts);
12296 }
12297 return ret;
12298 }
12299#endif
63d7651b
PB
12300#ifdef TARGET_NR_clock_nanosleep
12301 case TARGET_NR_clock_nanosleep:
12302 {
12303 struct timespec ts;
b09d6406
FB
12304 if (target_to_host_timespec(&ts, arg3)) {
12305 return -TARGET_EFAULT;
12306 }
9e518226
PM
12307 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12308 &ts, arg4 ? &ts : NULL));
8ec68a0a
LV
12309 /*
12310 * if the call is interrupted by a signal handler, it fails
12311 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12312 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12313 */
b09d6406
FB
12314 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12315 host_to_target_timespec(arg4, &ts)) {
12316 return -TARGET_EFAULT;
8ec68a0a 12317 }
8fbe8fdf 12318
72eb7ea8 12319 return ret;
63d7651b
PB
12320 }
12321#endif
6ac03b2c
FB
12322#ifdef TARGET_NR_clock_nanosleep_time64
12323 case TARGET_NR_clock_nanosleep_time64:
12324 {
12325 struct timespec ts;
12326
12327 if (target_to_host_timespec64(&ts, arg3)) {
12328 return -TARGET_EFAULT;
12329 }
12330
12331 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12332 &ts, arg4 ? &ts : NULL));
12333
12334 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12335 host_to_target_timespec64(arg4, &ts)) {
12336 return -TARGET_EFAULT;
12337 }
12338 return ret;
12339 }
12340#endif
b5906f95 12341
9a7f682c 12342#if defined(TARGET_NR_set_tid_address)
6f5b89a0 12343 case TARGET_NR_set_tid_address:
9a7f682c
HD
12344 {
12345 TaskState *ts = cpu->opaque;
12346 ts->child_tidptr = arg1;
12347 /* do not call host set_tid_address() syscall, instead return tid() */
12348 return get_errno(sys_gettid());
12349 }
6f5b89a0
TS
12350#endif
12351
4cae1d16 12352 case TARGET_NR_tkill:
72eb7ea8 12353 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16 12354
71455574 12355 case TARGET_NR_tgkill:
72eb7ea8
RH
12356 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12357 target_to_host_signal(arg3)));
71455574 12358
4f2b1fe8
TS
12359#ifdef TARGET_NR_set_robust_list
12360 case TARGET_NR_set_robust_list:
e9a970a8
PM
12361 case TARGET_NR_get_robust_list:
12362 /* The ABI for supporting robust futexes has userspace pass
12363 * the kernel a pointer to a linked list which is updated by
12364 * userspace after the syscall; the list is walked by the kernel
12365 * when the thread exits. Since the linked list in QEMU guest
12366 * memory isn't a valid linked list for the host and we have
12367 * no way to reliably intercept the thread-death event, we can't
12368 * support these. Silently return ENOSYS so that guest userspace
12369 * falls back to a non-robust futex implementation (which should
12370 * be OK except in the corner case of the guest crashing while
12371 * holding a mutex that is shared with another process via
12372 * shared memory).
12373 */
10f45d98 12374 return -TARGET_ENOSYS;
4f2b1fe8
TS
12375#endif
12376
1acae9f2 12377#if defined(TARGET_NR_utimensat)
9007f0ef
TS
12378 case TARGET_NR_utimensat:
12379 {
ebc996f3
RV
12380 struct timespec *tsp, ts[2];
12381 if (!arg3) {
12382 tsp = NULL;
12383 } else {
b3a3af70
FB
12384 if (target_to_host_timespec(ts, arg3)) {
12385 return -TARGET_EFAULT;
12386 }
12387 if (target_to_host_timespec(ts + 1, arg3 +
12388 sizeof(struct target_timespec))) {
12389 return -TARGET_EFAULT;
12390 }
ebc996f3
RV
12391 tsp = ts;
12392 }
9007f0ef 12393 if (!arg2)
ebc996f3 12394 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 12395 else {
579a97f7 12396 if (!(p = lock_user_string(arg2))) {
259841c1 12397 return -TARGET_EFAULT;
579a97f7 12398 }
ebc996f3 12399 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 12400 unlock_user(p, arg2, 0);
cac46eb0
FB
12401 }
12402 }
12403 return ret;
12404#endif
12405#ifdef TARGET_NR_utimensat_time64
12406 case TARGET_NR_utimensat_time64:
12407 {
12408 struct timespec *tsp, ts[2];
12409 if (!arg3) {
12410 tsp = NULL;
12411 } else {
12412 if (target_to_host_timespec64(ts, arg3)) {
12413 return -TARGET_EFAULT;
12414 }
12415 if (target_to_host_timespec64(ts + 1, arg3 +
12416 sizeof(struct target__kernel_timespec))) {
12417 return -TARGET_EFAULT;
12418 }
12419 tsp = ts;
12420 }
12421 if (!arg2)
12422 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12423 else {
12424 p = lock_user_string(arg2);
12425 if (!p) {
12426 return -TARGET_EFAULT;
12427 }
12428 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12429 unlock_user(p, arg2, 0);
9007f0ef
TS
12430 }
12431 }
72eb7ea8 12432 return ret;
9007f0ef 12433#endif
859e8a89 12434#ifdef TARGET_NR_futex
bd0c5661 12435 case TARGET_NR_futex:
0fbc0f8d 12436 return do_futex(cpu, false, arg1, arg2, arg3, arg4, arg5, arg6);
859e8a89 12437#endif
14690296
AF
12438#ifdef TARGET_NR_futex_time64
12439 case TARGET_NR_futex_time64:
0fbc0f8d 12440 return do_futex(cpu, true, arg1, arg2, arg3, arg4, arg5, arg6);
14690296 12441#endif
33f53ac5
PB
12442#ifdef CONFIG_INOTIFY
12443#if defined(TARGET_NR_inotify_init)
39b59763 12444 case TARGET_NR_inotify_init:
33f53ac5 12445 ret = get_errno(inotify_init());
b929f7e5
PMD
12446 if (ret >= 0) {
12447 fd_trans_register(ret, &target_inotify_trans);
12448 }
72eb7ea8 12449 return ret;
39b59763 12450#endif
33f53ac5 12451#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
c05c7a73 12452 case TARGET_NR_inotify_init1:
33f53ac5 12453 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
fea243e9 12454 fcntl_flags_tbl)));
b929f7e5
PMD
12455 if (ret >= 0) {
12456 fd_trans_register(ret, &target_inotify_trans);
12457 }
72eb7ea8 12458 return ret;
c05c7a73 12459#endif
33f53ac5 12460#if defined(TARGET_NR_inotify_add_watch)
39b59763
AJ
12461 case TARGET_NR_inotify_add_watch:
12462 p = lock_user_string(arg2);
33f53ac5 12463 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
39b59763 12464 unlock_user(p, arg2, 0);
72eb7ea8 12465 return ret;
39b59763 12466#endif
33f53ac5 12467#if defined(TARGET_NR_inotify_rm_watch)
39b59763 12468 case TARGET_NR_inotify_rm_watch:
33f53ac5
PB
12469 return get_errno(inotify_rm_watch(arg1, arg2));
12470#endif
39b59763 12471#endif
9007f0ef 12472
8ec9cf89 12473#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
12474 case TARGET_NR_mq_open:
12475 {
c7536ab6 12476 struct mq_attr posix_mq_attr;
26400775 12477 struct mq_attr *pposix_mq_attr;
c7536ab6 12478 int host_flags;
24e1003a 12479
c7536ab6 12480 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
26400775
LD
12481 pposix_mq_attr = NULL;
12482 if (arg4) {
12483 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
2852aafd 12484 return -TARGET_EFAULT;
26400775
LD
12485 }
12486 pposix_mq_attr = &posix_mq_attr;
c7536ab6 12487 }
24e1003a 12488 p = lock_user_string(arg1 - 1);
c7536ab6 12489 if (!p) {
2852aafd 12490 return -TARGET_EFAULT;
b6ce1f6b 12491 }
26400775 12492 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
24e1003a
AJ
12493 unlock_user (p, arg1, 0);
12494 }
72eb7ea8 12495 return ret;
24e1003a
AJ
12496
12497 case TARGET_NR_mq_unlink:
12498 p = lock_user_string(arg1 - 1);
3211215e 12499 if (!p) {
72eb7ea8 12500 return -TARGET_EFAULT;
3211215e 12501 }
24e1003a
AJ
12502 ret = get_errno(mq_unlink(p));
12503 unlock_user (p, arg1, 0);
72eb7ea8 12504 return ret;
24e1003a 12505
859e8a89 12506#ifdef TARGET_NR_mq_timedsend
24e1003a
AJ
12507 case TARGET_NR_mq_timedsend:
12508 {
12509 struct timespec ts;
12510
12511 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12512 if (arg5 != 0) {
dcbcf5cf
FB
12513 if (target_to_host_timespec(&ts, arg5)) {
12514 return -TARGET_EFAULT;
12515 }
d40ecd66 12516 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
dcbcf5cf
FB
12517 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12518 return -TARGET_EFAULT;
12519 }
d40ecd66
PM
12520 } else {
12521 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
24e1003a 12522 }
24e1003a
AJ
12523 unlock_user (p, arg2, arg3);
12524 }
72eb7ea8 12525 return ret;
859e8a89 12526#endif
d107e375
FB
12527#ifdef TARGET_NR_mq_timedsend_time64
12528 case TARGET_NR_mq_timedsend_time64:
12529 {
12530 struct timespec ts;
12531
12532 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12533 if (arg5 != 0) {
12534 if (target_to_host_timespec64(&ts, arg5)) {
12535 return -TARGET_EFAULT;
12536 }
12537 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12538 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12539 return -TARGET_EFAULT;
12540 }
12541 } else {
12542 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12543 }
12544 unlock_user(p, arg2, arg3);
12545 }
12546 return ret;
12547#endif
24e1003a 12548
859e8a89 12549#ifdef TARGET_NR_mq_timedreceive
24e1003a
AJ
12550 case TARGET_NR_mq_timedreceive:
12551 {
12552 struct timespec ts;
12553 unsigned int prio;
12554
12555 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12556 if (arg5 != 0) {
dcbcf5cf
FB
12557 if (target_to_host_timespec(&ts, arg5)) {
12558 return -TARGET_EFAULT;
12559 }
d40ecd66
PM
12560 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12561 &prio, &ts));
dcbcf5cf
FB
12562 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12563 return -TARGET_EFAULT;
12564 }
d40ecd66
PM
12565 } else {
12566 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12567 &prio, NULL));
24e1003a 12568 }
24e1003a
AJ
12569 unlock_user (p, arg2, arg3);
12570 if (arg4 != 0)
12571 put_user_u32(prio, arg4);
12572 }
72eb7ea8 12573 return ret;
859e8a89 12574#endif
d107e375
FB
12575#ifdef TARGET_NR_mq_timedreceive_time64
12576 case TARGET_NR_mq_timedreceive_time64:
12577 {
12578 struct timespec ts;
12579 unsigned int prio;
12580
12581 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12582 if (arg5 != 0) {
12583 if (target_to_host_timespec64(&ts, arg5)) {
12584 return -TARGET_EFAULT;
12585 }
12586 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12587 &prio, &ts));
12588 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12589 return -TARGET_EFAULT;
12590 }
12591 } else {
12592 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12593 &prio, NULL));
12594 }
12595 unlock_user(p, arg2, arg3);
12596 if (arg4 != 0) {
12597 put_user_u32(prio, arg4);
12598 }
12599 }
12600 return ret;
12601#endif
24e1003a
AJ
12602
12603 /* Not implemented for now... */
12604/* case TARGET_NR_mq_notify: */
12605/* break; */
12606
12607 case TARGET_NR_mq_getsetattr:
12608 {
12609 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12610 ret = 0;
24e1003a
AJ
12611 if (arg2 != 0) {
12612 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
a23ea409
MF
12613 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12614 &posix_mq_attr_out));
12615 } else if (arg3 != 0) {
12616 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
12617 }
12618 if (ret == 0 && arg3 != 0) {
12619 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
24e1003a 12620 }
24e1003a 12621 }
72eb7ea8 12622 return ret;
24e1003a
AJ
12623#endif
12624
3ce34dfb
VS
12625#ifdef CONFIG_SPLICE
12626#ifdef TARGET_NR_tee
12627 case TARGET_NR_tee:
12628 {
12629 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12630 }
72eb7ea8 12631 return ret;
3ce34dfb
VS
12632#endif
12633#ifdef TARGET_NR_splice
12634 case TARGET_NR_splice:
12635 {
12636 loff_t loff_in, loff_out;
12637 loff_t *ploff_in = NULL, *ploff_out = NULL;
17644b36
AS
12638 if (arg2) {
12639 if (get_user_u64(loff_in, arg2)) {
2852aafd 12640 return -TARGET_EFAULT;
17644b36 12641 }
3ce34dfb
VS
12642 ploff_in = &loff_in;
12643 }
17644b36
AS
12644 if (arg4) {
12645 if (get_user_u64(loff_out, arg4)) {
2852aafd 12646 return -TARGET_EFAULT;
17644b36 12647 }
3ce34dfb
VS
12648 ploff_out = &loff_out;
12649 }
12650 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
17644b36
AS
12651 if (arg2) {
12652 if (put_user_u64(loff_in, arg2)) {
2852aafd 12653 return -TARGET_EFAULT;
17644b36
AS
12654 }
12655 }
12656 if (arg4) {
12657 if (put_user_u64(loff_out, arg4)) {
2852aafd 12658 return -TARGET_EFAULT;
17644b36
AS
12659 }
12660 }
3ce34dfb 12661 }
72eb7ea8 12662 return ret;
3ce34dfb
VS
12663#endif
12664#ifdef TARGET_NR_vmsplice
12665 case TARGET_NR_vmsplice:
12666 {
f287b2c2
RH
12667 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12668 if (vec != NULL) {
12669 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12670 unlock_iovec(vec, arg2, arg3, 0);
12671 } else {
12672 ret = -host_to_target_errno(errno);
12673 }
3ce34dfb 12674 }
72eb7ea8 12675 return ret;
3ce34dfb
VS
12676#endif
12677#endif /* CONFIG_SPLICE */
c2882b96
RV
12678#ifdef CONFIG_EVENTFD
12679#if defined(TARGET_NR_eventfd)
12680 case TARGET_NR_eventfd:
12681 ret = get_errno(eventfd(arg1, 0));
b929f7e5
PMD
12682 if (ret >= 0) {
12683 fd_trans_register(ret, &target_eventfd_trans);
12684 }
72eb7ea8 12685 return ret;
c2882b96
RV
12686#endif
12687#if defined(TARGET_NR_eventfd2)
12688 case TARGET_NR_eventfd2:
5947c697 12689 {
78721301 12690 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
5947c697
PJ
12691 if (arg2 & TARGET_O_NONBLOCK) {
12692 host_flags |= O_NONBLOCK;
12693 }
12694 if (arg2 & TARGET_O_CLOEXEC) {
12695 host_flags |= O_CLOEXEC;
12696 }
12697 ret = get_errno(eventfd(arg1, host_flags));
b929f7e5
PMD
12698 if (ret >= 0) {
12699 fd_trans_register(ret, &target_eventfd_trans);
12700 }
72eb7ea8 12701 return ret;
5947c697 12702 }
c2882b96
RV
12703#endif
12704#endif /* CONFIG_EVENTFD */
d0927938
UH
12705#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12706 case TARGET_NR_fallocate:
eeed2291 12707#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
20249ae1
AG
12708 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12709 target_offset64(arg5, arg6)));
12710#else
d0927938 12711 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 12712#endif
72eb7ea8 12713 return ret;
c727f47d
PM
12714#endif
12715#if defined(CONFIG_SYNC_FILE_RANGE)
12716#if defined(TARGET_NR_sync_file_range)
12717 case TARGET_NR_sync_file_range:
eeed2291 12718#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
bfcedc57
RV
12719#if defined(TARGET_MIPS)
12720 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12721 target_offset64(arg5, arg6), arg7));
12722#else
c727f47d
PM
12723 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12724 target_offset64(arg4, arg5), arg6));
bfcedc57 12725#endif /* !TARGET_MIPS */
c727f47d
PM
12726#else
12727 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12728#endif
72eb7ea8 12729 return ret;
c727f47d 12730#endif
5bcb4986
LV
12731#if defined(TARGET_NR_sync_file_range2) || \
12732 defined(TARGET_NR_arm_sync_file_range)
c727f47d
PM
12733#if defined(TARGET_NR_sync_file_range2)
12734 case TARGET_NR_sync_file_range2:
5bcb4986
LV
12735#endif
12736#if defined(TARGET_NR_arm_sync_file_range)
12737 case TARGET_NR_arm_sync_file_range:
12738#endif
c727f47d 12739 /* This is like sync_file_range but the arguments are reordered */
eeed2291 12740#if TARGET_ABI_BITS == 32 && !defined(TARGET_ABI_MIPSN32)
c727f47d
PM
12741 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12742 target_offset64(arg5, arg6), arg2));
12743#else
12744 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12745#endif
72eb7ea8 12746 return ret;
c727f47d 12747#endif
3b6edd16 12748#endif
e36800c9
LV
12749#if defined(TARGET_NR_signalfd4)
12750 case TARGET_NR_signalfd4:
72eb7ea8 12751 return do_signalfd4(arg1, arg2, arg4);
e36800c9
LV
12752#endif
12753#if defined(TARGET_NR_signalfd)
12754 case TARGET_NR_signalfd:
72eb7ea8 12755 return do_signalfd4(arg1, arg2, 0);
e36800c9 12756#endif
3b6edd16
PM
12757#if defined(CONFIG_EPOLL)
12758#if defined(TARGET_NR_epoll_create)
12759 case TARGET_NR_epoll_create:
72eb7ea8 12760 return get_errno(epoll_create(arg1));
3b6edd16
PM
12761#endif
12762#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12763 case TARGET_NR_epoll_create1:
386d3865 12764 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
3b6edd16
PM
12765#endif
12766#if defined(TARGET_NR_epoll_ctl)
12767 case TARGET_NR_epoll_ctl:
12768 {
12769 struct epoll_event ep;
12770 struct epoll_event *epp = 0;
12771 if (arg4) {
c7811022
L
12772 if (arg2 != EPOLL_CTL_DEL) {
12773 struct target_epoll_event *target_ep;
12774 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12775 return -TARGET_EFAULT;
12776 }
12777 ep.events = tswap32(target_ep->events);
12778 /*
12779 * The epoll_data_t union is just opaque data to the kernel,
12780 * so we transfer all 64 bits across and need not worry what
12781 * actual data type it is.
12782 */
12783 ep.data.u64 = tswap64(target_ep->data.u64);
12784 unlock_user_struct(target_ep, arg4, 0);
3b6edd16 12785 }
c7811022
L
12786 /*
12787 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12788 * non-null pointer, even though this argument is ignored.
12789 *
3b6edd16 12790 */
3b6edd16
PM
12791 epp = &ep;
12792 }
72eb7ea8 12793 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
3b6edd16
PM
12794 }
12795#endif
12796
227f0214 12797#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12798#if defined(TARGET_NR_epoll_wait)
12799 case TARGET_NR_epoll_wait:
12800#endif
227f0214 12801#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12802 case TARGET_NR_epoll_pwait:
12803#endif
12804 {
12805 struct target_epoll_event *target_ep;
12806 struct epoll_event *ep;
12807 int epfd = arg1;
12808 int maxevents = arg3;
12809 int timeout = arg4;
12810
2ba7fae3 12811 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
72eb7ea8 12812 return -TARGET_EINVAL;
2ba7fae3
PM
12813 }
12814
3b6edd16
PM
12815 target_ep = lock_user(VERIFY_WRITE, arg2,
12816 maxevents * sizeof(struct target_epoll_event), 1);
12817 if (!target_ep) {
2852aafd 12818 return -TARGET_EFAULT;
3b6edd16
PM
12819 }
12820
04c95f4d
PM
12821 ep = g_try_new(struct epoll_event, maxevents);
12822 if (!ep) {
12823 unlock_user(target_ep, arg2, 0);
72eb7ea8 12824 return -TARGET_ENOMEM;
04c95f4d 12825 }
3b6edd16
PM
12826
12827 switch (num) {
227f0214 12828#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12829 case TARGET_NR_epoll_pwait:
12830 {
cd0e31a4 12831 sigset_t *set = NULL;
3b6edd16
PM
12832
12833 if (arg5) {
cd0e31a4
RH
12834 ret = process_sigsuspend_mask(&set, arg5, arg6);
12835 if (ret != 0) {
c815701e
PM
12836 break;
12837 }
3b6edd16
PM
12838 }
12839
227f0214
PM
12840 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12841 set, SIGSET_T_SIZE));
cd0e31a4
RH
12842
12843 if (set) {
12844 finish_sigsuspend_mask(ret);
12845 }
3b6edd16
PM
12846 break;
12847 }
12848#endif
12849#if defined(TARGET_NR_epoll_wait)
12850 case TARGET_NR_epoll_wait:
227f0214
PM
12851 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12852 NULL, 0));
3b6edd16
PM
12853 break;
12854#endif
12855 default:
12856 ret = -TARGET_ENOSYS;
12857 }
12858 if (!is_error(ret)) {
12859 int i;
12860 for (i = 0; i < ret; i++) {
12861 target_ep[i].events = tswap32(ep[i].events);
12862 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12863 }
04c95f4d
PM
12864 unlock_user(target_ep, arg2,
12865 ret * sizeof(struct target_epoll_event));
12866 } else {
12867 unlock_user(target_ep, arg2, 0);
3b6edd16 12868 }
04c95f4d 12869 g_free(ep);
72eb7ea8 12870 return ret;
3b6edd16
PM
12871 }
12872#endif
163a05a8
PM
12873#endif
12874#ifdef TARGET_NR_prlimit64
12875 case TARGET_NR_prlimit64:
12876 {
12877 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12878 struct target_rlimit64 *target_rnew, *target_rold;
12879 struct host_rlimit64 rnew, rold, *rnewp = 0;
95018018 12880 int resource = target_to_host_resource(arg2);
055d92f8
TK
12881
12882 if (arg3 && (resource != RLIMIT_AS &&
12883 resource != RLIMIT_DATA &&
12884 resource != RLIMIT_STACK)) {
163a05a8 12885 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
2852aafd 12886 return -TARGET_EFAULT;
163a05a8
PM
12887 }
12888 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12889 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12890 unlock_user_struct(target_rnew, arg3, 0);
12891 rnewp = &rnew;
12892 }
12893
95018018 12894 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
163a05a8
PM
12895 if (!is_error(ret) && arg4) {
12896 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
2852aafd 12897 return -TARGET_EFAULT;
163a05a8
PM
12898 }
12899 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12900 target_rold->rlim_max = tswap64(rold.rlim_max);
12901 unlock_user_struct(target_rold, arg4, 1);
12902 }
72eb7ea8 12903 return ret;
163a05a8 12904 }
3d21d29c
RH
12905#endif
12906#ifdef TARGET_NR_gethostname
12907 case TARGET_NR_gethostname:
12908 {
12909 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12910 if (name) {
12911 ret = get_errno(gethostname(name, arg2));
12912 unlock_user(name, arg1, arg2);
12913 } else {
12914 ret = -TARGET_EFAULT;
12915 }
72eb7ea8 12916 return ret;
3d21d29c 12917 }
89aaf1a6
RV
12918#endif
12919#ifdef TARGET_NR_atomic_cmpxchg_32
12920 case TARGET_NR_atomic_cmpxchg_32:
12921 {
12922 /* should use start_exclusive from main.c */
12923 abi_ulong mem_value;
12924 if (get_user_u32(mem_value, arg6)) {
12925 target_siginfo_t info;
12926 info.si_signo = SIGSEGV;
12927 info.si_errno = 0;
12928 info.si_code = TARGET_SEGV_MAPERR;
12929 info._sifields._sigfault._addr = arg6;
0effdc29 12930 queue_signal(cpu_env, info.si_signo, QEMU_SI_FAULT, &info);
89aaf1a6
RV
12931 ret = 0xdeadbeef;
12932
12933 }
12934 if (mem_value == arg2)
12935 put_user_u32(arg1, arg6);
72eb7ea8 12936 return mem_value;
89aaf1a6
RV
12937 }
12938#endif
12939#ifdef TARGET_NR_atomic_barrier
12940 case TARGET_NR_atomic_barrier:
72eb7ea8
RH
12941 /* Like the kernel implementation and the
12942 qemu arm barrier, no-op this? */
12943 return 0;
d0927938 12944#endif
f4f1e10a
ECL
12945
12946#ifdef TARGET_NR_timer_create
12947 case TARGET_NR_timer_create:
12948 {
12949 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12950
12951 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
f4f1e10a
ECL
12952
12953 int clkid = arg1;
12954 int timer_index = next_free_host_timer();
12955
12956 if (timer_index < 0) {
12957 ret = -TARGET_EAGAIN;
12958 } else {
12959 timer_t *phtimer = g_posix_timers + timer_index;
12960
12961 if (arg2) {
f4f1e10a 12962 phost_sevp = &host_sevp;
c065976f
PM
12963 ret = target_to_host_sigevent(phost_sevp, arg2);
12964 if (ret != 0) {
9e59899f 12965 free_host_timer_slot(timer_index);
72eb7ea8 12966 return ret;
c065976f 12967 }
f4f1e10a
ECL
12968 }
12969
12970 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12971 if (ret) {
9e59899f 12972 free_host_timer_slot(timer_index);
f4f1e10a 12973 } else {
aecc8861 12974 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
9e59899f
PM
12975 timer_delete(*phtimer);
12976 free_host_timer_slot(timer_index);
2852aafd 12977 return -TARGET_EFAULT;
f4f1e10a 12978 }
f4f1e10a
ECL
12979 }
12980 }
72eb7ea8 12981 return ret;
f4f1e10a
ECL
12982 }
12983#endif
12984
12985#ifdef TARGET_NR_timer_settime
12986 case TARGET_NR_timer_settime:
12987 {
12988 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12989 * struct itimerspec * old_value */
aecc8861 12990 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12991
aecc8861
AG
12992 if (timerid < 0) {
12993 ret = timerid;
12994 } else if (arg3 == 0) {
f4f1e10a
ECL
12995 ret = -TARGET_EINVAL;
12996 } else {
e52a99f7 12997 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12998 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12999
40c80b5e 13000 if (target_to_host_itimerspec(&hspec_new, arg3)) {
2852aafd 13001 return -TARGET_EFAULT;
40c80b5e 13002 }
f4f1e10a
ECL
13003 ret = get_errno(
13004 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
40c80b5e 13005 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
2852aafd 13006 return -TARGET_EFAULT;
40c80b5e 13007 }
f4f1e10a 13008 }
72eb7ea8 13009 return ret;
f4f1e10a
ECL
13010 }
13011#endif
13012
828cb3a1
FB
13013#ifdef TARGET_NR_timer_settime64
13014 case TARGET_NR_timer_settime64:
13015 {
13016 target_timer_t timerid = get_timer_id(arg1);
13017
13018 if (timerid < 0) {
13019 ret = timerid;
13020 } else if (arg3 == 0) {
13021 ret = -TARGET_EINVAL;
13022 } else {
13023 timer_t htimer = g_posix_timers[timerid];
13024 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
13025
13026 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
13027 return -TARGET_EFAULT;
13028 }
13029 ret = get_errno(
13030 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
13031 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
13032 return -TARGET_EFAULT;
13033 }
13034 }
13035 return ret;
13036 }
13037#endif
13038
f4f1e10a
ECL
13039#ifdef TARGET_NR_timer_gettime
13040 case TARGET_NR_timer_gettime:
13041 {
13042 /* args: timer_t timerid, struct itimerspec *curr_value */
aecc8861 13043 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13044
aecc8861
AG
13045 if (timerid < 0) {
13046 ret = timerid;
13047 } else if (!arg2) {
13048 ret = -TARGET_EFAULT;
f4f1e10a 13049 } else {
e52a99f7 13050 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
13051 struct itimerspec hspec;
13052 ret = get_errno(timer_gettime(htimer, &hspec));
13053
13054 if (host_to_target_itimerspec(arg2, &hspec)) {
13055 ret = -TARGET_EFAULT;
13056 }
13057 }
72eb7ea8 13058 return ret;
f4f1e10a
ECL
13059 }
13060#endif
13061
828cb3a1
FB
13062#ifdef TARGET_NR_timer_gettime64
13063 case TARGET_NR_timer_gettime64:
13064 {
13065 /* args: timer_t timerid, struct itimerspec64 *curr_value */
13066 target_timer_t timerid = get_timer_id(arg1);
13067
13068 if (timerid < 0) {
13069 ret = timerid;
13070 } else if (!arg2) {
13071 ret = -TARGET_EFAULT;
13072 } else {
13073 timer_t htimer = g_posix_timers[timerid];
13074 struct itimerspec hspec;
13075 ret = get_errno(timer_gettime(htimer, &hspec));
13076
13077 if (host_to_target_itimerspec64(arg2, &hspec)) {
13078 ret = -TARGET_EFAULT;
13079 }
13080 }
13081 return ret;
13082 }
13083#endif
13084
f4f1e10a
ECL
13085#ifdef TARGET_NR_timer_getoverrun
13086 case TARGET_NR_timer_getoverrun:
13087 {
13088 /* args: timer_t timerid */
aecc8861 13089 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13090
aecc8861
AG
13091 if (timerid < 0) {
13092 ret = timerid;
f4f1e10a 13093 } else {
e52a99f7 13094 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
13095 ret = get_errno(timer_getoverrun(htimer));
13096 }
72eb7ea8 13097 return ret;
f4f1e10a
ECL
13098 }
13099#endif
13100
13101#ifdef TARGET_NR_timer_delete
13102 case TARGET_NR_timer_delete:
13103 {
13104 /* args: timer_t timerid */
aecc8861 13105 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 13106
aecc8861
AG
13107 if (timerid < 0) {
13108 ret = timerid;
f4f1e10a 13109 } else {
e52a99f7 13110 timer_t htimer = g_posix_timers[timerid];
f4f1e10a 13111 ret = get_errno(timer_delete(htimer));
9e59899f 13112 free_host_timer_slot(timerid);
f4f1e10a 13113 }
72eb7ea8 13114 return ret;
f4f1e10a
ECL
13115 }
13116#endif
13117
51834341
RV
13118#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13119 case TARGET_NR_timerfd_create:
72eb7ea8
RH
13120 return get_errno(timerfd_create(arg1,
13121 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
51834341
RV
13122#endif
13123
13124#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13125 case TARGET_NR_timerfd_gettime:
13126 {
13127 struct itimerspec its_curr;
13128
13129 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13130
13131 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
2852aafd 13132 return -TARGET_EFAULT;
51834341
RV
13133 }
13134 }
72eb7ea8 13135 return ret;
51834341
RV
13136#endif
13137
828cb3a1
FB
13138#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13139 case TARGET_NR_timerfd_gettime64:
13140 {
13141 struct itimerspec its_curr;
13142
13143 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13144
13145 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13146 return -TARGET_EFAULT;
13147 }
13148 }
13149 return ret;
13150#endif
13151
51834341
RV
13152#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13153 case TARGET_NR_timerfd_settime:
13154 {
13155 struct itimerspec its_new, its_old, *p_new;
13156
13157 if (arg3) {
13158 if (target_to_host_itimerspec(&its_new, arg3)) {
2852aafd 13159 return -TARGET_EFAULT;
51834341
RV
13160 }
13161 p_new = &its_new;
13162 } else {
13163 p_new = NULL;
13164 }
13165
13166 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13167
13168 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
2852aafd 13169 return -TARGET_EFAULT;
51834341
RV
13170 }
13171 }
72eb7ea8 13172 return ret;
51834341
RV
13173#endif
13174
828cb3a1
FB
13175#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13176 case TARGET_NR_timerfd_settime64:
13177 {
13178 struct itimerspec its_new, its_old, *p_new;
13179
13180 if (arg3) {
13181 if (target_to_host_itimerspec64(&its_new, arg3)) {
13182 return -TARGET_EFAULT;
13183 }
13184 p_new = &its_new;
13185 } else {
13186 p_new = NULL;
13187 }
13188
13189 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13190
13191 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13192 return -TARGET_EFAULT;
13193 }
13194 }
13195 return ret;
13196#endif
13197
ab31cda3
PB
13198#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13199 case TARGET_NR_ioprio_get:
72eb7ea8 13200 return get_errno(ioprio_get(arg1, arg2));
ab31cda3
PB
13201#endif
13202
13203#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13204 case TARGET_NR_ioprio_set:
72eb7ea8 13205 return get_errno(ioprio_set(arg1, arg2, arg3));
ab31cda3
PB
13206#endif
13207
9af5c906
RV
13208#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13209 case TARGET_NR_setns:
72eb7ea8 13210 return get_errno(setns(arg1, arg2));
9af5c906
RV
13211#endif
13212#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13213 case TARGET_NR_unshare:
72eb7ea8 13214 return get_errno(unshare(arg1));
9af5c906 13215#endif
2f14788c
LV
13216#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13217 case TARGET_NR_kcmp:
72eb7ea8 13218 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
2f14788c 13219#endif
fa97e38e
RH
13220#ifdef TARGET_NR_swapcontext
13221 case TARGET_NR_swapcontext:
13222 /* PowerPC specific. */
72eb7ea8 13223 return do_swapcontext(cpu_env, arg1, arg2, arg3);
fa97e38e 13224#endif
9bdfa4d2
SCW
13225#ifdef TARGET_NR_memfd_create
13226 case TARGET_NR_memfd_create:
13227 p = lock_user_string(arg1);
13228 if (!p) {
13229 return -TARGET_EFAULT;
13230 }
13231 ret = get_errno(memfd_create(p, arg2));
13232 fd_trans_unregister(ret);
13233 unlock_user(p, arg1, 0);
13234 return ret;
13235#endif
8500476f
AS
13236#if defined TARGET_NR_membarrier && defined __NR_membarrier
13237 case TARGET_NR_membarrier:
13238 return get_errno(membarrier(arg1, arg2));
13239#endif
9af5c906 13240
84946457
AS
13241#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13242 case TARGET_NR_copy_file_range:
13243 {
13244 loff_t inoff, outoff;
13245 loff_t *pinoff = NULL, *poutoff = NULL;
13246
13247 if (arg2) {
13248 if (get_user_u64(inoff, arg2)) {
13249 return -TARGET_EFAULT;
13250 }
13251 pinoff = &inoff;
13252 }
13253 if (arg4) {
13254 if (get_user_u64(outoff, arg4)) {
13255 return -TARGET_EFAULT;
13256 }
13257 poutoff = &outoff;
13258 }
0fa259dd 13259 /* Do not sign-extend the count parameter. */
84946457 13260 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
0fa259dd 13261 (abi_ulong)arg5, arg6));
84946457
AS
13262 if (!is_error(ret) && ret > 0) {
13263 if (arg2) {
13264 if (put_user_u64(inoff, arg2)) {
13265 return -TARGET_EFAULT;
13266 }
13267 }
13268 if (arg4) {
13269 if (put_user_u64(outoff, arg4)) {
13270 return -TARGET_EFAULT;
13271 }
13272 }
13273 }
13274 }
13275 return ret;
13276#endif
13277
e10fbe8f
YT
13278#if defined(TARGET_NR_pivot_root)
13279 case TARGET_NR_pivot_root:
13280 {
13281 void *p2;
13282 p = lock_user_string(arg1); /* new_root */
13283 p2 = lock_user_string(arg2); /* put_old */
13284 if (!p || !p2) {
13285 ret = -TARGET_EFAULT;
13286 } else {
13287 ret = get_errno(pivot_root(p, p2));
13288 }
13289 unlock_user(p2, arg2, 0);
13290 unlock_user(p, arg1, 0);
13291 }
13292 return ret;
13293#endif
13294
31e31b8a 13295 default:
122f9c83 13296 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
72eb7ea8 13297 return -TARGET_ENOSYS;
31e31b8a 13298 }
31e31b8a
FB
13299 return ret;
13300}
dc1ce18b 13301
a0939b89 13302abi_long do_syscall(CPUArchState *cpu_env, int num, abi_long arg1,
dc1ce18b
RH
13303 abi_long arg2, abi_long arg3, abi_long arg4,
13304 abi_long arg5, abi_long arg6, abi_long arg7,
13305 abi_long arg8)
13306{
29a0af61 13307 CPUState *cpu = env_cpu(cpu_env);
dc1ce18b
RH
13308 abi_long ret;
13309
13310#ifdef DEBUG_ERESTARTSYS
13311 /* Debug-only code for exercising the syscall-restart code paths
13312 * in the per-architecture cpu main loops: restart every syscall
13313 * the guest makes once before letting it through.
13314 */
13315 {
13316 static bool flag;
13317 flag = !flag;
13318 if (flag) {
af254a27 13319 return -QEMU_ERESTARTSYS;
dc1ce18b
RH
13320 }
13321 }
13322#endif
13323
c36f7a64
EC
13324 record_syscall_start(cpu, num, arg1,
13325 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
dc1ce18b 13326
4b25a506 13327 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119 13328 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
4b25a506
JK
13329 }
13330
13331 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13332 arg5, arg6, arg7, arg8);
13333
13334 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119
FB
13335 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13336 arg3, arg4, arg5, arg6);
dc1ce18b
RH
13337 }
13338
c36f7a64 13339 record_syscall_return(cpu, num, ret);
dc1ce18b
RH
13340 return ret;
13341}