]> git.proxmox.com Git - mirror_qemu.git/blame - linux-user/syscall.c
linux-user/alpha: Fix sigsuspend for big-endian hosts
[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"
31e31b8a 143
5ea2fc84
PM
144#ifndef CLONE_IO
145#define CLONE_IO 0x80000000 /* Clone io context */
146#endif
147
148/* We can't directly call the host clone syscall, because this will
149 * badly confuse libc (breaking mutexes, for example). So we must
150 * divide clone flags into:
151 * * flag combinations that look like pthread_create()
152 * * flag combinations that look like fork()
153 * * flags we can implement within QEMU itself
154 * * flags we can't support and will return an error for
155 */
156/* For thread creation, all these flags must be present; for
157 * fork, none must be present.
158 */
159#define CLONE_THREAD_FLAGS \
160 (CLONE_VM | CLONE_FS | CLONE_FILES | \
161 CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM)
162
163/* These flags are ignored:
164 * CLONE_DETACHED is now ignored by the kernel;
165 * CLONE_IO is just an optimisation hint to the I/O scheduler
166 */
167#define CLONE_IGNORED_FLAGS \
168 (CLONE_DETACHED | CLONE_IO)
169
170/* Flags for fork which we can implement within QEMU itself */
171#define CLONE_OPTIONAL_FORK_FLAGS \
172 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
173 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID)
174
175/* Flags for thread creation which we can implement within QEMU itself */
176#define CLONE_OPTIONAL_THREAD_FLAGS \
177 (CLONE_SETTLS | CLONE_PARENT_SETTID | \
178 CLONE_CHILD_CLEARTID | CLONE_CHILD_SETTID | CLONE_PARENT)
179
180#define CLONE_INVALID_FORK_FLAGS \
181 (~(CSIGNAL | CLONE_OPTIONAL_FORK_FLAGS | CLONE_IGNORED_FLAGS))
182
183#define CLONE_INVALID_THREAD_FLAGS \
184 (~(CSIGNAL | CLONE_THREAD_FLAGS | CLONE_OPTIONAL_THREAD_FLAGS | \
185 CLONE_IGNORED_FLAGS))
186
187/* CLONE_VFORK is special cased early in do_fork(). The other flag bits
188 * have almost all been allocated. We cannot support any of
189 * CLONE_NEWNS, CLONE_NEWCGROUP, CLONE_NEWUTS, CLONE_NEWIPC,
190 * CLONE_NEWUSER, CLONE_NEWPID, CLONE_NEWNET, CLONE_PTRACE, CLONE_UNTRACED.
191 * The checks against the invalid thread masks above will catch these.
192 * (The one remaining unallocated bit is 0x1000 which used to be CLONE_PID.)
193 */
30813cea 194
71a8f7fe
TB
195/* Define DEBUG_ERESTARTSYS to force every syscall to be restarted
196 * once. This exercises the codepaths for restart.
197 */
198//#define DEBUG_ERESTARTSYS
31e31b8a 199
1a9353d2 200//#include <linux/msdos_fs.h>
540a736f
RH
201#define VFAT_IOCTL_READDIR_BOTH \
202 _IOC(_IOC_READ, 'r', 1, (sizeof(struct linux_dirent) + 256) * 2)
203#define VFAT_IOCTL_READDIR_SHORT \
204 _IOC(_IOC_READ, 'r', 2, (sizeof(struct linux_dirent) + 256) * 2)
1a9353d2 205
70a194b9
FB
206#undef _syscall0
207#undef _syscall1
208#undef _syscall2
209#undef _syscall3
210#undef _syscall4
211#undef _syscall5
83fcb515 212#undef _syscall6
70a194b9 213
83fcb515 214#define _syscall0(type,name) \
8fcd3692 215static type name (void) \
83fcb515
FB
216{ \
217 return syscall(__NR_##name); \
218}
70a194b9 219
83fcb515 220#define _syscall1(type,name,type1,arg1) \
8fcd3692 221static type name (type1 arg1) \
83fcb515
FB
222{ \
223 return syscall(__NR_##name, arg1); \
70a194b9
FB
224}
225
83fcb515 226#define _syscall2(type,name,type1,arg1,type2,arg2) \
8fcd3692 227static type name (type1 arg1,type2 arg2) \
83fcb515
FB
228{ \
229 return syscall(__NR_##name, arg1, arg2); \
70a194b9
FB
230}
231
83fcb515 232#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
8fcd3692 233static type name (type1 arg1,type2 arg2,type3 arg3) \
83fcb515
FB
234{ \
235 return syscall(__NR_##name, arg1, arg2, arg3); \
70a194b9
FB
236}
237
83fcb515 238#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
8fcd3692 239static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
83fcb515
FB
240{ \
241 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
70a194b9
FB
242}
243
83fcb515
FB
244#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
245 type5,arg5) \
8fcd3692 246static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
83fcb515
FB
247{ \
248 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
70a194b9
FB
249}
250
83fcb515
FB
251
252#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
253 type5,arg5,type6,arg6) \
8fcd3692
BS
254static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
255 type6 arg6) \
83fcb515
FB
256{ \
257 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
70a194b9 258}
83fcb515 259
70a194b9 260
31e31b8a 261#define __NR_sys_uname __NR_uname
72f03900 262#define __NR_sys_getcwd1 __NR_getcwd
72f03900 263#define __NR_sys_getdents __NR_getdents
dab2ed99 264#define __NR_sys_getdents64 __NR_getdents64
c6cda17a 265#define __NR_sys_getpriority __NR_getpriority
66fb9763 266#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
cf8b8bfc 267#define __NR_sys_rt_tgsigqueueinfo __NR_rt_tgsigqueueinfo
7494b0f9 268#define __NR_sys_syslog __NR_syslog
14690296
AF
269#if defined(__NR_futex)
270# define __NR_sys_futex __NR_futex
271#endif
272#if defined(__NR_futex_time64)
273# define __NR_sys_futex_time64 __NR_futex_time64
274#endif
efa92184 275#define __NR_sys_statx __NR_statx
31e31b8a 276
b1cef6d0 277#if defined(__alpha__) || defined(__x86_64__) || defined(__s390x__)
9af9eaaa
FB
278#define __NR__llseek __NR_lseek
279#endif
280
a29e5ba2
JH
281/* Newer kernel ports have llseek() instead of _llseek() */
282#if defined(TARGET_NR_llseek) && !defined(TARGET_NR__llseek)
283#define TARGET_NR__llseek TARGET_NR_llseek
284#endif
285
78721301
HD
286/* some platforms need to mask more bits than just TARGET_O_NONBLOCK */
287#ifndef TARGET_O_NONBLOCK_MASK
288#define TARGET_O_NONBLOCK_MASK TARGET_O_NONBLOCK
289#endif
290
71ba74f6
DB
291#define __NR_sys_gettid __NR_gettid
292_syscall0(int, sys_gettid)
2b3f64cb
PM
293
294/* For the 64-bit guest on 32-bit host case we must emulate
295 * getdents using getdents64, because otherwise the host
296 * might hand us back more dirent records than we can fit
297 * into the guest buffer after structure format conversion.
298 * Otherwise we emulate getdents with getdents if the host has it.
299 */
300#if defined(__NR_getdents) && HOST_LONG_BITS >= TARGET_ABI_BITS
301#define EMULATE_GETDENTS_WITH_GETDENTS
302#endif
303
304#if defined(TARGET_NR_getdents) && defined(EMULATE_GETDENTS_WITH_GETDENTS)
3b3f24ad 305_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
3307e236 306#endif
2b3f64cb
PM
307#if (defined(TARGET_NR_getdents) && \
308 !defined(EMULATE_GETDENTS_WITH_GETDENTS)) || \
3307e236 309 (defined(TARGET_NR_getdents64) && defined(__NR_getdents64))
3b3f24ad
AJ
310_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
311#endif
d35b261c 312#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
3b3f24ad
AJ
313_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
314 loff_t *, res, uint, wh);
315#endif
c1a402a7 316_syscall3(int, sys_rt_sigqueueinfo, pid_t, pid, int, sig, siginfo_t *, uinfo)
cf8b8bfc
MS
317_syscall4(int, sys_rt_tgsigqueueinfo, pid_t, pid, pid_t, tid, int, sig,
318 siginfo_t *, uinfo)
3b3f24ad 319_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
3b3f24ad
AJ
320#ifdef __NR_exit_group
321_syscall1(int,exit_group,int,error_code)
322#endif
323#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
324_syscall1(int,set_tid_address,int *,tidptr)
325#endif
14690296 326#if defined(__NR_futex)
3b3f24ad
AJ
327_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
328 const struct timespec *,timeout,int *,uaddr2,int,val3)
329#endif
14690296
AF
330#if defined(__NR_futex_time64)
331_syscall6(int,sys_futex_time64,int *,uaddr,int,op,int,val,
332 const struct timespec *,timeout,int *,uaddr2,int,val3)
333#endif
737de1d1
MF
334#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
335_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
336 unsigned long *, user_mask_ptr);
337#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
338_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
339 unsigned long *, user_mask_ptr);
45ad761c
TT
340/* sched_attr is not defined in glibc */
341struct sched_attr {
342 uint32_t size;
343 uint32_t sched_policy;
344 uint64_t sched_flags;
345 int32_t sched_nice;
346 uint32_t sched_priority;
347 uint64_t sched_runtime;
348 uint64_t sched_deadline;
349 uint64_t sched_period;
350 uint32_t sched_util_min;
351 uint32_t sched_util_max;
352};
353#define __NR_sys_sched_getattr __NR_sched_getattr
354_syscall4(int, sys_sched_getattr, pid_t, pid, struct sched_attr *, attr,
355 unsigned int, size, unsigned int, flags);
356#define __NR_sys_sched_setattr __NR_sched_setattr
357_syscall3(int, sys_sched_setattr, pid_t, pid, struct sched_attr *, attr,
358 unsigned int, flags);
407a119b
TT
359#define __NR_sys_sched_getscheduler __NR_sched_getscheduler
360_syscall1(int, sys_sched_getscheduler, pid_t, pid);
361#define __NR_sys_sched_setscheduler __NR_sched_setscheduler
362_syscall3(int, sys_sched_setscheduler, pid_t, pid, int, policy,
363 const struct sched_param *, param);
364#define __NR_sys_sched_getparam __NR_sched_getparam
365_syscall2(int, sys_sched_getparam, pid_t, pid,
366 struct sched_param *, param);
367#define __NR_sys_sched_setparam __NR_sched_setparam
368_syscall2(int, sys_sched_setparam, pid_t, pid,
369 const struct sched_param *, param);
b827c3ed
ST
370#define __NR_sys_getcpu __NR_getcpu
371_syscall3(int, sys_getcpu, unsigned *, cpu, unsigned *, node, void *, tcache);
0f6b4d21
AG
372_syscall4(int, reboot, int, magic1, int, magic2, unsigned int, cmd,
373 void *, arg);
e0eb210e
PM
374_syscall2(int, capget, struct __user_cap_header_struct *, header,
375 struct __user_cap_data_struct *, data);
376_syscall2(int, capset, struct __user_cap_header_struct *, header,
377 struct __user_cap_data_struct *, data);
ab31cda3
PB
378#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
379_syscall2(int, ioprio_get, int, which, int, who)
380#endif
381#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
382_syscall3(int, ioprio_set, int, which, int, who, int, ioprio)
383#endif
f894efd1
LV
384#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
385_syscall3(int, getrandom, void *, buf, size_t, buflen, unsigned int, flags)
386#endif
3b3f24ad 387
2f14788c
LV
388#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
389_syscall5(int, kcmp, pid_t, pid1, pid_t, pid2, int, type,
390 unsigned long, idx1, unsigned long, idx2)
391#endif
392
efa92184
AR
393/*
394 * It is assumed that struct statx is architecture independent.
395 */
396#if defined(TARGET_NR_statx) && defined(__NR_statx)
397_syscall5(int, sys_statx, int, dirfd, const char *, pathname, int, flags,
398 unsigned int, mask, struct target_statx *, statxbuf)
399#endif
8500476f
AS
400#if defined(TARGET_NR_membarrier) && defined(__NR_membarrier)
401_syscall2(int, membarrier, int, cmd, int, flags)
402#endif
efa92184 403
180d4ef3 404static const bitmask_transtbl fcntl_flags_tbl[] = {
3b3f24ad
AJ
405 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
406 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
407 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
408 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
409 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
410 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
411 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
412 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
afc8763f 413 { TARGET_O_SYNC, TARGET_O_DSYNC, O_SYNC, O_DSYNC, },
3b3f24ad
AJ
414 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
415 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
416 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
417 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
3b3f24ad
AJ
418#if defined(O_DIRECT)
419 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
afc8763f
RH
420#endif
421#if defined(O_NOATIME)
422 { TARGET_O_NOATIME, TARGET_O_NOATIME, O_NOATIME, O_NOATIME },
423#endif
424#if defined(O_CLOEXEC)
425 { TARGET_O_CLOEXEC, TARGET_O_CLOEXEC, O_CLOEXEC, O_CLOEXEC },
426#endif
427#if defined(O_PATH)
428 { TARGET_O_PATH, TARGET_O_PATH, O_PATH, O_PATH },
5f9cee46
RV
429#endif
430#if defined(O_TMPFILE)
431 { TARGET_O_TMPFILE, TARGET_O_TMPFILE, O_TMPFILE, O_TMPFILE },
afc8763f
RH
432#endif
433 /* Don't terminate the list prematurely on 64-bit host+guest. */
434#if TARGET_O_LARGEFILE != 0 || O_LARGEFILE != 0
435 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
3b3f24ad
AJ
436#endif
437 { 0, 0, 0, 0 }
438};
439
0f6bb195 440_syscall2(int, sys_getcwd1, char *, buf, size_t, size)
3b3f24ad 441
cac46eb0 442#if defined(TARGET_NR_utimensat) || defined(TARGET_NR_utimensat_time64)
700fa58e 443#if defined(__NR_utimensat)
1acae9f2 444#define __NR_sys_utimensat __NR_utimensat
9007f0ef
TS
445_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
446 const struct timespec *,tsp,int,flags)
1acae9f2
PM
447#else
448static int sys_utimensat(int dirfd, const char *pathname,
449 const struct timespec times[2], int flags)
450{
451 errno = ENOSYS;
452 return -1;
453}
9007f0ef 454#endif
1acae9f2 455#endif /* TARGET_NR_utimensat */
3b3f24ad 456
95d0307c
AS
457#ifdef TARGET_NR_renameat2
458#if defined(__NR_renameat2)
459#define __NR_sys_renameat2 __NR_renameat2
460_syscall5(int, sys_renameat2, int, oldfd, const char *, old, int, newfd,
461 const char *, new, unsigned int, flags)
462#else
463static int sys_renameat2(int oldfd, const char *old,
464 int newfd, const char *new, int flags)
465{
466 if (flags == 0) {
467 return renameat(oldfd, old, newfd, new);
468 }
469 errno = ENOSYS;
470 return -1;
471}
472#endif
473#endif /* TARGET_NR_renameat2 */
474
3b3f24ad 475#ifdef CONFIG_INOTIFY
8690e420 476#include <sys/inotify.h>
3b3f24ad
AJ
477#else
478/* Userspace can usually survive runtime without inotify */
479#undef TARGET_NR_inotify_init
c05c7a73 480#undef TARGET_NR_inotify_init1
3b3f24ad
AJ
481#undef TARGET_NR_inotify_add_watch
482#undef TARGET_NR_inotify_rm_watch
483#endif /* CONFIG_INOTIFY */
484
163a05a8
PM
485#if defined(TARGET_NR_prlimit64)
486#ifndef __NR_prlimit64
487# define __NR_prlimit64 -1
488#endif
489#define __NR_sys_prlimit64 __NR_prlimit64
490/* The glibc rlimit structure may not be that used by the underlying syscall */
491struct host_rlimit64 {
492 uint64_t rlim_cur;
493 uint64_t rlim_max;
494};
495_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
496 const struct host_rlimit64 *, new_limit,
497 struct host_rlimit64 *, old_limit)
498#endif
499
f4f1e10a
ECL
500
501#if defined(TARGET_NR_timer_create)
6f9ff551 502/* Maximum of 32 active POSIX timers allowed at any one time. */
f4f1e10a
ECL
503static timer_t g_posix_timers[32] = { 0, } ;
504
505static inline int next_free_host_timer(void)
506{
507 int k ;
508 /* FIXME: Does finding the next free slot require a lock? */
509 for (k = 0; k < ARRAY_SIZE(g_posix_timers); k++) {
510 if (g_posix_timers[k] == 0) {
511 g_posix_timers[k] = (timer_t) 1;
512 return k;
513 }
514 }
515 return -1;
516}
517#endif
518
3ffe3268 519static inline int host_to_target_errno(int host_errno)
637947f1 520{
3ffe3268
PMD
521 switch (host_errno) {
522#define E(X) case X: return TARGET_##X;
523#include "errnos.c.inc"
524#undef E
525 default:
526 return host_errno;
2466119c 527 }
637947f1
TS
528}
529
3ffe3268 530static inline int target_to_host_errno(int target_errno)
b92c47c1 531{
3ffe3268
PMD
532 switch (target_errno) {
533#define E(X) case TARGET_##X: return X;
534#include "errnos.c.inc"
535#undef E
536 default:
537 return target_errno;
2466119c 538 }
b92c47c1
TS
539}
540
992f48a0 541static inline abi_long get_errno(abi_long ret)
31e31b8a
FB
542{
543 if (ret == -1)
637947f1 544 return -host_to_target_errno(errno);
31e31b8a
FB
545 else
546 return ret;
547}
548
7dcdaeaf 549const char *target_strerror(int err)
b92c47c1 550{
af254a27 551 if (err == QEMU_ERESTARTSYS) {
da2a34f7
PM
552 return "To be restarted";
553 }
57a0c938 554 if (err == QEMU_ESIGRETURN) {
da2a34f7
PM
555 return "Successful exit from sigreturn";
556 }
557
b92c47c1
TS
558 return strerror(target_to_host_errno(err));
559}
560
45ad761c
TT
561static int check_zeroed_user(abi_long addr, size_t ksize, size_t usize)
562{
563 int i;
564 uint8_t b;
565 if (usize <= ksize) {
566 return 1;
567 }
568 for (i = ksize; i < usize; i++) {
569 if (get_user_u8(b, addr + i)) {
570 return -TARGET_EFAULT;
571 }
572 if (b != 0) {
573 return 0;
574 }
575 }
576 return 1;
577}
578
4d330cee
TB
579#define safe_syscall0(type, name) \
580static type safe_##name(void) \
581{ \
582 return safe_syscall(__NR_##name); \
583}
584
585#define safe_syscall1(type, name, type1, arg1) \
586static type safe_##name(type1 arg1) \
587{ \
588 return safe_syscall(__NR_##name, arg1); \
589}
590
591#define safe_syscall2(type, name, type1, arg1, type2, arg2) \
592static type safe_##name(type1 arg1, type2 arg2) \
593{ \
594 return safe_syscall(__NR_##name, arg1, arg2); \
595}
596
597#define safe_syscall3(type, name, type1, arg1, type2, arg2, type3, arg3) \
598static type safe_##name(type1 arg1, type2 arg2, type3 arg3) \
599{ \
600 return safe_syscall(__NR_##name, arg1, arg2, arg3); \
601}
602
603#define safe_syscall4(type, name, type1, arg1, type2, arg2, type3, arg3, \
604 type4, arg4) \
605static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) \
606{ \
607 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4); \
608}
609
610#define safe_syscall5(type, name, type1, arg1, type2, arg2, type3, arg3, \
611 type4, arg4, type5, arg5) \
612static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
613 type5 arg5) \
614{ \
615 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
616}
617
618#define safe_syscall6(type, name, type1, arg1, type2, arg2, type3, arg3, \
619 type4, arg4, type5, arg5, type6, arg6) \
620static type safe_##name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, \
621 type5 arg5, type6 arg6) \
622{ \
623 return safe_syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
624}
625
50afd02b
TB
626safe_syscall3(ssize_t, read, int, fd, void *, buff, size_t, count)
627safe_syscall3(ssize_t, write, int, fd, const void *, buff, size_t, count)
c10a0738
TB
628safe_syscall4(int, openat, int, dirfd, const char *, pathname, \
629 int, flags, mode_t, mode)
859e8a89 630#if defined(TARGET_NR_wait4) || defined(TARGET_NR_waitpid)
4af80a37
TB
631safe_syscall4(pid_t, wait4, pid_t, pid, int *, status, int, options, \
632 struct rusage *, rusage)
859e8a89 633#endif
4af80a37
TB
634safe_syscall5(int, waitid, idtype_t, idtype, id_t, id, siginfo_t *, infop, \
635 int, options, struct rusage *, rusage)
ffdcbe22 636safe_syscall3(int, execve, const char *, filename, char **, argv, char **, envp)
859e8a89 637#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 638 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
6df9d38d
PM
639safe_syscall6(int, pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds, \
640 fd_set *, exceptfds, struct timespec *, timeout, void *, sig)
859e8a89 641#endif
e5ce9688 642#if defined(TARGET_NR_ppoll) || defined(TARGET_NR_ppoll_time64)
a6130237
PM
643safe_syscall5(int, ppoll, struct pollfd *, ufds, unsigned int, nfds,
644 struct timespec *, tsp, const sigset_t *, sigmask,
645 size_t, sigsetsize)
859e8a89 646#endif
227f0214
PM
647safe_syscall6(int, epoll_pwait, int, epfd, struct epoll_event *, events,
648 int, maxevents, int, timeout, const sigset_t *, sigmask,
649 size_t, sigsetsize)
14690296 650#if defined(__NR_futex)
d509eeb1
PM
651safe_syscall6(int,futex,int *,uaddr,int,op,int,val, \
652 const struct timespec *,timeout,int *,uaddr2,int,val3)
859e8a89 653#endif
14690296
AF
654#if defined(__NR_futex_time64)
655safe_syscall6(int,futex_time64,int *,uaddr,int,op,int,val, \
656 const struct timespec *,timeout,int *,uaddr2,int,val3)
657#endif
2fe4fba1 658safe_syscall2(int, rt_sigsuspend, sigset_t *, newset, size_t, sigsetsize)
bef653d9
PM
659safe_syscall2(int, kill, pid_t, pid, int, sig)
660safe_syscall2(int, tkill, int, tid, int, sig)
661safe_syscall3(int, tgkill, int, tgid, int, pid, int, sig)
918c03ed
PM
662safe_syscall3(ssize_t, readv, int, fd, const struct iovec *, iov, int, iovcnt)
663safe_syscall3(ssize_t, writev, int, fd, const struct iovec *, iov, int, iovcnt)
0f26386c
DJ
664safe_syscall5(ssize_t, preadv, int, fd, const struct iovec *, iov, int, iovcnt,
665 unsigned long, pos_l, unsigned long, pos_h)
f8d00fba
DJ
666safe_syscall5(ssize_t, pwritev, int, fd, const struct iovec *, iov, int, iovcnt,
667 unsigned long, pos_l, unsigned long, pos_h)
2a3c7619
PM
668safe_syscall3(int, connect, int, fd, const struct sockaddr *, addr,
669 socklen_t, addrlen)
66687530
PM
670safe_syscall6(ssize_t, sendto, int, fd, const void *, buf, size_t, len,
671 int, flags, const struct sockaddr *, addr, socklen_t, addrlen)
672safe_syscall6(ssize_t, recvfrom, int, fd, void *, buf, size_t, len,
673 int, flags, struct sockaddr *, addr, socklen_t *, addrlen)
674safe_syscall3(ssize_t, sendmsg, int, fd, const struct msghdr *, msg, int, flags)
675safe_syscall3(ssize_t, recvmsg, int, fd, struct msghdr *, msg, int, flags)
2a845989 676safe_syscall2(int, flock, int, fd, int, operation)
ddcbde15 677#if defined(TARGET_NR_rt_sigtimedwait) || defined(TARGET_NR_rt_sigtimedwait_time64)
b3f82330
PM
678safe_syscall4(int, rt_sigtimedwait, const sigset_t *, these, siginfo_t *, uinfo,
679 const struct timespec *, uts, size_t, sigsetsize)
859e8a89 680#endif
ff6dc130
PM
681safe_syscall4(int, accept4, int, fd, struct sockaddr *, addr, socklen_t *, len,
682 int, flags)
859e8a89 683#if defined(TARGET_NR_nanosleep)
9e518226
PM
684safe_syscall2(int, nanosleep, const struct timespec *, req,
685 struct timespec *, rem)
859e8a89 686#endif
6ac03b2c
FB
687#if defined(TARGET_NR_clock_nanosleep) || \
688 defined(TARGET_NR_clock_nanosleep_time64)
9e518226
PM
689safe_syscall4(int, clock_nanosleep, const clockid_t, clock, int, flags,
690 const struct timespec *, req, struct timespec *, rem)
691#endif
524fa340 692#ifdef __NR_ipc
d8c08b1e
MK
693#ifdef __s390x__
694safe_syscall5(int, ipc, int, call, long, first, long, second, long, third,
695 void *, ptr)
696#else
89f9fe44
PM
697safe_syscall6(int, ipc, int, call, long, first, long, second, long, third,
698 void *, ptr, long, fifth)
86e63695 699#endif
d8c08b1e 700#endif
86e63695
LV
701#ifdef __NR_msgsnd
702safe_syscall4(int, msgsnd, int, msgid, const void *, msgp, size_t, sz,
703 int, flags)
86e63695
LV
704#endif
705#ifdef __NR_msgrcv
706safe_syscall5(int, msgrcv, int, msgid, void *, msgp, size_t, sz,
707 long, msgtype, int, flags)
86e63695
LV
708#endif
709#ifdef __NR_semtimedop
710safe_syscall4(int, semtimedop, int, semid, struct sembuf *, tsops,
711 unsigned, nsops, const struct timespec *, timeout)
89f9fe44 712#endif
d107e375
FB
713#if defined(TARGET_NR_mq_timedsend) || \
714 defined(TARGET_NR_mq_timedsend_time64)
d40ecd66
PM
715safe_syscall5(int, mq_timedsend, int, mqdes, const char *, msg_ptr,
716 size_t, len, unsigned, prio, const struct timespec *, timeout)
859e8a89 717#endif
d107e375
FB
718#if defined(TARGET_NR_mq_timedreceive) || \
719 defined(TARGET_NR_mq_timedreceive_time64)
d40ecd66
PM
720safe_syscall5(int, mq_timedreceive, int, mqdes, char *, msg_ptr,
721 size_t, len, unsigned *, prio, const struct timespec *, timeout)
722#endif
84946457
AS
723#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
724safe_syscall6(ssize_t, copy_file_range, int, infd, loff_t *, pinoff,
725 int, outfd, loff_t *, poutoff, size_t, length,
726 unsigned int, flags)
727#endif
728
49ca6f3e
PM
729/* We do ioctl like this rather than via safe_syscall3 to preserve the
730 * "third argument might be integer or pointer or not present" behaviour of
731 * the libc function.
732 */
733#define safe_ioctl(...) safe_syscall(__NR_ioctl, __VA_ARGS__)
435da5e7
PM
734/* Similarly for fcntl. Note that callers must always:
735 * pass the F_GETLK64 etc constants rather than the unsuffixed F_GETLK
736 * use the flock64 struct rather than unsuffixed flock
737 * This will then work and use a 64-bit offset for both 32-bit and 64-bit hosts.
738 */
739#ifdef __NR_fcntl64
740#define safe_fcntl(...) safe_syscall(__NR_fcntl64, __VA_ARGS__)
741#else
742#define safe_fcntl(...) safe_syscall(__NR_fcntl, __VA_ARGS__)
743#endif
50afd02b 744
8289d112
PB
745static inline int host_to_target_sock_type(int host_type)
746{
747 int target_type;
748
749 switch (host_type & 0xf /* SOCK_TYPE_MASK */) {
750 case SOCK_DGRAM:
751 target_type = TARGET_SOCK_DGRAM;
752 break;
753 case SOCK_STREAM:
754 target_type = TARGET_SOCK_STREAM;
755 break;
756 default:
757 target_type = host_type & 0xf /* SOCK_TYPE_MASK */;
758 break;
759 }
760
761#if defined(SOCK_CLOEXEC)
762 if (host_type & SOCK_CLOEXEC) {
763 target_type |= TARGET_SOCK_CLOEXEC;
764 }
765#endif
766
767#if defined(SOCK_NONBLOCK)
768 if (host_type & SOCK_NONBLOCK) {
769 target_type |= TARGET_SOCK_NONBLOCK;
770 }
771#endif
772
773 return target_type;
774}
775
992f48a0
BS
776static abi_ulong target_brk;
777static abi_ulong target_original_brk;
4d1de87c 778static abi_ulong brk_page;
31e31b8a 779
992f48a0 780void target_set_brk(abi_ulong new_brk)
31e31b8a 781{
4c1de73d 782 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
4d1de87c 783 brk_page = HOST_PAGE_ALIGN(target_brk);
31e31b8a
FB
784}
785
4d1de87c
CV
786//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
787#define DEBUGF_BRK(message, args...)
788
0da46a6e 789/* do_brk() must return target values and target errnos. */
992f48a0 790abi_long do_brk(abi_ulong new_brk)
31e31b8a 791{
992f48a0 792 abi_long mapped_addr;
ef4330c2 793 abi_ulong new_alloc_size;
31e31b8a 794
ee1bf83d
RH
795 /* brk pointers are always untagged */
796
3a0c6c4a 797 DEBUGF_BRK("do_brk(" TARGET_ABI_FMT_lx ") -> ", new_brk);
4d1de87c
CV
798
799 if (!new_brk) {
3a0c6c4a 800 DEBUGF_BRK(TARGET_ABI_FMT_lx " (!new_brk)\n", target_brk);
53a5960a 801 return target_brk;
4d1de87c
CV
802 }
803 if (new_brk < target_original_brk) {
3a0c6c4a
PB
804 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk < target_original_brk)\n",
805 target_brk);
7ab240ad 806 return target_brk;
4d1de87c 807 }
3b46e624 808
4d1de87c
CV
809 /* If the new brk is less than the highest page reserved to the
810 * target heap allocation, set it and we're almost done... */
811 if (new_brk <= brk_page) {
812 /* Heap contents are initialized to zero, as for anonymous
813 * mapped pages. */
814 if (new_brk > target_brk) {
3e8f1628 815 memset(g2h_untagged(target_brk), 0, new_brk - target_brk);
4d1de87c 816 }
31e31b8a 817 target_brk = new_brk;
3a0c6c4a 818 DEBUGF_BRK(TARGET_ABI_FMT_lx " (new_brk <= brk_page)\n", target_brk);
72e21db7 819 return target_brk;
31e31b8a
FB
820 }
821
00faf08c
PM
822 /* We need to allocate more memory after the brk... Note that
823 * we don't use MAP_FIXED because that will map over the top of
824 * any existing mapping (like the one with the host libc or qemu
825 * itself); instead we treat "mapped but at wrong address" as
826 * a failure and unmap again.
827 */
4d1de87c 828 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
5fafdf24 829 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
54936004 830 PROT_READ|PROT_WRITE,
00faf08c
PM
831 MAP_ANON|MAP_PRIVATE, 0, 0));
832
833 if (mapped_addr == brk_page) {
70afc343
CV
834 /* Heap contents are initialized to zero, as for anonymous
835 * mapped pages. Technically the new pages are already
836 * initialized to zero since they *are* anonymous mapped
837 * pages, however we have to take care with the contents that
838 * come from the remaining part of the previous page: it may
839 * contains garbage data due to a previous heap usage (grown
840 * then shrunken). */
3e8f1628 841 memset(g2h_untagged(target_brk), 0, brk_page - target_brk);
70afc343 842
00faf08c 843 target_brk = new_brk;
4d1de87c 844 brk_page = HOST_PAGE_ALIGN(target_brk);
3a0c6c4a
PB
845 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr == brk_page)\n",
846 target_brk);
00faf08c
PM
847 return target_brk;
848 } else if (mapped_addr != -1) {
849 /* Mapped but at wrong address, meaning there wasn't actually
850 * enough space for this brk.
851 */
852 target_munmap(mapped_addr, new_alloc_size);
853 mapped_addr = -1;
3a0c6c4a 854 DEBUGF_BRK(TARGET_ABI_FMT_lx " (mapped_addr != -1)\n", target_brk);
4d1de87c
CV
855 }
856 else {
3a0c6c4a 857 DEBUGF_BRK(TARGET_ABI_FMT_lx " (otherwise)\n", target_brk);
00faf08c 858 }
7ab240ad 859
7dd46c02
RH
860#if defined(TARGET_ALPHA)
861 /* We (partially) emulate OSF/1 on Alpha, which requires we
862 return a proper errno, not an unchanged brk value. */
00faf08c 863 return -TARGET_ENOMEM;
7dd46c02 864#endif
00faf08c 865 /* For everything else, return the previous break. */
7ab240ad 866 return target_brk;
31e31b8a
FB
867}
868
859e8a89 869#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect) || \
e5ce9688 870 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
26edcf41
TS
871static inline abi_long copy_from_user_fdset(fd_set *fds,
872 abi_ulong target_fds_addr,
873 int n)
31e31b8a 874{
26edcf41
TS
875 int i, nw, j, k;
876 abi_ulong b, *target_fds;
877
b1b2db29 878 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
879 if (!(target_fds = lock_user(VERIFY_READ,
880 target_fds_addr,
881 sizeof(abi_ulong) * nw,
882 1)))
883 return -TARGET_EFAULT;
884
885 FD_ZERO(fds);
886 k = 0;
887 for (i = 0; i < nw; i++) {
888 /* grab the abi_ulong */
889 __get_user(b, &target_fds[i]);
890 for (j = 0; j < TARGET_ABI_BITS; j++) {
891 /* check the bit inside the abi_ulong */
892 if ((b >> j) & 1)
893 FD_SET(k, fds);
894 k++;
31e31b8a 895 }
31e31b8a 896 }
26edcf41
TS
897
898 unlock_user(target_fds, target_fds_addr, 0);
899
900 return 0;
31e31b8a
FB
901}
902
055e0906
MF
903static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
904 abi_ulong target_fds_addr,
905 int n)
906{
907 if (target_fds_addr) {
908 if (copy_from_user_fdset(fds, target_fds_addr, n))
909 return -TARGET_EFAULT;
910 *fds_ptr = fds;
911 } else {
912 *fds_ptr = NULL;
913 }
914 return 0;
915}
916
26edcf41
TS
917static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
918 const fd_set *fds,
919 int n)
31e31b8a 920{
31e31b8a 921 int i, nw, j, k;
992f48a0 922 abi_long v;
26edcf41 923 abi_ulong *target_fds;
31e31b8a 924
b1b2db29 925 nw = DIV_ROUND_UP(n, TARGET_ABI_BITS);
26edcf41
TS
926 if (!(target_fds = lock_user(VERIFY_WRITE,
927 target_fds_addr,
928 sizeof(abi_ulong) * nw,
929 0)))
930 return -TARGET_EFAULT;
931
932 k = 0;
933 for (i = 0; i < nw; i++) {
934 v = 0;
935 for (j = 0; j < TARGET_ABI_BITS; j++) {
9ab709be 936 v |= ((abi_ulong)(FD_ISSET(k, fds) != 0) << j);
26edcf41 937 k++;
31e31b8a 938 }
26edcf41 939 __put_user(v, &target_fds[i]);
31e31b8a 940 }
26edcf41
TS
941
942 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
943
944 return 0;
31e31b8a 945}
859e8a89 946#endif
31e31b8a 947
c596ed17
FB
948#if defined(__alpha__)
949#define HOST_HZ 1024
950#else
951#define HOST_HZ 100
952#endif
953
992f48a0 954static inline abi_long host_to_target_clock_t(long ticks)
c596ed17
FB
955{
956#if HOST_HZ == TARGET_HZ
957 return ticks;
958#else
959 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
960#endif
961}
962
579a97f7
FB
963static inline abi_long host_to_target_rusage(abi_ulong target_addr,
964 const struct rusage *rusage)
b409186b 965{
53a5960a
PB
966 struct target_rusage *target_rusage;
967
579a97f7
FB
968 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
969 return -TARGET_EFAULT;
cbb21eed
MB
970 target_rusage->ru_utime.tv_sec = tswapal(rusage->ru_utime.tv_sec);
971 target_rusage->ru_utime.tv_usec = tswapal(rusage->ru_utime.tv_usec);
972 target_rusage->ru_stime.tv_sec = tswapal(rusage->ru_stime.tv_sec);
973 target_rusage->ru_stime.tv_usec = tswapal(rusage->ru_stime.tv_usec);
974 target_rusage->ru_maxrss = tswapal(rusage->ru_maxrss);
975 target_rusage->ru_ixrss = tswapal(rusage->ru_ixrss);
976 target_rusage->ru_idrss = tswapal(rusage->ru_idrss);
977 target_rusage->ru_isrss = tswapal(rusage->ru_isrss);
978 target_rusage->ru_minflt = tswapal(rusage->ru_minflt);
979 target_rusage->ru_majflt = tswapal(rusage->ru_majflt);
980 target_rusage->ru_nswap = tswapal(rusage->ru_nswap);
981 target_rusage->ru_inblock = tswapal(rusage->ru_inblock);
982 target_rusage->ru_oublock = tswapal(rusage->ru_oublock);
983 target_rusage->ru_msgsnd = tswapal(rusage->ru_msgsnd);
984 target_rusage->ru_msgrcv = tswapal(rusage->ru_msgrcv);
985 target_rusage->ru_nsignals = tswapal(rusage->ru_nsignals);
986 target_rusage->ru_nvcsw = tswapal(rusage->ru_nvcsw);
987 target_rusage->ru_nivcsw = tswapal(rusage->ru_nivcsw);
53a5960a 988 unlock_user_struct(target_rusage, target_addr, 1);
579a97f7
FB
989
990 return 0;
b409186b
FB
991}
992
859e8a89 993#ifdef TARGET_NR_setrlimit
cbb21eed 994static inline rlim_t target_to_host_rlim(abi_ulong target_rlim)
81bbe906 995{
cbb21eed 996 abi_ulong target_rlim_swap;
95b33b2f
WT
997 rlim_t result;
998
cbb21eed
MB
999 target_rlim_swap = tswapal(target_rlim);
1000 if (target_rlim_swap == TARGET_RLIM_INFINITY)
1001 return RLIM_INFINITY;
1002
1003 result = target_rlim_swap;
1004 if (target_rlim_swap != (rlim_t)result)
1005 return RLIM_INFINITY;
95b33b2f
WT
1006
1007 return result;
81bbe906 1008}
859e8a89 1009#endif
81bbe906 1010
859e8a89 1011#if defined(TARGET_NR_getrlimit) || defined(TARGET_NR_ugetrlimit)
cbb21eed 1012static inline abi_ulong host_to_target_rlim(rlim_t rlim)
81bbe906 1013{
cbb21eed
MB
1014 abi_ulong target_rlim_swap;
1015 abi_ulong result;
95b33b2f 1016
cbb21eed 1017 if (rlim == RLIM_INFINITY || rlim != (abi_long)rlim)
95b33b2f 1018 target_rlim_swap = TARGET_RLIM_INFINITY;
81bbe906 1019 else
95b33b2f 1020 target_rlim_swap = rlim;
cbb21eed 1021 result = tswapal(target_rlim_swap);
95b33b2f
WT
1022
1023 return result;
81bbe906 1024}
859e8a89 1025#endif
81bbe906 1026
e22b7015
WT
1027static inline int target_to_host_resource(int code)
1028{
1029 switch (code) {
1030 case TARGET_RLIMIT_AS:
1031 return RLIMIT_AS;
1032 case TARGET_RLIMIT_CORE:
1033 return RLIMIT_CORE;
1034 case TARGET_RLIMIT_CPU:
1035 return RLIMIT_CPU;
1036 case TARGET_RLIMIT_DATA:
1037 return RLIMIT_DATA;
1038 case TARGET_RLIMIT_FSIZE:
1039 return RLIMIT_FSIZE;
1040 case TARGET_RLIMIT_LOCKS:
1041 return RLIMIT_LOCKS;
1042 case TARGET_RLIMIT_MEMLOCK:
1043 return RLIMIT_MEMLOCK;
1044 case TARGET_RLIMIT_MSGQUEUE:
1045 return RLIMIT_MSGQUEUE;
1046 case TARGET_RLIMIT_NICE:
1047 return RLIMIT_NICE;
1048 case TARGET_RLIMIT_NOFILE:
1049 return RLIMIT_NOFILE;
1050 case TARGET_RLIMIT_NPROC:
1051 return RLIMIT_NPROC;
1052 case TARGET_RLIMIT_RSS:
1053 return RLIMIT_RSS;
1054 case TARGET_RLIMIT_RTPRIO:
1055 return RLIMIT_RTPRIO;
244fd083
SB
1056 case TARGET_RLIMIT_RTTIME:
1057 return RLIMIT_RTTIME;
e22b7015
WT
1058 case TARGET_RLIMIT_SIGPENDING:
1059 return RLIMIT_SIGPENDING;
1060 case TARGET_RLIMIT_STACK:
1061 return RLIMIT_STACK;
1062 default:
1063 return code;
1064 }
1065}
1066
788f5ec4
TS
1067static inline abi_long copy_from_user_timeval(struct timeval *tv,
1068 abi_ulong target_tv_addr)
31e31b8a 1069{
53a5960a
PB
1070 struct target_timeval *target_tv;
1071
6d5d5dde 1072 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
579a97f7 1073 return -TARGET_EFAULT;
6d5d5dde 1074 }
788f5ec4
TS
1075
1076 __get_user(tv->tv_sec, &target_tv->tv_sec);
1077 __get_user(tv->tv_usec, &target_tv->tv_usec);
1078
1079 unlock_user_struct(target_tv, target_tv_addr, 0);
579a97f7
FB
1080
1081 return 0;
31e31b8a
FB
1082}
1083
788f5ec4
TS
1084static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
1085 const struct timeval *tv)
31e31b8a 1086{
53a5960a
PB
1087 struct target_timeval *target_tv;
1088
6d5d5dde
DB
1089 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
1090 return -TARGET_EFAULT;
1091 }
1092
1093 __put_user(tv->tv_sec, &target_tv->tv_sec);
1094 __put_user(tv->tv_usec, &target_tv->tv_usec);
1095
1096 unlock_user_struct(target_tv, target_tv_addr, 1);
1097
1098 return 0;
1099}
1100
6ac03b2c
FB
1101#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
1102static inline abi_long copy_from_user_timeval64(struct timeval *tv,
1103 abi_ulong target_tv_addr)
1104{
1105 struct target__kernel_sock_timeval *target_tv;
1106
1107 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1)) {
1108 return -TARGET_EFAULT;
1109 }
1110
1111 __get_user(tv->tv_sec, &target_tv->tv_sec);
1112 __get_user(tv->tv_usec, &target_tv->tv_usec);
1113
1114 unlock_user_struct(target_tv, target_tv_addr, 0);
1115
1116 return 0;
1117}
1118#endif
1119
6d5d5dde 1120static inline abi_long copy_to_user_timeval64(abi_ulong target_tv_addr,
6ac03b2c 1121 const struct timeval *tv)
6d5d5dde
DB
1122{
1123 struct target__kernel_sock_timeval *target_tv;
1124
1125 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0)) {
579a97f7 1126 return -TARGET_EFAULT;
6d5d5dde 1127 }
788f5ec4
TS
1128
1129 __put_user(tv->tv_sec, &target_tv->tv_sec);
1130 __put_user(tv->tv_usec, &target_tv->tv_usec);
1131
1132 unlock_user_struct(target_tv, target_tv_addr, 1);
579a97f7
FB
1133
1134 return 0;
31e31b8a
FB
1135}
1136
859e8a89
AF
1137#if defined(TARGET_NR_futex) || \
1138 defined(TARGET_NR_rt_sigtimedwait) || \
1139 defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6) || \
1140 defined(TARGET_NR_nanosleep) || defined(TARGET_NR_clock_settime) || \
1141 defined(TARGET_NR_utimensat) || defined(TARGET_NR_mq_timedsend) || \
d8c08b1e 1142 defined(TARGET_NR_mq_timedreceive) || defined(TARGET_NR_ipc) || \
2c86c90f
FB
1143 defined(TARGET_NR_semop) || defined(TARGET_NR_semtimedop) || \
1144 defined(TARGET_NR_timer_settime) || \
1145 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
6d5d5dde
DB
1146static inline abi_long target_to_host_timespec(struct timespec *host_ts,
1147 abi_ulong target_addr)
1148{
1149 struct target_timespec *target_ts;
1150
1151 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1152 return -TARGET_EFAULT;
1153 }
1154 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1155 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1156 unlock_user_struct(target_ts, target_addr, 0);
1157 return 0;
1158}
859e8a89 1159#endif
6d5d5dde 1160
828cb3a1
FB
1161#if defined(TARGET_NR_clock_settime64) || defined(TARGET_NR_futex_time64) || \
1162 defined(TARGET_NR_timer_settime64) || \
d107e375
FB
1163 defined(TARGET_NR_mq_timedsend_time64) || \
1164 defined(TARGET_NR_mq_timedreceive_time64) || \
6ac03b2c 1165 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)) || \
ddcbde15 1166 defined(TARGET_NR_clock_nanosleep_time64) || \
cac46eb0
FB
1167 defined(TARGET_NR_rt_sigtimedwait_time64) || \
1168 defined(TARGET_NR_utimensat) || \
1169 defined(TARGET_NR_utimensat_time64) || \
e5ce9688
FB
1170 defined(TARGET_NR_semtimedop_time64) || \
1171 defined(TARGET_NR_pselect6_time64) || defined(TARGET_NR_ppoll_time64)
c6c8d102
AF
1172static inline abi_long target_to_host_timespec64(struct timespec *host_ts,
1173 abi_ulong target_addr)
1174{
1175 struct target__kernel_timespec *target_ts;
1176
1177 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1)) {
1178 return -TARGET_EFAULT;
1179 }
1180 __get_user(host_ts->tv_sec, &target_ts->tv_sec);
1181 __get_user(host_ts->tv_nsec, &target_ts->tv_nsec);
00576757
LV
1182 /* in 32bit mode, this drops the padding */
1183 host_ts->tv_nsec = (long)(abi_long)host_ts->tv_nsec;
c6c8d102
AF
1184 unlock_user_struct(target_ts, target_addr, 0);
1185 return 0;
1186}
1187#endif
1188
6d5d5dde
DB
1189static inline abi_long host_to_target_timespec(abi_ulong target_addr,
1190 struct timespec *host_ts)
1191{
1192 struct target_timespec *target_ts;
1193
1194 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1195 return -TARGET_EFAULT;
1196 }
1197 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1198 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1199 unlock_user_struct(target_ts, target_addr, 1);
1200 return 0;
1201}
1202
1203static inline abi_long host_to_target_timespec64(abi_ulong target_addr,
1204 struct timespec *host_ts)
1205{
1206 struct target__kernel_timespec *target_ts;
1207
1208 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0)) {
1209 return -TARGET_EFAULT;
1210 }
1211 __put_user(host_ts->tv_sec, &target_ts->tv_sec);
1212 __put_user(host_ts->tv_nsec, &target_ts->tv_nsec);
1213 unlock_user_struct(target_ts, target_addr, 1);
1214 return 0;
1215}
1216
a52f5f87
RH
1217#if defined(TARGET_NR_gettimeofday)
1218static inline abi_long copy_to_user_timezone(abi_ulong target_tz_addr,
1219 struct timezone *tz)
1220{
1221 struct target_timezone *target_tz;
1222
1223 if (!lock_user_struct(VERIFY_WRITE, target_tz, target_tz_addr, 1)) {
1224 return -TARGET_EFAULT;
1225 }
1226
1227 __put_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1228 __put_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1229
1230 unlock_user_struct(target_tz, target_tz_addr, 1);
1231
1232 return 0;
1233}
1234#endif
1235
859e8a89 1236#if defined(TARGET_NR_settimeofday)
ef4467e9
PB
1237static inline abi_long copy_from_user_timezone(struct timezone *tz,
1238 abi_ulong target_tz_addr)
1239{
1240 struct target_timezone *target_tz;
1241
1242 if (!lock_user_struct(VERIFY_READ, target_tz, target_tz_addr, 1)) {
1243 return -TARGET_EFAULT;
1244 }
1245
1246 __get_user(tz->tz_minuteswest, &target_tz->tz_minuteswest);
1247 __get_user(tz->tz_dsttime, &target_tz->tz_dsttime);
1248
1249 unlock_user_struct(target_tz, target_tz_addr, 0);
1250
1251 return 0;
1252}
859e8a89 1253#endif
ef4467e9 1254
8ec9cf89
NF
1255#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
1256#include <mqueue.h>
1257
24e1003a
AJ
1258static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
1259 abi_ulong target_mq_attr_addr)
1260{
1261 struct target_mq_attr *target_mq_attr;
1262
1263 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
1264 target_mq_attr_addr, 1))
1265 return -TARGET_EFAULT;
1266
1267 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
1268 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1269 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1270 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1271
1272 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1273
1274 return 0;
1275}
1276
1277static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1278 const struct mq_attr *attr)
1279{
1280 struct target_mq_attr *target_mq_attr;
1281
1282 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1283 target_mq_attr_addr, 0))
1284 return -TARGET_EFAULT;
1285
1286 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1287 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1288 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1289 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1290
1291 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1292
1293 return 0;
1294}
8ec9cf89 1295#endif
31e31b8a 1296
055e0906 1297#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
0da46a6e 1298/* do_select() must return target values and target errnos. */
992f48a0 1299static abi_long do_select(int n,
26edcf41
TS
1300 abi_ulong rfd_addr, abi_ulong wfd_addr,
1301 abi_ulong efd_addr, abi_ulong target_tv_addr)
31e31b8a
FB
1302{
1303 fd_set rfds, wfds, efds;
1304 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
6df9d38d
PM
1305 struct timeval tv;
1306 struct timespec ts, *ts_ptr;
992f48a0 1307 abi_long ret;
31e31b8a 1308
055e0906
MF
1309 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1310 if (ret) {
1311 return ret;
53a5960a 1312 }
055e0906
MF
1313 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1314 if (ret) {
1315 return ret;
53a5960a 1316 }
055e0906
MF
1317 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1318 if (ret) {
1319 return ret;
53a5960a 1320 }
3b46e624 1321
26edcf41 1322 if (target_tv_addr) {
788f5ec4
TS
1323 if (copy_from_user_timeval(&tv, target_tv_addr))
1324 return -TARGET_EFAULT;
6df9d38d
PM
1325 ts.tv_sec = tv.tv_sec;
1326 ts.tv_nsec = tv.tv_usec * 1000;
1327 ts_ptr = &ts;
31e31b8a 1328 } else {
6df9d38d 1329 ts_ptr = NULL;
31e31b8a 1330 }
26edcf41 1331
6df9d38d
PM
1332 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1333 ts_ptr, NULL));
53a5960a 1334
26edcf41
TS
1335 if (!is_error(ret)) {
1336 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1337 return -TARGET_EFAULT;
1338 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1339 return -TARGET_EFAULT;
1340 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1341 return -TARGET_EFAULT;
31e31b8a 1342
6df9d38d
PM
1343 if (target_tv_addr) {
1344 tv.tv_sec = ts.tv_sec;
1345 tv.tv_usec = ts.tv_nsec / 1000;
1346 if (copy_to_user_timeval(target_tv_addr, &tv)) {
1347 return -TARGET_EFAULT;
1348 }
1349 }
31e31b8a 1350 }
579a97f7 1351
31e31b8a
FB
1352 return ret;
1353}
5457dc9e
LV
1354
1355#if defined(TARGET_WANT_OLD_SYS_SELECT)
1356static abi_long do_old_select(abi_ulong arg1)
1357{
1358 struct target_sel_arg_struct *sel;
1359 abi_ulong inp, outp, exp, tvp;
1360 long nsel;
1361
1362 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1)) {
1363 return -TARGET_EFAULT;
1364 }
1365
1366 nsel = tswapal(sel->n);
1367 inp = tswapal(sel->inp);
1368 outp = tswapal(sel->outp);
1369 exp = tswapal(sel->exp);
1370 tvp = tswapal(sel->tvp);
1371
1372 unlock_user_struct(sel, arg1, 0);
1373
1374 return do_select(nsel, inp, outp, exp, tvp);
1375}
1376#endif
055e0906 1377#endif
31e31b8a 1378
e5ce9688
FB
1379#if defined(TARGET_NR_pselect6) || defined(TARGET_NR_pselect6_time64)
1380static abi_long do_pselect6(abi_long arg1, abi_long arg2, abi_long arg3,
1381 abi_long arg4, abi_long arg5, abi_long arg6,
1382 bool time64)
1383{
1384 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
1385 fd_set rfds, wfds, efds;
1386 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1387 struct timespec ts, *ts_ptr;
1388 abi_long ret;
1389
1390 /*
1391 * The 6th arg is actually two args smashed together,
1392 * so we cannot use the C library.
1393 */
1394 sigset_t set;
1395 struct {
1396 sigset_t *set;
1397 size_t size;
1398 } sig, *sig_ptr;
1399
1400 abi_ulong arg_sigset, arg_sigsize, *arg7;
1401 target_sigset_t *target_sigset;
1402
1403 n = arg1;
1404 rfd_addr = arg2;
1405 wfd_addr = arg3;
1406 efd_addr = arg4;
1407 ts_addr = arg5;
1408
1409 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1410 if (ret) {
1411 return ret;
1412 }
1413 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1414 if (ret) {
1415 return ret;
1416 }
1417 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1418 if (ret) {
1419 return ret;
1420 }
1421
1422 /*
1423 * This takes a timespec, and not a timeval, so we cannot
1424 * use the do_select() helper ...
1425 */
1426 if (ts_addr) {
1427 if (time64) {
1428 if (target_to_host_timespec64(&ts, ts_addr)) {
1429 return -TARGET_EFAULT;
1430 }
1431 } else {
1432 if (target_to_host_timespec(&ts, ts_addr)) {
1433 return -TARGET_EFAULT;
1434 }
1435 }
1436 ts_ptr = &ts;
1437 } else {
1438 ts_ptr = NULL;
1439 }
1440
1441 /* Extract the two packed args for the sigset */
1442 if (arg6) {
1443 sig_ptr = &sig;
1444 sig.size = SIGSET_T_SIZE;
1445
1446 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
1447 if (!arg7) {
1448 return -TARGET_EFAULT;
1449 }
1450 arg_sigset = tswapal(arg7[0]);
1451 arg_sigsize = tswapal(arg7[1]);
1452 unlock_user(arg7, arg6, 0);
1453
1454 if (arg_sigset) {
1455 sig.set = &set;
1456 if (arg_sigsize != sizeof(*target_sigset)) {
1457 /* Like the kernel, we enforce correct size sigsets */
1458 return -TARGET_EINVAL;
1459 }
1460 target_sigset = lock_user(VERIFY_READ, arg_sigset,
1461 sizeof(*target_sigset), 1);
1462 if (!target_sigset) {
1463 return -TARGET_EFAULT;
1464 }
1465 target_to_host_sigset(&set, target_sigset);
1466 unlock_user(target_sigset, arg_sigset, 0);
1467 } else {
1468 sig.set = NULL;
1469 }
1470 } else {
1471 sig_ptr = NULL;
1472 }
1473
1474 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
1475 ts_ptr, sig_ptr));
1476
1477 if (!is_error(ret)) {
1478 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n)) {
1479 return -TARGET_EFAULT;
1480 }
1481 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n)) {
1482 return -TARGET_EFAULT;
1483 }
1484 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n)) {
1485 return -TARGET_EFAULT;
1486 }
1487 if (time64) {
1488 if (ts_addr && host_to_target_timespec64(ts_addr, &ts)) {
1489 return -TARGET_EFAULT;
1490 }
1491 } else {
1492 if (ts_addr && host_to_target_timespec(ts_addr, &ts)) {
1493 return -TARGET_EFAULT;
1494 }
1495 }
1496 }
1497 return ret;
1498}
1499#endif
1500
1501#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll) || \
1502 defined(TARGET_NR_ppoll_time64)
1503static abi_long do_ppoll(abi_long arg1, abi_long arg2, abi_long arg3,
1504 abi_long arg4, abi_long arg5, bool ppoll, bool time64)
1505{
1506 struct target_pollfd *target_pfd;
1507 unsigned int nfds = arg2;
1508 struct pollfd *pfd;
1509 unsigned int i;
1510 abi_long ret;
1511
1512 pfd = NULL;
1513 target_pfd = NULL;
1514 if (nfds) {
1515 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
1516 return -TARGET_EINVAL;
1517 }
1518 target_pfd = lock_user(VERIFY_WRITE, arg1,
1519 sizeof(struct target_pollfd) * nfds, 1);
1520 if (!target_pfd) {
1521 return -TARGET_EFAULT;
1522 }
1523
1524 pfd = alloca(sizeof(struct pollfd) * nfds);
1525 for (i = 0; i < nfds; i++) {
1526 pfd[i].fd = tswap32(target_pfd[i].fd);
1527 pfd[i].events = tswap16(target_pfd[i].events);
1528 }
1529 }
1530 if (ppoll) {
1531 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
1532 target_sigset_t *target_set;
1533 sigset_t _set, *set = &_set;
1534
1535 if (arg3) {
1536 if (time64) {
1537 if (target_to_host_timespec64(timeout_ts, arg3)) {
1538 unlock_user(target_pfd, arg1, 0);
1539 return -TARGET_EFAULT;
1540 }
1541 } else {
1542 if (target_to_host_timespec(timeout_ts, arg3)) {
1543 unlock_user(target_pfd, arg1, 0);
1544 return -TARGET_EFAULT;
1545 }
1546 }
1547 } else {
1548 timeout_ts = NULL;
1549 }
1550
1551 if (arg4) {
1552 if (arg5 != sizeof(target_sigset_t)) {
1553 unlock_user(target_pfd, arg1, 0);
1554 return -TARGET_EINVAL;
1555 }
1556
1557 target_set = lock_user(VERIFY_READ, arg4,
1558 sizeof(target_sigset_t), 1);
1559 if (!target_set) {
1560 unlock_user(target_pfd, arg1, 0);
1561 return -TARGET_EFAULT;
1562 }
1563 target_to_host_sigset(set, target_set);
1564 } else {
1565 set = NULL;
1566 }
1567
1568 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
1569 set, SIGSET_T_SIZE));
1570
1571 if (!is_error(ret) && arg3) {
1572 if (time64) {
1573 if (host_to_target_timespec64(arg3, timeout_ts)) {
1574 return -TARGET_EFAULT;
1575 }
1576 } else {
1577 if (host_to_target_timespec(arg3, timeout_ts)) {
1578 return -TARGET_EFAULT;
1579 }
1580 }
1581 }
1582 if (arg4) {
1583 unlock_user(target_set, arg4, 0);
1584 }
1585 } else {
1586 struct timespec ts, *pts;
1587
1588 if (arg3 >= 0) {
1589 /* Convert ms to secs, ns */
1590 ts.tv_sec = arg3 / 1000;
1591 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
1592 pts = &ts;
1593 } else {
1594 /* -ve poll() timeout means "infinite" */
1595 pts = NULL;
1596 }
1597 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
1598 }
1599
1600 if (!is_error(ret)) {
1601 for (i = 0; i < nfds; i++) {
1602 target_pfd[i].revents = tswap16(pfd[i].revents);
1603 }
1604 }
1605 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
1606 return ret;
1607}
1608#endif
1609
099d6b0f
RV
1610static abi_long do_pipe2(int host_pipe[], int flags)
1611{
1612#ifdef CONFIG_PIPE2
1613 return pipe2(host_pipe, flags);
1614#else
1615 return -ENOSYS;
1616#endif
1617}
1618
fb41a66e
RH
1619static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1620 int flags, int is_pipe2)
099d6b0f
RV
1621{
1622 int host_pipe[2];
1623 abi_long ret;
1624 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1625
1626 if (is_error(ret))
1627 return get_errno(ret);
fb41a66e
RH
1628
1629 /* Several targets have special calling conventions for the original
1630 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1631 if (!is_pipe2) {
1632#if defined(TARGET_ALPHA)
1633 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1634 return host_pipe[0];
1635#elif defined(TARGET_MIPS)
1636 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1637 return host_pipe[0];
1638#elif defined(TARGET_SH4)
597c0212 1639 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
fb41a66e 1640 return host_pipe[0];
82f05b69
PM
1641#elif defined(TARGET_SPARC)
1642 ((CPUSPARCState*)cpu_env)->regwptr[1] = host_pipe[1];
1643 return host_pipe[0];
597c0212 1644#endif
fb41a66e
RH
1645 }
1646
099d6b0f
RV
1647 if (put_user_s32(host_pipe[0], pipedes)
1648 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1649 return -TARGET_EFAULT;
099d6b0f
RV
1650 return get_errno(ret);
1651}
1652
b975b83b
LL
1653static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1654 abi_ulong target_addr,
1655 socklen_t len)
1656{
1657 struct target_ip_mreqn *target_smreqn;
1658
1659 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1660 if (!target_smreqn)
1661 return -TARGET_EFAULT;
1662 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1663 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1664 if (len == sizeof(struct target_ip_mreqn))
cbb21eed 1665 mreqn->imr_ifindex = tswapal(target_smreqn->imr_ifindex);
b975b83b
LL
1666 unlock_user(target_smreqn, target_addr, 0);
1667
1668 return 0;
1669}
1670
7b36f782 1671static inline abi_long target_to_host_sockaddr(int fd, struct sockaddr *addr,
579a97f7
FB
1672 abi_ulong target_addr,
1673 socklen_t len)
7854b056 1674{
607175e0
AJ
1675 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1676 sa_family_t sa_family;
53a5960a
PB
1677 struct target_sockaddr *target_saddr;
1678
7b36f782
LV
1679 if (fd_trans_target_to_host_addr(fd)) {
1680 return fd_trans_target_to_host_addr(fd)(addr, target_addr, len);
1681 }
1682
579a97f7
FB
1683 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1684 if (!target_saddr)
1685 return -TARGET_EFAULT;
607175e0
AJ
1686
1687 sa_family = tswap16(target_saddr->sa_family);
1688
1689 /* Oops. The caller might send a incomplete sun_path; sun_path
1690 * must be terminated by \0 (see the manual page), but
1691 * unfortunately it is quite common to specify sockaddr_un
1692 * length as "strlen(x->sun_path)" while it should be
1693 * "strlen(...) + 1". We'll fix that here if needed.
1694 * Linux kernel has a similar feature.
1695 */
1696
1697 if (sa_family == AF_UNIX) {
1698 if (len < unix_maxlen && len > 0) {
1699 char *cp = (char*)target_saddr;
1700
1701 if ( cp[len-1] && !cp[len] )
1702 len++;
1703 }
1704 if (len > unix_maxlen)
1705 len = unix_maxlen;
1706 }
1707
53a5960a 1708 memcpy(addr, target_saddr, len);
607175e0 1709 addr->sa_family = sa_family;
6c5b5645
LV
1710 if (sa_family == AF_NETLINK) {
1711 struct sockaddr_nl *nladdr;
1712
1713 nladdr = (struct sockaddr_nl *)addr;
1714 nladdr->nl_pid = tswap32(nladdr->nl_pid);
1715 nladdr->nl_groups = tswap32(nladdr->nl_groups);
1716 } else if (sa_family == AF_PACKET) {
33a29b51
JT
1717 struct target_sockaddr_ll *lladdr;
1718
1719 lladdr = (struct target_sockaddr_ll *)addr;
1720 lladdr->sll_ifindex = tswap32(lladdr->sll_ifindex);
1721 lladdr->sll_hatype = tswap16(lladdr->sll_hatype);
1722 }
53a5960a 1723 unlock_user(target_saddr, target_addr, 0);
579a97f7
FB
1724
1725 return 0;
7854b056
FB
1726}
1727
579a97f7
FB
1728static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1729 struct sockaddr *addr,
1730 socklen_t len)
7854b056 1731{
53a5960a
PB
1732 struct target_sockaddr *target_saddr;
1733
a1e22192
PM
1734 if (len == 0) {
1735 return 0;
1736 }
6860710c 1737 assert(addr);
a1e22192 1738
579a97f7
FB
1739 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1740 if (!target_saddr)
1741 return -TARGET_EFAULT;
53a5960a 1742 memcpy(target_saddr, addr, len);
a1e22192
PM
1743 if (len >= offsetof(struct target_sockaddr, sa_family) +
1744 sizeof(target_saddr->sa_family)) {
1745 target_saddr->sa_family = tswap16(addr->sa_family);
1746 }
a47401bc
PMD
1747 if (addr->sa_family == AF_NETLINK &&
1748 len >= sizeof(struct target_sockaddr_nl)) {
1749 struct target_sockaddr_nl *target_nl =
1750 (struct target_sockaddr_nl *)target_saddr;
6c5b5645
LV
1751 target_nl->nl_pid = tswap32(target_nl->nl_pid);
1752 target_nl->nl_groups = tswap32(target_nl->nl_groups);
a82ea939
LV
1753 } else if (addr->sa_family == AF_PACKET) {
1754 struct sockaddr_ll *target_ll = (struct sockaddr_ll *)target_saddr;
1755 target_ll->sll_ifindex = tswap32(target_ll->sll_ifindex);
1756 target_ll->sll_hatype = tswap16(target_ll->sll_hatype);
ee1ac3a1
HD
1757 } else if (addr->sa_family == AF_INET6 &&
1758 len >= sizeof(struct target_sockaddr_in6)) {
1759 struct target_sockaddr_in6 *target_in6 =
1760 (struct target_sockaddr_in6 *)target_saddr;
1761 target_in6->sin6_scope_id = tswap16(target_in6->sin6_scope_id);
6c5b5645 1762 }
53a5960a 1763 unlock_user(target_saddr, target_addr, len);
579a97f7
FB
1764
1765 return 0;
7854b056
FB
1766}
1767
5a4a898d
FB
1768static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1769 struct target_msghdr *target_msgh)
7854b056
FB
1770{
1771 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1772 abi_long msg_controllen;
1773 abi_ulong target_cmsg_addr;
ee104587 1774 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056 1775 socklen_t space = 0;
5a4a898d 1776
cbb21eed 1777 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1778 if (msg_controllen < sizeof (struct target_cmsghdr))
1779 goto the_end;
cbb21eed 1780 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1781 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
ee104587 1782 target_cmsg_start = target_cmsg;
5a4a898d
FB
1783 if (!target_cmsg)
1784 return -TARGET_EFAULT;
7854b056
FB
1785
1786 while (cmsg && target_cmsg) {
1787 void *data = CMSG_DATA(cmsg);
1788 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1789
cbb21eed 1790 int len = tswapal(target_cmsg->cmsg_len)
ad762b99 1791 - sizeof(struct target_cmsghdr);
7854b056
FB
1792
1793 space += CMSG_SPACE(len);
1794 if (space > msgh->msg_controllen) {
1795 space -= CMSG_SPACE(len);
c2aeb258
PM
1796 /* This is a QEMU bug, since we allocated the payload
1797 * area ourselves (unlike overflow in host-to-target
1798 * conversion, which is just the guest giving us a buffer
1799 * that's too small). It can't happen for the payload types
1800 * we currently support; if it becomes an issue in future
1801 * we would need to improve our allocation strategy to
1802 * something more intelligent than "twice the size of the
1803 * target buffer we're reading from".
1804 */
39be5350
JK
1805 qemu_log_mask(LOG_UNIMP,
1806 ("Unsupported ancillary data %d/%d: "
1807 "unhandled msg size\n"),
1808 tswap32(target_cmsg->cmsg_level),
1809 tswap32(target_cmsg->cmsg_type));
7854b056
FB
1810 break;
1811 }
1812
dbf4f796
PJ
1813 if (tswap32(target_cmsg->cmsg_level) == TARGET_SOL_SOCKET) {
1814 cmsg->cmsg_level = SOL_SOCKET;
1815 } else {
1816 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1817 }
7854b056
FB
1818 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1819 cmsg->cmsg_len = CMSG_LEN(len);
1820
30b8b68e 1821 if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
7854b056
FB
1822 int *fd = (int *)data;
1823 int *target_fd = (int *)target_data;
1824 int i, numfds = len / sizeof(int);
1825
876e23cb
PM
1826 for (i = 0; i < numfds; i++) {
1827 __get_user(fd[i], target_fd + i);
1828 }
30b8b68e
AS
1829 } else if (cmsg->cmsg_level == SOL_SOCKET
1830 && cmsg->cmsg_type == SCM_CREDENTIALS) {
1831 struct ucred *cred = (struct ucred *)data;
1832 struct target_ucred *target_cred =
1833 (struct target_ucred *)target_data;
1834
876e23cb
PM
1835 __get_user(cred->pid, &target_cred->pid);
1836 __get_user(cred->uid, &target_cred->uid);
1837 __get_user(cred->gid, &target_cred->gid);
30b8b68e 1838 } else {
39be5350
JK
1839 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
1840 cmsg->cmsg_level, cmsg->cmsg_type);
30b8b68e 1841 memcpy(data, target_data, len);
7854b056
FB
1842 }
1843
1844 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
1845 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
1846 target_cmsg_start);
7854b056 1847 }
5a4a898d
FB
1848 unlock_user(target_cmsg, target_cmsg_addr, 0);
1849 the_end:
7854b056 1850 msgh->msg_controllen = space;
5a4a898d 1851 return 0;
7854b056
FB
1852}
1853
5a4a898d
FB
1854static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1855 struct msghdr *msgh)
7854b056
FB
1856{
1857 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
5a4a898d
FB
1858 abi_long msg_controllen;
1859 abi_ulong target_cmsg_addr;
ee104587 1860 struct target_cmsghdr *target_cmsg, *target_cmsg_start;
7854b056
FB
1861 socklen_t space = 0;
1862
cbb21eed 1863 msg_controllen = tswapal(target_msgh->msg_controllen);
5a4a898d
FB
1864 if (msg_controllen < sizeof (struct target_cmsghdr))
1865 goto the_end;
cbb21eed 1866 target_cmsg_addr = tswapal(target_msgh->msg_control);
5a4a898d 1867 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
ee104587 1868 target_cmsg_start = target_cmsg;
5a4a898d
FB
1869 if (!target_cmsg)
1870 return -TARGET_EFAULT;
1871
7854b056
FB
1872 while (cmsg && target_cmsg) {
1873 void *data = CMSG_DATA(cmsg);
1874 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1875
ad762b99 1876 int len = cmsg->cmsg_len - sizeof(struct cmsghdr);
c2aeb258 1877 int tgt_len, tgt_space;
7854b056 1878
c2aeb258
PM
1879 /* We never copy a half-header but may copy half-data;
1880 * this is Linux's behaviour in put_cmsg(). Note that
1881 * truncation here is a guest problem (which we report
1882 * to the guest via the CTRUNC bit), unlike truncation
1883 * in target_to_host_cmsg, which is a QEMU bug.
1884 */
7174970a 1885 if (msg_controllen < sizeof(struct target_cmsghdr)) {
c2aeb258 1886 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7854b056
FB
1887 break;
1888 }
1889
dbf4f796
PJ
1890 if (cmsg->cmsg_level == SOL_SOCKET) {
1891 target_cmsg->cmsg_level = tswap32(TARGET_SOL_SOCKET);
1892 } else {
1893 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1894 }
7854b056 1895 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
7854b056 1896
c2aeb258
PM
1897 /* Payload types which need a different size of payload on
1898 * the target must adjust tgt_len here.
1899 */
309786cf 1900 tgt_len = len;
c2aeb258
PM
1901 switch (cmsg->cmsg_level) {
1902 case SOL_SOCKET:
1903 switch (cmsg->cmsg_type) {
1904 case SO_TIMESTAMP:
1905 tgt_len = sizeof(struct target_timeval);
1906 break;
1907 default:
1908 break;
1909 }
309786cf 1910 break;
c2aeb258
PM
1911 default:
1912 break;
1913 }
1914
7174970a 1915 if (msg_controllen < TARGET_CMSG_LEN(tgt_len)) {
c2aeb258 1916 target_msgh->msg_flags |= tswap32(MSG_CTRUNC);
7174970a 1917 tgt_len = msg_controllen - sizeof(struct target_cmsghdr);
c2aeb258
PM
1918 }
1919
1920 /* We must now copy-and-convert len bytes of payload
1921 * into tgt_len bytes of destination space. Bear in mind
1922 * that in both source and destination we may be dealing
1923 * with a truncated value!
1924 */
52b65494
HD
1925 switch (cmsg->cmsg_level) {
1926 case SOL_SOCKET:
1927 switch (cmsg->cmsg_type) {
1928 case SCM_RIGHTS:
1929 {
1930 int *fd = (int *)data;
1931 int *target_fd = (int *)target_data;
c2aeb258 1932 int i, numfds = tgt_len / sizeof(int);
52b65494 1933
876e23cb
PM
1934 for (i = 0; i < numfds; i++) {
1935 __put_user(fd[i], target_fd + i);
1936 }
52b65494
HD
1937 break;
1938 }
1939 case SO_TIMESTAMP:
1940 {
1941 struct timeval *tv = (struct timeval *)data;
1942 struct target_timeval *target_tv =
1943 (struct target_timeval *)target_data;
1944
c2aeb258
PM
1945 if (len != sizeof(struct timeval) ||
1946 tgt_len != sizeof(struct target_timeval)) {
52b65494 1947 goto unimplemented;
c2aeb258 1948 }
52b65494
HD
1949
1950 /* copy struct timeval to target */
876e23cb
PM
1951 __put_user(tv->tv_sec, &target_tv->tv_sec);
1952 __put_user(tv->tv_usec, &target_tv->tv_usec);
52b65494
HD
1953 break;
1954 }
4bc29756
HD
1955 case SCM_CREDENTIALS:
1956 {
1957 struct ucred *cred = (struct ucred *)data;
1958 struct target_ucred *target_cred =
1959 (struct target_ucred *)target_data;
1960
1961 __put_user(cred->pid, &target_cred->pid);
1962 __put_user(cred->uid, &target_cred->uid);
1963 __put_user(cred->gid, &target_cred->gid);
1964 break;
1965 }
52b65494
HD
1966 default:
1967 goto unimplemented;
1968 }
1969 break;
7854b056 1970
ee1ac3a1
HD
1971 case SOL_IP:
1972 switch (cmsg->cmsg_type) {
1973 case IP_TTL:
1974 {
1975 uint32_t *v = (uint32_t *)data;
1976 uint32_t *t_int = (uint32_t *)target_data;
1977
7174970a
PM
1978 if (len != sizeof(uint32_t) ||
1979 tgt_len != sizeof(uint32_t)) {
1980 goto unimplemented;
1981 }
ee1ac3a1
HD
1982 __put_user(*v, t_int);
1983 break;
1984 }
1985 case IP_RECVERR:
1986 {
1987 struct errhdr_t {
1988 struct sock_extended_err ee;
1989 struct sockaddr_in offender;
1990 };
1991 struct errhdr_t *errh = (struct errhdr_t *)data;
1992 struct errhdr_t *target_errh =
1993 (struct errhdr_t *)target_data;
1994
7174970a
PM
1995 if (len != sizeof(struct errhdr_t) ||
1996 tgt_len != sizeof(struct errhdr_t)) {
1997 goto unimplemented;
1998 }
ee1ac3a1
HD
1999 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2000 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2001 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2002 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2003 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2004 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2005 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2006 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2007 (void *) &errh->offender, sizeof(errh->offender));
2008 break;
2009 }
2010 default:
2011 goto unimplemented;
2012 }
2013 break;
2014
2015 case SOL_IPV6:
2016 switch (cmsg->cmsg_type) {
2017 case IPV6_HOPLIMIT:
2018 {
2019 uint32_t *v = (uint32_t *)data;
2020 uint32_t *t_int = (uint32_t *)target_data;
2021
7174970a
PM
2022 if (len != sizeof(uint32_t) ||
2023 tgt_len != sizeof(uint32_t)) {
2024 goto unimplemented;
2025 }
ee1ac3a1
HD
2026 __put_user(*v, t_int);
2027 break;
2028 }
2029 case IPV6_RECVERR:
2030 {
2031 struct errhdr6_t {
2032 struct sock_extended_err ee;
2033 struct sockaddr_in6 offender;
2034 };
2035 struct errhdr6_t *errh = (struct errhdr6_t *)data;
2036 struct errhdr6_t *target_errh =
2037 (struct errhdr6_t *)target_data;
2038
7174970a
PM
2039 if (len != sizeof(struct errhdr6_t) ||
2040 tgt_len != sizeof(struct errhdr6_t)) {
2041 goto unimplemented;
2042 }
ee1ac3a1
HD
2043 __put_user(errh->ee.ee_errno, &target_errh->ee.ee_errno);
2044 __put_user(errh->ee.ee_origin, &target_errh->ee.ee_origin);
2045 __put_user(errh->ee.ee_type, &target_errh->ee.ee_type);
2046 __put_user(errh->ee.ee_code, &target_errh->ee.ee_code);
2047 __put_user(errh->ee.ee_pad, &target_errh->ee.ee_pad);
2048 __put_user(errh->ee.ee_info, &target_errh->ee.ee_info);
2049 __put_user(errh->ee.ee_data, &target_errh->ee.ee_data);
2050 host_to_target_sockaddr((unsigned long) &target_errh->offender,
2051 (void *) &errh->offender, sizeof(errh->offender));
2052 break;
2053 }
2054 default:
2055 goto unimplemented;
2056 }
2057 break;
2058
52b65494
HD
2059 default:
2060 unimplemented:
39be5350
JK
2061 qemu_log_mask(LOG_UNIMP, "Unsupported ancillary data: %d/%d\n",
2062 cmsg->cmsg_level, cmsg->cmsg_type);
c2aeb258
PM
2063 memcpy(target_data, data, MIN(len, tgt_len));
2064 if (tgt_len > len) {
2065 memset(target_data + len, 0, tgt_len - len);
2066 }
7854b056
FB
2067 }
2068
7174970a
PM
2069 target_cmsg->cmsg_len = tswapal(TARGET_CMSG_LEN(tgt_len));
2070 tgt_space = TARGET_CMSG_SPACE(tgt_len);
c2aeb258
PM
2071 if (msg_controllen < tgt_space) {
2072 tgt_space = msg_controllen;
2073 }
2074 msg_controllen -= tgt_space;
2075 space += tgt_space;
7854b056 2076 cmsg = CMSG_NXTHDR(msgh, cmsg);
ee104587
JN
2077 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg,
2078 target_cmsg_start);
7854b056 2079 }
5a4a898d
FB
2080 unlock_user(target_cmsg, target_cmsg_addr, space);
2081 the_end:
cbb21eed 2082 target_msgh->msg_controllen = tswapal(space);
5a4a898d 2083 return 0;
7854b056
FB
2084}
2085
0da46a6e 2086/* do_setsockopt() Must return target values and target errnos. */
992f48a0 2087static abi_long do_setsockopt(int sockfd, int level, int optname,
2f619698 2088 abi_ulong optval_addr, socklen_t optlen)
7854b056 2089{
992f48a0 2090 abi_long ret;
32407103 2091 int val;
b975b83b 2092 struct ip_mreqn *ip_mreq;
6e3cb58f 2093 struct ip_mreq_source *ip_mreq_source;
3b46e624 2094
8853f86e
FB
2095 switch(level) {
2096 case SOL_TCP:
fe51b0a5
SCW
2097 case SOL_UDP:
2098 /* TCP and UDP options all take an 'int' value. */
7854b056 2099 if (optlen < sizeof(uint32_t))
0da46a6e 2100 return -TARGET_EINVAL;
3b46e624 2101
2f619698
FB
2102 if (get_user_u32(val, optval_addr))
2103 return -TARGET_EFAULT;
8853f86e
FB
2104 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2105 break;
2106 case SOL_IP:
2107 switch(optname) {
2efbe911
FB
2108 case IP_TOS:
2109 case IP_TTL:
8853f86e 2110 case IP_HDRINCL:
2efbe911
FB
2111 case IP_ROUTER_ALERT:
2112 case IP_RECVOPTS:
2113 case IP_RETOPTS:
2114 case IP_PKTINFO:
2115 case IP_MTU_DISCOVER:
2116 case IP_RECVERR:
ee1ac3a1 2117 case IP_RECVTTL:
2efbe911
FB
2118 case IP_RECVTOS:
2119#ifdef IP_FREEBIND
2120 case IP_FREEBIND:
2121#endif
2122 case IP_MULTICAST_TTL:
2123 case IP_MULTICAST_LOOP:
8853f86e
FB
2124 val = 0;
2125 if (optlen >= sizeof(uint32_t)) {
2f619698
FB
2126 if (get_user_u32(val, optval_addr))
2127 return -TARGET_EFAULT;
8853f86e 2128 } else if (optlen >= 1) {
2f619698
FB
2129 if (get_user_u8(val, optval_addr))
2130 return -TARGET_EFAULT;
8853f86e
FB
2131 }
2132 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
2133 break;
b975b83b
LL
2134 case IP_ADD_MEMBERSHIP:
2135 case IP_DROP_MEMBERSHIP:
2136 if (optlen < sizeof (struct target_ip_mreq) ||
2137 optlen > sizeof (struct target_ip_mreqn))
2138 return -TARGET_EINVAL;
2139
2140 ip_mreq = (struct ip_mreqn *) alloca(optlen);
2141 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
2142 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
2143 break;
2144
6e3cb58f
LL
2145 case IP_BLOCK_SOURCE:
2146 case IP_UNBLOCK_SOURCE:
2147 case IP_ADD_SOURCE_MEMBERSHIP:
2148 case IP_DROP_SOURCE_MEMBERSHIP:
2149 if (optlen != sizeof (struct target_ip_mreq_source))
2150 return -TARGET_EINVAL;
2151
2152 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
74e43b04
PM
2153 if (!ip_mreq_source) {
2154 return -TARGET_EFAULT;
2155 }
6e3cb58f
LL
2156 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
2157 unlock_user (ip_mreq_source, optval_addr, 0);
2158 break;
2159
920394db
JH
2160 default:
2161 goto unimplemented;
2162 }
2163 break;
0d78b3b5
LV
2164 case SOL_IPV6:
2165 switch (optname) {
2166 case IPV6_MTU_DISCOVER:
2167 case IPV6_MTU:
2168 case IPV6_V6ONLY:
2169 case IPV6_RECVPKTINFO:
ee1ac3a1 2170 case IPV6_UNICAST_HOPS:
21749c4c
LV
2171 case IPV6_MULTICAST_HOPS:
2172 case IPV6_MULTICAST_LOOP:
ee1ac3a1
HD
2173 case IPV6_RECVERR:
2174 case IPV6_RECVHOPLIMIT:
2175 case IPV6_2292HOPLIMIT:
2176 case IPV6_CHECKSUM:
b9cce6d7
HD
2177 case IPV6_ADDRFORM:
2178 case IPV6_2292PKTINFO:
2179 case IPV6_RECVTCLASS:
2180 case IPV6_RECVRTHDR:
2181 case IPV6_2292RTHDR:
2182 case IPV6_RECVHOPOPTS:
2183 case IPV6_2292HOPOPTS:
2184 case IPV6_RECVDSTOPTS:
2185 case IPV6_2292DSTOPTS:
2186 case IPV6_TCLASS:
22db1213 2187 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2188#ifdef IPV6_RECVPATHMTU
2189 case IPV6_RECVPATHMTU:
2190#endif
2191#ifdef IPV6_TRANSPARENT
2192 case IPV6_TRANSPARENT:
2193#endif
2194#ifdef IPV6_FREEBIND
2195 case IPV6_FREEBIND:
2196#endif
2197#ifdef IPV6_RECVORIGDSTADDR
2198 case IPV6_RECVORIGDSTADDR:
2199#endif
0d78b3b5
LV
2200 val = 0;
2201 if (optlen < sizeof(uint32_t)) {
2202 return -TARGET_EINVAL;
2203 }
2204 if (get_user_u32(val, optval_addr)) {
2205 return -TARGET_EFAULT;
2206 }
2207 ret = get_errno(setsockopt(sockfd, level, optname,
2208 &val, sizeof(val)));
2209 break;
ee1ac3a1
HD
2210 case IPV6_PKTINFO:
2211 {
2212 struct in6_pktinfo pki;
2213
2214 if (optlen < sizeof(pki)) {
2215 return -TARGET_EINVAL;
2216 }
2217
2218 if (copy_from_user(&pki, optval_addr, sizeof(pki))) {
2219 return -TARGET_EFAULT;
2220 }
2221
2222 pki.ipi6_ifindex = tswap32(pki.ipi6_ifindex);
2223
2224 ret = get_errno(setsockopt(sockfd, level, optname,
2225 &pki, sizeof(pki)));
2226 break;
2227 }
22bf4ee9
NC
2228 case IPV6_ADD_MEMBERSHIP:
2229 case IPV6_DROP_MEMBERSHIP:
2230 {
2231 struct ipv6_mreq ipv6mreq;
2232
2233 if (optlen < sizeof(ipv6mreq)) {
2234 return -TARGET_EINVAL;
2235 }
2236
2237 if (copy_from_user(&ipv6mreq, optval_addr, sizeof(ipv6mreq))) {
2238 return -TARGET_EFAULT;
2239 }
2240
2241 ipv6mreq.ipv6mr_interface = tswap32(ipv6mreq.ipv6mr_interface);
2242
2243 ret = get_errno(setsockopt(sockfd, level, optname,
2244 &ipv6mreq, sizeof(ipv6mreq)));
2245 break;
2246 }
ee1ac3a1
HD
2247 default:
2248 goto unimplemented;
2249 }
2250 break;
2251 case SOL_ICMPV6:
2252 switch (optname) {
2253 case ICMPV6_FILTER:
2254 {
2255 struct icmp6_filter icmp6f;
2256
2257 if (optlen > sizeof(icmp6f)) {
2258 optlen = sizeof(icmp6f);
2259 }
2260
2261 if (copy_from_user(&icmp6f, optval_addr, optlen)) {
2262 return -TARGET_EFAULT;
2263 }
2264
2265 for (val = 0; val < 8; val++) {
2266 icmp6f.data[val] = tswap32(icmp6f.data[val]);
2267 }
2268
2269 ret = get_errno(setsockopt(sockfd, level, optname,
2270 &icmp6f, optlen));
2271 break;
2272 }
0d78b3b5
LV
2273 default:
2274 goto unimplemented;
2275 }
2276 break;
920394db
JH
2277 case SOL_RAW:
2278 switch (optname) {
2279 case ICMP_FILTER:
ee1ac3a1
HD
2280 case IPV6_CHECKSUM:
2281 /* those take an u32 value */
920394db
JH
2282 if (optlen < sizeof(uint32_t)) {
2283 return -TARGET_EINVAL;
2284 }
2285
2286 if (get_user_u32(val, optval_addr)) {
2287 return -TARGET_EFAULT;
2288 }
2289 ret = get_errno(setsockopt(sockfd, level, optname,
2290 &val, sizeof(val)));
2291 break;
2292
8853f86e
FB
2293 default:
2294 goto unimplemented;
2295 }
2296 break;
f31dddd2
YS
2297#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
2298 case SOL_ALG:
2299 switch (optname) {
2300 case ALG_SET_KEY:
2301 {
2302 char *alg_key = g_malloc(optlen);
2303
2304 if (!alg_key) {
2305 return -TARGET_ENOMEM;
2306 }
2307 if (copy_from_user(alg_key, optval_addr, optlen)) {
2308 g_free(alg_key);
2309 return -TARGET_EFAULT;
2310 }
2311 ret = get_errno(setsockopt(sockfd, level, optname,
2312 alg_key, optlen));
2313 g_free(alg_key);
2314 break;
2315 }
2316 case ALG_SET_AEAD_AUTHSIZE:
2317 {
2318 ret = get_errno(setsockopt(sockfd, level, optname,
2319 NULL, optlen));
2320 break;
2321 }
2322 default:
2323 goto unimplemented;
2324 }
2325 break;
2326#endif
3532fa74 2327 case TARGET_SOL_SOCKET:
8853f86e 2328 switch (optname) {
1b09aeb9
LV
2329 case TARGET_SO_RCVTIMEO:
2330 {
2331 struct timeval tv;
2332
2333 optname = SO_RCVTIMEO;
2334
2335set_timeout:
2336 if (optlen != sizeof(struct target_timeval)) {
2337 return -TARGET_EINVAL;
2338 }
2339
2340 if (copy_from_user_timeval(&tv, optval_addr)) {
2341 return -TARGET_EFAULT;
2342 }
2343
2344 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2345 &tv, sizeof(tv)));
2346 return ret;
2347 }
2348 case TARGET_SO_SNDTIMEO:
2349 optname = SO_SNDTIMEO;
2350 goto set_timeout;
f57d4192
LV
2351 case TARGET_SO_ATTACH_FILTER:
2352 {
2353 struct target_sock_fprog *tfprog;
2354 struct target_sock_filter *tfilter;
2355 struct sock_fprog fprog;
2356 struct sock_filter *filter;
2357 int i;
2358
2359 if (optlen != sizeof(*tfprog)) {
2360 return -TARGET_EINVAL;
2361 }
2362 if (!lock_user_struct(VERIFY_READ, tfprog, optval_addr, 0)) {
2363 return -TARGET_EFAULT;
2364 }
2365 if (!lock_user_struct(VERIFY_READ, tfilter,
2366 tswapal(tfprog->filter), 0)) {
2367 unlock_user_struct(tfprog, optval_addr, 1);
2368 return -TARGET_EFAULT;
2369 }
2370
2371 fprog.len = tswap16(tfprog->len);
0e173b24 2372 filter = g_try_new(struct sock_filter, fprog.len);
f57d4192
LV
2373 if (filter == NULL) {
2374 unlock_user_struct(tfilter, tfprog->filter, 1);
2375 unlock_user_struct(tfprog, optval_addr, 1);
2376 return -TARGET_ENOMEM;
2377 }
2378 for (i = 0; i < fprog.len; i++) {
2379 filter[i].code = tswap16(tfilter[i].code);
2380 filter[i].jt = tfilter[i].jt;
2381 filter[i].jf = tfilter[i].jf;
2382 filter[i].k = tswap32(tfilter[i].k);
2383 }
2384 fprog.filter = filter;
2385
2386 ret = get_errno(setsockopt(sockfd, SOL_SOCKET,
2387 SO_ATTACH_FILTER, &fprog, sizeof(fprog)));
0e173b24 2388 g_free(filter);
f57d4192
LV
2389
2390 unlock_user_struct(tfilter, tfprog->filter, 1);
2391 unlock_user_struct(tfprog, optval_addr, 1);
2392 return ret;
2393 }
451aaf68
JT
2394 case TARGET_SO_BINDTODEVICE:
2395 {
2396 char *dev_ifname, *addr_ifname;
2397
2398 if (optlen > IFNAMSIZ - 1) {
2399 optlen = IFNAMSIZ - 1;
2400 }
2401 dev_ifname = lock_user(VERIFY_READ, optval_addr, optlen, 1);
2402 if (!dev_ifname) {
2403 return -TARGET_EFAULT;
2404 }
2405 optname = SO_BINDTODEVICE;
2406 addr_ifname = alloca(IFNAMSIZ);
2407 memcpy(addr_ifname, dev_ifname, optlen);
2408 addr_ifname[optlen] = 0;
fad6c58a
CG
2409 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname,
2410 addr_ifname, optlen));
451aaf68
JT
2411 unlock_user (dev_ifname, optval_addr, 0);
2412 return ret;
2413 }
83eb6e50
CMAB
2414 case TARGET_SO_LINGER:
2415 {
2416 struct linger lg;
2417 struct target_linger *tlg;
2418
2419 if (optlen != sizeof(struct target_linger)) {
2420 return -TARGET_EINVAL;
2421 }
2422 if (!lock_user_struct(VERIFY_READ, tlg, optval_addr, 1)) {
2423 return -TARGET_EFAULT;
2424 }
2425 __get_user(lg.l_onoff, &tlg->l_onoff);
2426 __get_user(lg.l_linger, &tlg->l_linger);
2427 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, SO_LINGER,
2428 &lg, sizeof(lg)));
2429 unlock_user_struct(tlg, optval_addr, 0);
2430 return ret;
2431 }
8853f86e 2432 /* Options with 'int' argument. */
3532fa74
FB
2433 case TARGET_SO_DEBUG:
2434 optname = SO_DEBUG;
2435 break;
2436 case TARGET_SO_REUSEADDR:
2437 optname = SO_REUSEADDR;
2438 break;
113a9dd7
YS
2439#ifdef SO_REUSEPORT
2440 case TARGET_SO_REUSEPORT:
2441 optname = SO_REUSEPORT;
2442 break;
2443#endif
3532fa74
FB
2444 case TARGET_SO_TYPE:
2445 optname = SO_TYPE;
2446 break;
2447 case TARGET_SO_ERROR:
2448 optname = SO_ERROR;
2449 break;
2450 case TARGET_SO_DONTROUTE:
2451 optname = SO_DONTROUTE;
2452 break;
2453 case TARGET_SO_BROADCAST:
2454 optname = SO_BROADCAST;
2455 break;
2456 case TARGET_SO_SNDBUF:
2457 optname = SO_SNDBUF;
2458 break;
d79b6cc4
PB
2459 case TARGET_SO_SNDBUFFORCE:
2460 optname = SO_SNDBUFFORCE;
2461 break;
3532fa74
FB
2462 case TARGET_SO_RCVBUF:
2463 optname = SO_RCVBUF;
2464 break;
d79b6cc4
PB
2465 case TARGET_SO_RCVBUFFORCE:
2466 optname = SO_RCVBUFFORCE;
2467 break;
3532fa74
FB
2468 case TARGET_SO_KEEPALIVE:
2469 optname = SO_KEEPALIVE;
2470 break;
2471 case TARGET_SO_OOBINLINE:
2472 optname = SO_OOBINLINE;
2473 break;
2474 case TARGET_SO_NO_CHECK:
2475 optname = SO_NO_CHECK;
2476 break;
2477 case TARGET_SO_PRIORITY:
2478 optname = SO_PRIORITY;
2479 break;
5e83e8e3 2480#ifdef SO_BSDCOMPAT
3532fa74
FB
2481 case TARGET_SO_BSDCOMPAT:
2482 optname = SO_BSDCOMPAT;
2483 break;
5e83e8e3 2484#endif
3532fa74
FB
2485 case TARGET_SO_PASSCRED:
2486 optname = SO_PASSCRED;
2487 break;
82d0fe6b
PB
2488 case TARGET_SO_PASSSEC:
2489 optname = SO_PASSSEC;
2490 break;
3532fa74
FB
2491 case TARGET_SO_TIMESTAMP:
2492 optname = SO_TIMESTAMP;
2493 break;
2494 case TARGET_SO_RCVLOWAT:
2495 optname = SO_RCVLOWAT;
2496 break;
8853f86e
FB
2497 default:
2498 goto unimplemented;
2499 }
3532fa74 2500 if (optlen < sizeof(uint32_t))
2f619698 2501 return -TARGET_EINVAL;
3532fa74 2502
2f619698
FB
2503 if (get_user_u32(val, optval_addr))
2504 return -TARGET_EFAULT;
3532fa74 2505 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
8853f86e 2506 break;
a2d86682
JK
2507#ifdef SOL_NETLINK
2508 case SOL_NETLINK:
2509 switch (optname) {
2510 case NETLINK_PKTINFO:
2511 case NETLINK_ADD_MEMBERSHIP:
2512 case NETLINK_DROP_MEMBERSHIP:
2513 case NETLINK_BROADCAST_ERROR:
2514 case NETLINK_NO_ENOBUFS:
2515#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2516 case NETLINK_LISTEN_ALL_NSID:
2517 case NETLINK_CAP_ACK:
2518#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2519#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2520 case NETLINK_EXT_ACK:
2521#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2522#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2523 case NETLINK_GET_STRICT_CHK:
2524#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2525 break;
2526 default:
2527 goto unimplemented;
2528 }
2529 val = 0;
2530 if (optlen < sizeof(uint32_t)) {
2531 return -TARGET_EINVAL;
2532 }
2533 if (get_user_u32(val, optval_addr)) {
2534 return -TARGET_EFAULT;
2535 }
2536 ret = get_errno(setsockopt(sockfd, SOL_NETLINK, optname, &val,
2537 sizeof(val)));
2538 break;
2539#endif /* SOL_NETLINK */
7854b056 2540 default:
8853f86e 2541 unimplemented:
39be5350
JK
2542 qemu_log_mask(LOG_UNIMP, "Unsupported setsockopt level=%d optname=%d\n",
2543 level, optname);
6fa13c17 2544 ret = -TARGET_ENOPROTOOPT;
7854b056 2545 }
8853f86e 2546 return ret;
7854b056
FB
2547}
2548
0da46a6e 2549/* do_getsockopt() Must return target values and target errnos. */
992f48a0 2550static abi_long do_getsockopt(int sockfd, int level, int optname,
2f619698 2551 abi_ulong optval_addr, abi_ulong optlen)
7854b056 2552{
992f48a0 2553 abi_long ret;
b55266b5
BS
2554 int len, val;
2555 socklen_t lv;
8853f86e
FB
2556
2557 switch(level) {
3532fa74 2558 case TARGET_SOL_SOCKET:
f3b974cd
JL
2559 level = SOL_SOCKET;
2560 switch (optname) {
2561 /* These don't just return a single integer */
f3b974cd
JL
2562 case TARGET_SO_PEERNAME:
2563 goto unimplemented;
405dc4cf
AS
2564 case TARGET_SO_RCVTIMEO: {
2565 struct timeval tv;
2566 socklen_t tvlen;
2567
2568 optname = SO_RCVTIMEO;
2569
2570get_timeout:
2571 if (get_user_u32(len, optlen)) {
2572 return -TARGET_EFAULT;
2573 }
2574 if (len < 0) {
2575 return -TARGET_EINVAL;
2576 }
2577
2578 tvlen = sizeof(tv);
2579 ret = get_errno(getsockopt(sockfd, level, optname,
2580 &tv, &tvlen));
2581 if (ret < 0) {
2582 return ret;
2583 }
2584 if (len > sizeof(struct target_timeval)) {
2585 len = sizeof(struct target_timeval);
2586 }
2587 if (copy_to_user_timeval(optval_addr, &tv)) {
2588 return -TARGET_EFAULT;
2589 }
2590 if (put_user_u32(len, optlen)) {
2591 return -TARGET_EFAULT;
2592 }
2593 break;
2594 }
2595 case TARGET_SO_SNDTIMEO:
2596 optname = SO_SNDTIMEO;
2597 goto get_timeout;
583359a6
AP
2598 case TARGET_SO_PEERCRED: {
2599 struct ucred cr;
2600 socklen_t crlen;
2601 struct target_ucred *tcr;
2602
2603 if (get_user_u32(len, optlen)) {
2604 return -TARGET_EFAULT;
2605 }
2606 if (len < 0) {
2607 return -TARGET_EINVAL;
2608 }
2609
2610 crlen = sizeof(cr);
2611 ret = get_errno(getsockopt(sockfd, level, SO_PEERCRED,
2612 &cr, &crlen));
2613 if (ret < 0) {
2614 return ret;
2615 }
2616 if (len > crlen) {
2617 len = crlen;
2618 }
2619 if (!lock_user_struct(VERIFY_WRITE, tcr, optval_addr, 0)) {
2620 return -TARGET_EFAULT;
2621 }
2622 __put_user(cr.pid, &tcr->pid);
2623 __put_user(cr.uid, &tcr->uid);
2624 __put_user(cr.gid, &tcr->gid);
2625 unlock_user_struct(tcr, optval_addr, 1);
2626 if (put_user_u32(len, optlen)) {
83eb6e50
CMAB
2627 return -TARGET_EFAULT;
2628 }
2629 break;
2630 }
6d485a55
LV
2631 case TARGET_SO_PEERSEC: {
2632 char *name;
2633
2634 if (get_user_u32(len, optlen)) {
2635 return -TARGET_EFAULT;
2636 }
2637 if (len < 0) {
2638 return -TARGET_EINVAL;
2639 }
2640 name = lock_user(VERIFY_WRITE, optval_addr, len, 0);
2641 if (!name) {
2642 return -TARGET_EFAULT;
2643 }
2644 lv = len;
2645 ret = get_errno(getsockopt(sockfd, level, SO_PEERSEC,
2646 name, &lv));
2647 if (put_user_u32(lv, optlen)) {
2648 ret = -TARGET_EFAULT;
2649 }
2650 unlock_user(name, optval_addr, lv);
2651 break;
2652 }
83eb6e50
CMAB
2653 case TARGET_SO_LINGER:
2654 {
2655 struct linger lg;
2656 socklen_t lglen;
2657 struct target_linger *tlg;
2658
2659 if (get_user_u32(len, optlen)) {
2660 return -TARGET_EFAULT;
2661 }
2662 if (len < 0) {
2663 return -TARGET_EINVAL;
2664 }
2665
2666 lglen = sizeof(lg);
2667 ret = get_errno(getsockopt(sockfd, level, SO_LINGER,
2668 &lg, &lglen));
2669 if (ret < 0) {
2670 return ret;
2671 }
2672 if (len > lglen) {
2673 len = lglen;
2674 }
2675 if (!lock_user_struct(VERIFY_WRITE, tlg, optval_addr, 0)) {
2676 return -TARGET_EFAULT;
2677 }
2678 __put_user(lg.l_onoff, &tlg->l_onoff);
2679 __put_user(lg.l_linger, &tlg->l_linger);
2680 unlock_user_struct(tlg, optval_addr, 1);
2681 if (put_user_u32(len, optlen)) {
583359a6
AP
2682 return -TARGET_EFAULT;
2683 }
2684 break;
2685 }
f3b974cd
JL
2686 /* Options with 'int' argument. */
2687 case TARGET_SO_DEBUG:
2688 optname = SO_DEBUG;
2689 goto int_case;
2690 case TARGET_SO_REUSEADDR:
2691 optname = SO_REUSEADDR;
2692 goto int_case;
113a9dd7
YS
2693#ifdef SO_REUSEPORT
2694 case TARGET_SO_REUSEPORT:
2695 optname = SO_REUSEPORT;
2696 goto int_case;
2697#endif
f3b974cd
JL
2698 case TARGET_SO_TYPE:
2699 optname = SO_TYPE;
2700 goto int_case;
2701 case TARGET_SO_ERROR:
2702 optname = SO_ERROR;
2703 goto int_case;
2704 case TARGET_SO_DONTROUTE:
2705 optname = SO_DONTROUTE;
2706 goto int_case;
2707 case TARGET_SO_BROADCAST:
2708 optname = SO_BROADCAST;
2709 goto int_case;
2710 case TARGET_SO_SNDBUF:
2711 optname = SO_SNDBUF;
2712 goto int_case;
2713 case TARGET_SO_RCVBUF:
2714 optname = SO_RCVBUF;
2715 goto int_case;
2716 case TARGET_SO_KEEPALIVE:
2717 optname = SO_KEEPALIVE;
2718 goto int_case;
2719 case TARGET_SO_OOBINLINE:
2720 optname = SO_OOBINLINE;
2721 goto int_case;
2722 case TARGET_SO_NO_CHECK:
2723 optname = SO_NO_CHECK;
2724 goto int_case;
2725 case TARGET_SO_PRIORITY:
2726 optname = SO_PRIORITY;
2727 goto int_case;
2728#ifdef SO_BSDCOMPAT
2729 case TARGET_SO_BSDCOMPAT:
2730 optname = SO_BSDCOMPAT;
2731 goto int_case;
2732#endif
2733 case TARGET_SO_PASSCRED:
2734 optname = SO_PASSCRED;
2735 goto int_case;
2736 case TARGET_SO_TIMESTAMP:
2737 optname = SO_TIMESTAMP;
2738 goto int_case;
2739 case TARGET_SO_RCVLOWAT:
2740 optname = SO_RCVLOWAT;
2741 goto int_case;
aec1ca41
PB
2742 case TARGET_SO_ACCEPTCONN:
2743 optname = SO_ACCEPTCONN;
2744 goto int_case;
ec63e06e
JD
2745 case TARGET_SO_PROTOCOL:
2746 optname = SO_PROTOCOL;
2747 goto int_case;
2748 case TARGET_SO_DOMAIN:
2749 optname = SO_DOMAIN;
2750 goto int_case;
8853f86e 2751 default:
2efbe911
FB
2752 goto int_case;
2753 }
2754 break;
2755 case SOL_TCP:
fe51b0a5
SCW
2756 case SOL_UDP:
2757 /* TCP and UDP options all take an 'int' value. */
2efbe911 2758 int_case:
2f619698
FB
2759 if (get_user_u32(len, optlen))
2760 return -TARGET_EFAULT;
2efbe911 2761 if (len < 0)
0da46a6e 2762 return -TARGET_EINVAL;
73160d95 2763 lv = sizeof(lv);
2efbe911
FB
2764 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2765 if (ret < 0)
2766 return ret;
8289d112
PB
2767 if (optname == SO_TYPE) {
2768 val = host_to_target_sock_type(val);
2769 }
2efbe911
FB
2770 if (len > lv)
2771 len = lv;
2f619698
FB
2772 if (len == 4) {
2773 if (put_user_u32(val, optval_addr))
2774 return -TARGET_EFAULT;
2775 } else {
2776 if (put_user_u8(val, optval_addr))
2777 return -TARGET_EFAULT;
f3b974cd 2778 }
2f619698
FB
2779 if (put_user_u32(len, optlen))
2780 return -TARGET_EFAULT;
2efbe911
FB
2781 break;
2782 case SOL_IP:
2783 switch(optname) {
2784 case IP_TOS:
2785 case IP_TTL:
2786 case IP_HDRINCL:
2787 case IP_ROUTER_ALERT:
2788 case IP_RECVOPTS:
2789 case IP_RETOPTS:
2790 case IP_PKTINFO:
2791 case IP_MTU_DISCOVER:
2792 case IP_RECVERR:
2793 case IP_RECVTOS:
2794#ifdef IP_FREEBIND
2795 case IP_FREEBIND:
2796#endif
2797 case IP_MULTICAST_TTL:
2798 case IP_MULTICAST_LOOP:
2f619698
FB
2799 if (get_user_u32(len, optlen))
2800 return -TARGET_EFAULT;
8853f86e 2801 if (len < 0)
0da46a6e 2802 return -TARGET_EINVAL;
73160d95 2803 lv = sizeof(lv);
8853f86e
FB
2804 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2805 if (ret < 0)
2806 return ret;
2efbe911 2807 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2efbe911 2808 len = 1;
2f619698
FB
2809 if (put_user_u32(len, optlen)
2810 || put_user_u8(val, optval_addr))
2811 return -TARGET_EFAULT;
2efbe911 2812 } else {
2efbe911
FB
2813 if (len > sizeof(int))
2814 len = sizeof(int);
2f619698
FB
2815 if (put_user_u32(len, optlen)
2816 || put_user_u32(val, optval_addr))
2817 return -TARGET_EFAULT;
2efbe911 2818 }
8853f86e 2819 break;
2efbe911 2820 default:
c02f499e
TS
2821 ret = -TARGET_ENOPROTOOPT;
2822 break;
8853f86e
FB
2823 }
2824 break;
bd8ed485
TD
2825 case SOL_IPV6:
2826 switch (optname) {
2827 case IPV6_MTU_DISCOVER:
2828 case IPV6_MTU:
2829 case IPV6_V6ONLY:
2830 case IPV6_RECVPKTINFO:
2831 case IPV6_UNICAST_HOPS:
2832 case IPV6_MULTICAST_HOPS:
2833 case IPV6_MULTICAST_LOOP:
2834 case IPV6_RECVERR:
2835 case IPV6_RECVHOPLIMIT:
2836 case IPV6_2292HOPLIMIT:
2837 case IPV6_CHECKSUM:
b9cce6d7
HD
2838 case IPV6_ADDRFORM:
2839 case IPV6_2292PKTINFO:
2840 case IPV6_RECVTCLASS:
2841 case IPV6_RECVRTHDR:
2842 case IPV6_2292RTHDR:
2843 case IPV6_RECVHOPOPTS:
2844 case IPV6_2292HOPOPTS:
2845 case IPV6_RECVDSTOPTS:
2846 case IPV6_2292DSTOPTS:
2847 case IPV6_TCLASS:
22db1213 2848 case IPV6_ADDR_PREFERENCES:
b9cce6d7
HD
2849#ifdef IPV6_RECVPATHMTU
2850 case IPV6_RECVPATHMTU:
2851#endif
2852#ifdef IPV6_TRANSPARENT
2853 case IPV6_TRANSPARENT:
2854#endif
2855#ifdef IPV6_FREEBIND
2856 case IPV6_FREEBIND:
2857#endif
2858#ifdef IPV6_RECVORIGDSTADDR
2859 case IPV6_RECVORIGDSTADDR:
2860#endif
bd8ed485
TD
2861 if (get_user_u32(len, optlen))
2862 return -TARGET_EFAULT;
2863 if (len < 0)
2864 return -TARGET_EINVAL;
2865 lv = sizeof(lv);
2866 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2867 if (ret < 0)
2868 return ret;
2869 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
2870 len = 1;
2871 if (put_user_u32(len, optlen)
2872 || put_user_u8(val, optval_addr))
2873 return -TARGET_EFAULT;
2874 } else {
2875 if (len > sizeof(int))
2876 len = sizeof(int);
2877 if (put_user_u32(len, optlen)
2878 || put_user_u32(val, optval_addr))
2879 return -TARGET_EFAULT;
2880 }
2881 break;
2882 default:
2883 ret = -TARGET_ENOPROTOOPT;
2884 break;
2885 }
2886 break;
a2d86682
JK
2887#ifdef SOL_NETLINK
2888 case SOL_NETLINK:
2889 switch (optname) {
2890 case NETLINK_PKTINFO:
2891 case NETLINK_BROADCAST_ERROR:
2892 case NETLINK_NO_ENOBUFS:
2893#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2894 case NETLINK_LISTEN_ALL_NSID:
2895 case NETLINK_CAP_ACK:
2896#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2897#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0)
2898 case NETLINK_EXT_ACK:
2899#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2900#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
2901 case NETLINK_GET_STRICT_CHK:
2902#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 12, 0) */
2903 if (get_user_u32(len, optlen)) {
2904 return -TARGET_EFAULT;
2905 }
2906 if (len != sizeof(val)) {
2907 return -TARGET_EINVAL;
2908 }
2909 lv = len;
2910 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
2911 if (ret < 0) {
2912 return ret;
2913 }
2914 if (put_user_u32(lv, optlen)
2915 || put_user_u32(val, optval_addr)) {
2916 return -TARGET_EFAULT;
2917 }
2918 break;
2919#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0)
2920 case NETLINK_LIST_MEMBERSHIPS:
2921 {
2922 uint32_t *results;
2923 int i;
2924 if (get_user_u32(len, optlen)) {
2925 return -TARGET_EFAULT;
2926 }
2927 if (len < 0) {
2928 return -TARGET_EINVAL;
2929 }
2930 results = lock_user(VERIFY_WRITE, optval_addr, len, 1);
13e340c8 2931 if (!results && len > 0) {
a2d86682
JK
2932 return -TARGET_EFAULT;
2933 }
2934 lv = len;
2935 ret = get_errno(getsockopt(sockfd, level, optname, results, &lv));
2936 if (ret < 0) {
2937 unlock_user(results, optval_addr, 0);
2938 return ret;
2939 }
2940 /* swap host endianess to target endianess. */
2941 for (i = 0; i < (len / sizeof(uint32_t)); i++) {
2942 results[i] = tswap32(results[i]);
2943 }
2944 if (put_user_u32(lv, optlen)) {
2945 return -TARGET_EFAULT;
2946 }
2947 unlock_user(results, optval_addr, 0);
2948 break;
2949 }
2950#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 2, 0) */
2951 default:
2952 goto unimplemented;
2953 }
c0cb8801 2954 break;
a2d86682 2955#endif /* SOL_NETLINK */
8853f86e
FB
2956 default:
2957 unimplemented:
39be5350
JK
2958 qemu_log_mask(LOG_UNIMP,
2959 "getsockopt level=%d optname=%d not yet supported\n",
2960 level, optname);
c02f499e 2961 ret = -TARGET_EOPNOTSUPP;
8853f86e
FB
2962 break;
2963 }
2964 return ret;
7854b056
FB
2965}
2966
9ac22517
MF
2967/* Convert target low/high pair representing file offset into the host
2968 * low/high pair. This function doesn't handle offsets bigger than 64 bits
2969 * as the kernel doesn't handle them either.
2970 */
2971static void target_to_host_low_high(abi_ulong tlow,
2972 abi_ulong thigh,
2973 unsigned long *hlow,
2974 unsigned long *hhigh)
2975{
2976 uint64_t off = tlow |
2977 ((unsigned long long)thigh << TARGET_LONG_BITS / 2) <<
2978 TARGET_LONG_BITS / 2;
2979
2980 *hlow = off;
2981 *hhigh = (off >> HOST_LONG_BITS / 2) >> HOST_LONG_BITS / 2;
2982}
2983
f287b2c2 2984static struct iovec *lock_iovec(int type, abi_ulong target_addr,
dab32b32 2985 abi_ulong count, int copy)
53a5960a
PB
2986{
2987 struct target_iovec *target_vec;
f287b2c2
RH
2988 struct iovec *vec;
2989 abi_ulong total_len, max_len;
d732dcb4 2990 int i;
501bb4b0 2991 int err = 0;
29560a6c 2992 bool bad_address = false;
53a5960a 2993
f287b2c2
RH
2994 if (count == 0) {
2995 errno = 0;
2996 return NULL;
2997 }
dab32b32 2998 if (count > IOV_MAX) {
f287b2c2
RH
2999 errno = EINVAL;
3000 return NULL;
3001 }
3002
0e173b24 3003 vec = g_try_new0(struct iovec, count);
f287b2c2
RH
3004 if (vec == NULL) {
3005 errno = ENOMEM;
3006 return NULL;
3007 }
3008
3009 target_vec = lock_user(VERIFY_READ, target_addr,
3010 count * sizeof(struct target_iovec), 1);
3011 if (target_vec == NULL) {
501bb4b0 3012 err = EFAULT;
f287b2c2
RH
3013 goto fail2;
3014 }
3015
3016 /* ??? If host page size > target page size, this will result in a
3017 value larger than what we can actually support. */
3018 max_len = 0x7fffffff & TARGET_PAGE_MASK;
3019 total_len = 0;
3020
3021 for (i = 0; i < count; i++) {
3022 abi_ulong base = tswapal(target_vec[i].iov_base);
3023 abi_long len = tswapal(target_vec[i].iov_len);
3024
3025 if (len < 0) {
501bb4b0 3026 err = EINVAL;
f287b2c2
RH
3027 goto fail;
3028 } else if (len == 0) {
3029 /* Zero length pointer is ignored. */
3030 vec[i].iov_base = 0;
41df8411 3031 } else {
f287b2c2 3032 vec[i].iov_base = lock_user(type, base, len, copy);
29560a6c
TM
3033 /* If the first buffer pointer is bad, this is a fault. But
3034 * subsequent bad buffers will result in a partial write; this
3035 * is realized by filling the vector with null pointers and
3036 * zero lengths. */
f287b2c2 3037 if (!vec[i].iov_base) {
29560a6c
TM
3038 if (i == 0) {
3039 err = EFAULT;
3040 goto fail;
3041 } else {
3042 bad_address = true;
3043 }
3044 }
3045 if (bad_address) {
3046 len = 0;
f287b2c2
RH
3047 }
3048 if (len > max_len - total_len) {
3049 len = max_len - total_len;
3050 }
41df8411 3051 }
f287b2c2
RH
3052 vec[i].iov_len = len;
3053 total_len += len;
579a97f7 3054 }
f287b2c2
RH
3055
3056 unlock_user(target_vec, target_addr, 0);
3057 return vec;
3058
3059 fail:
7eff518b
CG
3060 while (--i >= 0) {
3061 if (tswapal(target_vec[i].iov_len) > 0) {
3062 unlock_user(vec[i].iov_base, tswapal(target_vec[i].iov_base), 0);
3063 }
3064 }
f287b2c2 3065 unlock_user(target_vec, target_addr, 0);
501bb4b0 3066 fail2:
0e173b24 3067 g_free(vec);
501bb4b0 3068 errno = err;
f287b2c2 3069 return NULL;
53a5960a
PB
3070}
3071
f287b2c2 3072static void unlock_iovec(struct iovec *vec, abi_ulong target_addr,
dab32b32 3073 abi_ulong count, int copy)
53a5960a
PB
3074{
3075 struct target_iovec *target_vec;
53a5960a
PB
3076 int i;
3077
f287b2c2
RH
3078 target_vec = lock_user(VERIFY_READ, target_addr,
3079 count * sizeof(struct target_iovec), 1);
3080 if (target_vec) {
3081 for (i = 0; i < count; i++) {
3082 abi_ulong base = tswapal(target_vec[i].iov_base);
71ec7cef 3083 abi_long len = tswapal(target_vec[i].iov_len);
f287b2c2
RH
3084 if (len < 0) {
3085 break;
3086 }
d732dcb4
AZ
3087 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
3088 }
f287b2c2 3089 unlock_user(target_vec, target_addr, 0);
53a5960a 3090 }
579a97f7 3091
0e173b24 3092 g_free(vec);
53a5960a
PB
3093}
3094
53d09b76 3095static inline int target_to_host_sock_type(int *type)
3532fa74 3096{
f651e6ae
PJ
3097 int host_type = 0;
3098 int target_type = *type;
3099
3100 switch (target_type & TARGET_SOCK_TYPE_MASK) {
3532fa74 3101 case TARGET_SOCK_DGRAM:
f651e6ae 3102 host_type = SOCK_DGRAM;
3532fa74
FB
3103 break;
3104 case TARGET_SOCK_STREAM:
f651e6ae 3105 host_type = SOCK_STREAM;
3532fa74 3106 break;
f651e6ae
PJ
3107 default:
3108 host_type = target_type & TARGET_SOCK_TYPE_MASK;
3532fa74
FB
3109 break;
3110 }
f651e6ae 3111 if (target_type & TARGET_SOCK_CLOEXEC) {
53d09b76 3112#if defined(SOCK_CLOEXEC)
f651e6ae 3113 host_type |= SOCK_CLOEXEC;
53d09b76
EI
3114#else
3115 return -TARGET_EINVAL;
3116#endif
f651e6ae
PJ
3117 }
3118 if (target_type & TARGET_SOCK_NONBLOCK) {
53d09b76 3119#if defined(SOCK_NONBLOCK)
f651e6ae 3120 host_type |= SOCK_NONBLOCK;
53d09b76
EI
3121#elif !defined(O_NONBLOCK)
3122 return -TARGET_EINVAL;
3123#endif
f651e6ae
PJ
3124 }
3125 *type = host_type;
53d09b76
EI
3126 return 0;
3127}
3128
3129/* Try to emulate socket type flags after socket creation. */
3130static int sock_flags_fixup(int fd, int target_type)
3131{
3132#if !defined(SOCK_NONBLOCK) && defined(O_NONBLOCK)
3133 if (target_type & TARGET_SOCK_NONBLOCK) {
3134 int flags = fcntl(fd, F_GETFL);
3135 if (fcntl(fd, F_SETFL, O_NONBLOCK | flags) == -1) {
3136 close(fd);
3137 return -TARGET_EINVAL;
3138 }
3139 }
3140#endif
3141 return fd;
f651e6ae
PJ
3142}
3143
3144/* do_socket() Must return target values and target errnos. */
3145static abi_long do_socket(int domain, int type, int protocol)
3146{
53d09b76
EI
3147 int target_type = type;
3148 int ret;
3149
3150 ret = target_to_host_sock_type(&type);
3151 if (ret) {
3152 return ret;
3153 }
f651e6ae 3154
575b22b1
LV
3155 if (domain == PF_NETLINK && !(
3156#ifdef CONFIG_RTNETLINK
3157 protocol == NETLINK_ROUTE ||
3158#endif
3159 protocol == NETLINK_KOBJECT_UEVENT ||
3160 protocol == NETLINK_AUDIT)) {
71e2443e 3161 return -TARGET_EPROTONOSUPPORT;
6c5b5645 3162 }
ff626f2d
LV
3163
3164 if (domain == AF_PACKET ||
3165 (domain == AF_INET && type == SOCK_PACKET)) {
3166 protocol = tswap16(protocol);
3167 }
3168
53d09b76
EI
3169 ret = get_errno(socket(domain, type, protocol));
3170 if (ret >= 0) {
3171 ret = sock_flags_fixup(ret, target_type);
0cf22722
LV
3172 if (type == SOCK_PACKET) {
3173 /* Manage an obsolete case :
3174 * if socket type is SOCK_PACKET, bind by name
3175 */
3176 fd_trans_register(ret, &target_packet_trans);
6c5b5645
LV
3177 } else if (domain == PF_NETLINK) {
3178 switch (protocol) {
575b22b1 3179#ifdef CONFIG_RTNETLINK
6c5b5645
LV
3180 case NETLINK_ROUTE:
3181 fd_trans_register(ret, &target_netlink_route_trans);
3182 break;
575b22b1 3183#endif
b265620b
LV
3184 case NETLINK_KOBJECT_UEVENT:
3185 /* nothing to do: messages are strings */
3186 break;
5ce9bb59
LV
3187 case NETLINK_AUDIT:
3188 fd_trans_register(ret, &target_netlink_audit_trans);
3189 break;
6c5b5645
LV
3190 default:
3191 g_assert_not_reached();
3192 }
0cf22722 3193 }
53d09b76
EI
3194 }
3195 return ret;
3532fa74
FB
3196}
3197
0da46a6e 3198/* do_bind() Must return target values and target errnos. */
992f48a0
BS
3199static abi_long do_bind(int sockfd, abi_ulong target_addr,
3200 socklen_t addrlen)
3532fa74 3201{
8f7aeaf6 3202 void *addr;
917507b0 3203 abi_long ret;
8f7aeaf6 3204
38724253 3205 if ((int)addrlen < 0) {
8f7aeaf6 3206 return -TARGET_EINVAL;
38724253 3207 }
8f7aeaf6 3208
607175e0 3209 addr = alloca(addrlen+1);
3b46e624 3210
7b36f782 3211 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3212 if (ret)
3213 return ret;
3214
3532fa74
FB
3215 return get_errno(bind(sockfd, addr, addrlen));
3216}
3217
0da46a6e 3218/* do_connect() Must return target values and target errnos. */
992f48a0
BS
3219static abi_long do_connect(int sockfd, abi_ulong target_addr,
3220 socklen_t addrlen)
3532fa74 3221{
8f7aeaf6 3222 void *addr;
917507b0 3223 abi_long ret;
8f7aeaf6 3224
38724253 3225 if ((int)addrlen < 0) {
8f7aeaf6 3226 return -TARGET_EINVAL;
38724253 3227 }
8f7aeaf6 3228
2dd08dfd 3229 addr = alloca(addrlen+1);
3b46e624 3230
7b36f782 3231 ret = target_to_host_sockaddr(sockfd, addr, target_addr, addrlen);
917507b0
AP
3232 if (ret)
3233 return ret;
3234
2a3c7619 3235 return get_errno(safe_connect(sockfd, addr, addrlen));
3532fa74
FB
3236}
3237
f19e00d7
AG
3238/* do_sendrecvmsg_locked() Must return target values and target errnos. */
3239static abi_long do_sendrecvmsg_locked(int fd, struct target_msghdr *msgp,
3240 int flags, int send)
3532fa74 3241{
6de645c7 3242 abi_long ret, len;
3532fa74 3243 struct msghdr msg;
dab32b32 3244 abi_ulong count;
3532fa74 3245 struct iovec *vec;
992f48a0 3246 abi_ulong target_vec;
3532fa74 3247
3532fa74
FB
3248 if (msgp->msg_name) {
3249 msg.msg_namelen = tswap32(msgp->msg_namelen);
2dd08dfd 3250 msg.msg_name = alloca(msg.msg_namelen+1);
7b36f782
LV
3251 ret = target_to_host_sockaddr(fd, msg.msg_name,
3252 tswapal(msgp->msg_name),
3253 msg.msg_namelen);
26a6fc96
PM
3254 if (ret == -TARGET_EFAULT) {
3255 /* For connected sockets msg_name and msg_namelen must
3256 * be ignored, so returning EFAULT immediately is wrong.
3257 * Instead, pass a bad msg_name to the host kernel, and
3258 * let it decide whether to return EFAULT or not.
3259 */
3260 msg.msg_name = (void *)-1;
3261 } else if (ret) {
f287b2c2 3262 goto out2;
917507b0 3263 }
3532fa74
FB
3264 } else {
3265 msg.msg_name = NULL;
3266 msg.msg_namelen = 0;
3267 }
cbb21eed 3268 msg.msg_controllen = 2 * tswapal(msgp->msg_controllen);
3532fa74 3269 msg.msg_control = alloca(msg.msg_controllen);
1d3d1b23
JS
3270 memset(msg.msg_control, 0, msg.msg_controllen);
3271
3532fa74 3272 msg.msg_flags = tswap32(msgp->msg_flags);
3b46e624 3273
cbb21eed 3274 count = tswapal(msgp->msg_iovlen);
cbb21eed 3275 target_vec = tswapal(msgp->msg_iov);
97b07970
PM
3276
3277 if (count > IOV_MAX) {
3278 /* sendrcvmsg returns a different errno for this condition than
3279 * readv/writev, so we must catch it here before lock_iovec() does.
3280 */
3281 ret = -TARGET_EMSGSIZE;
3282 goto out2;
3283 }
3284
f287b2c2
RH
3285 vec = lock_iovec(send ? VERIFY_READ : VERIFY_WRITE,
3286 target_vec, count, send);
3287 if (vec == NULL) {
3288 ret = -host_to_target_errno(errno);
3289 goto out2;
3290 }
3532fa74
FB
3291 msg.msg_iovlen = count;
3292 msg.msg_iov = vec;
3b46e624 3293
3532fa74 3294 if (send) {
6c5b5645 3295 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3296 void *host_msg;
3297
3298 host_msg = g_malloc(msg.msg_iov->iov_len);
3299 memcpy(host_msg, msg.msg_iov->iov_base, msg.msg_iov->iov_len);
3300 ret = fd_trans_target_to_host_data(fd)(host_msg,
6c5b5645 3301 msg.msg_iov->iov_len);
7d61d892
LV
3302 if (ret >= 0) {
3303 msg.msg_iov->iov_base = host_msg;
3304 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3305 }
3306 g_free(host_msg);
6c5b5645
LV
3307 } else {
3308 ret = target_to_host_cmsg(&msg, msgp);
7d61d892
LV
3309 if (ret == 0) {
3310 ret = get_errno(safe_sendmsg(fd, &msg, flags));
3311 }
6c5b5645 3312 }
3532fa74 3313 } else {
66687530 3314 ret = get_errno(safe_recvmsg(fd, &msg, flags));
6de645c7
AZ
3315 if (!is_error(ret)) {
3316 len = ret;
6c5b5645
LV
3317 if (fd_trans_host_to_target_data(fd)) {
3318 ret = fd_trans_host_to_target_data(fd)(msg.msg_iov->iov_base,
2a03d3e6 3319 MIN(msg.msg_iov->iov_len, len));
6c5b5645
LV
3320 } else {
3321 ret = host_to_target_cmsg(msgp, &msg);
3322 }
ca619067
JH
3323 if (!is_error(ret)) {
3324 msgp->msg_namelen = tswap32(msg.msg_namelen);
24894f39 3325 msgp->msg_flags = tswap32(msg.msg_flags);
26a6fc96 3326 if (msg.msg_name != NULL && msg.msg_name != (void *)-1) {
ca619067
JH
3327 ret = host_to_target_sockaddr(tswapal(msgp->msg_name),
3328 msg.msg_name, msg.msg_namelen);
3329 if (ret) {
3330 goto out;
3331 }
3332 }
3333
6de645c7 3334 ret = len;
ca619067 3335 }
6de645c7 3336 }
3532fa74 3337 }
ca619067
JH
3338
3339out:
3532fa74 3340 unlock_iovec(vec, target_vec, count, !send);
f287b2c2 3341out2:
f19e00d7
AG
3342 return ret;
3343}
3344
3345static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
3346 int flags, int send)
3347{
3348 abi_long ret;
3349 struct target_msghdr *msgp;
3350
3351 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
3352 msgp,
3353 target_msg,
3354 send ? 1 : 0)) {
3355 return -TARGET_EFAULT;
3356 }
3357 ret = do_sendrecvmsg_locked(fd, msgp, flags, send);
579a97f7 3358 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
3532fa74
FB
3359 return ret;
3360}
3361
f19e00d7
AG
3362/* We don't rely on the C library to have sendmmsg/recvmmsg support,
3363 * so it might not have this *mmsg-specific flag either.
3364 */
3365#ifndef MSG_WAITFORONE
3366#define MSG_WAITFORONE 0x10000
3367#endif
3368
3369static abi_long do_sendrecvmmsg(int fd, abi_ulong target_msgvec,
3370 unsigned int vlen, unsigned int flags,
3371 int send)
3372{
3373 struct target_mmsghdr *mmsgp;
3374 abi_long ret = 0;
3375 int i;
3376
3377 if (vlen > UIO_MAXIOV) {
3378 vlen = UIO_MAXIOV;
3379 }
3380
3381 mmsgp = lock_user(VERIFY_WRITE, target_msgvec, sizeof(*mmsgp) * vlen, 1);
3382 if (!mmsgp) {
3383 return -TARGET_EFAULT;
3384 }
3385
3386 for (i = 0; i < vlen; i++) {
3387 ret = do_sendrecvmsg_locked(fd, &mmsgp[i].msg_hdr, flags, send);
3388 if (is_error(ret)) {
3389 break;
3390 }
3391 mmsgp[i].msg_len = tswap32(ret);
3392 /* MSG_WAITFORONE turns on MSG_DONTWAIT after one packet */
3393 if (flags & MSG_WAITFORONE) {
3394 flags |= MSG_DONTWAIT;
3395 }
3396 }
3397
3398 unlock_user(mmsgp, target_msgvec, sizeof(*mmsgp) * i);
3399
3400 /* Return number of datagrams sent if we sent any at all;
3401 * otherwise return the error.
3402 */
3403 if (i) {
3404 return i;
3405 }
3406 return ret;
3407}
f19e00d7 3408
a94b4987
PM
3409/* do_accept4() Must return target values and target errnos. */
3410static abi_long do_accept4(int fd, abi_ulong target_addr,
3411 abi_ulong target_addrlen_addr, int flags)
1be9e1dc 3412{
cd813367 3413 socklen_t addrlen, ret_addrlen;
2f619698 3414 void *addr;
992f48a0 3415 abi_long ret;
d25295d4
PJ
3416 int host_flags;
3417
3418 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
1be9e1dc 3419
a94b4987 3420 if (target_addr == 0) {
ff6dc130 3421 return get_errno(safe_accept4(fd, NULL, NULL, host_flags));
a94b4987 3422 }
917507b0 3423
e554eb4b 3424 /* linux returns EFAULT if addrlen pointer is invalid */
2f619698 3425 if (get_user_u32(addrlen, target_addrlen_addr))
e554eb4b 3426 return -TARGET_EFAULT;
2f619698 3427
38724253 3428 if ((int)addrlen < 0) {
8f7aeaf6 3429 return -TARGET_EINVAL;
38724253 3430 }
8f7aeaf6 3431
c7169b02 3432 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
e554eb4b 3433 return -TARGET_EFAULT;
c7169b02 3434 }
917507b0 3435
2f619698
FB
3436 addr = alloca(addrlen);
3437
cd813367
AS
3438 ret_addrlen = addrlen;
3439 ret = get_errno(safe_accept4(fd, addr, &ret_addrlen, host_flags));
1be9e1dc 3440 if (!is_error(ret)) {
cd813367
AS
3441 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3442 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3443 ret = -TARGET_EFAULT;
cd813367 3444 }
1be9e1dc
PB
3445 }
3446 return ret;
3447}
3448
0da46a6e 3449/* do_getpeername() Must return target values and target errnos. */
992f48a0 3450static abi_long do_getpeername(int fd, abi_ulong target_addr,
2f619698 3451 abi_ulong target_addrlen_addr)
1be9e1dc 3452{
cd813367 3453 socklen_t addrlen, ret_addrlen;
2f619698 3454 void *addr;
992f48a0 3455 abi_long ret;
1be9e1dc 3456
2f619698
FB
3457 if (get_user_u32(addrlen, target_addrlen_addr))
3458 return -TARGET_EFAULT;
3459
38724253 3460 if ((int)addrlen < 0) {
8f7aeaf6 3461 return -TARGET_EINVAL;
38724253 3462 }
8f7aeaf6 3463
c7169b02 3464 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3465 return -TARGET_EFAULT;
c7169b02 3466 }
917507b0 3467
2f619698
FB
3468 addr = alloca(addrlen);
3469
cd813367
AS
3470 ret_addrlen = addrlen;
3471 ret = get_errno(getpeername(fd, addr, &ret_addrlen));
1be9e1dc 3472 if (!is_error(ret)) {
cd813367
AS
3473 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3474 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3475 ret = -TARGET_EFAULT;
cd813367 3476 }
1be9e1dc
PB
3477 }
3478 return ret;
3479}
3480
0da46a6e 3481/* do_getsockname() Must return target values and target errnos. */
992f48a0 3482static abi_long do_getsockname(int fd, abi_ulong target_addr,
2f619698 3483 abi_ulong target_addrlen_addr)
1be9e1dc 3484{
cd813367 3485 socklen_t addrlen, ret_addrlen;
2f619698 3486 void *addr;
992f48a0 3487 abi_long ret;
1be9e1dc 3488
2f619698
FB
3489 if (get_user_u32(addrlen, target_addrlen_addr))
3490 return -TARGET_EFAULT;
3491
38724253 3492 if ((int)addrlen < 0) {
8f7aeaf6 3493 return -TARGET_EINVAL;
38724253 3494 }
8f7aeaf6 3495
c7169b02 3496 if (!access_ok(thread_cpu, VERIFY_WRITE, target_addr, addrlen)) {
917507b0 3497 return -TARGET_EFAULT;
c7169b02 3498 }
917507b0 3499
2f619698
FB
3500 addr = alloca(addrlen);
3501
cd813367
AS
3502 ret_addrlen = addrlen;
3503 ret = get_errno(getsockname(fd, addr, &ret_addrlen));
1be9e1dc 3504 if (!is_error(ret)) {
cd813367
AS
3505 host_to_target_sockaddr(target_addr, addr, MIN(addrlen, ret_addrlen));
3506 if (put_user_u32(ret_addrlen, target_addrlen_addr)) {
2f619698 3507 ret = -TARGET_EFAULT;
cd813367 3508 }
1be9e1dc
PB
3509 }
3510 return ret;
3511}
3512
0da46a6e 3513/* do_socketpair() Must return target values and target errnos. */
992f48a0 3514static abi_long do_socketpair(int domain, int type, int protocol,
2f619698 3515 abi_ulong target_tab_addr)
1be9e1dc
PB
3516{
3517 int tab[2];
992f48a0 3518 abi_long ret;
1be9e1dc 3519
f651e6ae
PJ
3520 target_to_host_sock_type(&type);
3521
1be9e1dc
PB
3522 ret = get_errno(socketpair(domain, type, protocol, tab));
3523 if (!is_error(ret)) {
2f619698
FB
3524 if (put_user_s32(tab[0], target_tab_addr)
3525 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
3526 ret = -TARGET_EFAULT;
1be9e1dc
PB
3527 }
3528 return ret;
3529}
3530
0da46a6e 3531/* do_sendto() Must return target values and target errnos. */
992f48a0
BS
3532static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
3533 abi_ulong target_addr, socklen_t addrlen)
1be9e1dc
PB
3534{
3535 void *addr;
3536 void *host_msg;
7d61d892 3537 void *copy_msg = NULL;
992f48a0 3538 abi_long ret;
1be9e1dc 3539
38724253 3540 if ((int)addrlen < 0) {
8f7aeaf6 3541 return -TARGET_EINVAL;
38724253 3542 }
8f7aeaf6 3543
579a97f7
FB
3544 host_msg = lock_user(VERIFY_READ, msg, len, 1);
3545 if (!host_msg)
3546 return -TARGET_EFAULT;
6c5b5645 3547 if (fd_trans_target_to_host_data(fd)) {
7d61d892
LV
3548 copy_msg = host_msg;
3549 host_msg = g_malloc(len);
3550 memcpy(host_msg, copy_msg, len);
6c5b5645
LV
3551 ret = fd_trans_target_to_host_data(fd)(host_msg, len);
3552 if (ret < 0) {
7d61d892 3553 goto fail;
6c5b5645
LV
3554 }
3555 }
1be9e1dc 3556 if (target_addr) {
2dd08dfd 3557 addr = alloca(addrlen+1);
7b36f782 3558 ret = target_to_host_sockaddr(fd, addr, target_addr, addrlen);
917507b0 3559 if (ret) {
7d61d892 3560 goto fail;
917507b0 3561 }
66687530 3562 ret = get_errno(safe_sendto(fd, host_msg, len, flags, addr, addrlen));
1be9e1dc 3563 } else {
66687530 3564 ret = get_errno(safe_sendto(fd, host_msg, len, flags, NULL, 0));
1be9e1dc 3565 }
7d61d892
LV
3566fail:
3567 if (copy_msg) {
3568 g_free(host_msg);
3569 host_msg = copy_msg;
3570 }
1be9e1dc
PB
3571 unlock_user(host_msg, msg, 0);
3572 return ret;
3573}
3574
0da46a6e 3575/* do_recvfrom() Must return target values and target errnos. */
992f48a0
BS
3576static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
3577 abi_ulong target_addr,
3578 abi_ulong target_addrlen)
1be9e1dc 3579{
cd813367 3580 socklen_t addrlen, ret_addrlen;
1be9e1dc
PB
3581 void *addr;
3582 void *host_msg;
992f48a0 3583 abi_long ret;
1be9e1dc 3584
4a1e6bce
ZR
3585 if (!msg) {
3586 host_msg = NULL;
3587 } else {
3588 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
3589 if (!host_msg) {
3590 return -TARGET_EFAULT;
3591 }
3592 }
1be9e1dc 3593 if (target_addr) {
2f619698
FB
3594 if (get_user_u32(addrlen, target_addrlen)) {
3595 ret = -TARGET_EFAULT;
3596 goto fail;
3597 }
38724253 3598 if ((int)addrlen < 0) {
8f7aeaf6
AJ
3599 ret = -TARGET_EINVAL;
3600 goto fail;
3601 }
1be9e1dc 3602 addr = alloca(addrlen);
cd813367 3603 ret_addrlen = addrlen;
66687530 3604 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags,
cd813367 3605 addr, &ret_addrlen));
1be9e1dc
PB
3606 } else {
3607 addr = NULL; /* To keep compiler quiet. */
cd813367 3608 addrlen = 0; /* To keep compiler quiet. */
66687530 3609 ret = get_errno(safe_recvfrom(fd, host_msg, len, flags, NULL, 0));
1be9e1dc
PB
3610 }
3611 if (!is_error(ret)) {
c35e1f9c 3612 if (fd_trans_host_to_target_data(fd)) {
2a03d3e6
LV
3613 abi_long trans;
3614 trans = fd_trans_host_to_target_data(fd)(host_msg, MIN(ret, len));
3615 if (is_error(trans)) {
3616 ret = trans;
3617 goto fail;
3618 }
c35e1f9c 3619 }
1be9e1dc 3620 if (target_addr) {
cd813367
AS
3621 host_to_target_sockaddr(target_addr, addr,
3622 MIN(addrlen, ret_addrlen));
3623 if (put_user_u32(ret_addrlen, target_addrlen)) {
2f619698
FB
3624 ret = -TARGET_EFAULT;
3625 goto fail;
3626 }
1be9e1dc
PB
3627 }
3628 unlock_user(host_msg, msg, len);
3629 } else {
2f619698 3630fail:
1be9e1dc
PB
3631 unlock_user(host_msg, msg, 0);
3632 }
3633 return ret;
3634}
3635
32407103 3636#ifdef TARGET_NR_socketcall
ff71a454 3637/* do_socketcall() must return target values and target errnos. */
992f48a0 3638static abi_long do_socketcall(int num, abi_ulong vptr)
31e31b8a 3639{
ff71a454
AM
3640 static const unsigned nargs[] = { /* number of arguments per operation */
3641 [TARGET_SYS_SOCKET] = 3, /* domain, type, protocol */
3642 [TARGET_SYS_BIND] = 3, /* fd, addr, addrlen */
3643 [TARGET_SYS_CONNECT] = 3, /* fd, addr, addrlen */
3644 [TARGET_SYS_LISTEN] = 2, /* fd, backlog */
3645 [TARGET_SYS_ACCEPT] = 3, /* fd, addr, addrlen */
3646 [TARGET_SYS_GETSOCKNAME] = 3, /* fd, addr, addrlen */
3647 [TARGET_SYS_GETPEERNAME] = 3, /* fd, addr, addrlen */
3648 [TARGET_SYS_SOCKETPAIR] = 4, /* domain, type, protocol, tab */
3649 [TARGET_SYS_SEND] = 4, /* fd, msg, len, flags */
3650 [TARGET_SYS_RECV] = 4, /* fd, msg, len, flags */
3651 [TARGET_SYS_SENDTO] = 6, /* fd, msg, len, flags, addr, addrlen */
3652 [TARGET_SYS_RECVFROM] = 6, /* fd, msg, len, flags, addr, addrlen */
3653 [TARGET_SYS_SHUTDOWN] = 2, /* fd, how */
3654 [TARGET_SYS_SETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3655 [TARGET_SYS_GETSOCKOPT] = 5, /* fd, level, optname, optval, optlen */
3656 [TARGET_SYS_SENDMSG] = 3, /* fd, msg, flags */
3657 [TARGET_SYS_RECVMSG] = 3, /* fd, msg, flags */
3658 [TARGET_SYS_ACCEPT4] = 4, /* fd, addr, addrlen, flags */
3659 [TARGET_SYS_RECVMMSG] = 4, /* fd, msgvec, vlen, flags */
3660 [TARGET_SYS_SENDMMSG] = 4, /* fd, msgvec, vlen, flags */
62dc90c6
MT
3661 };
3662 abi_long a[6]; /* max 6 args */
ff71a454 3663 unsigned i;
62dc90c6 3664
ff71a454
AM
3665 /* check the range of the first argument num */
3666 /* (TARGET_SYS_SENDMMSG is the highest among TARGET_SYS_xxx) */
3667 if (num < 1 || num > TARGET_SYS_SENDMMSG) {
3668 return -TARGET_EINVAL;
3669 }
3670 /* ensure we have space for args */
3671 if (nargs[num] > ARRAY_SIZE(a)) {
3672 return -TARGET_EINVAL;
3673 }
3674 /* collect the arguments in a[] according to nargs[] */
3675 for (i = 0; i < nargs[num]; ++i) {
3676 if (get_user_ual(a[i], vptr + i * sizeof(abi_long)) != 0) {
3677 return -TARGET_EFAULT;
31e31b8a 3678 }
62dc90c6 3679 }
ff71a454 3680 /* now when we have the args, invoke the appropriate underlying function */
62dc90c6 3681 switch (num) {
ff71a454 3682 case TARGET_SYS_SOCKET: /* domain, type, protocol */
62dc90c6 3683 return do_socket(a[0], a[1], a[2]);
ff71a454 3684 case TARGET_SYS_BIND: /* sockfd, addr, addrlen */
62dc90c6 3685 return do_bind(a[0], a[1], a[2]);
ff71a454 3686 case TARGET_SYS_CONNECT: /* sockfd, addr, addrlen */
62dc90c6 3687 return do_connect(a[0], a[1], a[2]);
ff71a454 3688 case TARGET_SYS_LISTEN: /* sockfd, backlog */
62dc90c6 3689 return get_errno(listen(a[0], a[1]));
ff71a454 3690 case TARGET_SYS_ACCEPT: /* sockfd, addr, addrlen */
62dc90c6 3691 return do_accept4(a[0], a[1], a[2], 0);
ff71a454 3692 case TARGET_SYS_GETSOCKNAME: /* sockfd, addr, addrlen */
62dc90c6 3693 return do_getsockname(a[0], a[1], a[2]);
ff71a454 3694 case TARGET_SYS_GETPEERNAME: /* sockfd, addr, addrlen */
62dc90c6 3695 return do_getpeername(a[0], a[1], a[2]);
ff71a454 3696 case TARGET_SYS_SOCKETPAIR: /* domain, type, protocol, tab */
62dc90c6 3697 return do_socketpair(a[0], a[1], a[2], a[3]);
ff71a454 3698 case TARGET_SYS_SEND: /* sockfd, msg, len, flags */
62dc90c6 3699 return do_sendto(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3700 case TARGET_SYS_RECV: /* sockfd, msg, len, flags */
62dc90c6 3701 return do_recvfrom(a[0], a[1], a[2], a[3], 0, 0);
ff71a454 3702 case TARGET_SYS_SENDTO: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3703 return do_sendto(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3704 case TARGET_SYS_RECVFROM: /* sockfd, msg, len, flags, addr, addrlen */
62dc90c6 3705 return do_recvfrom(a[0], a[1], a[2], a[3], a[4], a[5]);
ff71a454 3706 case TARGET_SYS_SHUTDOWN: /* sockfd, how */
62dc90c6 3707 return get_errno(shutdown(a[0], a[1]));
ff71a454
AM
3708 case TARGET_SYS_SETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3709 return do_setsockopt(a[0], a[1], a[2], a[3], a[4]);
3710 case TARGET_SYS_GETSOCKOPT: /* sockfd, level, optname, optval, optlen */
3711 return do_getsockopt(a[0], a[1], a[2], a[3], a[4]);
3712 case TARGET_SYS_SENDMSG: /* sockfd, msg, flags */
62dc90c6 3713 return do_sendrecvmsg(a[0], a[1], a[2], 1);
ff71a454 3714 case TARGET_SYS_RECVMSG: /* sockfd, msg, flags */
62dc90c6 3715 return do_sendrecvmsg(a[0], a[1], a[2], 0);
ff71a454
AM
3716 case TARGET_SYS_ACCEPT4: /* sockfd, addr, addrlen, flags */
3717 return do_accept4(a[0], a[1], a[2], a[3]);
3718 case TARGET_SYS_RECVMMSG: /* sockfd, msgvec, vlen, flags */
5a53dc50 3719 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 0);
ff71a454
AM
3720 case TARGET_SYS_SENDMMSG: /* sockfd, msgvec, vlen, flags */
3721 return do_sendrecvmmsg(a[0], a[1], a[2], a[3], 1);
31e31b8a 3722 default:
39be5350 3723 qemu_log_mask(LOG_UNIMP, "Unsupported socketcall: %d\n", num);
ff71a454 3724 return -TARGET_EINVAL;
31e31b8a 3725 }
31e31b8a 3726}
32407103 3727#endif
31e31b8a 3728
8853f86e
FB
3729#define N_SHM_REGIONS 32
3730
3731static struct shm_region {
b6e17875
PM
3732 abi_ulong start;
3733 abi_ulong size;
3734 bool in_use;
8853f86e
FB
3735} shm_regions[N_SHM_REGIONS];
3736
005eb2ae
PM
3737#ifndef TARGET_SEMID64_DS
3738/* asm-generic version of this struct */
3739struct target_semid64_ds
3eb6b044
TS
3740{
3741 struct target_ipc_perm sem_perm;
992f48a0 3742 abi_ulong sem_otime;
005eb2ae 3743#if TARGET_ABI_BITS == 32
992f48a0 3744 abi_ulong __unused1;
03527344 3745#endif
992f48a0 3746 abi_ulong sem_ctime;
005eb2ae 3747#if TARGET_ABI_BITS == 32
992f48a0 3748 abi_ulong __unused2;
03527344 3749#endif
992f48a0
BS
3750 abi_ulong sem_nsems;
3751 abi_ulong __unused3;
3752 abi_ulong __unused4;
3eb6b044 3753};
005eb2ae 3754#endif
3eb6b044 3755
579a97f7
FB
3756static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
3757 abi_ulong target_addr)
3eb6b044
TS
3758{
3759 struct target_ipc_perm *target_ip;
005eb2ae 3760 struct target_semid64_ds *target_sd;
3eb6b044 3761
579a97f7
FB
3762 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3763 return -TARGET_EFAULT;
e8bbe36c 3764 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3765 host_ip->__key = tswap32(target_ip->__key);
3766 host_ip->uid = tswap32(target_ip->uid);
3767 host_ip->gid = tswap32(target_ip->gid);
3768 host_ip->cuid = tswap32(target_ip->cuid);
3769 host_ip->cgid = tswap32(target_ip->cgid);
3770#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3771 host_ip->mode = tswap32(target_ip->mode);
3772#else
cbb21eed 3773 host_ip->mode = tswap16(target_ip->mode);
55a2b163
PJ
3774#endif
3775#if defined(TARGET_PPC)
3776 host_ip->__seq = tswap32(target_ip->__seq);
3777#else
3778 host_ip->__seq = tswap16(target_ip->__seq);
3779#endif
3eb6b044 3780 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3781 return 0;
3eb6b044
TS
3782}
3783
579a97f7
FB
3784static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
3785 struct ipc_perm *host_ip)
3eb6b044
TS
3786{
3787 struct target_ipc_perm *target_ip;
005eb2ae 3788 struct target_semid64_ds *target_sd;
3eb6b044 3789
579a97f7
FB
3790 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3791 return -TARGET_EFAULT;
3eb6b044 3792 target_ip = &(target_sd->sem_perm);
55a2b163
PJ
3793 target_ip->__key = tswap32(host_ip->__key);
3794 target_ip->uid = tswap32(host_ip->uid);
3795 target_ip->gid = tswap32(host_ip->gid);
3796 target_ip->cuid = tswap32(host_ip->cuid);
3797 target_ip->cgid = tswap32(host_ip->cgid);
3798#if defined(TARGET_ALPHA) || defined(TARGET_MIPS) || defined(TARGET_PPC)
3799 target_ip->mode = tswap32(host_ip->mode);
3800#else
cbb21eed 3801 target_ip->mode = tswap16(host_ip->mode);
55a2b163
PJ
3802#endif
3803#if defined(TARGET_PPC)
3804 target_ip->__seq = tswap32(host_ip->__seq);
3805#else
3806 target_ip->__seq = tswap16(host_ip->__seq);
3807#endif
3eb6b044 3808 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3809 return 0;
3eb6b044
TS
3810}
3811
579a97f7
FB
3812static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
3813 abi_ulong target_addr)
3eb6b044 3814{
005eb2ae 3815 struct target_semid64_ds *target_sd;
3eb6b044 3816
579a97f7
FB
3817 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
3818 return -TARGET_EFAULT;
e5289087
AJ
3819 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
3820 return -TARGET_EFAULT;
cbb21eed
MB
3821 host_sd->sem_nsems = tswapal(target_sd->sem_nsems);
3822 host_sd->sem_otime = tswapal(target_sd->sem_otime);
3823 host_sd->sem_ctime = tswapal(target_sd->sem_ctime);
3eb6b044 3824 unlock_user_struct(target_sd, target_addr, 0);
579a97f7 3825 return 0;
3eb6b044
TS
3826}
3827
579a97f7
FB
3828static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
3829 struct semid_ds *host_sd)
3eb6b044 3830{
005eb2ae 3831 struct target_semid64_ds *target_sd;
3eb6b044 3832
579a97f7
FB
3833 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
3834 return -TARGET_EFAULT;
e5289087 3835 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
3a93113a 3836 return -TARGET_EFAULT;
cbb21eed
MB
3837 target_sd->sem_nsems = tswapal(host_sd->sem_nsems);
3838 target_sd->sem_otime = tswapal(host_sd->sem_otime);
3839 target_sd->sem_ctime = tswapal(host_sd->sem_ctime);
3eb6b044 3840 unlock_user_struct(target_sd, target_addr, 1);
579a97f7 3841 return 0;
3eb6b044
TS
3842}
3843
e5289087
AJ
3844struct target_seminfo {
3845 int semmap;
3846 int semmni;
3847 int semmns;
3848 int semmnu;
3849 int semmsl;
3850 int semopm;
3851 int semume;
3852 int semusz;
3853 int semvmx;
3854 int semaem;
3855};
3856
3857static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
3858 struct seminfo *host_seminfo)
3859{
3860 struct target_seminfo *target_seminfo;
3861 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
3862 return -TARGET_EFAULT;
3863 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
3864 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
3865 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
3866 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
3867 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
3868 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
3869 __put_user(host_seminfo->semume, &target_seminfo->semume);
3870 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
3871 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
3872 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
3873 unlock_user_struct(target_seminfo, target_addr, 1);
3874 return 0;
3875}
3876
fa294816
TS
3877union semun {
3878 int val;
3eb6b044 3879 struct semid_ds *buf;
fa294816 3880 unsigned short *array;
e5289087 3881 struct seminfo *__buf;
fa294816
TS
3882};
3883
3eb6b044
TS
3884union target_semun {
3885 int val;
e5289087
AJ
3886 abi_ulong buf;
3887 abi_ulong array;
3888 abi_ulong __buf;
3eb6b044
TS
3889};
3890
e5289087
AJ
3891static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
3892 abi_ulong target_addr)
3eb6b044 3893{
e5289087
AJ
3894 int nsems;
3895 unsigned short *array;
3896 union semun semun;
3897 struct semid_ds semid_ds;
3898 int i, ret;
3eb6b044 3899
e5289087
AJ
3900 semun.buf = &semid_ds;
3901
3902 ret = semctl(semid, 0, IPC_STAT, semun);
3903 if (ret == -1)
3904 return get_errno(ret);
3905
3906 nsems = semid_ds.sem_nsems;
3907
0e173b24 3908 *host_array = g_try_new(unsigned short, nsems);
69d4c703
PM
3909 if (!*host_array) {
3910 return -TARGET_ENOMEM;
3911 }
e5289087
AJ
3912 array = lock_user(VERIFY_READ, target_addr,
3913 nsems*sizeof(unsigned short), 1);
69d4c703 3914 if (!array) {
0e173b24 3915 g_free(*host_array);
e5289087 3916 return -TARGET_EFAULT;
69d4c703 3917 }
e5289087
AJ
3918
3919 for(i=0; i<nsems; i++) {
3920 __get_user((*host_array)[i], &array[i]);
3eb6b044 3921 }
e5289087
AJ
3922 unlock_user(array, target_addr, 0);
3923
579a97f7 3924 return 0;
3eb6b044
TS
3925}
3926
e5289087
AJ
3927static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
3928 unsigned short **host_array)
3eb6b044 3929{
e5289087
AJ
3930 int nsems;
3931 unsigned short *array;
3932 union semun semun;
3933 struct semid_ds semid_ds;
3934 int i, ret;
3eb6b044 3935
e5289087
AJ
3936 semun.buf = &semid_ds;
3937
3938 ret = semctl(semid, 0, IPC_STAT, semun);
3939 if (ret == -1)
3940 return get_errno(ret);
3941
3942 nsems = semid_ds.sem_nsems;
3943
3944 array = lock_user(VERIFY_WRITE, target_addr,
3945 nsems*sizeof(unsigned short), 0);
3946 if (!array)
3947 return -TARGET_EFAULT;
3948
3949 for(i=0; i<nsems; i++) {
3950 __put_user((*host_array)[i], &array[i]);
3eb6b044 3951 }
0e173b24 3952 g_free(*host_array);
e5289087
AJ
3953 unlock_user(array, target_addr, 1);
3954
579a97f7 3955 return 0;
3eb6b044
TS
3956}
3957
e5289087 3958static inline abi_long do_semctl(int semid, int semnum, int cmd,
d1c002b6 3959 abi_ulong target_arg)
3eb6b044 3960{
d1c002b6 3961 union target_semun target_su = { .buf = target_arg };
3eb6b044
TS
3962 union semun arg;
3963 struct semid_ds dsarg;
7b8118e8 3964 unsigned short *array = NULL;
e5289087
AJ
3965 struct seminfo seminfo;
3966 abi_long ret = -TARGET_EINVAL;
3967 abi_long err;
3968 cmd &= 0xff;
3eb6b044
TS
3969
3970 switch( cmd ) {
3971 case GETVAL:
3eb6b044 3972 case SETVAL:
5464baec
TM
3973 /* In 64 bit cross-endian situations, we will erroneously pick up
3974 * the wrong half of the union for the "val" element. To rectify
3975 * this, the entire 8-byte structure is byteswapped, followed by
3976 * a swap of the 4 byte val field. In other cases, the data is
3977 * already in proper host byte order. */
3978 if (sizeof(target_su.val) != (sizeof(target_su.buf))) {
3979 target_su.buf = tswapal(target_su.buf);
3980 arg.val = tswap32(target_su.val);
3981 } else {
3982 arg.val = target_su.val;
3983 }
e5289087 3984 ret = get_errno(semctl(semid, semnum, cmd, arg));
3eb6b044
TS
3985 break;
3986 case GETALL:
3eb6b044 3987 case SETALL:
e5289087
AJ
3988 err = target_to_host_semarray(semid, &array, target_su.array);
3989 if (err)
3990 return err;
3991 arg.array = array;
3992 ret = get_errno(semctl(semid, semnum, cmd, arg));
3993 err = host_to_target_semarray(semid, target_su.array, &array);
3994 if (err)
3995 return err;
3eb6b044
TS
3996 break;
3997 case IPC_STAT:
3eb6b044 3998 case IPC_SET:
e5289087
AJ
3999 case SEM_STAT:
4000 err = target_to_host_semid_ds(&dsarg, target_su.buf);
4001 if (err)
4002 return err;
4003 arg.buf = &dsarg;
4004 ret = get_errno(semctl(semid, semnum, cmd, arg));
4005 err = host_to_target_semid_ds(target_su.buf, &dsarg);
4006 if (err)
4007 return err;
4008 break;
4009 case IPC_INFO:
4010 case SEM_INFO:
4011 arg.__buf = &seminfo;
4012 ret = get_errno(semctl(semid, semnum, cmd, arg));
4013 err = host_to_target_seminfo(target_su.__buf, &seminfo);
4014 if (err)
4015 return err;
4016 break;
4017 case IPC_RMID:
4018 case GETPID:
4019 case GETNCNT:
4020 case GETZCNT:
4021 ret = get_errno(semctl(semid, semnum, cmd, NULL));
3eb6b044 4022 break;
3eb6b044
TS
4023 }
4024
4025 return ret;
4026}
4027
e5289087
AJ
4028struct target_sembuf {
4029 unsigned short sem_num;
4030 short sem_op;
4031 short sem_flg;
4032};
4033
4034static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
4035 abi_ulong target_addr,
4036 unsigned nsops)
4037{
4038 struct target_sembuf *target_sembuf;
4039 int i;
4040
4041 target_sembuf = lock_user(VERIFY_READ, target_addr,
4042 nsops*sizeof(struct target_sembuf), 1);
4043 if (!target_sembuf)
4044 return -TARGET_EFAULT;
4045
4046 for(i=0; i<nsops; i++) {
4047 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
4048 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
4049 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
4050 }
4051
4052 unlock_user(target_sembuf, target_addr, 0);
4053
4054 return 0;
4055}
4056
d8c08b1e 4057#if defined(TARGET_NR_ipc) || defined(TARGET_NR_semop) || \
cac46eb0 4058 defined(TARGET_NR_semtimedop) || defined(TARGET_NR_semtimedop_time64)
d8c08b1e
MK
4059
4060/*
4061 * This macro is required to handle the s390 variants, which passes the
4062 * arguments in a different order than default.
4063 */
4064#ifdef __s390x__
4065#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4066 (__nsops), (__timeout), (__sops)
4067#else
4068#define SEMTIMEDOP_IPC_ARGS(__nsops, __sops, __timeout) \
4069 (__nsops), 0, (__sops), (__timeout)
4070#endif
4071
4072static inline abi_long do_semtimedop(int semid,
4073 abi_long ptr,
4074 unsigned nsops,
cac46eb0 4075 abi_long timeout, bool time64)
e5289087 4076{
0a7ec849 4077 struct sembuf *sops;
d8c08b1e 4078 struct timespec ts, *pts = NULL;
524fa340 4079 abi_long ret;
e5289087 4080
d8c08b1e
MK
4081 if (timeout) {
4082 pts = &ts;
cac46eb0
FB
4083 if (time64) {
4084 if (target_to_host_timespec64(pts, timeout)) {
4085 return -TARGET_EFAULT;
4086 }
4087 } else {
4088 if (target_to_host_timespec(pts, timeout)) {
4089 return -TARGET_EFAULT;
4090 }
d8c08b1e
MK
4091 }
4092 }
4093
0a7ec849
FB
4094 if (nsops > TARGET_SEMOPM) {
4095 return -TARGET_E2BIG;
4096 }
4097
4098 sops = g_new(struct sembuf, nsops);
4099
4100 if (target_to_host_sembuf(sops, ptr, nsops)) {
4101 g_free(sops);
e5289087 4102 return -TARGET_EFAULT;
0a7ec849 4103 }
e5289087 4104
524fa340
LV
4105 ret = -TARGET_ENOSYS;
4106#ifdef __NR_semtimedop
d8c08b1e 4107 ret = get_errno(safe_semtimedop(semid, sops, nsops, pts));
524fa340
LV
4108#endif
4109#ifdef __NR_ipc
4110 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4111 ret = get_errno(safe_ipc(IPCOP_semtimedop, semid,
4112 SEMTIMEDOP_IPC_ARGS(nsops, sops, (long)pts)));
524fa340
LV
4113 }
4114#endif
0a7ec849 4115 g_free(sops);
524fa340 4116 return ret;
e5289087 4117}
d8c08b1e 4118#endif
e5289087 4119
1bc012f6
TS
4120struct target_msqid_ds
4121{
1c54ff97
AJ
4122 struct target_ipc_perm msg_perm;
4123 abi_ulong msg_stime;
4124#if TARGET_ABI_BITS == 32
4125 abi_ulong __unused1;
4126#endif
4127 abi_ulong msg_rtime;
4128#if TARGET_ABI_BITS == 32
4129 abi_ulong __unused2;
4130#endif
4131 abi_ulong msg_ctime;
4132#if TARGET_ABI_BITS == 32
4133 abi_ulong __unused3;
4134#endif
4135 abi_ulong __msg_cbytes;
4136 abi_ulong msg_qnum;
4137 abi_ulong msg_qbytes;
4138 abi_ulong msg_lspid;
4139 abi_ulong msg_lrpid;
4140 abi_ulong __unused4;
4141 abi_ulong __unused5;
1bc012f6
TS
4142};
4143
579a97f7
FB
4144static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
4145 abi_ulong target_addr)
1bc012f6
TS
4146{
4147 struct target_msqid_ds *target_md;
4148
579a97f7
FB
4149 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
4150 return -TARGET_EFAULT;
1c54ff97
AJ
4151 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
4152 return -TARGET_EFAULT;
cbb21eed
MB
4153 host_md->msg_stime = tswapal(target_md->msg_stime);
4154 host_md->msg_rtime = tswapal(target_md->msg_rtime);
4155 host_md->msg_ctime = tswapal(target_md->msg_ctime);
4156 host_md->__msg_cbytes = tswapal(target_md->__msg_cbytes);
4157 host_md->msg_qnum = tswapal(target_md->msg_qnum);
4158 host_md->msg_qbytes = tswapal(target_md->msg_qbytes);
4159 host_md->msg_lspid = tswapal(target_md->msg_lspid);
4160 host_md->msg_lrpid = tswapal(target_md->msg_lrpid);
1bc012f6 4161 unlock_user_struct(target_md, target_addr, 0);
579a97f7 4162 return 0;
1bc012f6
TS
4163}
4164
579a97f7
FB
4165static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
4166 struct msqid_ds *host_md)
1bc012f6
TS
4167{
4168 struct target_msqid_ds *target_md;
4169
579a97f7
FB
4170 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
4171 return -TARGET_EFAULT;
1c54ff97
AJ
4172 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
4173 return -TARGET_EFAULT;
cbb21eed
MB
4174 target_md->msg_stime = tswapal(host_md->msg_stime);
4175 target_md->msg_rtime = tswapal(host_md->msg_rtime);
4176 target_md->msg_ctime = tswapal(host_md->msg_ctime);
4177 target_md->__msg_cbytes = tswapal(host_md->__msg_cbytes);
4178 target_md->msg_qnum = tswapal(host_md->msg_qnum);
4179 target_md->msg_qbytes = tswapal(host_md->msg_qbytes);
4180 target_md->msg_lspid = tswapal(host_md->msg_lspid);
4181 target_md->msg_lrpid = tswapal(host_md->msg_lrpid);
1bc012f6 4182 unlock_user_struct(target_md, target_addr, 1);
579a97f7 4183 return 0;
1bc012f6
TS
4184}
4185
1c54ff97
AJ
4186struct target_msginfo {
4187 int msgpool;
4188 int msgmap;
4189 int msgmax;
4190 int msgmnb;
4191 int msgmni;
4192 int msgssz;
4193 int msgtql;
4194 unsigned short int msgseg;
4195};
4196
4197static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
4198 struct msginfo *host_msginfo)
4199{
4200 struct target_msginfo *target_msginfo;
4201 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
4202 return -TARGET_EFAULT;
4203 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
4204 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
4205 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
4206 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
4207 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
4208 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
4209 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
4210 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
4211 unlock_user_struct(target_msginfo, target_addr, 1);
00b229ac 4212 return 0;
1c54ff97
AJ
4213}
4214
4215static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
1bc012f6
TS
4216{
4217 struct msqid_ds dsarg;
1c54ff97
AJ
4218 struct msginfo msginfo;
4219 abi_long ret = -TARGET_EINVAL;
4220
4221 cmd &= 0xff;
4222
4223 switch (cmd) {
1bc012f6
TS
4224 case IPC_STAT:
4225 case IPC_SET:
1c54ff97
AJ
4226 case MSG_STAT:
4227 if (target_to_host_msqid_ds(&dsarg,ptr))
4228 return -TARGET_EFAULT;
4229 ret = get_errno(msgctl(msgid, cmd, &dsarg));
4230 if (host_to_target_msqid_ds(ptr,&dsarg))
4231 return -TARGET_EFAULT;
4232 break;
4233 case IPC_RMID:
4234 ret = get_errno(msgctl(msgid, cmd, NULL));
4235 break;
4236 case IPC_INFO:
4237 case MSG_INFO:
4238 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
4239 if (host_to_target_msginfo(ptr, &msginfo))
4240 return -TARGET_EFAULT;
4241 break;
1bc012f6 4242 }
1c54ff97 4243
1bc012f6
TS
4244 return ret;
4245}
4246
4247struct target_msgbuf {
1c54ff97
AJ
4248 abi_long mtype;
4249 char mtext[1];
1bc012f6
TS
4250};
4251
992f48a0 4252static inline abi_long do_msgsnd(int msqid, abi_long msgp,
edcc5f9d 4253 ssize_t msgsz, int msgflg)
1bc012f6
TS
4254{
4255 struct target_msgbuf *target_mb;
4256 struct msgbuf *host_mb;
992f48a0 4257 abi_long ret = 0;
1bc012f6 4258
edcc5f9d
TM
4259 if (msgsz < 0) {
4260 return -TARGET_EINVAL;
4261 }
4262
579a97f7
FB
4263 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
4264 return -TARGET_EFAULT;
0e173b24 4265 host_mb = g_try_malloc(msgsz + sizeof(long));
29e03fcb
HZ
4266 if (!host_mb) {
4267 unlock_user_struct(target_mb, msgp, 0);
4268 return -TARGET_ENOMEM;
4269 }
cbb21eed 4270 host_mb->mtype = (abi_long) tswapal(target_mb->mtype);
1c54ff97 4271 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
524fa340
LV
4272 ret = -TARGET_ENOSYS;
4273#ifdef __NR_msgsnd
89f9fe44 4274 ret = get_errno(safe_msgsnd(msqid, host_mb, msgsz, msgflg));
524fa340
LV
4275#endif
4276#ifdef __NR_ipc
4277 if (ret == -TARGET_ENOSYS) {
d8c08b1e
MK
4278#ifdef __s390x__
4279 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4280 host_mb));
4281#else
524fa340
LV
4282 ret = get_errno(safe_ipc(IPCOP_msgsnd, msqid, msgsz, msgflg,
4283 host_mb, 0));
d8c08b1e 4284#endif
524fa340
LV
4285 }
4286#endif
0e173b24 4287 g_free(host_mb);
1bc012f6
TS
4288 unlock_user_struct(target_mb, msgp, 0);
4289
4290 return ret;
4291}
4292
d8c08b1e
MK
4293#ifdef __NR_ipc
4294#if defined(__sparc__)
4295/* SPARC for msgrcv it does not use the kludge on final 2 arguments. */
4296#define MSGRCV_ARGS(__msgp, __msgtyp) __msgp, __msgtyp
4297#elif defined(__s390x__)
4298/* The s390 sys_ipc variant has only five parameters. */
4299#define MSGRCV_ARGS(__msgp, __msgtyp) \
4300 ((long int[]){(long int)__msgp, __msgtyp})
4301#else
4302#define MSGRCV_ARGS(__msgp, __msgtyp) \
4303 ((long int[]){(long int)__msgp, __msgtyp}), 0
4304#endif
4305#endif
4306
992f48a0 4307static inline abi_long do_msgrcv(int msqid, abi_long msgp,
99874f65 4308 ssize_t msgsz, abi_long msgtyp,
992f48a0 4309 int msgflg)
1bc012f6
TS
4310{
4311 struct target_msgbuf *target_mb;
579a97f7 4312 char *target_mtext;
1bc012f6 4313 struct msgbuf *host_mb;
992f48a0 4314 abi_long ret = 0;
1bc012f6 4315
99874f65
PM
4316 if (msgsz < 0) {
4317 return -TARGET_EINVAL;
4318 }
4319
579a97f7
FB
4320 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
4321 return -TARGET_EFAULT;
1c54ff97 4322
415d8471
PM
4323 host_mb = g_try_malloc(msgsz + sizeof(long));
4324 if (!host_mb) {
4325 ret = -TARGET_ENOMEM;
4326 goto end;
4327 }
524fa340
LV
4328 ret = -TARGET_ENOSYS;
4329#ifdef __NR_msgrcv
89f9fe44 4330 ret = get_errno(safe_msgrcv(msqid, host_mb, msgsz, msgtyp, msgflg));
524fa340
LV
4331#endif
4332#ifdef __NR_ipc
4333 if (ret == -TARGET_ENOSYS) {
4334 ret = get_errno(safe_ipc(IPCOP_CALL(1, IPCOP_msgrcv), msqid, msgsz,
d8c08b1e 4335 msgflg, MSGRCV_ARGS(host_mb, msgtyp)));
524fa340
LV
4336 }
4337#endif
1c54ff97 4338
579a97f7
FB
4339 if (ret > 0) {
4340 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
4341 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
4342 if (!target_mtext) {
4343 ret = -TARGET_EFAULT;
4344 goto end;
4345 }
1c54ff97 4346 memcpy(target_mb->mtext, host_mb->mtext, ret);
579a97f7
FB
4347 unlock_user(target_mtext, target_mtext_addr, ret);
4348 }
1c54ff97 4349
cbb21eed 4350 target_mb->mtype = tswapal(host_mb->mtype);
1bc012f6 4351
579a97f7
FB
4352end:
4353 if (target_mb)
4354 unlock_user_struct(target_mb, msgp, 1);
0d07fe47 4355 g_free(host_mb);
1bc012f6
TS
4356 return ret;
4357}
4358
88a8c984
RV
4359static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
4360 abi_ulong target_addr)
4361{
4362 struct target_shmid_ds *target_sd;
4363
4364 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
4365 return -TARGET_EFAULT;
4366 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
4367 return -TARGET_EFAULT;
4368 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4369 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
4370 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4371 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4372 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4373 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4374 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4375 unlock_user_struct(target_sd, target_addr, 0);
4376 return 0;
4377}
4378
4379static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
4380 struct shmid_ds *host_sd)
4381{
4382 struct target_shmid_ds *target_sd;
4383
4384 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
4385 return -TARGET_EFAULT;
4386 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
4387 return -TARGET_EFAULT;
4388 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
4389 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
4390 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
4391 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
4392 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
4393 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
4394 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
4395 unlock_user_struct(target_sd, target_addr, 1);
4396 return 0;
4397}
4398
4399struct target_shminfo {
4400 abi_ulong shmmax;
4401 abi_ulong shmmin;
4402 abi_ulong shmmni;
4403 abi_ulong shmseg;
4404 abi_ulong shmall;
4405};
4406
4407static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
4408 struct shminfo *host_shminfo)
4409{
4410 struct target_shminfo *target_shminfo;
4411 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
4412 return -TARGET_EFAULT;
4413 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
4414 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
4415 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
4416 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
4417 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
4418 unlock_user_struct(target_shminfo, target_addr, 1);
4419 return 0;
4420}
4421
4422struct target_shm_info {
4423 int used_ids;
4424 abi_ulong shm_tot;
4425 abi_ulong shm_rss;
4426 abi_ulong shm_swp;
4427 abi_ulong swap_attempts;
4428 abi_ulong swap_successes;
4429};
4430
4431static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
4432 struct shm_info *host_shm_info)
4433{
4434 struct target_shm_info *target_shm_info;
4435 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
4436 return -TARGET_EFAULT;
4437 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
4438 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
4439 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
4440 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
4441 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
4442 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
4443 unlock_user_struct(target_shm_info, target_addr, 1);
4444 return 0;
4445}
4446
4447static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
4448{
4449 struct shmid_ds dsarg;
4450 struct shminfo shminfo;
4451 struct shm_info shm_info;
4452 abi_long ret = -TARGET_EINVAL;
4453
4454 cmd &= 0xff;
4455
4456 switch(cmd) {
4457 case IPC_STAT:
4458 case IPC_SET:
4459 case SHM_STAT:
4460 if (target_to_host_shmid_ds(&dsarg, buf))
4461 return -TARGET_EFAULT;
4462 ret = get_errno(shmctl(shmid, cmd, &dsarg));
4463 if (host_to_target_shmid_ds(buf, &dsarg))
4464 return -TARGET_EFAULT;
4465 break;
4466 case IPC_INFO:
4467 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
4468 if (host_to_target_shminfo(buf, &shminfo))
4469 return -TARGET_EFAULT;
4470 break;
4471 case SHM_INFO:
4472 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
4473 if (host_to_target_shm_info(buf, &shm_info))
4474 return -TARGET_EFAULT;
4475 break;
4476 case IPC_RMID:
4477 case SHM_LOCK:
4478 case SHM_UNLOCK:
4479 ret = get_errno(shmctl(shmid, cmd, NULL));
4480 break;
4481 }
4482
4483 return ret;
4484}
4485
ee8e7614
PM
4486#ifndef TARGET_FORCE_SHMLBA
4487/* For most architectures, SHMLBA is the same as the page size;
4488 * some architectures have larger values, in which case they should
4489 * define TARGET_FORCE_SHMLBA and provide a target_shmlba() function.
4490 * This corresponds to the kernel arch code defining __ARCH_FORCE_SHMLBA
4491 * and defining its own value for SHMLBA.
4492 *
4493 * The kernel also permits SHMLBA to be set by the architecture to a
4494 * value larger than the page size without setting __ARCH_FORCE_SHMLBA;
4495 * this means that addresses are rounded to the large size if
4496 * SHM_RND is set but addresses not aligned to that size are not rejected
4497 * as long as they are at least page-aligned. Since the only architecture
4498 * which uses this is ia64 this code doesn't provide for that oddity.
4499 */
4500static inline abi_ulong target_shmlba(CPUArchState *cpu_env)
4501{
4502 return TARGET_PAGE_SIZE;
4503}
4504#endif
4505
4506static inline abi_ulong do_shmat(CPUArchState *cpu_env,
4507 int shmid, abi_ulong shmaddr, int shmflg)
88a8c984 4508{
228168cb 4509 CPUState *cpu = env_cpu(cpu_env);
88a8c984
RV
4510 abi_long raddr;
4511 void *host_raddr;
4512 struct shmid_ds shm_info;
4513 int i,ret;
ee8e7614 4514 abi_ulong shmlba;
88a8c984 4515
ee1bf83d
RH
4516 /* shmat pointers are always untagged */
4517
88a8c984
RV
4518 /* find out the length of the shared memory segment */
4519 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
4520 if (is_error(ret)) {
4521 /* can't get length, bail out */
4522 return ret;
4523 }
4524
ee8e7614
PM
4525 shmlba = target_shmlba(cpu_env);
4526
4527 if (shmaddr & (shmlba - 1)) {
4528 if (shmflg & SHM_RND) {
4529 shmaddr &= ~(shmlba - 1);
4530 } else {
4531 return -TARGET_EINVAL;
4532 }
4533 }
46b12f46 4534 if (!guest_range_valid_untagged(shmaddr, shm_info.shm_segsz)) {
ebf9a363
MF
4535 return -TARGET_EINVAL;
4536 }
ee8e7614 4537
88a8c984
RV
4538 mmap_lock();
4539
228168cb
RH
4540 /*
4541 * We're mapping shared memory, so ensure we generate code for parallel
4542 * execution and flush old translations. This will work up to the level
4543 * supported by the host -- anything that requires EXCP_ATOMIC will not
4544 * be atomic with respect to an external process.
4545 */
4546 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
4547 cpu->tcg_cflags |= CF_PARALLEL;
4548 tb_flush(cpu);
4549 }
4550
88a8c984 4551 if (shmaddr)
3e8f1628 4552 host_raddr = shmat(shmid, (void *)g2h_untagged(shmaddr), shmflg);
88a8c984
RV
4553 else {
4554 abi_ulong mmap_start;
4555
30ab9ef2
RH
4556 /* In order to use the host shmat, we need to honor host SHMLBA. */
4557 mmap_start = mmap_find_vma(0, shm_info.shm_segsz, MAX(SHMLBA, shmlba));
88a8c984
RV
4558
4559 if (mmap_start == -1) {
4560 errno = ENOMEM;
4561 host_raddr = (void *)-1;
4562 } else
3e8f1628
RH
4563 host_raddr = shmat(shmid, g2h_untagged(mmap_start),
4564 shmflg | SHM_REMAP);
88a8c984
RV
4565 }
4566
4567 if (host_raddr == (void *)-1) {
4568 mmap_unlock();
4569 return get_errno((long)host_raddr);
4570 }
4571 raddr=h2g((unsigned long)host_raddr);
4572
4573 page_set_flags(raddr, raddr + shm_info.shm_segsz,
d9c58585
RH
4574 PAGE_VALID | PAGE_RESET | PAGE_READ |
4575 (shmflg & SHM_RDONLY ? 0 : PAGE_WRITE));
88a8c984
RV
4576
4577 for (i = 0; i < N_SHM_REGIONS; i++) {
b6e17875
PM
4578 if (!shm_regions[i].in_use) {
4579 shm_regions[i].in_use = true;
88a8c984
RV
4580 shm_regions[i].start = raddr;
4581 shm_regions[i].size = shm_info.shm_segsz;
4582 break;
4583 }
4584 }
4585
4586 mmap_unlock();
4587 return raddr;
4588
4589}
4590
4591static inline abi_long do_shmdt(abi_ulong shmaddr)
4592{
4593 int i;
3c5f6a5f
MF
4594 abi_long rv;
4595
ee1bf83d
RH
4596 /* shmdt pointers are always untagged */
4597
3c5f6a5f 4598 mmap_lock();
88a8c984
RV
4599
4600 for (i = 0; i < N_SHM_REGIONS; ++i) {
b6e17875
PM
4601 if (shm_regions[i].in_use && shm_regions[i].start == shmaddr) {
4602 shm_regions[i].in_use = false;
e00ac249 4603 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
88a8c984
RV
4604 break;
4605 }
4606 }
3e8f1628 4607 rv = get_errno(shmdt(g2h_untagged(shmaddr)));
88a8c984 4608
3c5f6a5f 4609 mmap_unlock();
88a8c984 4610
3c5f6a5f 4611 return rv;
88a8c984
RV
4612}
4613
1c54ff97 4614#ifdef TARGET_NR_ipc
53a5960a 4615/* ??? This only works with linear mappings. */
0da46a6e 4616/* do_ipc() must return target values and target errnos. */
ee8e7614
PM
4617static abi_long do_ipc(CPUArchState *cpu_env,
4618 unsigned int call, abi_long first,
37ed0956 4619 abi_long second, abi_long third,
992f48a0 4620 abi_long ptr, abi_long fifth)
8853f86e
FB
4621{
4622 int version;
992f48a0 4623 abi_long ret = 0;
8853f86e
FB
4624
4625 version = call >> 16;
4626 call &= 0xffff;
4627
4628 switch (call) {
fa294816 4629 case IPCOP_semop:
cac46eb0 4630 ret = do_semtimedop(first, ptr, second, 0, false);
d8c08b1e
MK
4631 break;
4632 case IPCOP_semtimedop:
4633 /*
4634 * The s390 sys_ipc variant has only five parameters instead of six
4635 * (as for default variant) and the only difference is the handling of
4636 * SEMTIMEDOP where on s390 the third parameter is used as a pointer
4637 * to a struct timespec where the generic variant uses fifth parameter.
4638 */
4639#if defined(TARGET_S390X)
cac46eb0 4640 ret = do_semtimedop(first, ptr, second, third, TARGET_ABI_BITS == 64);
d8c08b1e 4641#else
cac46eb0 4642 ret = do_semtimedop(first, ptr, second, fifth, TARGET_ABI_BITS == 64);
d8c08b1e 4643#endif
fa294816
TS
4644 break;
4645
4646 case IPCOP_semget:
4647 ret = get_errno(semget(first, second, third));
4648 break;
4649
5d2fa8eb
TM
4650 case IPCOP_semctl: {
4651 /* The semun argument to semctl is passed by value, so dereference the
4652 * ptr argument. */
4653 abi_ulong atptr;
37ed0956 4654 get_user_ual(atptr, ptr);
d1c002b6 4655 ret = do_semctl(first, second, third, atptr);
fa294816 4656 break;
5d2fa8eb 4657 }
d96372ef 4658
1c54ff97
AJ
4659 case IPCOP_msgget:
4660 ret = get_errno(msgget(first, second));
4661 break;
d96372ef 4662
1c54ff97
AJ
4663 case IPCOP_msgsnd:
4664 ret = do_msgsnd(first, ptr, second, third);
4665 break;
d96372ef 4666
1c54ff97
AJ
4667 case IPCOP_msgctl:
4668 ret = do_msgctl(first, second, ptr);
4669 break;
d96372ef 4670
1c54ff97
AJ
4671 case IPCOP_msgrcv:
4672 switch (version) {
4673 case 0:
4674 {
4675 struct target_ipc_kludge {
4676 abi_long msgp;
4677 abi_long msgtyp;
4678 } *tmp;
4679
4680 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
4681 ret = -TARGET_EFAULT;
4682 break;
4683 }
d96372ef 4684
79dd77de 4685 ret = do_msgrcv(first, tswapal(tmp->msgp), second, tswapal(tmp->msgtyp), third);
d96372ef 4686
1c54ff97
AJ
4687 unlock_user_struct(tmp, ptr, 0);
4688 break;
4689 }
4690 default:
4691 ret = do_msgrcv(first, ptr, second, fifth, third);
4692 }
4693 break;
d96372ef 4694
8853f86e 4695 case IPCOP_shmat:
88a8c984
RV
4696 switch (version) {
4697 default:
5a4a898d
FB
4698 {
4699 abi_ulong raddr;
ee8e7614 4700 raddr = do_shmat(cpu_env, first, ptr, second);
88a8c984
RV
4701 if (is_error(raddr))
4702 return get_errno(raddr);
2f619698 4703 if (put_user_ual(raddr, third))
5a4a898d 4704 return -TARGET_EFAULT;
88a8c984
RV
4705 break;
4706 }
4707 case 1:
4708 ret = -TARGET_EINVAL;
4709 break;
5a4a898d 4710 }
8853f86e
FB
4711 break;
4712 case IPCOP_shmdt:
88a8c984 4713 ret = do_shmdt(ptr);
8853f86e
FB
4714 break;
4715
4716 case IPCOP_shmget:
4717 /* IPC_* flag values are the same on all linux platforms */
4718 ret = get_errno(shmget(first, second, third));
4719 break;
4720
4721 /* IPC_* and SHM_* command values are the same on all linux platforms */
4722 case IPCOP_shmctl:
a2926784 4723 ret = do_shmctl(first, second, ptr);
8853f86e
FB
4724 break;
4725 default:
39be5350
JK
4726 qemu_log_mask(LOG_UNIMP, "Unsupported ipc call: %d (version %d)\n",
4727 call, version);
0da46a6e 4728 ret = -TARGET_ENOSYS;
8853f86e
FB
4729 break;
4730 }
4731 return ret;
4732}
32407103 4733#endif
8853f86e 4734
31e31b8a 4735/* kernel structure types definitions */
31e31b8a 4736
001faf32 4737#define STRUCT(name, ...) STRUCT_ ## name,
31e31b8a
FB
4738#define STRUCT_SPECIAL(name) STRUCT_ ## name,
4739enum {
4740#include "syscall_types.h"
8be656b8 4741STRUCT_MAX
31e31b8a
FB
4742};
4743#undef STRUCT
4744#undef STRUCT_SPECIAL
4745
001faf32 4746#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
31e31b8a
FB
4747#define STRUCT_SPECIAL(name)
4748#include "syscall_types.h"
4749#undef STRUCT
4750#undef STRUCT_SPECIAL
4751
31e31b8a
FB
4752#define MAX_STRUCT_SIZE 4096
4753
dace20dc 4754#ifdef CONFIG_FIEMAP
285da2b9
PM
4755/* So fiemap access checks don't overflow on 32 bit systems.
4756 * This is very slightly smaller than the limit imposed by
4757 * the underlying kernel.
4758 */
4759#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
4760 / sizeof(struct fiemap_extent))
4761
4762static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4763 int fd, int cmd, abi_long arg)
285da2b9
PM
4764{
4765 /* The parameter for this ioctl is a struct fiemap followed
4766 * by an array of struct fiemap_extent whose size is set
4767 * in fiemap->fm_extent_count. The array is filled in by the
4768 * ioctl.
4769 */
4770 int target_size_in, target_size_out;
4771 struct fiemap *fm;
4772 const argtype *arg_type = ie->arg_type;
4773 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
4774 void *argptr, *p;
4775 abi_long ret;
4776 int i, extent_size = thunk_type_size(extent_arg_type, 0);
4777 uint32_t outbufsz;
4778 int free_fm = 0;
4779
4780 assert(arg_type[0] == TYPE_PTR);
4781 assert(ie->access == IOC_RW);
4782 arg_type++;
4783 target_size_in = thunk_type_size(arg_type, 0);
4784 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
4785 if (!argptr) {
4786 return -TARGET_EFAULT;
4787 }
4788 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4789 unlock_user(argptr, arg, 0);
4790 fm = (struct fiemap *)buf_temp;
4791 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
4792 return -TARGET_EINVAL;
4793 }
4794
4795 outbufsz = sizeof (*fm) +
4796 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
4797
4798 if (outbufsz > MAX_STRUCT_SIZE) {
4799 /* We can't fit all the extents into the fixed size buffer.
4800 * Allocate one that is large enough and use it instead.
4801 */
0e173b24 4802 fm = g_try_malloc(outbufsz);
285da2b9
PM
4803 if (!fm) {
4804 return -TARGET_ENOMEM;
4805 }
4806 memcpy(fm, buf_temp, sizeof(struct fiemap));
4807 free_fm = 1;
4808 }
49ca6f3e 4809 ret = get_errno(safe_ioctl(fd, ie->host_cmd, fm));
285da2b9
PM
4810 if (!is_error(ret)) {
4811 target_size_out = target_size_in;
4812 /* An extent_count of 0 means we were only counting the extents
4813 * so there are no structs to copy
4814 */
4815 if (fm->fm_extent_count != 0) {
4816 target_size_out += fm->fm_mapped_extents * extent_size;
4817 }
4818 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
4819 if (!argptr) {
4820 ret = -TARGET_EFAULT;
4821 } else {
4822 /* Convert the struct fiemap */
4823 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
4824 if (fm->fm_extent_count != 0) {
4825 p = argptr + target_size_in;
4826 /* ...and then all the struct fiemap_extents */
4827 for (i = 0; i < fm->fm_mapped_extents; i++) {
4828 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
4829 THUNK_TARGET);
4830 p += extent_size;
4831 }
4832 }
4833 unlock_user(argptr, arg, target_size_out);
4834 }
4835 }
4836 if (free_fm) {
0e173b24 4837 g_free(fm);
285da2b9
PM
4838 }
4839 return ret;
4840}
dace20dc 4841#endif
285da2b9 4842
059c2f2c 4843static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 4844 int fd, int cmd, abi_long arg)
059c2f2c
LV
4845{
4846 const argtype *arg_type = ie->arg_type;
4847 int target_size;
4848 void *argptr;
4849 int ret;
4850 struct ifconf *host_ifconf;
4851 uint32_t outbufsz;
4852 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
4df7b7fa 4853 const argtype ifreq_max_type[] = { MK_STRUCT(STRUCT_ifmap_ifreq) };
059c2f2c
LV
4854 int target_ifreq_size;
4855 int nb_ifreq;
4856 int free_buf = 0;
4857 int i;
4858 int target_ifc_len;
4859 abi_long target_ifc_buf;
4860 int host_ifc_len;
4861 char *host_ifc_buf;
4862
4863 assert(arg_type[0] == TYPE_PTR);
4864 assert(ie->access == IOC_RW);
4865
4866 arg_type++;
4867 target_size = thunk_type_size(arg_type, 0);
4868
4869 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
4870 if (!argptr)
4871 return -TARGET_EFAULT;
4872 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
4873 unlock_user(argptr, arg, 0);
4874
4875 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
059c2f2c 4876 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
4df7b7fa 4877 target_ifreq_size = thunk_type_size(ifreq_max_type, 0);
059c2f2c 4878
22e4a267
KL
4879 if (target_ifc_buf != 0) {
4880 target_ifc_len = host_ifconf->ifc_len;
4881 nb_ifreq = target_ifc_len / target_ifreq_size;
4882 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
4883
4884 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
4885 if (outbufsz > MAX_STRUCT_SIZE) {
4886 /*
4887 * We can't fit all the extents into the fixed size buffer.
4888 * Allocate one that is large enough and use it instead.
4889 */
7a5626a1 4890 host_ifconf = g_try_malloc(outbufsz);
22e4a267
KL
4891 if (!host_ifconf) {
4892 return -TARGET_ENOMEM;
4893 }
4894 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
4895 free_buf = 1;
059c2f2c 4896 }
22e4a267 4897 host_ifc_buf = (char *)host_ifconf + sizeof(*host_ifconf);
059c2f2c 4898
22e4a267
KL
4899 host_ifconf->ifc_len = host_ifc_len;
4900 } else {
4901 host_ifc_buf = NULL;
4902 }
059c2f2c
LV
4903 host_ifconf->ifc_buf = host_ifc_buf;
4904
49ca6f3e 4905 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_ifconf));
059c2f2c
LV
4906 if (!is_error(ret)) {
4907 /* convert host ifc_len to target ifc_len */
4908
4909 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
4910 target_ifc_len = nb_ifreq * target_ifreq_size;
4911 host_ifconf->ifc_len = target_ifc_len;
4912
4913 /* restore target ifc_buf */
4914
4915 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
4916
4917 /* copy struct ifconf to target user */
4918
4919 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
4920 if (!argptr)
4921 return -TARGET_EFAULT;
4922 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
4923 unlock_user(argptr, arg, target_size);
4924
22e4a267
KL
4925 if (target_ifc_buf != 0) {
4926 /* copy ifreq[] to target user */
4927 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
4928 for (i = 0; i < nb_ifreq ; i++) {
4929 thunk_convert(argptr + i * target_ifreq_size,
4930 host_ifc_buf + i * sizeof(struct ifreq),
4931 ifreq_arg_type, THUNK_TARGET);
4932 }
4933 unlock_user(argptr, target_ifc_buf, target_ifc_len);
059c2f2c 4934 }
059c2f2c
LV
4935 }
4936
4937 if (free_buf) {
7a5626a1 4938 g_free(host_ifconf);
059c2f2c
LV
4939 }
4940
4941 return ret;
4942}
4943
a133367e
CT
4944#if defined(CONFIG_USBFS)
4945#if HOST_LONG_BITS > 64
4946#error USBDEVFS thunks do not support >64 bit hosts yet.
4947#endif
4948struct live_urb {
4949 uint64_t target_urb_adr;
4950 uint64_t target_buf_adr;
4951 char *target_buf_ptr;
4952 struct usbdevfs_urb host_urb;
4953};
4954
4955static GHashTable *usbdevfs_urb_hashtable(void)
4956{
4957 static GHashTable *urb_hashtable;
4958
4959 if (!urb_hashtable) {
4960 urb_hashtable = g_hash_table_new(g_int64_hash, g_int64_equal);
4961 }
4962 return urb_hashtable;
4963}
4964
4965static void urb_hashtable_insert(struct live_urb *urb)
4966{
4967 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4968 g_hash_table_insert(urb_hashtable, urb, urb);
4969}
4970
4971static struct live_urb *urb_hashtable_lookup(uint64_t target_urb_adr)
4972{
4973 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4974 return g_hash_table_lookup(urb_hashtable, &target_urb_adr);
4975}
4976
4977static void urb_hashtable_remove(struct live_urb *urb)
4978{
4979 GHashTable *urb_hashtable = usbdevfs_urb_hashtable();
4980 g_hash_table_remove(urb_hashtable, urb);
4981}
4982
4983static abi_long
4984do_ioctl_usbdevfs_reapurb(const IOCTLEntry *ie, uint8_t *buf_temp,
4985 int fd, int cmd, abi_long arg)
4986{
4987 const argtype usbfsurb_arg_type[] = { MK_STRUCT(STRUCT_usbdevfs_urb) };
4988 const argtype ptrvoid_arg_type[] = { TYPE_PTRVOID, 0, 0 };
4989 struct live_urb *lurb;
4990 void *argptr;
4991 uint64_t hurb;
4992 int target_size;
4993 uintptr_t target_urb_adr;
4994 abi_long ret;
4995
4996 target_size = thunk_type_size(usbfsurb_arg_type, THUNK_TARGET);
4997
4998 memset(buf_temp, 0, sizeof(uint64_t));
4999 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
5000 if (is_error(ret)) {
5001 return ret;
5002 }
5003
5004 memcpy(&hurb, buf_temp, sizeof(uint64_t));
5005 lurb = (void *)((uintptr_t)hurb - offsetof(struct live_urb, host_urb));
5006 if (!lurb->target_urb_adr) {
5007 return -TARGET_EFAULT;
5008 }
5009 urb_hashtable_remove(lurb);
5010 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr,
5011 lurb->host_urb.buffer_length);
5012 lurb->target_buf_ptr = NULL;
5013
5014 /* restore the guest buffer pointer */
5015 lurb->host_urb.buffer = (void *)(uintptr_t)lurb->target_buf_adr;
5016
5017 /* update the guest urb struct */
5018 argptr = lock_user(VERIFY_WRITE, lurb->target_urb_adr, target_size, 0);
5019 if (!argptr) {
5020 g_free(lurb);
5021 return -TARGET_EFAULT;
5022 }
5023 thunk_convert(argptr, &lurb->host_urb, usbfsurb_arg_type, THUNK_TARGET);
5024 unlock_user(argptr, lurb->target_urb_adr, target_size);
5025
5026 target_size = thunk_type_size(ptrvoid_arg_type, THUNK_TARGET);
5027 /* write back the urb handle */
5028 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5029 if (!argptr) {
5030 g_free(lurb);
5031 return -TARGET_EFAULT;
5032 }
5033
5034 /* GHashTable uses 64-bit keys but thunk_convert expects uintptr_t */
5035 target_urb_adr = lurb->target_urb_adr;
5036 thunk_convert(argptr, &target_urb_adr, ptrvoid_arg_type, THUNK_TARGET);
5037 unlock_user(argptr, arg, target_size);
5038
5039 g_free(lurb);
5040 return ret;
5041}
5042
5043static abi_long
5044do_ioctl_usbdevfs_discardurb(const IOCTLEntry *ie,
5045 uint8_t *buf_temp __attribute__((unused)),
5046 int fd, int cmd, abi_long arg)
5047{
5048 struct live_urb *lurb;
5049
5050 /* map target address back to host URB with metadata. */
5051 lurb = urb_hashtable_lookup(arg);
5052 if (!lurb) {
5053 return -TARGET_EFAULT;
5054 }
5055 return get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5056}
5057
5058static abi_long
5059do_ioctl_usbdevfs_submiturb(const IOCTLEntry *ie, uint8_t *buf_temp,
5060 int fd, int cmd, abi_long arg)
5061{
5062 const argtype *arg_type = ie->arg_type;
5063 int target_size;
5064 abi_long ret;
5065 void *argptr;
5066 int rw_dir;
5067 struct live_urb *lurb;
5068
5069 /*
5070 * each submitted URB needs to map to a unique ID for the
5071 * kernel, and that unique ID needs to be a pointer to
5072 * host memory. hence, we need to malloc for each URB.
5073 * isochronous transfers have a variable length struct.
5074 */
5075 arg_type++;
5076 target_size = thunk_type_size(arg_type, THUNK_TARGET);
5077
5078 /* construct host copy of urb and metadata */
b21e2380 5079 lurb = g_try_new0(struct live_urb, 1);
a133367e
CT
5080 if (!lurb) {
5081 return -TARGET_ENOMEM;
5082 }
5083
5084 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5085 if (!argptr) {
5086 g_free(lurb);
5087 return -TARGET_EFAULT;
5088 }
5089 thunk_convert(&lurb->host_urb, argptr, arg_type, THUNK_HOST);
5090 unlock_user(argptr, arg, 0);
5091
5092 lurb->target_urb_adr = arg;
5093 lurb->target_buf_adr = (uintptr_t)lurb->host_urb.buffer;
5094
5095 /* buffer space used depends on endpoint type so lock the entire buffer */
5096 /* control type urbs should check the buffer contents for true direction */
5097 rw_dir = lurb->host_urb.endpoint & USB_DIR_IN ? VERIFY_WRITE : VERIFY_READ;
5098 lurb->target_buf_ptr = lock_user(rw_dir, lurb->target_buf_adr,
5099 lurb->host_urb.buffer_length, 1);
5100 if (lurb->target_buf_ptr == NULL) {
5101 g_free(lurb);
5102 return -TARGET_EFAULT;
5103 }
5104
5105 /* update buffer pointer in host copy */
5106 lurb->host_urb.buffer = lurb->target_buf_ptr;
5107
5108 ret = get_errno(safe_ioctl(fd, ie->host_cmd, &lurb->host_urb));
5109 if (is_error(ret)) {
5110 unlock_user(lurb->target_buf_ptr, lurb->target_buf_adr, 0);
5111 g_free(lurb);
5112 } else {
5113 urb_hashtable_insert(lurb);
5114 }
5115
5116 return ret;
5117}
5118#endif /* CONFIG_USBFS */
5119
56e904ec 5120static abi_long do_ioctl_dm(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5121 int cmd, abi_long arg)
56e904ec
AG
5122{
5123 void *argptr;
5124 struct dm_ioctl *host_dm;
5125 abi_long guest_data;
5126 uint32_t guest_data_size;
5127 int target_size;
5128 const argtype *arg_type = ie->arg_type;
5129 abi_long ret;
5130 void *big_buf = NULL;
5131 char *host_data;
5132
5133 arg_type++;
5134 target_size = thunk_type_size(arg_type, 0);
5135 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5136 if (!argptr) {
5137 ret = -TARGET_EFAULT;
5138 goto out;
5139 }
5140 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5141 unlock_user(argptr, arg, 0);
5142
5143 /* buf_temp is too small, so fetch things into a bigger buffer */
5144 big_buf = g_malloc0(((struct dm_ioctl*)buf_temp)->data_size * 2);
5145 memcpy(big_buf, buf_temp, target_size);
5146 buf_temp = big_buf;
5147 host_dm = big_buf;
5148
5149 guest_data = arg + host_dm->data_start;
5150 if ((guest_data - arg) < 0) {
f9757b1d 5151 ret = -TARGET_EINVAL;
56e904ec
AG
5152 goto out;
5153 }
5154 guest_data_size = host_dm->data_size - host_dm->data_start;
5155 host_data = (char*)host_dm + host_dm->data_start;
5156
5157 argptr = lock_user(VERIFY_READ, guest_data, guest_data_size, 1);
3211215e
PM
5158 if (!argptr) {
5159 ret = -TARGET_EFAULT;
5160 goto out;
5161 }
5162
56e904ec
AG
5163 switch (ie->host_cmd) {
5164 case DM_REMOVE_ALL:
5165 case DM_LIST_DEVICES:
5166 case DM_DEV_CREATE:
5167 case DM_DEV_REMOVE:
5168 case DM_DEV_SUSPEND:
5169 case DM_DEV_STATUS:
5170 case DM_DEV_WAIT:
5171 case DM_TABLE_STATUS:
5172 case DM_TABLE_CLEAR:
5173 case DM_TABLE_DEPS:
5174 case DM_LIST_VERSIONS:
5175 /* no input data */
5176 break;
5177 case DM_DEV_RENAME:
5178 case DM_DEV_SET_GEOMETRY:
5179 /* data contains only strings */
5180 memcpy(host_data, argptr, guest_data_size);
5181 break;
5182 case DM_TARGET_MSG:
5183 memcpy(host_data, argptr, guest_data_size);
5184 *(uint64_t*)host_data = tswap64(*(uint64_t*)argptr);
5185 break;
5186 case DM_TABLE_LOAD:
5187 {
5188 void *gspec = argptr;
5189 void *cur_data = host_data;
5190 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5191 int spec_size = thunk_type_size(arg_type, 0);
5192 int i;
5193
5194 for (i = 0; i < host_dm->target_count; i++) {
5195 struct dm_target_spec *spec = cur_data;
5196 uint32_t next;
5197 int slen;
5198
5199 thunk_convert(spec, gspec, arg_type, THUNK_HOST);
5200 slen = strlen((char*)gspec + spec_size) + 1;
5201 next = spec->next;
5202 spec->next = sizeof(*spec) + slen;
5203 strcpy((char*)&spec[1], gspec + spec_size);
5204 gspec += next;
5205 cur_data += spec->next;
5206 }
5207 break;
5208 }
5209 default:
5210 ret = -TARGET_EINVAL;
dec0473d 5211 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5212 goto out;
5213 }
5214 unlock_user(argptr, guest_data, 0);
5215
49ca6f3e 5216 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
56e904ec
AG
5217 if (!is_error(ret)) {
5218 guest_data = arg + host_dm->data_start;
5219 guest_data_size = host_dm->data_size - host_dm->data_start;
5220 argptr = lock_user(VERIFY_WRITE, guest_data, guest_data_size, 0);
5221 switch (ie->host_cmd) {
5222 case DM_REMOVE_ALL:
5223 case DM_DEV_CREATE:
5224 case DM_DEV_REMOVE:
5225 case DM_DEV_RENAME:
5226 case DM_DEV_SUSPEND:
5227 case DM_DEV_STATUS:
5228 case DM_TABLE_LOAD:
5229 case DM_TABLE_CLEAR:
5230 case DM_TARGET_MSG:
5231 case DM_DEV_SET_GEOMETRY:
5232 /* no return data */
5233 break;
5234 case DM_LIST_DEVICES:
5235 {
5236 struct dm_name_list *nl = (void*)host_dm + host_dm->data_start;
5237 uint32_t remaining_data = guest_data_size;
5238 void *cur_data = argptr;
5239 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_name_list) };
5240 int nl_size = 12; /* can't use thunk_size due to alignment */
5241
5242 while (1) {
5243 uint32_t next = nl->next;
5244 if (next) {
5245 nl->next = nl_size + (strlen(nl->name) + 1);
5246 }
5247 if (remaining_data < nl->next) {
5248 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5249 break;
5250 }
5251 thunk_convert(cur_data, nl, arg_type, THUNK_TARGET);
5252 strcpy(cur_data + nl_size, nl->name);
5253 cur_data += nl->next;
5254 remaining_data -= nl->next;
5255 if (!next) {
5256 break;
5257 }
5258 nl = (void*)nl + next;
5259 }
5260 break;
5261 }
5262 case DM_DEV_WAIT:
5263 case DM_TABLE_STATUS:
5264 {
5265 struct dm_target_spec *spec = (void*)host_dm + host_dm->data_start;
5266 void *cur_data = argptr;
5267 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_spec) };
5268 int spec_size = thunk_type_size(arg_type, 0);
5269 int i;
5270
5271 for (i = 0; i < host_dm->target_count; i++) {
5272 uint32_t next = spec->next;
5273 int slen = strlen((char*)&spec[1]) + 1;
5274 spec->next = (cur_data - argptr) + spec_size + slen;
5275 if (guest_data_size < spec->next) {
5276 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5277 break;
5278 }
5279 thunk_convert(cur_data, spec, arg_type, THUNK_TARGET);
5280 strcpy(cur_data + spec_size, (char*)&spec[1]);
5281 cur_data = argptr + spec->next;
5282 spec = (void*)host_dm + host_dm->data_start + next;
5283 }
5284 break;
5285 }
5286 case DM_TABLE_DEPS:
5287 {
5288 void *hdata = (void*)host_dm + host_dm->data_start;
5289 int count = *(uint32_t*)hdata;
5290 uint64_t *hdev = hdata + 8;
5291 uint64_t *gdev = argptr + 8;
5292 int i;
5293
5294 *(uint32_t*)argptr = tswap32(count);
5295 for (i = 0; i < count; i++) {
5296 *gdev = tswap64(*hdev);
5297 gdev++;
5298 hdev++;
5299 }
5300 break;
5301 }
5302 case DM_LIST_VERSIONS:
5303 {
5304 struct dm_target_versions *vers = (void*)host_dm + host_dm->data_start;
5305 uint32_t remaining_data = guest_data_size;
5306 void *cur_data = argptr;
5307 const argtype arg_type[] = { MK_STRUCT(STRUCT_dm_target_versions) };
5308 int vers_size = thunk_type_size(arg_type, 0);
5309
5310 while (1) {
5311 uint32_t next = vers->next;
5312 if (next) {
5313 vers->next = vers_size + (strlen(vers->name) + 1);
5314 }
5315 if (remaining_data < vers->next) {
5316 host_dm->flags |= DM_BUFFER_FULL_FLAG;
5317 break;
5318 }
5319 thunk_convert(cur_data, vers, arg_type, THUNK_TARGET);
5320 strcpy(cur_data + vers_size, vers->name);
5321 cur_data += vers->next;
5322 remaining_data -= vers->next;
5323 if (!next) {
5324 break;
5325 }
5326 vers = (void*)vers + next;
5327 }
5328 break;
5329 }
5330 default:
dec0473d 5331 unlock_user(argptr, guest_data, 0);
56e904ec
AG
5332 ret = -TARGET_EINVAL;
5333 goto out;
5334 }
5335 unlock_user(argptr, guest_data, guest_data_size);
5336
5337 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5338 if (!argptr) {
5339 ret = -TARGET_EFAULT;
5340 goto out;
5341 }
5342 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5343 unlock_user(argptr, arg, target_size);
5344 }
5345out:
ad11ad77 5346 g_free(big_buf);
56e904ec
AG
5347 return ret;
5348}
5349
a59b5e35 5350static abi_long do_ioctl_blkpg(const IOCTLEntry *ie, uint8_t *buf_temp, int fd,
45c874eb 5351 int cmd, abi_long arg)
a59b5e35
AG
5352{
5353 void *argptr;
5354 int target_size;
5355 const argtype *arg_type = ie->arg_type;
5356 const argtype part_arg_type[] = { MK_STRUCT(STRUCT_blkpg_partition) };
5357 abi_long ret;
5358
5359 struct blkpg_ioctl_arg *host_blkpg = (void*)buf_temp;
5360 struct blkpg_partition host_part;
5361
5362 /* Read and convert blkpg */
5363 arg_type++;
5364 target_size = thunk_type_size(arg_type, 0);
5365 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5366 if (!argptr) {
5367 ret = -TARGET_EFAULT;
5368 goto out;
5369 }
5370 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5371 unlock_user(argptr, arg, 0);
5372
5373 switch (host_blkpg->op) {
5374 case BLKPG_ADD_PARTITION:
5375 case BLKPG_DEL_PARTITION:
5376 /* payload is struct blkpg_partition */
5377 break;
5378 default:
5379 /* Unknown opcode */
5380 ret = -TARGET_EINVAL;
5381 goto out;
5382 }
5383
5384 /* Read and convert blkpg->data */
5385 arg = (abi_long)(uintptr_t)host_blkpg->data;
5386 target_size = thunk_type_size(part_arg_type, 0);
5387 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5388 if (!argptr) {
5389 ret = -TARGET_EFAULT;
5390 goto out;
5391 }
5392 thunk_convert(&host_part, argptr, part_arg_type, THUNK_HOST);
5393 unlock_user(argptr, arg, 0);
5394
5395 /* Swizzle the data pointer to our local copy and call! */
5396 host_blkpg->data = &host_part;
49ca6f3e 5397 ret = get_errno(safe_ioctl(fd, ie->host_cmd, host_blkpg));
a59b5e35
AG
5398
5399out:
5400 return ret;
5401}
5402
7ff7b666 5403static abi_long do_ioctl_rt(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5404 int fd, int cmd, abi_long arg)
7ff7b666
LV
5405{
5406 const argtype *arg_type = ie->arg_type;
5407 const StructEntry *se;
5408 const argtype *field_types;
5409 const int *dst_offsets, *src_offsets;
5410 int target_size;
5411 void *argptr;
b78c522a
MAL
5412 abi_ulong *target_rt_dev_ptr = NULL;
5413 unsigned long *host_rt_dev_ptr = NULL;
7ff7b666
LV
5414 abi_long ret;
5415 int i;
5416
5417 assert(ie->access == IOC_W);
5418 assert(*arg_type == TYPE_PTR);
5419 arg_type++;
5420 assert(*arg_type == TYPE_STRUCT);
5421 target_size = thunk_type_size(arg_type, 0);
5422 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5423 if (!argptr) {
5424 return -TARGET_EFAULT;
5425 }
5426 arg_type++;
5427 assert(*arg_type == (int)STRUCT_rtentry);
5428 se = struct_entries + *arg_type++;
5429 assert(se->convert[0] == NULL);
5430 /* convert struct here to be able to catch rt_dev string */
5431 field_types = se->field_types;
5432 dst_offsets = se->field_offsets[THUNK_HOST];
5433 src_offsets = se->field_offsets[THUNK_TARGET];
5434 for (i = 0; i < se->nb_fields; i++) {
5435 if (dst_offsets[i] == offsetof(struct rtentry, rt_dev)) {
5436 assert(*field_types == TYPE_PTRVOID);
5437 target_rt_dev_ptr = (abi_ulong *)(argptr + src_offsets[i]);
5438 host_rt_dev_ptr = (unsigned long *)(buf_temp + dst_offsets[i]);
5439 if (*target_rt_dev_ptr != 0) {
5440 *host_rt_dev_ptr = (unsigned long)lock_user_string(
5441 tswapal(*target_rt_dev_ptr));
5442 if (!*host_rt_dev_ptr) {
5443 unlock_user(argptr, arg, 0);
5444 return -TARGET_EFAULT;
5445 }
5446 } else {
5447 *host_rt_dev_ptr = 0;
5448 }
5449 field_types++;
5450 continue;
5451 }
5452 field_types = thunk_convert(buf_temp + dst_offsets[i],
5453 argptr + src_offsets[i],
5454 field_types, THUNK_HOST);
5455 }
5456 unlock_user(argptr, arg, 0);
5457
49ca6f3e 5458 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
b78c522a
MAL
5459
5460 assert(host_rt_dev_ptr != NULL);
5461 assert(target_rt_dev_ptr != NULL);
7ff7b666
LV
5462 if (*host_rt_dev_ptr != 0) {
5463 unlock_user((void *)*host_rt_dev_ptr,
5464 *target_rt_dev_ptr, 0);
5465 }
5466 return ret;
5467}
5468
ca56f5b5 5469static abi_long do_ioctl_kdsigaccept(const IOCTLEntry *ie, uint8_t *buf_temp,
45c874eb 5470 int fd, int cmd, abi_long arg)
ca56f5b5
PB
5471{
5472 int sig = target_to_host_signal(arg);
49ca6f3e 5473 return get_errno(safe_ioctl(fd, ie->host_cmd, sig));
ca56f5b5
PB
5474}
5475
6d5d5dde
DB
5476static abi_long do_ioctl_SIOCGSTAMP(const IOCTLEntry *ie, uint8_t *buf_temp,
5477 int fd, int cmd, abi_long arg)
5478{
5479 struct timeval tv;
5480 abi_long ret;
5481
5482 ret = get_errno(safe_ioctl(fd, SIOCGSTAMP, &tv));
5483 if (is_error(ret)) {
5484 return ret;
5485 }
5486
5487 if (cmd == (int)TARGET_SIOCGSTAMP_OLD) {
5488 if (copy_to_user_timeval(arg, &tv)) {
5489 return -TARGET_EFAULT;
5490 }
5491 } else {
5492 if (copy_to_user_timeval64(arg, &tv)) {
5493 return -TARGET_EFAULT;
5494 }
5495 }
5496
5497 return ret;
5498}
5499
5500static abi_long do_ioctl_SIOCGSTAMPNS(const IOCTLEntry *ie, uint8_t *buf_temp,
5501 int fd, int cmd, abi_long arg)
5502{
5503 struct timespec ts;
5504 abi_long ret;
5505
5506 ret = get_errno(safe_ioctl(fd, SIOCGSTAMPNS, &ts));
5507 if (is_error(ret)) {
5508 return ret;
5509 }
5510
5511 if (cmd == (int)TARGET_SIOCGSTAMPNS_OLD) {
5512 if (host_to_target_timespec(arg, &ts)) {
5513 return -TARGET_EFAULT;
5514 }
5515 } else{
5516 if (host_to_target_timespec64(arg, &ts)) {
5517 return -TARGET_EFAULT;
5518 }
5519 }
5520
5521 return ret;
5522}
5523
2b74f621
AS
5524#ifdef TIOCGPTPEER
5525static abi_long do_ioctl_tiocgptpeer(const IOCTLEntry *ie, uint8_t *buf_temp,
5526 int fd, int cmd, abi_long arg)
5527{
5528 int flags = target_to_host_bitmask(arg, fcntl_flags_tbl);
5529 return get_errno(safe_ioctl(fd, ie->host_cmd, flags));
5530}
5531#endif
5532
e865b97f
CG
5533#ifdef HAVE_DRM_H
5534
5535static void unlock_drm_version(struct drm_version *host_ver,
5536 struct target_drm_version *target_ver,
5537 bool copy)
5538{
5539 unlock_user(host_ver->name, target_ver->name,
5540 copy ? host_ver->name_len : 0);
5541 unlock_user(host_ver->date, target_ver->date,
5542 copy ? host_ver->date_len : 0);
5543 unlock_user(host_ver->desc, target_ver->desc,
5544 copy ? host_ver->desc_len : 0);
5545}
5546
5547static inline abi_long target_to_host_drmversion(struct drm_version *host_ver,
5548 struct target_drm_version *target_ver)
5549{
5550 memset(host_ver, 0, sizeof(*host_ver));
5551
5552 __get_user(host_ver->name_len, &target_ver->name_len);
5553 if (host_ver->name_len) {
5554 host_ver->name = lock_user(VERIFY_WRITE, target_ver->name,
5555 target_ver->name_len, 0);
5556 if (!host_ver->name) {
5557 return -EFAULT;
5558 }
5559 }
5560
5561 __get_user(host_ver->date_len, &target_ver->date_len);
5562 if (host_ver->date_len) {
5563 host_ver->date = lock_user(VERIFY_WRITE, target_ver->date,
5564 target_ver->date_len, 0);
5565 if (!host_ver->date) {
5566 goto err;
5567 }
5568 }
5569
5570 __get_user(host_ver->desc_len, &target_ver->desc_len);
5571 if (host_ver->desc_len) {
5572 host_ver->desc = lock_user(VERIFY_WRITE, target_ver->desc,
5573 target_ver->desc_len, 0);
5574 if (!host_ver->desc) {
5575 goto err;
5576 }
5577 }
5578
5579 return 0;
5580err:
5581 unlock_drm_version(host_ver, target_ver, false);
5582 return -EFAULT;
5583}
5584
5585static inline void host_to_target_drmversion(
5586 struct target_drm_version *target_ver,
5587 struct drm_version *host_ver)
5588{
5589 __put_user(host_ver->version_major, &target_ver->version_major);
5590 __put_user(host_ver->version_minor, &target_ver->version_minor);
5591 __put_user(host_ver->version_patchlevel, &target_ver->version_patchlevel);
5592 __put_user(host_ver->name_len, &target_ver->name_len);
5593 __put_user(host_ver->date_len, &target_ver->date_len);
5594 __put_user(host_ver->desc_len, &target_ver->desc_len);
5595 unlock_drm_version(host_ver, target_ver, true);
5596}
5597
5598static abi_long do_ioctl_drm(const IOCTLEntry *ie, uint8_t *buf_temp,
5599 int fd, int cmd, abi_long arg)
5600{
5601 struct drm_version *ver;
5602 struct target_drm_version *target_ver;
5603 abi_long ret;
5604
5605 switch (ie->host_cmd) {
5606 case DRM_IOCTL_VERSION:
5607 if (!lock_user_struct(VERIFY_WRITE, target_ver, arg, 0)) {
5608 return -TARGET_EFAULT;
5609 }
5610 ver = (struct drm_version *)buf_temp;
5611 ret = target_to_host_drmversion(ver, target_ver);
5612 if (!is_error(ret)) {
5613 ret = get_errno(safe_ioctl(fd, ie->host_cmd, ver));
5614 if (is_error(ret)) {
5615 unlock_drm_version(ver, target_ver, false);
5616 } else {
5617 host_to_target_drmversion(target_ver, ver);
5618 }
5619 }
5620 unlock_user_struct(target_ver, arg, 0);
5621 return ret;
5622 }
5623 return -TARGET_ENOSYS;
5624}
5625
913b03c2
CG
5626static abi_long do_ioctl_drm_i915_getparam(const IOCTLEntry *ie,
5627 struct drm_i915_getparam *gparam,
5628 int fd, abi_long arg)
5629{
5630 abi_long ret;
5631 int value;
5632 struct target_drm_i915_getparam *target_gparam;
5633
5634 if (!lock_user_struct(VERIFY_READ, target_gparam, arg, 0)) {
5635 return -TARGET_EFAULT;
5636 }
5637
5638 __get_user(gparam->param, &target_gparam->param);
5639 gparam->value = &value;
5640 ret = get_errno(safe_ioctl(fd, ie->host_cmd, gparam));
5641 put_user_s32(value, target_gparam->value);
5642
5643 unlock_user_struct(target_gparam, arg, 0);
5644 return ret;
5645}
5646
5647static abi_long do_ioctl_drm_i915(const IOCTLEntry *ie, uint8_t *buf_temp,
5648 int fd, int cmd, abi_long arg)
5649{
5650 switch (ie->host_cmd) {
5651 case DRM_IOCTL_I915_GETPARAM:
5652 return do_ioctl_drm_i915_getparam(ie,
5653 (struct drm_i915_getparam *)buf_temp,
5654 fd, arg);
5655 default:
5656 return -TARGET_ENOSYS;
5657 }
5658}
5659
e865b97f
CG
5660#endif
5661
6addf06a
SCW
5662static abi_long do_ioctl_TUNSETTXFILTER(const IOCTLEntry *ie, uint8_t *buf_temp,
5663 int fd, int cmd, abi_long arg)
5664{
5665 struct tun_filter *filter = (struct tun_filter *)buf_temp;
5666 struct tun_filter *target_filter;
5667 char *target_addr;
5668
5669 assert(ie->access == IOC_W);
5670
5671 target_filter = lock_user(VERIFY_READ, arg, sizeof(*target_filter), 1);
5672 if (!target_filter) {
5673 return -TARGET_EFAULT;
5674 }
5675 filter->flags = tswap16(target_filter->flags);
5676 filter->count = tswap16(target_filter->count);
5677 unlock_user(target_filter, arg, 0);
5678
5679 if (filter->count) {
5680 if (offsetof(struct tun_filter, addr) + filter->count * ETH_ALEN >
5681 MAX_STRUCT_SIZE) {
5682 return -TARGET_EFAULT;
5683 }
5684
5685 target_addr = lock_user(VERIFY_READ,
5686 arg + offsetof(struct tun_filter, addr),
5687 filter->count * ETH_ALEN, 1);
5688 if (!target_addr) {
5689 return -TARGET_EFAULT;
5690 }
5691 memcpy(filter->addr, target_addr, filter->count * ETH_ALEN);
5692 unlock_user(target_addr, arg + offsetof(struct tun_filter, addr), 0);
5693 }
5694
5695 return get_errno(safe_ioctl(fd, ie->host_cmd, filter));
5696}
5697
79482e59 5698IOCTLEntry ioctl_entries[] = {
001faf32 5699#define IOCTL(cmd, access, ...) \
d2ef05bb
PM
5700 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
5701#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
5702 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
8cb762fe
HD
5703#define IOCTL_IGNORE(cmd) \
5704 { TARGET_ ## cmd, 0, #cmd },
31e31b8a
FB
5705#include "ioctls.h"
5706 { 0, 0, },
5707};
5708
53a5960a 5709/* ??? Implement proper locking for ioctls. */
0da46a6e 5710/* do_ioctl() Must return target values and target errnos. */
45c874eb 5711static abi_long do_ioctl(int fd, int cmd, abi_long arg)
31e31b8a
FB
5712{
5713 const IOCTLEntry *ie;
5714 const argtype *arg_type;
992f48a0 5715 abi_long ret;
31e31b8a 5716 uint8_t buf_temp[MAX_STRUCT_SIZE];
53a5960a
PB
5717 int target_size;
5718 void *argptr;
31e31b8a
FB
5719
5720 ie = ioctl_entries;
5721 for(;;) {
5722 if (ie->target_cmd == 0) {
39be5350
JK
5723 qemu_log_mask(
5724 LOG_UNIMP, "Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
0da46a6e 5725 return -TARGET_ENOSYS;
31e31b8a
FB
5726 }
5727 if (ie->target_cmd == cmd)
5728 break;
5729 ie++;
5730 }
5731 arg_type = ie->arg_type;
d2ef05bb
PM
5732 if (ie->do_ioctl) {
5733 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
8cb762fe
HD
5734 } else if (!ie->host_cmd) {
5735 /* Some architectures define BSD ioctls in their headers
5736 that are not implemented in Linux. */
5737 return -TARGET_ENOSYS;
d2ef05bb
PM
5738 }
5739
31e31b8a
FB
5740 switch(arg_type[0]) {
5741 case TYPE_NULL:
5742 /* no argument */
49ca6f3e 5743 ret = get_errno(safe_ioctl(fd, ie->host_cmd));
31e31b8a
FB
5744 break;
5745 case TYPE_PTRVOID:
5746 case TYPE_INT:
c858e537
FB
5747 case TYPE_LONG:
5748 case TYPE_ULONG:
49ca6f3e 5749 ret = get_errno(safe_ioctl(fd, ie->host_cmd, arg));
31e31b8a
FB
5750 break;
5751 case TYPE_PTR:
5752 arg_type++;
53a5960a 5753 target_size = thunk_type_size(arg_type, 0);
31e31b8a
FB
5754 switch(ie->access) {
5755 case IOC_R:
49ca6f3e 5756 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5757 if (!is_error(ret)) {
579a97f7
FB
5758 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5759 if (!argptr)
5760 return -TARGET_EFAULT;
53a5960a
PB
5761 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5762 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5763 }
5764 break;
5765 case IOC_W:
579a97f7
FB
5766 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5767 if (!argptr)
5768 return -TARGET_EFAULT;
53a5960a
PB
5769 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5770 unlock_user(argptr, arg, 0);
49ca6f3e 5771 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a
FB
5772 break;
5773 default:
5774 case IOC_RW:
579a97f7
FB
5775 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
5776 if (!argptr)
5777 return -TARGET_EFAULT;
53a5960a
PB
5778 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
5779 unlock_user(argptr, arg, 0);
49ca6f3e 5780 ret = get_errno(safe_ioctl(fd, ie->host_cmd, buf_temp));
31e31b8a 5781 if (!is_error(ret)) {
579a97f7
FB
5782 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
5783 if (!argptr)
5784 return -TARGET_EFAULT;
53a5960a
PB
5785 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
5786 unlock_user(argptr, arg, target_size);
31e31b8a
FB
5787 }
5788 break;
5789 }
5790 break;
5791 default:
39be5350
JK
5792 qemu_log_mask(LOG_UNIMP,
5793 "Unsupported ioctl type: cmd=0x%04lx type=%d\n",
5794 (long)cmd, arg_type[0]);
0da46a6e 5795 ret = -TARGET_ENOSYS;
31e31b8a
FB
5796 break;
5797 }
5798 return ret;
5799}
5800
b39bc503 5801static const bitmask_transtbl iflag_tbl[] = {
31e31b8a
FB
5802 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
5803 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
5804 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
5805 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
5806 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
5807 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
5808 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
5809 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
5810 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
5811 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
5812 { TARGET_IXON, TARGET_IXON, IXON, IXON },
5813 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
5814 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
5815 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
c218b4ed 5816 { TARGET_IUTF8, TARGET_IUTF8, IUTF8, IUTF8},
31e31b8a
FB
5817 { 0, 0, 0, 0 }
5818};
5819
b39bc503 5820static const bitmask_transtbl oflag_tbl[] = {
31e31b8a
FB
5821 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
5822 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
5823 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
5824 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
5825 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
5826 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
5827 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
5828 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
5829 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
5830 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
5831 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
5832 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
5833 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
5834 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
5835 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
5836 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
5837 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
5838 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
5839 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
5840 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
5841 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
5842 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
5843 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
5844 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
5845 { 0, 0, 0, 0 }
5846};
5847
b39bc503 5848static const bitmask_transtbl cflag_tbl[] = {
31e31b8a
FB
5849 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
5850 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
5851 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
5852 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
5853 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
5854 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
5855 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
5856 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
5857 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
5858 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
5859 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
5860 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
5861 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
5862 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
5863 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
5864 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
5865 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
5866 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
5867 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
5868 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
5869 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
5870 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
5871 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
5872 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
5873 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
5874 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
5875 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
5876 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
5877 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
5878 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
5879 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
5880 { 0, 0, 0, 0 }
5881};
5882
b39bc503 5883static const bitmask_transtbl lflag_tbl[] = {
c218b4ed
FB
5884 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
5885 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
5886 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
5887 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
5888 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
5889 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
5890 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
5891 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
5892 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
5893 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
5894 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
5895 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
5896 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
5897 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
5898 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
5899 { TARGET_EXTPROC, TARGET_EXTPROC, EXTPROC, EXTPROC},
5900 { 0, 0, 0, 0 }
31e31b8a
FB
5901};
5902
5903static void target_to_host_termios (void *dst, const void *src)
5904{
5905 struct host_termios *host = dst;
5906 const struct target_termios *target = src;
3b46e624 5907
5fafdf24 5908 host->c_iflag =
31e31b8a 5909 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
5fafdf24 5910 host->c_oflag =
31e31b8a 5911 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
5fafdf24 5912 host->c_cflag =
31e31b8a 5913 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
5fafdf24 5914 host->c_lflag =
31e31b8a
FB
5915 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
5916 host->c_line = target->c_line;
3b46e624 5917
44607123 5918 memset(host->c_cc, 0, sizeof(host->c_cc));
5fafdf24
TS
5919 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
5920 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
3b46e624 5921 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
5fafdf24 5922 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
3b46e624 5923 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
5fafdf24 5924 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
3b46e624 5925 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
5fafdf24 5926 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
3b46e624 5927 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
5fafdf24
TS
5928 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
5929 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
3b46e624
TS
5930 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
5931 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
5932 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
5933 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
5934 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
5fafdf24 5935 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
31e31b8a 5936}
3b46e624 5937
31e31b8a
FB
5938static void host_to_target_termios (void *dst, const void *src)
5939{
5940 struct target_termios *target = dst;
5941 const struct host_termios *host = src;
5942
5fafdf24 5943 target->c_iflag =
31e31b8a 5944 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
5fafdf24 5945 target->c_oflag =
31e31b8a 5946 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
5fafdf24 5947 target->c_cflag =
31e31b8a 5948 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
5fafdf24 5949 target->c_lflag =
31e31b8a
FB
5950 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
5951 target->c_line = host->c_line;
3b46e624 5952
44607123 5953 memset(target->c_cc, 0, sizeof(target->c_cc));
31e31b8a
FB
5954 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
5955 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
5956 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
5957 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
5958 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
5959 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
5960 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
5961 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
5962 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
5963 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
5964 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
5965 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
5966 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
5967 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
5968 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
5969 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
5970 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
5971}
5972
8e853dc7 5973static const StructEntry struct_termios_def = {
31e31b8a
FB
5974 .convert = { host_to_target_termios, target_to_host_termios },
5975 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
5976 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
888468db 5977 .print = print_termios,
31e31b8a
FB
5978};
5979
180d4ef3 5980static const bitmask_transtbl mmap_flags_tbl[] = {
541e1690
HD
5981 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
5982 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
5983 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
5984 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS,
5985 MAP_ANONYMOUS, MAP_ANONYMOUS },
5986 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN,
5987 MAP_GROWSDOWN, MAP_GROWSDOWN },
5988 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE,
5989 MAP_DENYWRITE, MAP_DENYWRITE },
5990 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE,
5991 MAP_EXECUTABLE, MAP_EXECUTABLE },
5992 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
5993 { TARGET_MAP_NORESERVE, TARGET_MAP_NORESERVE,
5994 MAP_NORESERVE, MAP_NORESERVE },
5995 { TARGET_MAP_HUGETLB, TARGET_MAP_HUGETLB, MAP_HUGETLB, MAP_HUGETLB },
5996 /* MAP_STACK had been ignored by the kernel for quite some time.
5997 Recognize it for the target insofar as we do not want to pass
5998 it through to the host. */
5999 { TARGET_MAP_STACK, TARGET_MAP_STACK, 0, 0 },
6000 { 0, 0, 0, 0 }
5286db75
FB
6001};
6002
9d12f79d
LV
6003/*
6004 * NOTE: TARGET_ABI32 is defined for TARGET_I386 (but not for TARGET_X86_64)
6005 * TARGET_I386 is defined if TARGET_X86_64 is defined
6006 */
2ab83ea7 6007#if defined(TARGET_I386)
6dbad63e
FB
6008
6009/* NOTE: there is really one LDT for all the threads */
b1d8e52e 6010static uint8_t *ldt_table;
6dbad63e 6011
03acab66 6012static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
6dbad63e
FB
6013{
6014 int size;
53a5960a 6015 void *p;
6dbad63e
FB
6016
6017 if (!ldt_table)
6018 return 0;
6019 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
6020 if (size > bytecount)
6021 size = bytecount;
579a97f7
FB
6022 p = lock_user(VERIFY_WRITE, ptr, size, 0);
6023 if (!p)
03acab66 6024 return -TARGET_EFAULT;
579a97f7 6025 /* ??? Should this by byteswapped? */
53a5960a
PB
6026 memcpy(p, ldt_table, size);
6027 unlock_user(p, ptr, size);
6dbad63e
FB
6028 return size;
6029}
6030
6031/* XXX: add locking support */
03acab66
FB
6032static abi_long write_ldt(CPUX86State *env,
6033 abi_ulong ptr, unsigned long bytecount, int oldmode)
6dbad63e
FB
6034{
6035 struct target_modify_ldt_ldt_s ldt_info;
53a5960a 6036 struct target_modify_ldt_ldt_s *target_ldt_info;
6dbad63e 6037 int seg_32bit, contents, read_exec_only, limit_in_pages;
8d18e893 6038 int seg_not_present, useable, lm;
6dbad63e
FB
6039 uint32_t *lp, entry_1, entry_2;
6040
6041 if (bytecount != sizeof(ldt_info))
03acab66 6042 return -TARGET_EINVAL;
579a97f7 6043 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
03acab66 6044 return -TARGET_EFAULT;
53a5960a 6045 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6046 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
53a5960a
PB
6047 ldt_info.limit = tswap32(target_ldt_info->limit);
6048 ldt_info.flags = tswap32(target_ldt_info->flags);
6049 unlock_user_struct(target_ldt_info, ptr, 0);
3b46e624 6050
6dbad63e 6051 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
03acab66 6052 return -TARGET_EINVAL;
6dbad63e
FB
6053 seg_32bit = ldt_info.flags & 1;
6054 contents = (ldt_info.flags >> 1) & 3;
6055 read_exec_only = (ldt_info.flags >> 3) & 1;
6056 limit_in_pages = (ldt_info.flags >> 4) & 1;
6057 seg_not_present = (ldt_info.flags >> 5) & 1;
6058 useable = (ldt_info.flags >> 6) & 1;
8d18e893
FB
6059#ifdef TARGET_ABI32
6060 lm = 0;
6061#else
6062 lm = (ldt_info.flags >> 7) & 1;
6063#endif
6dbad63e
FB
6064 if (contents == 3) {
6065 if (oldmode)
03acab66 6066 return -TARGET_EINVAL;
6dbad63e 6067 if (seg_not_present == 0)
03acab66 6068 return -TARGET_EINVAL;
6dbad63e
FB
6069 }
6070 /* allocate the LDT */
6071 if (!ldt_table) {
e441570f
AZ
6072 env->ldt.base = target_mmap(0,
6073 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
6074 PROT_READ|PROT_WRITE,
6075 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
6076 if (env->ldt.base == -1)
03acab66 6077 return -TARGET_ENOMEM;
3e8f1628 6078 memset(g2h_untagged(env->ldt.base), 0,
e441570f 6079 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
6dbad63e 6080 env->ldt.limit = 0xffff;
3e8f1628 6081 ldt_table = g2h_untagged(env->ldt.base);
6dbad63e
FB
6082 }
6083
6084 /* NOTE: same code as Linux kernel */
6085 /* Allow LDTs to be cleared by the user. */
6086 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6087 if (oldmode ||
6088 (contents == 0 &&
6089 read_exec_only == 1 &&
6090 seg_32bit == 0 &&
6091 limit_in_pages == 0 &&
6092 seg_not_present == 1 &&
6093 useable == 0 )) {
6094 entry_1 = 0;
6095 entry_2 = 0;
6096 goto install;
6097 }
6098 }
3b46e624 6099
6dbad63e
FB
6100 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6101 (ldt_info.limit & 0x0ffff);
6102 entry_2 = (ldt_info.base_addr & 0xff000000) |
6103 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6104 (ldt_info.limit & 0xf0000) |
6105 ((read_exec_only ^ 1) << 9) |
6106 (contents << 10) |
6107 ((seg_not_present ^ 1) << 15) |
6108 (seg_32bit << 22) |
6109 (limit_in_pages << 23) |
8d18e893 6110 (lm << 21) |
6dbad63e
FB
6111 0x7000;
6112 if (!oldmode)
6113 entry_2 |= (useable << 20);
14ae3ba7 6114
6dbad63e
FB
6115 /* Install the new entry ... */
6116install:
6117 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
6118 lp[0] = tswap32(entry_1);
6119 lp[1] = tswap32(entry_2);
6120 return 0;
6121}
6122
6123/* specific and weird i386 syscalls */
8fcd3692
BS
6124static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
6125 unsigned long bytecount)
6dbad63e 6126{
03acab66 6127 abi_long ret;
3b46e624 6128
6dbad63e
FB
6129 switch (func) {
6130 case 0:
6131 ret = read_ldt(ptr, bytecount);
6132 break;
6133 case 1:
6134 ret = write_ldt(env, ptr, bytecount, 1);
6135 break;
6136 case 0x11:
6137 ret = write_ldt(env, ptr, bytecount, 0);
6138 break;
03acab66
FB
6139 default:
6140 ret = -TARGET_ENOSYS;
6141 break;
6dbad63e
FB
6142 }
6143 return ret;
6144}
1b6b029e 6145
9d12f79d 6146#if defined(TARGET_ABI32)
bc22eb44 6147abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893 6148{
3e8f1628 6149 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6150 struct target_modify_ldt_ldt_s ldt_info;
6151 struct target_modify_ldt_ldt_s *target_ldt_info;
6152 int seg_32bit, contents, read_exec_only, limit_in_pages;
6153 int seg_not_present, useable, lm;
6154 uint32_t *lp, entry_1, entry_2;
6155 int i;
6156
6157 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6158 if (!target_ldt_info)
6159 return -TARGET_EFAULT;
6160 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
cbb21eed 6161 ldt_info.base_addr = tswapal(target_ldt_info->base_addr);
8d18e893
FB
6162 ldt_info.limit = tswap32(target_ldt_info->limit);
6163 ldt_info.flags = tswap32(target_ldt_info->flags);
6164 if (ldt_info.entry_number == -1) {
6165 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
6166 if (gdt_table[i] == 0) {
6167 ldt_info.entry_number = i;
6168 target_ldt_info->entry_number = tswap32(i);
6169 break;
6170 }
6171 }
6172 }
6173 unlock_user_struct(target_ldt_info, ptr, 1);
6174
6175 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
6176 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
6177 return -TARGET_EINVAL;
6178 seg_32bit = ldt_info.flags & 1;
6179 contents = (ldt_info.flags >> 1) & 3;
6180 read_exec_only = (ldt_info.flags >> 3) & 1;
6181 limit_in_pages = (ldt_info.flags >> 4) & 1;
6182 seg_not_present = (ldt_info.flags >> 5) & 1;
6183 useable = (ldt_info.flags >> 6) & 1;
6184#ifdef TARGET_ABI32
6185 lm = 0;
6186#else
6187 lm = (ldt_info.flags >> 7) & 1;
6188#endif
6189
6190 if (contents == 3) {
6191 if (seg_not_present == 0)
6192 return -TARGET_EINVAL;
6193 }
6194
6195 /* NOTE: same code as Linux kernel */
6196 /* Allow LDTs to be cleared by the user. */
6197 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
6198 if ((contents == 0 &&
6199 read_exec_only == 1 &&
6200 seg_32bit == 0 &&
6201 limit_in_pages == 0 &&
6202 seg_not_present == 1 &&
6203 useable == 0 )) {
6204 entry_1 = 0;
6205 entry_2 = 0;
6206 goto install;
6207 }
6208 }
6209
6210 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
6211 (ldt_info.limit & 0x0ffff);
6212 entry_2 = (ldt_info.base_addr & 0xff000000) |
6213 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
6214 (ldt_info.limit & 0xf0000) |
6215 ((read_exec_only ^ 1) << 9) |
6216 (contents << 10) |
6217 ((seg_not_present ^ 1) << 15) |
6218 (seg_32bit << 22) |
6219 (limit_in_pages << 23) |
6220 (useable << 20) |
6221 (lm << 21) |
6222 0x7000;
6223
6224 /* Install the new entry ... */
6225install:
6226 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
6227 lp[0] = tswap32(entry_1);
6228 lp[1] = tswap32(entry_2);
6229 return 0;
6230}
6231
8fcd3692 6232static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
8d18e893
FB
6233{
6234 struct target_modify_ldt_ldt_s *target_ldt_info;
3e8f1628 6235 uint64_t *gdt_table = g2h_untagged(env->gdt.base);
8d18e893
FB
6236 uint32_t base_addr, limit, flags;
6237 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
6238 int seg_not_present, useable, lm;
6239 uint32_t *lp, entry_1, entry_2;
6240
6241 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
6242 if (!target_ldt_info)
6243 return -TARGET_EFAULT;
6244 idx = tswap32(target_ldt_info->entry_number);
6245 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
6246 idx > TARGET_GDT_ENTRY_TLS_MAX) {
6247 unlock_user_struct(target_ldt_info, ptr, 1);
6248 return -TARGET_EINVAL;
6249 }
6250 lp = (uint32_t *)(gdt_table + idx);
6251 entry_1 = tswap32(lp[0]);
6252 entry_2 = tswap32(lp[1]);
6253
6254 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
6255 contents = (entry_2 >> 10) & 3;
6256 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
6257 seg_32bit = (entry_2 >> 22) & 1;
6258 limit_in_pages = (entry_2 >> 23) & 1;
6259 useable = (entry_2 >> 20) & 1;
6260#ifdef TARGET_ABI32
6261 lm = 0;
6262#else
6263 lm = (entry_2 >> 21) & 1;
6264#endif
6265 flags = (seg_32bit << 0) | (contents << 1) |
6266 (read_exec_only << 3) | (limit_in_pages << 4) |
6267 (seg_not_present << 5) | (useable << 6) | (lm << 7);
6268 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
6269 base_addr = (entry_1 >> 16) |
6270 (entry_2 & 0xff000000) |
6271 ((entry_2 & 0xff) << 16);
cbb21eed 6272 target_ldt_info->base_addr = tswapal(base_addr);
8d18e893
FB
6273 target_ldt_info->limit = tswap32(limit);
6274 target_ldt_info->flags = tswap32(flags);
6275 unlock_user_struct(target_ldt_info, ptr, 1);
6276 return 0;
6277}
6278
9d12f79d
LV
6279abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
6280{
538fabcb 6281 return -TARGET_ENOSYS;
9d12f79d
LV
6282}
6283#else
2667e71c 6284abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
d2fd1af7 6285{
1add8698 6286 abi_long ret = 0;
d2fd1af7
FB
6287 abi_ulong val;
6288 int idx;
1add8698 6289
d2fd1af7
FB
6290 switch(code) {
6291 case TARGET_ARCH_SET_GS:
6292 case TARGET_ARCH_SET_FS:
6293 if (code == TARGET_ARCH_SET_GS)
6294 idx = R_GS;
6295 else
6296 idx = R_FS;
6297 cpu_x86_load_seg(env, idx, 0);
6298 env->segs[idx].base = addr;
6299 break;
6300 case TARGET_ARCH_GET_GS:
6301 case TARGET_ARCH_GET_FS:
6302 if (code == TARGET_ARCH_GET_GS)
6303 idx = R_GS;
6304 else
6305 idx = R_FS;
6306 val = env->segs[idx].base;
6307 if (put_user(val, addr, abi_ulong))
1add8698 6308 ret = -TARGET_EFAULT;
d2fd1af7
FB
6309 break;
6310 default:
6311 ret = -TARGET_EINVAL;
6312 break;
6313 }
1add8698 6314 return ret;
d2fd1af7 6315}
9d12f79d 6316#endif /* defined(TARGET_ABI32 */
2ab83ea7
FB
6317#endif /* defined(TARGET_I386) */
6318
87e9bf23
RH
6319/*
6320 * These constants are generic. Supply any that are missing from the host.
6321 */
6322#ifndef PR_SET_NAME
6323# define PR_SET_NAME 15
6324# define PR_GET_NAME 16
6325#endif
6326#ifndef PR_SET_FP_MODE
6327# define PR_SET_FP_MODE 45
6328# define PR_GET_FP_MODE 46
6329# define PR_FP_MODE_FR (1 << 0)
6330# define PR_FP_MODE_FRE (1 << 1)
6331#endif
6332#ifndef PR_SVE_SET_VL
6333# define PR_SVE_SET_VL 50
6334# define PR_SVE_GET_VL 51
6335# define PR_SVE_VL_LEN_MASK 0xffff
6336# define PR_SVE_VL_INHERIT (1 << 17)
6337#endif
6338#ifndef PR_PAC_RESET_KEYS
6339# define PR_PAC_RESET_KEYS 54
6340# define PR_PAC_APIAKEY (1 << 0)
6341# define PR_PAC_APIBKEY (1 << 1)
6342# define PR_PAC_APDAKEY (1 << 2)
6343# define PR_PAC_APDBKEY (1 << 3)
6344# define PR_PAC_APGAKEY (1 << 4)
6345#endif
6346#ifndef PR_SET_TAGGED_ADDR_CTRL
6347# define PR_SET_TAGGED_ADDR_CTRL 55
6348# define PR_GET_TAGGED_ADDR_CTRL 56
6349# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
6350#endif
6351#ifndef PR_MTE_TCF_SHIFT
6352# define PR_MTE_TCF_SHIFT 1
6353# define PR_MTE_TCF_NONE (0UL << PR_MTE_TCF_SHIFT)
6354# define PR_MTE_TCF_SYNC (1UL << PR_MTE_TCF_SHIFT)
6355# define PR_MTE_TCF_ASYNC (2UL << PR_MTE_TCF_SHIFT)
6356# define PR_MTE_TCF_MASK (3UL << PR_MTE_TCF_SHIFT)
6357# define PR_MTE_TAG_SHIFT 3
6358# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
6359#endif
220717a6
RH
6360#ifndef PR_SET_IO_FLUSHER
6361# define PR_SET_IO_FLUSHER 57
6362# define PR_GET_IO_FLUSHER 58
6363#endif
6364#ifndef PR_SET_SYSCALL_USER_DISPATCH
6365# define PR_SET_SYSCALL_USER_DISPATCH 59
6366#endif
87e9bf23
RH
6367
6368#include "target_prctl.h"
6369
6370static abi_long do_prctl_inval0(CPUArchState *env)
6371{
6372 return -TARGET_EINVAL;
6373}
6374
6375static abi_long do_prctl_inval1(CPUArchState *env, abi_long arg2)
6376{
6377 return -TARGET_EINVAL;
6378}
6379
6380#ifndef do_prctl_get_fp_mode
6381#define do_prctl_get_fp_mode do_prctl_inval0
6382#endif
6383#ifndef do_prctl_set_fp_mode
6384#define do_prctl_set_fp_mode do_prctl_inval1
6385#endif
6386#ifndef do_prctl_get_vl
6387#define do_prctl_get_vl do_prctl_inval0
6388#endif
6389#ifndef do_prctl_set_vl
6390#define do_prctl_set_vl do_prctl_inval1
6391#endif
6392#ifndef do_prctl_reset_keys
6393#define do_prctl_reset_keys do_prctl_inval1
6394#endif
6395#ifndef do_prctl_set_tagged_addr_ctrl
6396#define do_prctl_set_tagged_addr_ctrl do_prctl_inval1
6397#endif
6398#ifndef do_prctl_get_tagged_addr_ctrl
6399#define do_prctl_get_tagged_addr_ctrl do_prctl_inval0
6400#endif
6e8dcacd
RH
6401#ifndef do_prctl_get_unalign
6402#define do_prctl_get_unalign do_prctl_inval1
6403#endif
6404#ifndef do_prctl_set_unalign
6405#define do_prctl_set_unalign do_prctl_inval1
6406#endif
87e9bf23
RH
6407
6408static abi_long do_prctl(CPUArchState *env, abi_long option, abi_long arg2,
6409 abi_long arg3, abi_long arg4, abi_long arg5)
6410{
6411 abi_long ret;
6412
6413 switch (option) {
6414 case PR_GET_PDEATHSIG:
6415 {
6416 int deathsig;
6417 ret = get_errno(prctl(PR_GET_PDEATHSIG, &deathsig,
6418 arg3, arg4, arg5));
1edebb36
RH
6419 if (!is_error(ret) &&
6420 put_user_s32(host_to_target_signal(deathsig), arg2)) {
87e9bf23
RH
6421 return -TARGET_EFAULT;
6422 }
6423 return ret;
6424 }
f746c659
RH
6425 case PR_SET_PDEATHSIG:
6426 return get_errno(prctl(PR_SET_PDEATHSIG, target_to_host_signal(arg2),
6427 arg3, arg4, arg5));
87e9bf23
RH
6428 case PR_GET_NAME:
6429 {
6430 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
6431 if (!name) {
6432 return -TARGET_EFAULT;
6433 }
6434 ret = get_errno(prctl(PR_GET_NAME, (uintptr_t)name,
6435 arg3, arg4, arg5));
6436 unlock_user(name, arg2, 16);
6437 return ret;
6438 }
6439 case PR_SET_NAME:
6440 {
6441 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
6442 if (!name) {
6443 return -TARGET_EFAULT;
6444 }
6445 ret = get_errno(prctl(PR_SET_NAME, (uintptr_t)name,
6446 arg3, arg4, arg5));
6447 unlock_user(name, arg2, 0);
6448 return ret;
6449 }
6450 case PR_GET_FP_MODE:
6451 return do_prctl_get_fp_mode(env);
6452 case PR_SET_FP_MODE:
6453 return do_prctl_set_fp_mode(env, arg2);
6454 case PR_SVE_GET_VL:
6455 return do_prctl_get_vl(env);
6456 case PR_SVE_SET_VL:
6457 return do_prctl_set_vl(env, arg2);
6458 case PR_PAC_RESET_KEYS:
6459 if (arg3 || arg4 || arg5) {
6460 return -TARGET_EINVAL;
6461 }
6462 return do_prctl_reset_keys(env, arg2);
6463 case PR_SET_TAGGED_ADDR_CTRL:
6464 if (arg3 || arg4 || arg5) {
6465 return -TARGET_EINVAL;
6466 }
6467 return do_prctl_set_tagged_addr_ctrl(env, arg2);
6468 case PR_GET_TAGGED_ADDR_CTRL:
6469 if (arg2 || arg3 || arg4 || arg5) {
6470 return -TARGET_EINVAL;
6471 }
6472 return do_prctl_get_tagged_addr_ctrl(env);
220717a6 6473
6e8dcacd
RH
6474 case PR_GET_UNALIGN:
6475 return do_prctl_get_unalign(env, arg2);
6476 case PR_SET_UNALIGN:
6477 return do_prctl_set_unalign(env, arg2);
6478
4f4e5567
RH
6479 case PR_CAP_AMBIENT:
6480 case PR_CAPBSET_READ:
6481 case PR_CAPBSET_DROP:
220717a6
RH
6482 case PR_GET_DUMPABLE:
6483 case PR_SET_DUMPABLE:
6484 case PR_GET_KEEPCAPS:
6485 case PR_SET_KEEPCAPS:
4f4e5567
RH
6486 case PR_GET_SECUREBITS:
6487 case PR_SET_SECUREBITS:
220717a6
RH
6488 case PR_GET_TIMING:
6489 case PR_SET_TIMING:
6490 case PR_GET_TIMERSLACK:
6491 case PR_SET_TIMERSLACK:
6492 case PR_MCE_KILL:
6493 case PR_MCE_KILL_GET:
6494 case PR_GET_NO_NEW_PRIVS:
6495 case PR_SET_NO_NEW_PRIVS:
6496 case PR_GET_IO_FLUSHER:
6497 case PR_SET_IO_FLUSHER:
6498 /* Some prctl options have no pointer arguments and we can pass on. */
6499 return get_errno(prctl(option, arg2, arg3, arg4, arg5));
6500
6501 case PR_GET_CHILD_SUBREAPER:
6502 case PR_SET_CHILD_SUBREAPER:
6503 case PR_GET_SPECULATION_CTRL:
6504 case PR_SET_SPECULATION_CTRL:
6505 case PR_GET_TID_ADDRESS:
6506 /* TODO */
6507 return -TARGET_EINVAL;
6508
6509 case PR_GET_FPEXC:
6510 case PR_SET_FPEXC:
6511 /* Was used for SPE on PowerPC. */
6512 return -TARGET_EINVAL;
6513
6514 case PR_GET_ENDIAN:
6515 case PR_SET_ENDIAN:
6516 case PR_GET_FPEMU:
6517 case PR_SET_FPEMU:
6518 case PR_SET_MM:
87e9bf23
RH
6519 case PR_GET_SECCOMP:
6520 case PR_SET_SECCOMP:
220717a6
RH
6521 case PR_SET_SYSCALL_USER_DISPATCH:
6522 case PR_GET_THP_DISABLE:
6523 case PR_SET_THP_DISABLE:
6524 case PR_GET_TSC:
6525 case PR_SET_TSC:
220717a6 6526 /* Disable to prevent the target disabling stuff we need. */
87e9bf23 6527 return -TARGET_EINVAL;
220717a6 6528
87e9bf23 6529 default:
220717a6
RH
6530 qemu_log_mask(LOG_UNIMP, "Unsupported prctl: " TARGET_ABI_FMT_ld "\n",
6531 option);
6532 return -TARGET_EINVAL;
87e9bf23
RH
6533 }
6534}
6535
05098a93 6536#define NEW_STACK_SIZE 0x40000
d865bab5 6537
d865bab5
PB
6538
6539static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
6540typedef struct {
9349b4f9 6541 CPUArchState *env;
d865bab5
PB
6542 pthread_mutex_t mutex;
6543 pthread_cond_t cond;
6544 pthread_t thread;
6545 uint32_t tid;
6546 abi_ulong child_tidptr;
6547 abi_ulong parent_tidptr;
6548 sigset_t sigmask;
6549} new_thread_info;
6550
6551static void *clone_func(void *arg)
6552{
6553 new_thread_info *info = arg;
9349b4f9 6554 CPUArchState *env;
0d34282f 6555 CPUState *cpu;
edf8e2af 6556 TaskState *ts;
d865bab5 6557
70903763 6558 rcu_register_thread();
3468b59e 6559 tcg_register_thread();
d865bab5 6560 env = info->env;
29a0af61 6561 cpu = env_cpu(env);
a2247f8e 6562 thread_cpu = cpu;
0429a971 6563 ts = (TaskState *)cpu->opaque;
71ba74f6 6564 info->tid = sys_gettid();
edf8e2af 6565 task_settid(ts);
d865bab5
PB
6566 if (info->child_tidptr)
6567 put_user_u32(info->tid, info->child_tidptr);
6568 if (info->parent_tidptr)
6569 put_user_u32(info->tid, info->parent_tidptr);
5ebdd774 6570 qemu_guest_random_seed_thread_part2(cpu->random_seed);
d865bab5
PB
6571 /* Enable signals. */
6572 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
6573 /* Signal to the parent that we're ready. */
6574 pthread_mutex_lock(&info->mutex);
6575 pthread_cond_broadcast(&info->cond);
6576 pthread_mutex_unlock(&info->mutex);
a4dd3d51 6577 /* Wait until the parent has finished initializing the tls state. */
d865bab5
PB
6578 pthread_mutex_lock(&clone_lock);
6579 pthread_mutex_unlock(&clone_lock);
6580 cpu_loop(env);
6581 /* never exits */
6582 return NULL;
6583}
1b6b029e 6584
0da46a6e
TS
6585/* do_fork() Must return host values and target errnos (unlike most
6586 do_*() functions). */
9349b4f9 6587static int do_fork(CPUArchState *env, unsigned int flags, abi_ulong newsp,
d865bab5
PB
6588 abi_ulong parent_tidptr, target_ulong newtls,
6589 abi_ulong child_tidptr)
1b6b029e 6590{
29a0af61 6591 CPUState *cpu = env_cpu(env);
1b6b029e 6592 int ret;
5cd4393b 6593 TaskState *ts;
0429a971 6594 CPUState *new_cpu;
9349b4f9 6595 CPUArchState *new_env;
d865bab5 6596 sigset_t sigmask;
3b46e624 6597
5ea2fc84
PM
6598 flags &= ~CLONE_IGNORED_FLAGS;
6599
436d124b
AZ
6600 /* Emulate vfork() with fork() */
6601 if (flags & CLONE_VFORK)
6602 flags &= ~(CLONE_VFORK | CLONE_VM);
6603
1b6b029e 6604 if (flags & CLONE_VM) {
0429a971 6605 TaskState *parent_ts = (TaskState *)cpu->opaque;
d865bab5
PB
6606 new_thread_info info;
6607 pthread_attr_t attr;
24cb36a6 6608
5ea2fc84
PM
6609 if (((flags & CLONE_THREAD_FLAGS) != CLONE_THREAD_FLAGS) ||
6610 (flags & CLONE_INVALID_THREAD_FLAGS)) {
6611 return -TARGET_EINVAL;
6612 }
6613
c78d65e8 6614 ts = g_new0(TaskState, 1);
624f7979 6615 init_task_state(ts);
73a988d9
MF
6616
6617 /* Grab a mutex so that thread setup appears atomic. */
6618 pthread_mutex_lock(&clone_lock);
6619
6cc9d67c
RH
6620 /*
6621 * If this is our first additional thread, we need to ensure we
6622 * generate code for parallel execution and flush old translations.
6623 * Do this now so that the copy gets CF_PARALLEL too.
6624 */
6625 if (!(cpu->tcg_cflags & CF_PARALLEL)) {
6626 cpu->tcg_cflags |= CF_PARALLEL;
6627 tb_flush(cpu);
6628 }
6629
1b6b029e 6630 /* we create a new CPU instance. */
c5be9f08 6631 new_env = cpu_copy(env);
6e68e076 6632 /* Init regs that differ from the parent. */
608999d1 6633 cpu_clone_regs_child(new_env, newsp, flags);
07a6ecf4 6634 cpu_clone_regs_parent(env, flags);
29a0af61 6635 new_cpu = env_cpu(new_env);
0429a971 6636 new_cpu->opaque = ts;
edf8e2af
MW
6637 ts->bprm = parent_ts->bprm;
6638 ts->info = parent_ts->info;
3d3efba0 6639 ts->signal_mask = parent_ts->signal_mask;
d865bab5 6640
7cfbd386 6641 if (flags & CLONE_CHILD_CLEARTID) {
c2764719
PB
6642 ts->child_tidptr = child_tidptr;
6643 }
6644
7cfbd386 6645 if (flags & CLONE_SETTLS) {
d865bab5 6646 cpu_set_tls (new_env, newtls);
7cfbd386 6647 }
d865bab5 6648
d865bab5
PB
6649 memset(&info, 0, sizeof(info));
6650 pthread_mutex_init(&info.mutex, NULL);
6651 pthread_mutex_lock(&info.mutex);
6652 pthread_cond_init(&info.cond, NULL);
6653 info.env = new_env;
7cfbd386 6654 if (flags & CLONE_CHILD_SETTID) {
d865bab5 6655 info.child_tidptr = child_tidptr;
7cfbd386
PM
6656 }
6657 if (flags & CLONE_PARENT_SETTID) {
d865bab5 6658 info.parent_tidptr = parent_tidptr;
7cfbd386 6659 }
d865bab5
PB
6660
6661 ret = pthread_attr_init(&attr);
48e15fc2
NF
6662 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
6663 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
d865bab5
PB
6664 /* It is not safe to deliver signals until the child has finished
6665 initializing, so temporarily block all signals. */
6666 sigfillset(&sigmask);
6667 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
5ebdd774 6668 cpu->random_seed = qemu_guest_random_seed_thread_part1();
d865bab5
PB
6669
6670 ret = pthread_create(&info.thread, &attr, clone_func, &info);
c2764719 6671 /* TODO: Free new CPU state if thread creation failed. */
d865bab5
PB
6672
6673 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
6674 pthread_attr_destroy(&attr);
6675 if (ret == 0) {
6676 /* Wait for the child to initialize. */
6677 pthread_cond_wait(&info.cond, &info.mutex);
6678 ret = info.tid;
d865bab5
PB
6679 } else {
6680 ret = -1;
6681 }
6682 pthread_mutex_unlock(&info.mutex);
6683 pthread_cond_destroy(&info.cond);
6684 pthread_mutex_destroy(&info.mutex);
6685 pthread_mutex_unlock(&clone_lock);
1b6b029e
FB
6686 } else {
6687 /* if no CLONE_VM, we consider it is a fork */
5ea2fc84
PM
6688 if (flags & CLONE_INVALID_FORK_FLAGS) {
6689 return -TARGET_EINVAL;
6690 }
6691
6692 /* We can't support custom termination signals */
6693 if ((flags & CSIGNAL) != TARGET_SIGCHLD) {
93b4eff8
TB
6694 return -TARGET_EINVAL;
6695 }
7d92d34e
TB
6696
6697 if (block_signals()) {
af254a27 6698 return -QEMU_ERESTARTSYS;
7d92d34e
TB
6699 }
6700
d865bab5 6701 fork_start();
1b6b029e 6702 ret = fork();
d865bab5 6703 if (ret == 0) {
2b1319c8 6704 /* Child Process. */
608999d1 6705 cpu_clone_regs_child(env, newsp, flags);
d865bab5 6706 fork_end(1);
2b1319c8
AJ
6707 /* There is a race condition here. The parent process could
6708 theoretically read the TID in the child process before the child
6709 tid is set. This would require using either ptrace
6710 (not implemented) or having *_tidptr to point at a shared memory
6711 mapping. We can't repeat the spinlock hack used above because
6712 the child process gets its own copy of the lock. */
d865bab5 6713 if (flags & CLONE_CHILD_SETTID)
71ba74f6 6714 put_user_u32(sys_gettid(), child_tidptr);
d865bab5 6715 if (flags & CLONE_PARENT_SETTID)
71ba74f6 6716 put_user_u32(sys_gettid(), parent_tidptr);
0429a971 6717 ts = (TaskState *)cpu->opaque;
d865bab5
PB
6718 if (flags & CLONE_SETTLS)
6719 cpu_set_tls (env, newtls);
c2764719
PB
6720 if (flags & CLONE_CHILD_CLEARTID)
6721 ts->child_tidptr = child_tidptr;
d865bab5 6722 } else {
07a6ecf4 6723 cpu_clone_regs_parent(env, flags);
d865bab5
PB
6724 fork_end(0);
6725 }
1b6b029e
FB
6726 }
6727 return ret;
6728}
6729
5f106811
APR
6730/* warning : doesn't handle linux specific flags... */
6731static int target_to_host_fcntl_cmd(int cmd)
6732{
4a545761
SB
6733 int ret;
6734
5f106811 6735 switch(cmd) {
4a545761
SB
6736 case TARGET_F_DUPFD:
6737 case TARGET_F_GETFD:
6738 case TARGET_F_SETFD:
6739 case TARGET_F_GETFL:
6740 case TARGET_F_SETFL:
2d92c682
AS
6741 case TARGET_F_OFD_GETLK:
6742 case TARGET_F_OFD_SETLK:
6743 case TARGET_F_OFD_SETLKW:
4a545761
SB
6744 ret = cmd;
6745 break;
6746 case TARGET_F_GETLK:
6747 ret = F_GETLK64;
6748 break;
6749 case TARGET_F_SETLK:
6750 ret = F_SETLK64;
6751 break;
6752 case TARGET_F_SETLKW:
6753 ret = F_SETLKW64;
6754 break;
6755 case TARGET_F_GETOWN:
6756 ret = F_GETOWN;
6757 break;
6758 case TARGET_F_SETOWN:
6759 ret = F_SETOWN;
6760 break;
6761 case TARGET_F_GETSIG:
6762 ret = F_GETSIG;
6763 break;
6764 case TARGET_F_SETSIG:
6765 ret = F_SETSIG;
6766 break;
5f106811 6767#if TARGET_ABI_BITS == 32
4a545761
SB
6768 case TARGET_F_GETLK64:
6769 ret = F_GETLK64;
6770 break;
6771 case TARGET_F_SETLK64:
6772 ret = F_SETLK64;
6773 break;
6774 case TARGET_F_SETLKW64:
6775 ret = F_SETLKW64;
6776 break;
5f106811 6777#endif
4a545761
SB
6778 case TARGET_F_SETLEASE:
6779 ret = F_SETLEASE;
6780 break;
6781 case TARGET_F_GETLEASE:
6782 ret = F_GETLEASE;
6783 break;
fbd5de9b 6784#ifdef F_DUPFD_CLOEXEC
4a545761
SB
6785 case TARGET_F_DUPFD_CLOEXEC:
6786 ret = F_DUPFD_CLOEXEC;
6787 break;
fbd5de9b 6788#endif
4a545761
SB
6789 case TARGET_F_NOTIFY:
6790 ret = F_NOTIFY;
6791 break;
8d5d3004 6792#ifdef F_GETOWN_EX
4a545761
SB
6793 case TARGET_F_GETOWN_EX:
6794 ret = F_GETOWN_EX;
6795 break;
8d5d3004
AS
6796#endif
6797#ifdef F_SETOWN_EX
4a545761
SB
6798 case TARGET_F_SETOWN_EX:
6799 ret = F_SETOWN_EX;
6800 break;
8d5d3004 6801#endif
ddf31aa8 6802#ifdef F_SETPIPE_SZ
4a545761
SB
6803 case TARGET_F_SETPIPE_SZ:
6804 ret = F_SETPIPE_SZ;
6805 break;
6806 case TARGET_F_GETPIPE_SZ:
6807 ret = F_GETPIPE_SZ;
6808 break;
2bb963ff
SCW
6809#endif
6810#ifdef F_ADD_SEALS
6811 case TARGET_F_ADD_SEALS:
6812 ret = F_ADD_SEALS;
6813 break;
6814 case TARGET_F_GET_SEALS:
6815 ret = F_GET_SEALS;
6816 break;
ddf31aa8 6817#endif
4a545761
SB
6818 default:
6819 ret = -TARGET_EINVAL;
6820 break;
6821 }
6822
6823#if defined(__powerpc64__)
6824 /* On PPC64, glibc headers has the F_*LK* defined to 12, 13 and 14 and
6825 * is not supported by kernel. The glibc fcntl call actually adjusts
6826 * them to 5, 6 and 7 before making the syscall(). Since we make the
6827 * syscall directly, adjust to what is supported by the kernel.
6828 */
6829 if (ret >= F_GETLK64 && ret <= F_SETLKW64) {
6830 ret -= F_GETLK64 - 5;
5f106811 6831 }
4a545761
SB
6832#endif
6833
6834 return ret;
5f106811
APR
6835}
6836
ae68ad9f
LV
6837#define FLOCK_TRANSTBL \
6838 switch (type) { \
6839 TRANSTBL_CONVERT(F_RDLCK); \
6840 TRANSTBL_CONVERT(F_WRLCK); \
6841 TRANSTBL_CONVERT(F_UNLCK); \
ae68ad9f
LV
6842 }
6843
6844static int target_to_host_flock(int type)
6845{
6846#define TRANSTBL_CONVERT(a) case TARGET_##a: return a
6847 FLOCK_TRANSTBL
6848#undef TRANSTBL_CONVERT
6849 return -TARGET_EINVAL;
6850}
6851
6852static int host_to_target_flock(int type)
6853{
6854#define TRANSTBL_CONVERT(a) case a: return TARGET_##a
6855 FLOCK_TRANSTBL
6856#undef TRANSTBL_CONVERT
6857 /* if we don't know how to convert the value coming
6858 * from the host we copy to the target field as-is
6859 */
6860 return type;
6861}
2ba7f730 6862
213d3e9e
PM
6863static inline abi_long copy_from_user_flock(struct flock64 *fl,
6864 abi_ulong target_flock_addr)
7775e9ec 6865{
53a5960a 6866 struct target_flock *target_fl;
ae68ad9f 6867 int l_type;
213d3e9e
PM
6868
6869 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6870 return -TARGET_EFAULT;
6871 }
6872
6873 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6874 l_type = target_to_host_flock(l_type);
6875 if (l_type < 0) {
6876 return l_type;
6877 }
6878 fl->l_type = l_type;
213d3e9e
PM
6879 __get_user(fl->l_whence, &target_fl->l_whence);
6880 __get_user(fl->l_start, &target_fl->l_start);
6881 __get_user(fl->l_len, &target_fl->l_len);
6882 __get_user(fl->l_pid, &target_fl->l_pid);
6883 unlock_user_struct(target_fl, target_flock_addr, 0);
6884 return 0;
6885}
6886
6887static inline abi_long copy_to_user_flock(abi_ulong target_flock_addr,
6888 const struct flock64 *fl)
6889{
6890 struct target_flock *target_fl;
6891 short l_type;
6892
6893 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6894 return -TARGET_EFAULT;
6895 }
6896
ae68ad9f 6897 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6898 __put_user(l_type, &target_fl->l_type);
6899 __put_user(fl->l_whence, &target_fl->l_whence);
6900 __put_user(fl->l_start, &target_fl->l_start);
6901 __put_user(fl->l_len, &target_fl->l_len);
6902 __put_user(fl->l_pid, &target_fl->l_pid);
6903 unlock_user_struct(target_fl, target_flock_addr, 1);
6904 return 0;
6905}
6906
6907typedef abi_long from_flock64_fn(struct flock64 *fl, abi_ulong target_addr);
6908typedef abi_long to_flock64_fn(abi_ulong target_addr, const struct flock64 *fl);
6909
6910#if defined(TARGET_ARM) && TARGET_ABI_BITS == 32
ffe81d43
RH
6911struct target_oabi_flock64 {
6912 abi_short l_type;
6913 abi_short l_whence;
6914 abi_llong l_start;
6915 abi_llong l_len;
6916 abi_int l_pid;
6917} QEMU_PACKED;
6918
7f254c5c 6919static inline abi_long copy_from_user_oabi_flock64(struct flock64 *fl,
213d3e9e
PM
6920 abi_ulong target_flock_addr)
6921{
7f254c5c 6922 struct target_oabi_flock64 *target_fl;
ae68ad9f 6923 int l_type;
213d3e9e
PM
6924
6925 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6926 return -TARGET_EFAULT;
6927 }
6928
6929 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6930 l_type = target_to_host_flock(l_type);
6931 if (l_type < 0) {
6932 return l_type;
6933 }
6934 fl->l_type = l_type;
213d3e9e
PM
6935 __get_user(fl->l_whence, &target_fl->l_whence);
6936 __get_user(fl->l_start, &target_fl->l_start);
6937 __get_user(fl->l_len, &target_fl->l_len);
6938 __get_user(fl->l_pid, &target_fl->l_pid);
6939 unlock_user_struct(target_fl, target_flock_addr, 0);
6940 return 0;
6941}
6942
7f254c5c 6943static inline abi_long copy_to_user_oabi_flock64(abi_ulong target_flock_addr,
213d3e9e
PM
6944 const struct flock64 *fl)
6945{
7f254c5c 6946 struct target_oabi_flock64 *target_fl;
213d3e9e
PM
6947 short l_type;
6948
6949 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6950 return -TARGET_EFAULT;
6951 }
6952
ae68ad9f 6953 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6954 __put_user(l_type, &target_fl->l_type);
6955 __put_user(fl->l_whence, &target_fl->l_whence);
6956 __put_user(fl->l_start, &target_fl->l_start);
6957 __put_user(fl->l_len, &target_fl->l_len);
6958 __put_user(fl->l_pid, &target_fl->l_pid);
6959 unlock_user_struct(target_fl, target_flock_addr, 1);
6960 return 0;
6961}
6962#endif
6963
6964static inline abi_long copy_from_user_flock64(struct flock64 *fl,
6965 abi_ulong target_flock_addr)
6966{
6967 struct target_flock64 *target_fl;
ae68ad9f 6968 int l_type;
213d3e9e
PM
6969
6970 if (!lock_user_struct(VERIFY_READ, target_fl, target_flock_addr, 1)) {
6971 return -TARGET_EFAULT;
6972 }
6973
6974 __get_user(l_type, &target_fl->l_type);
ae68ad9f
LV
6975 l_type = target_to_host_flock(l_type);
6976 if (l_type < 0) {
6977 return l_type;
6978 }
6979 fl->l_type = l_type;
213d3e9e
PM
6980 __get_user(fl->l_whence, &target_fl->l_whence);
6981 __get_user(fl->l_start, &target_fl->l_start);
6982 __get_user(fl->l_len, &target_fl->l_len);
6983 __get_user(fl->l_pid, &target_fl->l_pid);
6984 unlock_user_struct(target_fl, target_flock_addr, 0);
6985 return 0;
6986}
6987
6988static inline abi_long copy_to_user_flock64(abi_ulong target_flock_addr,
6989 const struct flock64 *fl)
6990{
6991 struct target_flock64 *target_fl;
6992 short l_type;
6993
6994 if (!lock_user_struct(VERIFY_WRITE, target_fl, target_flock_addr, 0)) {
6995 return -TARGET_EFAULT;
6996 }
6997
ae68ad9f 6998 l_type = host_to_target_flock(fl->l_type);
213d3e9e
PM
6999 __put_user(l_type, &target_fl->l_type);
7000 __put_user(fl->l_whence, &target_fl->l_whence);
7001 __put_user(fl->l_start, &target_fl->l_start);
7002 __put_user(fl->l_len, &target_fl->l_len);
7003 __put_user(fl->l_pid, &target_fl->l_pid);
7004 unlock_user_struct(target_fl, target_flock_addr, 1);
7005 return 0;
7006}
7007
7008static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
7009{
43f238d7 7010 struct flock64 fl64;
8d5d3004
AS
7011#ifdef F_GETOWN_EX
7012 struct f_owner_ex fox;
7013 struct target_f_owner_ex *target_fox;
7014#endif
992f48a0 7015 abi_long ret;
5f106811
APR
7016 int host_cmd = target_to_host_fcntl_cmd(cmd);
7017
7018 if (host_cmd == -TARGET_EINVAL)
7019 return host_cmd;
53a5960a 7020
7775e9ec
FB
7021 switch(cmd) {
7022 case TARGET_F_GETLK:
213d3e9e
PM
7023 ret = copy_from_user_flock(&fl64, arg);
7024 if (ret) {
7025 return ret;
7026 }
435da5e7 7027 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7028 if (ret == 0) {
213d3e9e 7029 ret = copy_to_user_flock(arg, &fl64);
7775e9ec
FB
7030 }
7031 break;
3b46e624 7032
7775e9ec
FB
7033 case TARGET_F_SETLK:
7034 case TARGET_F_SETLKW:
213d3e9e
PM
7035 ret = copy_from_user_flock(&fl64, arg);
7036 if (ret) {
7037 return ret;
7038 }
435da5e7 7039 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec 7040 break;
3b46e624 7041
7775e9ec 7042 case TARGET_F_GETLK64:
2d92c682 7043 case TARGET_F_OFD_GETLK:
213d3e9e
PM
7044 ret = copy_from_user_flock64(&fl64, arg);
7045 if (ret) {
7046 return ret;
7047 }
435da5e7 7048 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
43f238d7 7049 if (ret == 0) {
213d3e9e 7050 ret = copy_to_user_flock64(arg, &fl64);
43f238d7 7051 }
9ee1fa2c 7052 break;
7775e9ec
FB
7053 case TARGET_F_SETLK64:
7054 case TARGET_F_SETLKW64:
2d92c682
AS
7055 case TARGET_F_OFD_SETLK:
7056 case TARGET_F_OFD_SETLKW:
213d3e9e
PM
7057 ret = copy_from_user_flock64(&fl64, arg);
7058 if (ret) {
7059 return ret;
7060 }
435da5e7 7061 ret = get_errno(safe_fcntl(fd, host_cmd, &fl64));
7775e9ec
FB
7062 break;
7063
5f106811 7064 case TARGET_F_GETFL:
435da5e7 7065 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
9ee1fa2c
FB
7066 if (ret >= 0) {
7067 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
7068 }
ffa65c3b
FB
7069 break;
7070
5f106811 7071 case TARGET_F_SETFL:
435da5e7
PM
7072 ret = get_errno(safe_fcntl(fd, host_cmd,
7073 target_to_host_bitmask(arg,
7074 fcntl_flags_tbl)));
5f106811
APR
7075 break;
7076
8d5d3004
AS
7077#ifdef F_GETOWN_EX
7078 case TARGET_F_GETOWN_EX:
435da5e7 7079 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7080 if (ret >= 0) {
7081 if (!lock_user_struct(VERIFY_WRITE, target_fox, arg, 0))
7082 return -TARGET_EFAULT;
7083 target_fox->type = tswap32(fox.type);
7084 target_fox->pid = tswap32(fox.pid);
7085 unlock_user_struct(target_fox, arg, 1);
7086 }
7087 break;
7088#endif
7089
7090#ifdef F_SETOWN_EX
7091 case TARGET_F_SETOWN_EX:
7092 if (!lock_user_struct(VERIFY_READ, target_fox, arg, 1))
7093 return -TARGET_EFAULT;
7094 fox.type = tswap32(target_fox->type);
7095 fox.pid = tswap32(target_fox->pid);
7096 unlock_user_struct(target_fox, arg, 0);
435da5e7 7097 ret = get_errno(safe_fcntl(fd, host_cmd, &fox));
8d5d3004
AS
7098 break;
7099#endif
7100
5f106811 7101 case TARGET_F_SETSIG:
a7b4c9b1
TB
7102 ret = get_errno(safe_fcntl(fd, host_cmd, target_to_host_signal(arg)));
7103 break;
7104
5f106811 7105 case TARGET_F_GETSIG:
a7b4c9b1
TB
7106 ret = host_to_target_signal(get_errno(safe_fcntl(fd, host_cmd, arg)));
7107 break;
7108
7109 case TARGET_F_SETOWN:
7110 case TARGET_F_GETOWN:
7e22e546
UH
7111 case TARGET_F_SETLEASE:
7112 case TARGET_F_GETLEASE:
7e3b92ec
PM
7113 case TARGET_F_SETPIPE_SZ:
7114 case TARGET_F_GETPIPE_SZ:
2bb963ff
SCW
7115 case TARGET_F_ADD_SEALS:
7116 case TARGET_F_GET_SEALS:
435da5e7 7117 ret = get_errno(safe_fcntl(fd, host_cmd, arg));
ffa65c3b
FB
7118 break;
7119
7775e9ec 7120 default:
435da5e7 7121 ret = get_errno(safe_fcntl(fd, cmd, arg));
7775e9ec
FB
7122 break;
7123 }
7124 return ret;
7125}
7126
67867308 7127#ifdef USE_UID16
7775e9ec 7128
67867308
FB
7129static inline int high2lowuid(int uid)
7130{
7131 if (uid > 65535)
7132 return 65534;
7133 else
7134 return uid;
7135}
7136
7137static inline int high2lowgid(int gid)
7138{
7139 if (gid > 65535)
7140 return 65534;
7141 else
7142 return gid;
7143}
7144
7145static inline int low2highuid(int uid)
7146{
7147 if ((int16_t)uid == -1)
7148 return -1;
7149 else
7150 return uid;
7151}
7152
7153static inline int low2highgid(int gid)
7154{
7155 if ((int16_t)gid == -1)
7156 return -1;
7157 else
7158 return gid;
7159}
0c866a7e
RV
7160static inline int tswapid(int id)
7161{
7162 return tswap16(id);
7163}
76ca310a
PM
7164
7165#define put_user_id(x, gaddr) put_user_u16(x, gaddr)
7166
0c866a7e
RV
7167#else /* !USE_UID16 */
7168static inline int high2lowuid(int uid)
7169{
7170 return uid;
7171}
7172static inline int high2lowgid(int gid)
7173{
7174 return gid;
7175}
7176static inline int low2highuid(int uid)
7177{
7178 return uid;
7179}
7180static inline int low2highgid(int gid)
7181{
7182 return gid;
7183}
7184static inline int tswapid(int id)
7185{
7186 return tswap32(id);
7187}
76ca310a
PM
7188
7189#define put_user_id(x, gaddr) put_user_u32(x, gaddr)
7190
67867308 7191#endif /* USE_UID16 */
1b6b029e 7192
fd6f7798
PM
7193/* We must do direct syscalls for setting UID/GID, because we want to
7194 * implement the Linux system call semantics of "change only for this thread",
7195 * not the libc/POSIX semantics of "change for all threads in process".
7196 * (See http://ewontfix.com/17/ for more details.)
7197 * We use the 32-bit version of the syscalls if present; if it is not
7198 * then either the host architecture supports 32-bit UIDs natively with
7199 * the standard syscall, or the 16-bit UID is the best we can do.
7200 */
7201#ifdef __NR_setuid32
7202#define __NR_sys_setuid __NR_setuid32
7203#else
7204#define __NR_sys_setuid __NR_setuid
7205#endif
7206#ifdef __NR_setgid32
7207#define __NR_sys_setgid __NR_setgid32
7208#else
7209#define __NR_sys_setgid __NR_setgid
7210#endif
7211#ifdef __NR_setresuid32
7212#define __NR_sys_setresuid __NR_setresuid32
7213#else
7214#define __NR_sys_setresuid __NR_setresuid
7215#endif
7216#ifdef __NR_setresgid32
7217#define __NR_sys_setresgid __NR_setresgid32
7218#else
7219#define __NR_sys_setresgid __NR_setresgid
7220#endif
7221
7222_syscall1(int, sys_setuid, uid_t, uid)
7223_syscall1(int, sys_setgid, gid_t, gid)
7224_syscall3(int, sys_setresuid, uid_t, ruid, uid_t, euid, uid_t, suid)
7225_syscall3(int, sys_setresgid, gid_t, rgid, gid_t, egid, gid_t, sgid)
7226
31e31b8a
FB
7227void syscall_init(void)
7228{
2ab83ea7
FB
7229 IOCTLEntry *ie;
7230 const argtype *arg_type;
7231 int size;
7232
8be656b8
AG
7233 thunk_init(STRUCT_MAX);
7234
001faf32 7235#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
5fafdf24 7236#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
31e31b8a
FB
7237#include "syscall_types.h"
7238#undef STRUCT
7239#undef STRUCT_SPECIAL
2ab83ea7
FB
7240
7241 /* we patch the ioctl size if necessary. We rely on the fact that
7242 no ioctl has all the bits at '1' in the size field */
7243 ie = ioctl_entries;
7244 while (ie->target_cmd != 0) {
7245 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
7246 TARGET_IOC_SIZEMASK) {
7247 arg_type = ie->arg_type;
7248 if (arg_type[0] != TYPE_PTR) {
5fafdf24 7249 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
2ab83ea7
FB
7250 ie->target_cmd);
7251 exit(1);
7252 }
7253 arg_type++;
7254 size = thunk_type_size(arg_type, 0);
5fafdf24 7255 ie->target_cmd = (ie->target_cmd &
2ab83ea7
FB
7256 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
7257 (size << TARGET_IOC_SIZESHIFT);
7258 }
b92c47c1 7259
2ab83ea7 7260 /* automatic consistency check if same arch */
872ea0c0
AZ
7261#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
7262 (defined(__x86_64__) && defined(TARGET_X86_64))
7263 if (unlikely(ie->target_cmd != ie->host_cmd)) {
7264 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
7265 ie->name, ie->target_cmd, ie->host_cmd);
2ab83ea7
FB
7266 }
7267#endif
7268 ie++;
7269 }
31e31b8a 7270}
c573ff67 7271
ce4defa0 7272#ifdef TARGET_NR_truncate64
992f48a0
BS
7273static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
7274 abi_long arg2,
7275 abi_long arg3,
7276 abi_long arg4)
ce4defa0 7277{
8bf8e9df 7278 if (regpairs_aligned(cpu_env, TARGET_NR_truncate64)) {
ce4defa0
PB
7279 arg2 = arg3;
7280 arg3 = arg4;
48e515d4 7281 }
ce4defa0
PB
7282 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
7283}
7284#endif
7285
7286#ifdef TARGET_NR_ftruncate64
992f48a0
BS
7287static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
7288 abi_long arg2,
7289 abi_long arg3,
7290 abi_long arg4)
ce4defa0 7291{
8bf8e9df 7292 if (regpairs_aligned(cpu_env, TARGET_NR_ftruncate64)) {
ce4defa0
PB
7293 arg2 = arg3;
7294 arg3 = arg4;
48e515d4 7295 }
ce4defa0
PB
7296 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
7297}
7298#endif
7299
859e8a89
AF
7300#if defined(TARGET_NR_timer_settime) || \
7301 (defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD))
2c86c90f 7302static inline abi_long target_to_host_itimerspec(struct itimerspec *host_its,
f4f1e10a
ECL
7303 abi_ulong target_addr)
7304{
2c86c90f
FB
7305 if (target_to_host_timespec(&host_its->it_interval, target_addr +
7306 offsetof(struct target_itimerspec,
7307 it_interval)) ||
7308 target_to_host_timespec(&host_its->it_value, target_addr +
7309 offsetof(struct target_itimerspec,
7310 it_value))) {
f4f1e10a
ECL
7311 return -TARGET_EFAULT;
7312 }
7313
f4f1e10a
ECL
7314 return 0;
7315}
859e8a89 7316#endif
f4f1e10a 7317
828cb3a1
FB
7318#if defined(TARGET_NR_timer_settime64) || \
7319 (defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD))
7320static inline abi_long target_to_host_itimerspec64(struct itimerspec *host_its,
7321 abi_ulong target_addr)
7322{
7323 if (target_to_host_timespec64(&host_its->it_interval, target_addr +
7324 offsetof(struct target__kernel_itimerspec,
7325 it_interval)) ||
7326 target_to_host_timespec64(&host_its->it_value, target_addr +
7327 offsetof(struct target__kernel_itimerspec,
7328 it_value))) {
7329 return -TARGET_EFAULT;
7330 }
7331
7332 return 0;
7333}
7334#endif
7335
859e8a89
AF
7336#if ((defined(TARGET_NR_timerfd_gettime) || \
7337 defined(TARGET_NR_timerfd_settime)) && defined(CONFIG_TIMERFD)) || \
2c86c90f 7338 defined(TARGET_NR_timer_gettime) || defined(TARGET_NR_timer_settime)
f4f1e10a 7339static inline abi_long host_to_target_itimerspec(abi_ulong target_addr,
2c86c90f
FB
7340 struct itimerspec *host_its)
7341{
7342 if (host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7343 it_interval),
7344 &host_its->it_interval) ||
7345 host_to_target_timespec(target_addr + offsetof(struct target_itimerspec,
7346 it_value),
7347 &host_its->it_value)) {
f4f1e10a
ECL
7348 return -TARGET_EFAULT;
7349 }
f4f1e10a
ECL
7350 return 0;
7351}
859e8a89 7352#endif
f4f1e10a 7353
828cb3a1
FB
7354#if ((defined(TARGET_NR_timerfd_gettime64) || \
7355 defined(TARGET_NR_timerfd_settime64)) && defined(CONFIG_TIMERFD)) || \
7356 defined(TARGET_NR_timer_gettime64) || defined(TARGET_NR_timer_settime64)
7357static inline abi_long host_to_target_itimerspec64(abi_ulong target_addr,
7358 struct itimerspec *host_its)
7359{
7360 if (host_to_target_timespec64(target_addr +
7361 offsetof(struct target__kernel_itimerspec,
7362 it_interval),
7363 &host_its->it_interval) ||
7364 host_to_target_timespec64(target_addr +
7365 offsetof(struct target__kernel_itimerspec,
7366 it_value),
7367 &host_its->it_value)) {
7368 return -TARGET_EFAULT;
7369 }
7370 return 0;
7371}
7372#endif
7373
859e8a89
AF
7374#if defined(TARGET_NR_adjtimex) || \
7375 (defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME))
19f59bce
AM
7376static inline abi_long target_to_host_timex(struct timex *host_tx,
7377 abi_long target_addr)
7378{
7379 struct target_timex *target_tx;
7380
7381 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7382 return -TARGET_EFAULT;
7383 }
7384
7385 __get_user(host_tx->modes, &target_tx->modes);
7386 __get_user(host_tx->offset, &target_tx->offset);
7387 __get_user(host_tx->freq, &target_tx->freq);
7388 __get_user(host_tx->maxerror, &target_tx->maxerror);
7389 __get_user(host_tx->esterror, &target_tx->esterror);
7390 __get_user(host_tx->status, &target_tx->status);
7391 __get_user(host_tx->constant, &target_tx->constant);
7392 __get_user(host_tx->precision, &target_tx->precision);
7393 __get_user(host_tx->tolerance, &target_tx->tolerance);
7394 __get_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7395 __get_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7396 __get_user(host_tx->tick, &target_tx->tick);
7397 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7398 __get_user(host_tx->jitter, &target_tx->jitter);
7399 __get_user(host_tx->shift, &target_tx->shift);
7400 __get_user(host_tx->stabil, &target_tx->stabil);
7401 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7402 __get_user(host_tx->calcnt, &target_tx->calcnt);
7403 __get_user(host_tx->errcnt, &target_tx->errcnt);
7404 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7405 __get_user(host_tx->tai, &target_tx->tai);
7406
7407 unlock_user_struct(target_tx, target_addr, 0);
7408 return 0;
7409}
7410
7411static inline abi_long host_to_target_timex(abi_long target_addr,
7412 struct timex *host_tx)
7413{
7414 struct target_timex *target_tx;
7415
7416 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7417 return -TARGET_EFAULT;
7418 }
7419
7420 __put_user(host_tx->modes, &target_tx->modes);
7421 __put_user(host_tx->offset, &target_tx->offset);
7422 __put_user(host_tx->freq, &target_tx->freq);
7423 __put_user(host_tx->maxerror, &target_tx->maxerror);
7424 __put_user(host_tx->esterror, &target_tx->esterror);
7425 __put_user(host_tx->status, &target_tx->status);
7426 __put_user(host_tx->constant, &target_tx->constant);
7427 __put_user(host_tx->precision, &target_tx->precision);
7428 __put_user(host_tx->tolerance, &target_tx->tolerance);
7429 __put_user(host_tx->time.tv_sec, &target_tx->time.tv_sec);
7430 __put_user(host_tx->time.tv_usec, &target_tx->time.tv_usec);
7431 __put_user(host_tx->tick, &target_tx->tick);
7432 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7433 __put_user(host_tx->jitter, &target_tx->jitter);
7434 __put_user(host_tx->shift, &target_tx->shift);
7435 __put_user(host_tx->stabil, &target_tx->stabil);
7436 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7437 __put_user(host_tx->calcnt, &target_tx->calcnt);
7438 __put_user(host_tx->errcnt, &target_tx->errcnt);
7439 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7440 __put_user(host_tx->tai, &target_tx->tai);
7441
7442 unlock_user_struct(target_tx, target_addr, 1);
7443 return 0;
7444}
859e8a89 7445#endif
19f59bce 7446
6ac03b2c
FB
7447
7448#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
7449static inline abi_long target_to_host_timex64(struct timex *host_tx,
7450 abi_long target_addr)
7451{
7452 struct target__kernel_timex *target_tx;
7453
7454 if (copy_from_user_timeval64(&host_tx->time, target_addr +
7455 offsetof(struct target__kernel_timex,
7456 time))) {
7457 return -TARGET_EFAULT;
7458 }
7459
7460 if (!lock_user_struct(VERIFY_READ, target_tx, target_addr, 1)) {
7461 return -TARGET_EFAULT;
7462 }
7463
7464 __get_user(host_tx->modes, &target_tx->modes);
7465 __get_user(host_tx->offset, &target_tx->offset);
7466 __get_user(host_tx->freq, &target_tx->freq);
7467 __get_user(host_tx->maxerror, &target_tx->maxerror);
7468 __get_user(host_tx->esterror, &target_tx->esterror);
7469 __get_user(host_tx->status, &target_tx->status);
7470 __get_user(host_tx->constant, &target_tx->constant);
7471 __get_user(host_tx->precision, &target_tx->precision);
7472 __get_user(host_tx->tolerance, &target_tx->tolerance);
7473 __get_user(host_tx->tick, &target_tx->tick);
7474 __get_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7475 __get_user(host_tx->jitter, &target_tx->jitter);
7476 __get_user(host_tx->shift, &target_tx->shift);
7477 __get_user(host_tx->stabil, &target_tx->stabil);
7478 __get_user(host_tx->jitcnt, &target_tx->jitcnt);
7479 __get_user(host_tx->calcnt, &target_tx->calcnt);
7480 __get_user(host_tx->errcnt, &target_tx->errcnt);
7481 __get_user(host_tx->stbcnt, &target_tx->stbcnt);
7482 __get_user(host_tx->tai, &target_tx->tai);
7483
7484 unlock_user_struct(target_tx, target_addr, 0);
7485 return 0;
7486}
7487
7488static inline abi_long host_to_target_timex64(abi_long target_addr,
7489 struct timex *host_tx)
7490{
7491 struct target__kernel_timex *target_tx;
7492
7493 if (copy_to_user_timeval64(target_addr +
7494 offsetof(struct target__kernel_timex, time),
7495 &host_tx->time)) {
7496 return -TARGET_EFAULT;
7497 }
7498
7499 if (!lock_user_struct(VERIFY_WRITE, target_tx, target_addr, 0)) {
7500 return -TARGET_EFAULT;
7501 }
7502
7503 __put_user(host_tx->modes, &target_tx->modes);
7504 __put_user(host_tx->offset, &target_tx->offset);
7505 __put_user(host_tx->freq, &target_tx->freq);
7506 __put_user(host_tx->maxerror, &target_tx->maxerror);
7507 __put_user(host_tx->esterror, &target_tx->esterror);
7508 __put_user(host_tx->status, &target_tx->status);
7509 __put_user(host_tx->constant, &target_tx->constant);
7510 __put_user(host_tx->precision, &target_tx->precision);
7511 __put_user(host_tx->tolerance, &target_tx->tolerance);
7512 __put_user(host_tx->tick, &target_tx->tick);
7513 __put_user(host_tx->ppsfreq, &target_tx->ppsfreq);
7514 __put_user(host_tx->jitter, &target_tx->jitter);
7515 __put_user(host_tx->shift, &target_tx->shift);
7516 __put_user(host_tx->stabil, &target_tx->stabil);
7517 __put_user(host_tx->jitcnt, &target_tx->jitcnt);
7518 __put_user(host_tx->calcnt, &target_tx->calcnt);
7519 __put_user(host_tx->errcnt, &target_tx->errcnt);
7520 __put_user(host_tx->stbcnt, &target_tx->stbcnt);
7521 __put_user(host_tx->tai, &target_tx->tai);
7522
7523 unlock_user_struct(target_tx, target_addr, 1);
7524 return 0;
7525}
7526#endif
7527
96ff758c
MF
7528#ifndef HAVE_SIGEV_NOTIFY_THREAD_ID
7529#define sigev_notify_thread_id _sigev_un._tid
7530#endif
7531
c065976f
PM
7532static inline abi_long target_to_host_sigevent(struct sigevent *host_sevp,
7533 abi_ulong target_addr)
7534{
7535 struct target_sigevent *target_sevp;
7536
7537 if (!lock_user_struct(VERIFY_READ, target_sevp, target_addr, 1)) {
7538 return -TARGET_EFAULT;
7539 }
7540
7541 /* This union is awkward on 64 bit systems because it has a 32 bit
7542 * integer and a pointer in it; we follow the conversion approach
7543 * used for handling sigval types in signal.c so the guest should get
7544 * the correct value back even if we did a 64 bit byteswap and it's
7545 * using the 32 bit integer.
7546 */
7547 host_sevp->sigev_value.sival_ptr =
7548 (void *)(uintptr_t)tswapal(target_sevp->sigev_value.sival_ptr);
7549 host_sevp->sigev_signo =
7550 target_to_host_signal(tswap32(target_sevp->sigev_signo));
7551 host_sevp->sigev_notify = tswap32(target_sevp->sigev_notify);
96ff758c 7552 host_sevp->sigev_notify_thread_id = tswap32(target_sevp->_sigev_un._tid);
c065976f
PM
7553
7554 unlock_user_struct(target_sevp, target_addr, 1);
7555 return 0;
7556}
7557
6f6a4032
TM
7558#if defined(TARGET_NR_mlockall)
7559static inline int target_to_host_mlockall_arg(int arg)
7560{
7561 int result = 0;
7562
02e5d7d7 7563 if (arg & TARGET_MCL_CURRENT) {
6f6a4032
TM
7564 result |= MCL_CURRENT;
7565 }
02e5d7d7 7566 if (arg & TARGET_MCL_FUTURE) {
6f6a4032
TM
7567 result |= MCL_FUTURE;
7568 }
02e5d7d7
FB
7569#ifdef MCL_ONFAULT
7570 if (arg & TARGET_MCL_ONFAULT) {
7571 result |= MCL_ONFAULT;
7572 }
7573#endif
7574
6f6a4032
TM
7575 return result;
7576}
7577#endif
7578
4f7f8924
AR
7579#if (defined(TARGET_NR_stat64) || defined(TARGET_NR_lstat64) || \
7580 defined(TARGET_NR_fstat64) || defined(TARGET_NR_fstatat64) || \
7581 defined(TARGET_NR_newfstatat))
6a24a778
AZ
7582static inline abi_long host_to_target_stat64(void *cpu_env,
7583 abi_ulong target_addr,
7584 struct stat *host_st)
7585{
09701199 7586#if defined(TARGET_ARM) && defined(TARGET_ABI32)
6a24a778
AZ
7587 if (((CPUARMState *)cpu_env)->eabi) {
7588 struct target_eabi_stat64 *target_st;
7589
7590 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7591 return -TARGET_EFAULT;
7592 memset(target_st, 0, sizeof(struct target_eabi_stat64));
7593 __put_user(host_st->st_dev, &target_st->st_dev);
7594 __put_user(host_st->st_ino, &target_st->st_ino);
7595#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7596 __put_user(host_st->st_ino, &target_st->__st_ino);
7597#endif
7598 __put_user(host_st->st_mode, &target_st->st_mode);
7599 __put_user(host_st->st_nlink, &target_st->st_nlink);
7600 __put_user(host_st->st_uid, &target_st->st_uid);
7601 __put_user(host_st->st_gid, &target_st->st_gid);
7602 __put_user(host_st->st_rdev, &target_st->st_rdev);
7603 __put_user(host_st->st_size, &target_st->st_size);
7604 __put_user(host_st->st_blksize, &target_st->st_blksize);
7605 __put_user(host_st->st_blocks, &target_st->st_blocks);
7606 __put_user(host_st->st_atime, &target_st->target_st_atime);
7607 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7608 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7609#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7610 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7611 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7612 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7613#endif
6a24a778
AZ
7614 unlock_user_struct(target_st, target_addr, 1);
7615 } else
7616#endif
7617 {
20d155bc 7618#if defined(TARGET_HAS_STRUCT_STAT64)
6a24a778 7619 struct target_stat64 *target_st;
20d155bc
SW
7620#else
7621 struct target_stat *target_st;
9d33b76b 7622#endif
6a24a778
AZ
7623
7624 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
7625 return -TARGET_EFAULT;
9d33b76b 7626 memset(target_st, 0, sizeof(*target_st));
6a24a778
AZ
7627 __put_user(host_st->st_dev, &target_st->st_dev);
7628 __put_user(host_st->st_ino, &target_st->st_ino);
7629#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
7630 __put_user(host_st->st_ino, &target_st->__st_ino);
7631#endif
7632 __put_user(host_st->st_mode, &target_st->st_mode);
7633 __put_user(host_st->st_nlink, &target_st->st_nlink);
7634 __put_user(host_st->st_uid, &target_st->st_uid);
7635 __put_user(host_st->st_gid, &target_st->st_gid);
7636 __put_user(host_st->st_rdev, &target_st->st_rdev);
7637 /* XXX: better use of kernel struct */
7638 __put_user(host_st->st_size, &target_st->st_size);
7639 __put_user(host_st->st_blksize, &target_st->st_blksize);
7640 __put_user(host_st->st_blocks, &target_st->st_blocks);
7641 __put_user(host_st->st_atime, &target_st->target_st_atime);
7642 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
7643 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
febf6fad 7644#ifdef HAVE_STRUCT_STAT_ST_ATIM
5f992db6
CYT
7645 __put_user(host_st->st_atim.tv_nsec, &target_st->target_st_atime_nsec);
7646 __put_user(host_st->st_mtim.tv_nsec, &target_st->target_st_mtime_nsec);
7647 __put_user(host_st->st_ctim.tv_nsec, &target_st->target_st_ctime_nsec);
7648#endif
6a24a778
AZ
7649 unlock_user_struct(target_st, target_addr, 1);
7650 }
7651
7652 return 0;
7653}
4f7f8924 7654#endif
6a24a778 7655
efa92184
AR
7656#if defined(TARGET_NR_statx) && defined(__NR_statx)
7657static inline abi_long host_to_target_statx(struct target_statx *host_stx,
7658 abi_ulong target_addr)
7659{
7660 struct target_statx *target_stx;
7661
7662 if (!lock_user_struct(VERIFY_WRITE, target_stx, target_addr, 0)) {
7663 return -TARGET_EFAULT;
7664 }
7665 memset(target_stx, 0, sizeof(*target_stx));
7666
7667 __put_user(host_stx->stx_mask, &target_stx->stx_mask);
7668 __put_user(host_stx->stx_blksize, &target_stx->stx_blksize);
7669 __put_user(host_stx->stx_attributes, &target_stx->stx_attributes);
7670 __put_user(host_stx->stx_nlink, &target_stx->stx_nlink);
7671 __put_user(host_stx->stx_uid, &target_stx->stx_uid);
7672 __put_user(host_stx->stx_gid, &target_stx->stx_gid);
7673 __put_user(host_stx->stx_mode, &target_stx->stx_mode);
7674 __put_user(host_stx->stx_ino, &target_stx->stx_ino);
7675 __put_user(host_stx->stx_size, &target_stx->stx_size);
7676 __put_user(host_stx->stx_blocks, &target_stx->stx_blocks);
7677 __put_user(host_stx->stx_attributes_mask, &target_stx->stx_attributes_mask);
7678 __put_user(host_stx->stx_atime.tv_sec, &target_stx->stx_atime.tv_sec);
7679 __put_user(host_stx->stx_atime.tv_nsec, &target_stx->stx_atime.tv_nsec);
d1e26707
AC
7680 __put_user(host_stx->stx_btime.tv_sec, &target_stx->stx_btime.tv_sec);
7681 __put_user(host_stx->stx_btime.tv_nsec, &target_stx->stx_btime.tv_nsec);
7682 __put_user(host_stx->stx_ctime.tv_sec, &target_stx->stx_ctime.tv_sec);
7683 __put_user(host_stx->stx_ctime.tv_nsec, &target_stx->stx_ctime.tv_nsec);
7684 __put_user(host_stx->stx_mtime.tv_sec, &target_stx->stx_mtime.tv_sec);
7685 __put_user(host_stx->stx_mtime.tv_nsec, &target_stx->stx_mtime.tv_nsec);
efa92184
AR
7686 __put_user(host_stx->stx_rdev_major, &target_stx->stx_rdev_major);
7687 __put_user(host_stx->stx_rdev_minor, &target_stx->stx_rdev_minor);
7688 __put_user(host_stx->stx_dev_major, &target_stx->stx_dev_major);
7689 __put_user(host_stx->stx_dev_minor, &target_stx->stx_dev_minor);
7690
7691 unlock_user_struct(target_stx, target_addr, 1);
7692
7693 return 0;
7694}
7695#endif
7696
14690296
AF
7697static int do_sys_futex(int *uaddr, int op, int val,
7698 const struct timespec *timeout, int *uaddr2,
7699 int val3)
7700{
7701#if HOST_LONG_BITS == 64
7702#if defined(__NR_futex)
7703 /* always a 64-bit time_t, it doesn't define _time64 version */
7704 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7705
7706#endif
7707#else /* HOST_LONG_BITS == 64 */
7708#if defined(__NR_futex_time64)
7709 if (sizeof(timeout->tv_sec) == 8) {
7710 /* _time64 function on 32bit arch */
7711 return sys_futex_time64(uaddr, op, val, timeout, uaddr2, val3);
7712 }
7713#endif
7714#if defined(__NR_futex)
7715 /* old function on 32bit arch */
7716 return sys_futex(uaddr, op, val, timeout, uaddr2, val3);
7717#endif
7718#endif /* HOST_LONG_BITS == 64 */
7719 g_assert_not_reached();
7720}
7721
7722static int do_safe_futex(int *uaddr, int op, int val,
7723 const struct timespec *timeout, int *uaddr2,
7724 int val3)
7725{
7726#if HOST_LONG_BITS == 64
7727#if defined(__NR_futex)
7728 /* always a 64-bit time_t, it doesn't define _time64 version */
7729 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7730#endif
7731#else /* HOST_LONG_BITS == 64 */
7732#if defined(__NR_futex_time64)
7733 if (sizeof(timeout->tv_sec) == 8) {
7734 /* _time64 function on 32bit arch */
7735 return get_errno(safe_futex_time64(uaddr, op, val, timeout, uaddr2,
7736 val3));
7737 }
7738#endif
7739#if defined(__NR_futex)
7740 /* old function on 32bit arch */
7741 return get_errno(safe_futex(uaddr, op, val, timeout, uaddr2, val3));
7742#endif
7743#endif /* HOST_LONG_BITS == 64 */
7744 return -TARGET_ENOSYS;
7745}
efa92184 7746
bd0c5661
PB
7747/* ??? Using host futex calls even when target atomic operations
7748 are not really atomic probably breaks things. However implementing
7749 futexes locally would make futexes shared between multiple processes
7750 tricky. However they're probably useless because guest atomic
7751 operations won't work either. */
859e8a89 7752#if defined(TARGET_NR_futex)
3e8f1628
RH
7753static int do_futex(CPUState *cpu, target_ulong uaddr, int op, int val,
7754 target_ulong timeout, target_ulong uaddr2, int val3)
bd0c5661
PB
7755{
7756 struct timespec ts, *pts;
a16aae0c 7757 int base_op;
bd0c5661
PB
7758
7759 /* ??? We assume FUTEX_* constants are the same on both host
7760 and target. */
a29ccd63 7761#ifdef FUTEX_CMD_MASK
a16aae0c 7762 base_op = op & FUTEX_CMD_MASK;
a29ccd63 7763#else
a16aae0c 7764 base_op = op;
a29ccd63 7765#endif
a16aae0c 7766 switch (base_op) {
bd0c5661 7767 case FUTEX_WAIT:
cce246e0 7768 case FUTEX_WAIT_BITSET:
bd0c5661
PB
7769 if (timeout) {
7770 pts = &ts;
7771 target_to_host_timespec(pts, timeout);
7772 } else {
7773 pts = NULL;
7774 }
3e8f1628
RH
7775 return do_safe_futex(g2h(cpu, uaddr),
7776 op, tswap32(val), pts, NULL, val3);
bd0c5661 7777 case FUTEX_WAKE:
3e8f1628
RH
7778 return do_safe_futex(g2h(cpu, uaddr),
7779 op, val, NULL, NULL, 0);
bd0c5661 7780 case FUTEX_FD:
3e8f1628
RH
7781 return do_safe_futex(g2h(cpu, uaddr),
7782 op, val, NULL, NULL, 0);
bd0c5661 7783 case FUTEX_REQUEUE:
bd0c5661 7784 case FUTEX_CMP_REQUEUE:
a16aae0c
NF
7785 case FUTEX_WAKE_OP:
7786 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7787 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7788 But the prototype takes a `struct timespec *'; insert casts
7789 to satisfy the compiler. We do not need to tswap TIMEOUT
7790 since it's not compared to guest memory. */
7791 pts = (struct timespec *)(uintptr_t) timeout;
3e8f1628 7792 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
14690296 7793 (base_op == FUTEX_CMP_REQUEUE
3e8f1628 7794 ? tswap32(val3) : val3));
bd0c5661
PB
7795 default:
7796 return -TARGET_ENOSYS;
7797 }
7798}
859e8a89 7799#endif
14690296
AF
7800
7801#if defined(TARGET_NR_futex_time64)
3e8f1628
RH
7802static int do_futex_time64(CPUState *cpu, target_ulong uaddr, int op,
7803 int val, target_ulong timeout,
14690296
AF
7804 target_ulong uaddr2, int val3)
7805{
7806 struct timespec ts, *pts;
7807 int base_op;
7808
7809 /* ??? We assume FUTEX_* constants are the same on both host
7810 and target. */
7811#ifdef FUTEX_CMD_MASK
7812 base_op = op & FUTEX_CMD_MASK;
7813#else
7814 base_op = op;
7815#endif
7816 switch (base_op) {
7817 case FUTEX_WAIT:
7818 case FUTEX_WAIT_BITSET:
7819 if (timeout) {
7820 pts = &ts;
e4ce178b
AF
7821 if (target_to_host_timespec64(pts, timeout)) {
7822 return -TARGET_EFAULT;
7823 }
14690296
AF
7824 } else {
7825 pts = NULL;
7826 }
3e8f1628
RH
7827 return do_safe_futex(g2h(cpu, uaddr), op,
7828 tswap32(val), pts, NULL, val3);
14690296 7829 case FUTEX_WAKE:
3e8f1628 7830 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
14690296 7831 case FUTEX_FD:
3e8f1628 7832 return do_safe_futex(g2h(cpu, uaddr), op, val, NULL, NULL, 0);
14690296
AF
7833 case FUTEX_REQUEUE:
7834 case FUTEX_CMP_REQUEUE:
7835 case FUTEX_WAKE_OP:
7836 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
7837 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
7838 But the prototype takes a `struct timespec *'; insert casts
7839 to satisfy the compiler. We do not need to tswap TIMEOUT
7840 since it's not compared to guest memory. */
7841 pts = (struct timespec *)(uintptr_t) timeout;
3e8f1628 7842 return do_safe_futex(g2h(cpu, uaddr), op, val, pts, g2h(cpu, uaddr2),
14690296 7843 (base_op == FUTEX_CMP_REQUEUE
3e8f1628 7844 ? tswap32(val3) : val3));
14690296
AF
7845 default:
7846 return -TARGET_ENOSYS;
7847 }
7848}
7849#endif
7850
0f0426f3
LV
7851#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7852static abi_long do_name_to_handle_at(abi_long dirfd, abi_long pathname,
7853 abi_long handle, abi_long mount_id,
7854 abi_long flags)
7855{
7856 struct file_handle *target_fh;
7857 struct file_handle *fh;
7858 int mid = 0;
7859 abi_long ret;
7860 char *name;
7861 unsigned int size, total_size;
7862
7863 if (get_user_s32(size, handle)) {
7864 return -TARGET_EFAULT;
7865 }
7866
7867 name = lock_user_string(pathname);
7868 if (!name) {
7869 return -TARGET_EFAULT;
7870 }
7871
7872 total_size = sizeof(struct file_handle) + size;
7873 target_fh = lock_user(VERIFY_WRITE, handle, total_size, 0);
7874 if (!target_fh) {
7875 unlock_user(name, pathname, 0);
7876 return -TARGET_EFAULT;
7877 }
7878
7879 fh = g_malloc0(total_size);
7880 fh->handle_bytes = size;
7881
7882 ret = get_errno(name_to_handle_at(dirfd, path(name), fh, &mid, flags));
7883 unlock_user(name, pathname, 0);
7884
7885 /* man name_to_handle_at(2):
7886 * Other than the use of the handle_bytes field, the caller should treat
7887 * the file_handle structure as an opaque data type
7888 */
7889
7890 memcpy(target_fh, fh, total_size);
7891 target_fh->handle_bytes = tswap32(fh->handle_bytes);
7892 target_fh->handle_type = tswap32(fh->handle_type);
7893 g_free(fh);
7894 unlock_user(target_fh, handle, total_size);
7895
7896 if (put_user_s32(mid, mount_id)) {
7897 return -TARGET_EFAULT;
7898 }
7899
7900 return ret;
7901
7902}
7903#endif
7904
7905#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
7906static abi_long do_open_by_handle_at(abi_long mount_fd, abi_long handle,
7907 abi_long flags)
7908{
7909 struct file_handle *target_fh;
7910 struct file_handle *fh;
7911 unsigned int size, total_size;
7912 abi_long ret;
7913
7914 if (get_user_s32(size, handle)) {
7915 return -TARGET_EFAULT;
7916 }
7917
7918 total_size = sizeof(struct file_handle) + size;
7919 target_fh = lock_user(VERIFY_READ, handle, total_size, 1);
7920 if (!target_fh) {
7921 return -TARGET_EFAULT;
7922 }
7923
e9d49d51 7924 fh = g_memdup(target_fh, total_size);
0f0426f3
LV
7925 fh->handle_bytes = size;
7926 fh->handle_type = tswap32(target_fh->handle_type);
7927
7928 ret = get_errno(open_by_handle_at(mount_fd, fh,
7929 target_to_host_bitmask(flags, fcntl_flags_tbl)));
7930
7931 g_free(fh);
7932
7933 unlock_user(target_fh, handle, total_size);
7934
7935 return ret;
7936}
7937#endif
bd0c5661 7938
e36800c9
LV
7939#if defined(TARGET_NR_signalfd) || defined(TARGET_NR_signalfd4)
7940
e36800c9
LV
7941static abi_long do_signalfd4(int fd, abi_long mask, int flags)
7942{
7943 int host_flags;
7944 target_sigset_t *target_mask;
7945 sigset_t host_mask;
7946 abi_long ret;
7947
78721301 7948 if (flags & ~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC)) {
e36800c9
LV
7949 return -TARGET_EINVAL;
7950 }
7951 if (!lock_user_struct(VERIFY_READ, target_mask, mask, 1)) {
7952 return -TARGET_EFAULT;
7953 }
7954
7955 target_to_host_sigset(&host_mask, target_mask);
7956
7957 host_flags = target_to_host_bitmask(flags, fcntl_flags_tbl);
7958
7959 ret = get_errno(signalfd(fd, &host_mask, host_flags));
7960 if (ret >= 0) {
7961 fd_trans_register(ret, &target_signalfd_trans);
7962 }
7963
7964 unlock_user_struct(target_mask, mask, 0);
7965
7966 return ret;
7967}
7968#endif
7969
1d9d8b55
PB
7970/* Map host to target signal numbers for the wait family of syscalls.
7971 Assume all other status bits are the same. */
a05c6409 7972int host_to_target_waitstatus(int status)
1d9d8b55
PB
7973{
7974 if (WIFSIGNALED(status)) {
7975 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
7976 }
7977 if (WIFSTOPPED(status)) {
7978 return (host_to_target_signal(WSTOPSIG(status)) << 8)
7979 | (status & 0xff);
7980 }
7981 return status;
7982}
7983
76b94245
WVS
7984static int open_self_cmdline(void *cpu_env, int fd)
7985{
29a0af61 7986 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
58de8b96
AS
7987 struct linux_binprm *bprm = ((TaskState *)cpu->opaque)->bprm;
7988 int i;
76b94245 7989
58de8b96
AS
7990 for (i = 0; i < bprm->argc; i++) {
7991 size_t len = strlen(bprm->argv[i]) + 1;
76b94245 7992
58de8b96 7993 if (write(fd, bprm->argv[i], len) != len) {
76b94245 7994 return -1;
76b94245
WVS
7995 }
7996 }
7997
58de8b96 7998 return 0;
76b94245
WVS
7999}
8000
36c08d49
AG
8001static int open_self_maps(void *cpu_env, int fd)
8002{
29a0af61 8003 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
0429a971 8004 TaskState *ts = cpu->opaque;
01ef6b9e
AB
8005 GSList *map_info = read_self_maps();
8006 GSList *s;
bb55173c 8007 int count;
1a49ef2a 8008
01ef6b9e
AB
8009 for (s = map_info; s; s = g_slist_next(s)) {
8010 MapInfo *e = (MapInfo *) s->data;
1a49ef2a 8011
01ef6b9e
AB
8012 if (h2g_valid(e->start)) {
8013 unsigned long min = e->start;
8014 unsigned long max = e->end;
d67f4aaa 8015 int flags = page_get_flags(h2g(min));
01ef6b9e
AB
8016 const char *path;
8017
8018 max = h2g_valid(max - 1) ?
3e8f1628 8019 max : (uintptr_t) g2h_untagged(GUEST_ADDR_MAX) + 1;
01ef6b9e 8020
d67f4aaa
MI
8021 if (page_check_range(h2g(min), max - min, flags) == -1) {
8022 continue;
8023 }
01ef6b9e 8024
d67f4aaa 8025 if (h2g(min) == ts->info->stack_limit) {
bb55173c 8026 path = "[stack]";
01ef6b9e
AB
8027 } else {
8028 path = e->path;
d67f4aaa 8029 }
01ef6b9e 8030
bb55173c
AB
8031 count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
8032 " %c%c%c%c %08" PRIx64 " %s %"PRId64,
8033 h2g(min), h2g(max - 1) + 1,
08f3a96b
NS
8034 (flags & PAGE_READ) ? 'r' : '-',
8035 (flags & PAGE_WRITE_ORG) ? 'w' : '-',
8036 (flags & PAGE_EXEC) ? 'x' : '-',
e13685a6 8037 e->is_priv ? 'p' : 's',
bb55173c
AB
8038 (uint64_t) e->offset, e->dev, e->inode);
8039 if (path) {
8040 dprintf(fd, "%*s%s\n", 73 - count, "", path);
8041 } else {
8042 dprintf(fd, "\n");
8043 }
1a49ef2a
AG
8044 }
8045 }
8046
01ef6b9e
AB
8047 free_self_maps(map_info);
8048
bf02adcd
RH
8049#ifdef TARGET_VSYSCALL_PAGE
8050 /*
8051 * We only support execution from the vsyscall page.
8052 * This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
8053 */
bb55173c
AB
8054 count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
8055 " --xp 00000000 00:00 0",
8056 TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
8057 dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
bf02adcd
RH
8058#endif
8059
36c08d49
AG
8060 return 0;
8061}
8062
480b8e7d
AG
8063static int open_self_stat(void *cpu_env, int fd)
8064{
29a0af61 8065 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
0429a971 8066 TaskState *ts = cpu->opaque;
7ad4d5a4 8067 g_autoptr(GString) buf = g_string_new(NULL);
480b8e7d
AG
8068 int i;
8069
8070 for (i = 0; i < 44; i++) {
7ad4d5a4
AB
8071 if (i == 0) {
8072 /* pid */
8073 g_string_printf(buf, FMT_pid " ", getpid());
8074 } else if (i == 1) {
8075 /* app name */
8076 gchar *bin = g_strrstr(ts->bprm->argv[0], "/");
8077 bin = bin ? bin + 1 : ts->bprm->argv[0];
8078 g_string_printf(buf, "(%.15s) ", bin);
7aa9fe3a
AS
8079 } else if (i == 3) {
8080 /* ppid */
8081 g_string_printf(buf, FMT_pid " ", getppid());
eb33cdae
CE
8082 } else if (i == 21) {
8083 /* starttime */
8084 g_string_printf(buf, "%" PRIu64 " ", ts->start_boottime);
7ad4d5a4
AB
8085 } else if (i == 27) {
8086 /* stack bottom */
8087 g_string_printf(buf, TARGET_ABI_FMT_ld " ", ts->info->start_stack);
8088 } else {
8089 /* for the rest, there is MasterCard */
8090 g_string_printf(buf, "0%c", i == 43 ? '\n' : ' ');
8091 }
8092
8093 if (write(fd, buf->str, buf->len) != buf->len) {
8094 return -1;
8095 }
480b8e7d
AG
8096 }
8097
8098 return 0;
8099}
8100
257450ee
AG
8101static int open_self_auxv(void *cpu_env, int fd)
8102{
29a0af61 8103 CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
0429a971 8104 TaskState *ts = cpu->opaque;
257450ee
AG
8105 abi_ulong auxv = ts->info->saved_auxv;
8106 abi_ulong len = ts->info->auxv_len;
8107 char *ptr;
8108
8109 /*
8110 * Auxiliary vector is stored in target process stack.
8111 * read in whole auxv vector and copy it to file
8112 */
8113 ptr = lock_user(VERIFY_READ, auxv, len, 0);
8114 if (ptr != NULL) {
8115 while (len > 0) {
8116 ssize_t r;
8117 r = write(fd, ptr, len);
8118 if (r <= 0) {
8119 break;
8120 }
8121 len -= r;
8122 ptr += r;
8123 }
8124 lseek(fd, 0, SEEK_SET);
8125 unlock_user(ptr, auxv, len);
8126 }
8127
8128 return 0;
8129}
8130
463d8e73
AS
8131static int is_proc_myself(const char *filename, const char *entry)
8132{
8133 if (!strncmp(filename, "/proc/", strlen("/proc/"))) {
8134 filename += strlen("/proc/");
8135 if (!strncmp(filename, "self/", strlen("self/"))) {
8136 filename += strlen("self/");
8137 } else if (*filename >= '1' && *filename <= '9') {
8138 char myself[80];
8139 snprintf(myself, sizeof(myself), "%d/", getpid());
8140 if (!strncmp(filename, myself, strlen(myself))) {
8141 filename += strlen(myself);
8142 } else {
8143 return 0;
8144 }
8145 } else {
8146 return 0;
8147 }
8148 if (!strcmp(filename, entry)) {
8149 return 1;
8150 }
8151 }
8152 return 0;
8153}
8154
fff69382 8155#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN) || \
93a5661d 8156 defined(TARGET_SPARC) || defined(TARGET_M68K) || defined(TARGET_HPPA)
de6b9933
LV
8157static int is_proc(const char *filename, const char *entry)
8158{
8159 return strcmp(filename, entry) == 0;
8160}
fff69382 8161#endif
de6b9933 8162
fff69382 8163#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
de6b9933
LV
8164static int open_net_route(void *cpu_env, int fd)
8165{
8166 FILE *fp;
8167 char *line = NULL;
8168 size_t len = 0;
8169 ssize_t read;
8170
8171 fp = fopen("/proc/net/route", "r");
8172 if (fp == NULL) {
a3ca7bb2 8173 return -1;
de6b9933
LV
8174 }
8175
8176 /* read header */
8177
8178 read = getline(&line, &len, fp);
8179 dprintf(fd, "%s", line);
8180
8181 /* read routes */
8182
8183 while ((read = getline(&line, &len, fp)) != -1) {
8184 char iface[16];
8185 uint32_t dest, gw, mask;
8186 unsigned int flags, refcnt, use, metric, mtu, window, irtt;
9d0bd0cd
PM
8187 int fields;
8188
8189 fields = sscanf(line,
8190 "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8191 iface, &dest, &gw, &flags, &refcnt, &use, &metric,
8192 &mask, &mtu, &window, &irtt);
8193 if (fields != 11) {
8194 continue;
8195 }
de6b9933
LV
8196 dprintf(fd, "%s\t%08x\t%08x\t%04x\t%d\t%d\t%d\t%08x\t%d\t%u\t%u\n",
8197 iface, tswap32(dest), tswap32(gw), flags, refcnt, use,
8198 metric, tswap32(mask), mtu, window, irtt);
8199 }
8200
8201 free(line);
8202 fclose(fp);
8203
8204 return 0;
8205}
8206#endif
8207
fff69382
LV
8208#if defined(TARGET_SPARC)
8209static int open_cpuinfo(void *cpu_env, int fd)
8210{
8211 dprintf(fd, "type\t\t: sun4u\n");
8212 return 0;
8213}
8214#endif
8215
93a5661d
HD
8216#if defined(TARGET_HPPA)
8217static int open_cpuinfo(void *cpu_env, int fd)
8218{
8219 dprintf(fd, "cpu family\t: PA-RISC 1.1e\n");
8220 dprintf(fd, "cpu\t\t: PA7300LC (PCX-L2)\n");
8221 dprintf(fd, "capabilities\t: os32\n");
8222 dprintf(fd, "model\t\t: 9000/778/B160L\n");
8223 dprintf(fd, "model name\t: Merlin L2 160 QEMU (9000/778/B160L)\n");
8224 return 0;
8225}
8226#endif
8227
4ab6713e
LV
8228#if defined(TARGET_M68K)
8229static int open_hardware(void *cpu_env, int fd)
8230{
8231 dprintf(fd, "Model:\t\tqemu-m68k\n");
8232 return 0;
8233}
8234#endif
8235
0b2effd7 8236static int do_openat(void *cpu_env, int dirfd, const char *pathname, int flags, mode_t mode)
3be14d05
AG
8237{
8238 struct fake_open {
8239 const char *filename;
8240 int (*fill)(void *cpu_env, int fd);
de6b9933 8241 int (*cmp)(const char *s1, const char *s2);
3be14d05
AG
8242 };
8243 const struct fake_open *fake_open;
8244 static const struct fake_open fakes[] = {
de6b9933
LV
8245 { "maps", open_self_maps, is_proc_myself },
8246 { "stat", open_self_stat, is_proc_myself },
8247 { "auxv", open_self_auxv, is_proc_myself },
76b94245 8248 { "cmdline", open_self_cmdline, is_proc_myself },
de6b9933
LV
8249#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
8250 { "/proc/net/route", open_net_route, is_proc },
fff69382 8251#endif
93a5661d 8252#if defined(TARGET_SPARC) || defined(TARGET_HPPA)
fff69382 8253 { "/proc/cpuinfo", open_cpuinfo, is_proc },
4ab6713e
LV
8254#endif
8255#if defined(TARGET_M68K)
8256 { "/proc/hardware", open_hardware, is_proc },
de6b9933
LV
8257#endif
8258 { NULL, NULL, NULL }
3be14d05
AG
8259 };
8260
aa07f5ec
MO
8261 if (is_proc_myself(pathname, "exe")) {
8262 int execfd = qemu_getauxval(AT_EXECFD);
c10a0738 8263 return execfd ? execfd : safe_openat(dirfd, exec_path, flags, mode);
aa07f5ec
MO
8264 }
8265
3be14d05 8266 for (fake_open = fakes; fake_open->filename; fake_open++) {
de6b9933 8267 if (fake_open->cmp(pathname, fake_open->filename)) {
3be14d05
AG
8268 break;
8269 }
8270 }
8271
8272 if (fake_open->filename) {
8273 const char *tmpdir;
8274 char filename[PATH_MAX];
8275 int fd, r;
8276
8277 /* create temporary file to map stat to */
8278 tmpdir = getenv("TMPDIR");
8279 if (!tmpdir)
8280 tmpdir = "/tmp";
8281 snprintf(filename, sizeof(filename), "%s/qemu-open.XXXXXX", tmpdir);
8282 fd = mkstemp(filename);
8283 if (fd < 0) {
8284 return fd;
8285 }
8286 unlink(filename);
8287
8288 if ((r = fake_open->fill(cpu_env, fd))) {
a3ca7bb2 8289 int e = errno;
3be14d05 8290 close(fd);
a3ca7bb2 8291 errno = e;
3be14d05
AG
8292 return r;
8293 }
8294 lseek(fd, 0, SEEK_SET);
8295
8296 return fd;
8297 }
8298
c10a0738 8299 return safe_openat(dirfd, path(pathname), flags, mode);
3be14d05
AG
8300}
8301
aecc8861
AG
8302#define TIMER_MAGIC 0x0caf0000
8303#define TIMER_MAGIC_MASK 0xffff0000
8304
8305/* Convert QEMU provided timer ID back to internal 16bit index format */
8306static target_timer_t get_timer_id(abi_long arg)
8307{
8308 target_timer_t timerid = arg;
8309
8310 if ((timerid & TIMER_MAGIC_MASK) != TIMER_MAGIC) {
8311 return -TARGET_EINVAL;
8312 }
8313
8314 timerid &= 0xffff;
8315
8316 if (timerid >= ARRAY_SIZE(g_posix_timers)) {
8317 return -TARGET_EINVAL;
8318 }
8319
8320 return timerid;
8321}
8322
2e0a8713
ST
8323static int target_to_host_cpu_mask(unsigned long *host_mask,
8324 size_t host_size,
8325 abi_ulong target_addr,
8326 size_t target_size)
8327{
8328 unsigned target_bits = sizeof(abi_ulong) * 8;
8329 unsigned host_bits = sizeof(*host_mask) * 8;
8330 abi_ulong *target_mask;
8331 unsigned i, j;
8332
8333 assert(host_size >= target_size);
8334
8335 target_mask = lock_user(VERIFY_READ, target_addr, target_size, 1);
8336 if (!target_mask) {
8337 return -TARGET_EFAULT;
8338 }
8339 memset(host_mask, 0, host_size);
8340
8341 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8342 unsigned bit = i * target_bits;
8343 abi_ulong val;
8344
8345 __get_user(val, &target_mask[i]);
8346 for (j = 0; j < target_bits; j++, bit++) {
8347 if (val & (1UL << j)) {
8348 host_mask[bit / host_bits] |= 1UL << (bit % host_bits);
8349 }
8350 }
8351 }
8352
8353 unlock_user(target_mask, target_addr, 0);
8354 return 0;
8355}
8356
8357static int host_to_target_cpu_mask(const unsigned long *host_mask,
8358 size_t host_size,
8359 abi_ulong target_addr,
8360 size_t target_size)
8361{
8362 unsigned target_bits = sizeof(abi_ulong) * 8;
8363 unsigned host_bits = sizeof(*host_mask) * 8;
8364 abi_ulong *target_mask;
8365 unsigned i, j;
8366
8367 assert(host_size >= target_size);
8368
8369 target_mask = lock_user(VERIFY_WRITE, target_addr, target_size, 0);
8370 if (!target_mask) {
8371 return -TARGET_EFAULT;
8372 }
8373
8374 for (i = 0 ; i < target_size / sizeof(abi_ulong); i++) {
8375 unsigned bit = i * target_bits;
8376 abi_ulong val = 0;
8377
8378 for (j = 0; j < target_bits; j++, bit++) {
8379 if (host_mask[bit / host_bits] & (1UL << (bit % host_bits))) {
8380 val |= 1UL << j;
8381 }
8382 }
8383 __put_user(val, &target_mask[i]);
8384 }
8385
8386 unlock_user(target_mask, target_addr, target_size);
8387 return 0;
8388}
8389
fd08ddb9 8390#ifdef TARGET_NR_getdents
aee14c77 8391static int do_getdents(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8392{
aee14c77
RH
8393 g_autofree void *hdirp = NULL;
8394 void *tdirp;
8395 int hlen, hoff, toff;
8396 int hreclen, treclen;
8397 off64_t prev_diroff = 0;
8398
8399 hdirp = g_try_malloc(count);
8400 if (!hdirp) {
8401 return -TARGET_ENOMEM;
8402 }
fd08ddb9
RH
8403
8404#ifdef EMULATE_GETDENTS_WITH_GETDENTS
aee14c77
RH
8405 hlen = sys_getdents(dirfd, hdirp, count);
8406#else
8407 hlen = sys_getdents64(dirfd, hdirp, count);
8408#endif
fd08ddb9 8409
aee14c77
RH
8410 hlen = get_errno(hlen);
8411 if (is_error(hlen)) {
8412 return hlen;
fd08ddb9
RH
8413 }
8414
aee14c77
RH
8415 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8416 if (!tdirp) {
fd08ddb9
RH
8417 return -TARGET_EFAULT;
8418 }
aee14c77
RH
8419
8420 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8421#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8422 struct linux_dirent *hde = hdirp + hoff;
fd08ddb9 8423#else
aee14c77
RH
8424 struct linux_dirent64 *hde = hdirp + hoff;
8425#endif
8426 struct target_dirent *tde = tdirp + toff;
8427 int namelen;
8428 uint8_t type;
fd08ddb9 8429
aee14c77
RH
8430 namelen = strlen(hde->d_name);
8431 hreclen = hde->d_reclen;
8432 treclen = offsetof(struct target_dirent, d_name) + namelen + 2;
8433 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent));
fd08ddb9 8434
aee14c77 8435 if (toff + treclen > count) {
fd08ddb9 8436 /*
aee14c77
RH
8437 * If the host struct is smaller than the target struct, or
8438 * requires less alignment and thus packs into less space,
8439 * then the host can return more entries than we can pass
8440 * on to the guest.
fd08ddb9 8441 */
aee14c77
RH
8442 if (toff == 0) {
8443 toff = -TARGET_EINVAL; /* result buffer is too small */
8444 break;
8445 }
8446 /*
8447 * Return what we have, resetting the file pointer to the
8448 * location of the first record not returned.
8449 */
8450 lseek64(dirfd, prev_diroff, SEEK_SET);
8451 break;
fd08ddb9 8452 }
aee14c77
RH
8453
8454 prev_diroff = hde->d_off;
8455 tde->d_ino = tswapal(hde->d_ino);
8456 tde->d_off = tswapal(hde->d_off);
8457 tde->d_reclen = tswap16(treclen);
8458 memcpy(tde->d_name, hde->d_name, namelen + 1);
8459
8460 /*
8461 * The getdents type is in what was formerly a padding byte at the
8462 * end of the structure.
8463 */
8464#ifdef EMULATE_GETDENTS_WITH_GETDENTS
8465 type = *((uint8_t *)hde + hreclen - 1);
8466#else
8467 type = hde->d_type;
fd08ddb9 8468#endif
aee14c77
RH
8469 *((uint8_t *)tde + treclen - 1) = type;
8470 }
8471
8472 unlock_user(tdirp, arg2, toff);
8473 return toff;
fd08ddb9
RH
8474}
8475#endif /* TARGET_NR_getdents */
8476
8477#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
aee14c77 8478static int do_getdents64(abi_long dirfd, abi_long arg2, abi_long count)
fd08ddb9 8479{
aee14c77
RH
8480 g_autofree void *hdirp = NULL;
8481 void *tdirp;
8482 int hlen, hoff, toff;
8483 int hreclen, treclen;
8484 off64_t prev_diroff = 0;
8485
8486 hdirp = g_try_malloc(count);
8487 if (!hdirp) {
8488 return -TARGET_ENOMEM;
8489 }
fd08ddb9 8490
aee14c77
RH
8491 hlen = get_errno(sys_getdents64(dirfd, hdirp, count));
8492 if (is_error(hlen)) {
8493 return hlen;
8494 }
8495
8496 tdirp = lock_user(VERIFY_WRITE, arg2, count, 0);
8497 if (!tdirp) {
fd08ddb9
RH
8498 return -TARGET_EFAULT;
8499 }
aee14c77
RH
8500
8501 for (hoff = toff = 0; hoff < hlen; hoff += hreclen, toff += treclen) {
8502 struct linux_dirent64 *hde = hdirp + hoff;
8503 struct target_dirent64 *tde = tdirp + toff;
8504 int namelen;
8505
8506 namelen = strlen(hde->d_name) + 1;
8507 hreclen = hde->d_reclen;
8508 treclen = offsetof(struct target_dirent64, d_name) + namelen;
8509 treclen = QEMU_ALIGN_UP(treclen, __alignof(struct target_dirent64));
8510
8511 if (toff + treclen > count) {
8512 /*
8513 * If the host struct is smaller than the target struct, or
8514 * requires less alignment and thus packs into less space,
8515 * then the host can return more entries than we can pass
8516 * on to the guest.
8517 */
8518 if (toff == 0) {
8519 toff = -TARGET_EINVAL; /* result buffer is too small */
fd08ddb9
RH
8520 break;
8521 }
aee14c77
RH
8522 /*
8523 * Return what we have, resetting the file pointer to the
8524 * location of the first record not returned.
8525 */
8526 lseek64(dirfd, prev_diroff, SEEK_SET);
8527 break;
fd08ddb9 8528 }
aee14c77
RH
8529
8530 prev_diroff = hde->d_off;
8531 tde->d_ino = tswap64(hde->d_ino);
8532 tde->d_off = tswap64(hde->d_off);
8533 tde->d_reclen = tswap16(treclen);
8534 tde->d_type = hde->d_type;
8535 memcpy(tde->d_name, hde->d_name, namelen);
fd08ddb9 8536 }
aee14c77
RH
8537
8538 unlock_user(tdirp, arg2, toff);
8539 return toff;
fd08ddb9
RH
8540}
8541#endif /* TARGET_NR_getdents64 */
8542
e10fbe8f
YT
8543#if defined(TARGET_NR_pivot_root) && defined(__NR_pivot_root)
8544_syscall2(int, pivot_root, const char *, new_root, const char *, put_old)
8545#endif
8546
dc1ce18b
RH
8547/* This is an internal helper for do_syscall so that it is easier
8548 * to have a single return point, so that actions, such as logging
8549 * of syscall results, can be performed.
8550 * All errnos that do_syscall() returns must be -TARGET_<errcode>.
8551 */
8552static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
8553 abi_long arg2, abi_long arg3, abi_long arg4,
8554 abi_long arg5, abi_long arg6, abi_long arg7,
8555 abi_long arg8)
31e31b8a 8556{
29a0af61 8557 CPUState *cpu = env_cpu(cpu_env);
992f48a0 8558 abi_long ret;
4f7f8924
AR
8559#if defined(TARGET_NR_stat) || defined(TARGET_NR_stat64) \
8560 || defined(TARGET_NR_lstat) || defined(TARGET_NR_lstat64) \
efa92184
AR
8561 || defined(TARGET_NR_fstat) || defined(TARGET_NR_fstat64) \
8562 || defined(TARGET_NR_statx)
31e31b8a 8563 struct stat st;
4f7f8924
AR
8564#endif
8565#if defined(TARGET_NR_statfs) || defined(TARGET_NR_statfs64) \
8566 || defined(TARGET_NR_fstatfs)
56c8f68f 8567 struct statfs stfs;
4f7f8924 8568#endif
53a5960a 8569 void *p;
3b46e624 8570
31e31b8a
FB
8571 switch(num) {
8572 case TARGET_NR_exit:
9b056fcc 8573 /* In old applications this may be used to implement _exit(2).
6f9ff551 8574 However in threaded applications it is used for thread termination,
9b056fcc
AF
8575 and _exit_group is used for application termination.
8576 Do thread termination if we have more then one thread. */
a0995886
TB
8577
8578 if (block_signals()) {
af254a27 8579 return -QEMU_ERESTARTSYS;
a0995886
TB
8580 }
8581
1f81ce90 8582 pthread_mutex_lock(&clone_lock);
dd1f6349 8583
bdc44640 8584 if (CPU_NEXT(first_cpu)) {
1f81ce90 8585 TaskState *ts = cpu->opaque;
9b056fcc 8586
5325cc34 8587 object_property_set_bool(OBJECT(cpu), "realized", false, NULL);
1f81ce90
AB
8588 object_unref(OBJECT(cpu));
8589 /*
8590 * At this point the CPU should be unrealized and removed
8591 * from cpu lists. We can clean-up the rest of the thread
8592 * data without the lock held.
8593 */
dd1f6349 8594
1f81ce90 8595 pthread_mutex_unlock(&clone_lock);
dd1f6349 8596
9b056fcc
AF
8597 if (ts->child_tidptr) {
8598 put_user_u32(0, ts->child_tidptr);
3e8f1628
RH
8599 do_sys_futex(g2h(cpu, ts->child_tidptr),
8600 FUTEX_WAKE, INT_MAX, NULL, NULL, 0);
9b056fcc 8601 }
a2247f8e 8602 thread_cpu = NULL;
9b056fcc 8603 g_free(ts);
70903763 8604 rcu_unregister_thread();
9b056fcc
AF
8605 pthread_exit(NULL);
8606 }
dd1f6349 8607
1f81ce90 8608 pthread_mutex_unlock(&clone_lock);
708b6a64 8609 preexit_cleanup(cpu_env, arg1);
c2764719 8610 _exit(arg1);
72eb7ea8 8611 return 0; /* avoid warning */
31e31b8a 8612 case TARGET_NR_read:
ba584f1d
AS
8613 if (arg2 == 0 && arg3 == 0) {
8614 return get_errno(safe_read(arg1, 0, 0));
72eb7ea8 8615 } else {
38d840e6 8616 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
2852aafd 8617 return -TARGET_EFAULT;
50afd02b 8618 ret = get_errno(safe_read(arg1, p, arg3));
e36800c9 8619 if (ret >= 0 &&
5d4d3665
LV
8620 fd_trans_host_to_target_data(arg1)) {
8621 ret = fd_trans_host_to_target_data(arg1)(p, ret);
e36800c9 8622 }
38d840e6
AJ
8623 unlock_user(p, arg2, ret);
8624 }
72eb7ea8 8625 return ret;
31e31b8a 8626 case TARGET_NR_write:
58cfa6c2
TGJ
8627 if (arg2 == 0 && arg3 == 0) {
8628 return get_errno(safe_write(arg1, 0, 0));
8629 }
579a97f7 8630 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
2852aafd 8631 return -TARGET_EFAULT;
04b9bcf9
LV
8632 if (fd_trans_target_to_host_data(arg1)) {
8633 void *copy = g_malloc(arg3);
8634 memcpy(copy, p, arg3);
8635 ret = fd_trans_target_to_host_data(arg1)(copy, arg3);
8636 if (ret >= 0) {
8637 ret = get_errno(safe_write(arg1, copy, ret));
8638 }
8639 g_free(copy);
8640 } else {
8641 ret = get_errno(safe_write(arg1, p, arg3));
8642 }
53a5960a 8643 unlock_user(p, arg2, 0);
72eb7ea8
RH
8644 return ret;
8645
704eff6c 8646#ifdef TARGET_NR_open
31e31b8a 8647 case TARGET_NR_open:
2f619698 8648 if (!(p = lock_user_string(arg1)))
2852aafd 8649 return -TARGET_EFAULT;
0b2effd7
RV
8650 ret = get_errno(do_openat(cpu_env, AT_FDCWD, p,
8651 target_to_host_bitmask(arg2, fcntl_flags_tbl),
8652 arg3));
e36800c9 8653 fd_trans_unregister(ret);
53a5960a 8654 unlock_user(p, arg1, 0);
72eb7ea8 8655 return ret;
704eff6c 8656#endif
82424832 8657 case TARGET_NR_openat:
579a97f7 8658 if (!(p = lock_user_string(arg2)))
2852aafd 8659 return -TARGET_EFAULT;
0b2effd7
RV
8660 ret = get_errno(do_openat(cpu_env, arg1, p,
8661 target_to_host_bitmask(arg3, fcntl_flags_tbl),
8662 arg4));
e36800c9 8663 fd_trans_unregister(ret);
579a97f7 8664 unlock_user(p, arg2, 0);
72eb7ea8 8665 return ret;
0f0426f3
LV
8666#if defined(TARGET_NR_name_to_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8667 case TARGET_NR_name_to_handle_at:
8668 ret = do_name_to_handle_at(arg1, arg2, arg3, arg4, arg5);
72eb7ea8 8669 return ret;
0f0426f3
LV
8670#endif
8671#if defined(TARGET_NR_open_by_handle_at) && defined(CONFIG_OPEN_BY_HANDLE)
8672 case TARGET_NR_open_by_handle_at:
8673 ret = do_open_by_handle_at(arg1, arg2, arg3);
e36800c9 8674 fd_trans_unregister(ret);
72eb7ea8 8675 return ret;
0f0426f3 8676#endif
31e31b8a 8677 case TARGET_NR_close:
e36800c9 8678 fd_trans_unregister(arg1);
72eb7ea8
RH
8679 return get_errno(close(arg1));
8680
31e31b8a 8681 case TARGET_NR_brk:
72eb7ea8 8682 return do_brk(arg1);
704eff6c 8683#ifdef TARGET_NR_fork
31e31b8a 8684 case TARGET_NR_fork:
72eb7ea8 8685 return get_errno(do_fork(cpu_env, TARGET_SIGCHLD, 0, 0, 0, 0));
704eff6c 8686#endif
e5febef5 8687#ifdef TARGET_NR_waitpid
31e31b8a
FB
8688 case TARGET_NR_waitpid:
8689 {
53a5960a 8690 int status;
4af80a37 8691 ret = get_errno(safe_wait4(arg1, &status, arg3, 0));
5379557b 8692 if (!is_error(ret) && arg2 && ret
1d9d8b55 8693 && put_user_s32(host_to_target_waitstatus(status), arg2))
2852aafd 8694 return -TARGET_EFAULT;
31e31b8a 8695 }
72eb7ea8 8696 return ret;
e5febef5 8697#endif
f0cbb613
PB
8698#ifdef TARGET_NR_waitid
8699 case TARGET_NR_waitid:
8700 {
8701 siginfo_t info;
8702 info.si_pid = 0;
4af80a37 8703 ret = get_errno(safe_waitid(arg1, arg2, &info, arg4, NULL));
f0cbb613 8704 if (!is_error(ret) && arg3 && info.si_pid != 0) {
c227f099 8705 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
2852aafd 8706 return -TARGET_EFAULT;
f0cbb613 8707 host_to_target_siginfo(p, &info);
c227f099 8708 unlock_user(p, arg3, sizeof(target_siginfo_t));
f0cbb613
PB
8709 }
8710 }
72eb7ea8 8711 return ret;
f0cbb613 8712#endif
7a3148a9 8713#ifdef TARGET_NR_creat /* not on alpha */
31e31b8a 8714 case TARGET_NR_creat:
579a97f7 8715 if (!(p = lock_user_string(arg1)))
2852aafd 8716 return -TARGET_EFAULT;
53a5960a 8717 ret = get_errno(creat(p, arg2));
e36800c9 8718 fd_trans_unregister(ret);
53a5960a 8719 unlock_user(p, arg1, 0);
72eb7ea8 8720 return ret;
7a3148a9 8721#endif
704eff6c 8722#ifdef TARGET_NR_link
31e31b8a 8723 case TARGET_NR_link:
53a5960a
PB
8724 {
8725 void * p2;
8726 p = lock_user_string(arg1);
8727 p2 = lock_user_string(arg2);
579a97f7
FB
8728 if (!p || !p2)
8729 ret = -TARGET_EFAULT;
8730 else
8731 ret = get_errno(link(p, p2));
53a5960a
PB
8732 unlock_user(p2, arg2, 0);
8733 unlock_user(p, arg1, 0);
8734 }
72eb7ea8 8735 return ret;
704eff6c 8736#endif
c0d472b1 8737#if defined(TARGET_NR_linkat)
64f0ce4c 8738 case TARGET_NR_linkat:
64f0ce4c
TS
8739 {
8740 void * p2 = NULL;
579a97f7 8741 if (!arg2 || !arg4)
2852aafd 8742 return -TARGET_EFAULT;
64f0ce4c
TS
8743 p = lock_user_string(arg2);
8744 p2 = lock_user_string(arg4);
579a97f7 8745 if (!p || !p2)
0da46a6e 8746 ret = -TARGET_EFAULT;
64f0ce4c 8747 else
c0d472b1 8748 ret = get_errno(linkat(arg1, p, arg3, p2, arg5));
579a97f7
FB
8749 unlock_user(p, arg2, 0);
8750 unlock_user(p2, arg4, 0);
64f0ce4c 8751 }
72eb7ea8 8752 return ret;
64f0ce4c 8753#endif
704eff6c 8754#ifdef TARGET_NR_unlink
31e31b8a 8755 case TARGET_NR_unlink:
579a97f7 8756 if (!(p = lock_user_string(arg1)))
2852aafd 8757 return -TARGET_EFAULT;
53a5960a
PB
8758 ret = get_errno(unlink(p));
8759 unlock_user(p, arg1, 0);
72eb7ea8 8760 return ret;
704eff6c 8761#endif
c0d472b1 8762#if defined(TARGET_NR_unlinkat)
8170f56b 8763 case TARGET_NR_unlinkat:
579a97f7 8764 if (!(p = lock_user_string(arg2)))
2852aafd 8765 return -TARGET_EFAULT;
c0d472b1 8766 ret = get_errno(unlinkat(arg1, p, arg3));
579a97f7 8767 unlock_user(p, arg2, 0);
72eb7ea8 8768 return ret;
b7d35e65 8769#endif
31e31b8a 8770 case TARGET_NR_execve:
7854b056
FB
8771 {
8772 char **argp, **envp;
f7341ff4 8773 int argc, envc;
992f48a0
BS
8774 abi_ulong gp;
8775 abi_ulong guest_argp;
8776 abi_ulong guest_envp;
8777 abi_ulong addr;
7854b056
FB
8778 char **q;
8779
f7341ff4 8780 argc = 0;
53a5960a 8781 guest_argp = arg2;
da94d263 8782 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
03aa1976 8783 if (get_user_ual(addr, gp))
2852aafd 8784 return -TARGET_EFAULT;
03aa1976 8785 if (!addr)
2f619698 8786 break;
7854b056 8787 argc++;
2f619698 8788 }
f7341ff4 8789 envc = 0;
53a5960a 8790 guest_envp = arg3;
da94d263 8791 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
03aa1976 8792 if (get_user_ual(addr, gp))
2852aafd 8793 return -TARGET_EFAULT;
03aa1976 8794 if (!addr)
2f619698 8795 break;
7854b056 8796 envc++;
2f619698 8797 }
7854b056 8798
b936cb50
PP
8799 argp = g_new0(char *, argc + 1);
8800 envp = g_new0(char *, envc + 1);
7854b056 8801
da94d263 8802 for (gp = guest_argp, q = argp; gp;
992f48a0 8803 gp += sizeof(abi_ulong), q++) {
2f619698
FB
8804 if (get_user_ual(addr, gp))
8805 goto execve_efault;
53a5960a
PB
8806 if (!addr)
8807 break;
2f619698
FB
8808 if (!(*q = lock_user_string(addr)))
8809 goto execve_efault;
53a5960a 8810 }
f7341ff4
FB
8811 *q = NULL;
8812
da94d263 8813 for (gp = guest_envp, q = envp; gp;
992f48a0 8814 gp += sizeof(abi_ulong), q++) {
2f619698
FB
8815 if (get_user_ual(addr, gp))
8816 goto execve_efault;
53a5960a
PB
8817 if (!addr)
8818 break;
2f619698
FB
8819 if (!(*q = lock_user_string(addr)))
8820 goto execve_efault;
53a5960a 8821 }
f7341ff4 8822 *q = NULL;
7854b056 8823
2f619698
FB
8824 if (!(p = lock_user_string(arg1)))
8825 goto execve_efault;
ffdcbe22
TB
8826 /* Although execve() is not an interruptible syscall it is
8827 * a special case where we must use the safe_syscall wrapper:
8828 * if we allow a signal to happen before we make the host
8829 * syscall then we will 'lose' it, because at the point of
8830 * execve the process leaves QEMU's control. So we use the
8831 * safe syscall wrapper to ensure that we either take the
8832 * signal as a guest signal, or else it does not happen
8833 * before the execve completes and makes it the other
8834 * program's problem.
8835 */
8836 ret = get_errno(safe_execve(p, argp, envp));
53a5960a
PB
8837 unlock_user(p, arg1, 0);
8838
2f619698
FB
8839 goto execve_end;
8840
8841 execve_efault:
8842 ret = -TARGET_EFAULT;
8843
8844 execve_end:
53a5960a 8845 for (gp = guest_argp, q = argp; *q;
992f48a0 8846 gp += sizeof(abi_ulong), q++) {
2f619698
FB
8847 if (get_user_ual(addr, gp)
8848 || !addr)
8849 break;
53a5960a
PB
8850 unlock_user(*q, addr, 0);
8851 }
8852 for (gp = guest_envp, q = envp; *q;
992f48a0 8853 gp += sizeof(abi_ulong), q++) {
2f619698
FB
8854 if (get_user_ual(addr, gp)
8855 || !addr)
8856 break;
53a5960a
PB
8857 unlock_user(*q, addr, 0);
8858 }
b936cb50
PP
8859
8860 g_free(argp);
8861 g_free(envp);
7854b056 8862 }
72eb7ea8 8863 return ret;
31e31b8a 8864 case TARGET_NR_chdir:
579a97f7 8865 if (!(p = lock_user_string(arg1)))
2852aafd 8866 return -TARGET_EFAULT;
53a5960a
PB
8867 ret = get_errno(chdir(p));
8868 unlock_user(p, arg1, 0);
72eb7ea8 8869 return ret;
a315a145 8870#ifdef TARGET_NR_time
31e31b8a
FB
8871 case TARGET_NR_time:
8872 {
53a5960a
PB
8873 time_t host_time;
8874 ret = get_errno(time(&host_time));
2f619698
FB
8875 if (!is_error(ret)
8876 && arg1
8877 && put_user_sal(host_time, arg1))
2852aafd 8878 return -TARGET_EFAULT;
31e31b8a 8879 }
72eb7ea8 8880 return ret;
a315a145 8881#endif
704eff6c 8882#ifdef TARGET_NR_mknod
31e31b8a 8883 case TARGET_NR_mknod:
579a97f7 8884 if (!(p = lock_user_string(arg1)))
2852aafd 8885 return -TARGET_EFAULT;
53a5960a
PB
8886 ret = get_errno(mknod(p, arg2, arg3));
8887 unlock_user(p, arg1, 0);
72eb7ea8 8888 return ret;
704eff6c 8889#endif
c0d472b1 8890#if defined(TARGET_NR_mknodat)
75ac37a0 8891 case TARGET_NR_mknodat:
579a97f7 8892 if (!(p = lock_user_string(arg2)))
2852aafd 8893 return -TARGET_EFAULT;
c0d472b1 8894 ret = get_errno(mknodat(arg1, p, arg3, arg4));
579a97f7 8895 unlock_user(p, arg2, 0);
72eb7ea8 8896 return ret;
75ac37a0 8897#endif
704eff6c 8898#ifdef TARGET_NR_chmod
31e31b8a 8899 case TARGET_NR_chmod:
579a97f7 8900 if (!(p = lock_user_string(arg1)))
2852aafd 8901 return -TARGET_EFAULT;
53a5960a
PB
8902 ret = get_errno(chmod(p, arg2));
8903 unlock_user(p, arg1, 0);
72eb7ea8 8904 return ret;
704eff6c 8905#endif
4f7f8924 8906#ifdef TARGET_NR_lseek
31e31b8a 8907 case TARGET_NR_lseek:
72eb7ea8 8908 return get_errno(lseek(arg1, arg2, arg3));
4f7f8924 8909#endif
9231733a
RH
8910#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
8911 /* Alpha specific */
7a3148a9 8912 case TARGET_NR_getxpid:
9231733a 8913 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
72eb7ea8 8914 return get_errno(getpid());
7a3148a9 8915#endif
9231733a
RH
8916#ifdef TARGET_NR_getpid
8917 case TARGET_NR_getpid:
72eb7ea8 8918 return get_errno(getpid());
9231733a 8919#endif
31e31b8a 8920 case TARGET_NR_mount:
356d771b
PB
8921 {
8922 /* need to look at the data field */
8923 void *p2, *p3;
8924
8925 if (arg1) {
8926 p = lock_user_string(arg1);
8927 if (!p) {
2852aafd 8928 return -TARGET_EFAULT;
356d771b
PB
8929 }
8930 } else {
8931 p = NULL;
8932 }
8933
8934 p2 = lock_user_string(arg2);
8935 if (!p2) {
8936 if (arg1) {
8937 unlock_user(p, arg1, 0);
8938 }
2852aafd 8939 return -TARGET_EFAULT;
356d771b
PB
8940 }
8941
8942 if (arg3) {
8943 p3 = lock_user_string(arg3);
8944 if (!p3) {
8945 if (arg1) {
579a97f7 8946 unlock_user(p, arg1, 0);
356d771b
PB
8947 }
8948 unlock_user(p2, arg2, 0);
2852aafd 8949 return -TARGET_EFAULT;
356d771b
PB
8950 }
8951 } else {
8952 p3 = NULL;
8953 }
8954
8955 /* FIXME - arg5 should be locked, but it isn't clear how to
8956 * do that since it's not guaranteed to be a NULL-terminated
8957 * string.
8958 */
8959 if (!arg5) {
8960 ret = mount(p, p2, p3, (unsigned long)arg4, NULL);
8961 } else {
3e8f1628 8962 ret = mount(p, p2, p3, (unsigned long)arg4, g2h(cpu, arg5));
356d771b
PB
8963 }
8964 ret = get_errno(ret);
8965
8966 if (arg1) {
8967 unlock_user(p, arg1, 0);
8968 }
8969 unlock_user(p2, arg2, 0);
8970 if (arg3) {
8971 unlock_user(p3, arg3, 0);
8972 }
8973 }
72eb7ea8 8974 return ret;
6eb9dbf6
LV
8975#if defined(TARGET_NR_umount) || defined(TARGET_NR_oldumount)
8976#if defined(TARGET_NR_umount)
31e31b8a 8977 case TARGET_NR_umount:
6eb9dbf6
LV
8978#endif
8979#if defined(TARGET_NR_oldumount)
8980 case TARGET_NR_oldumount:
8981#endif
579a97f7 8982 if (!(p = lock_user_string(arg1)))
2852aafd 8983 return -TARGET_EFAULT;
53a5960a
PB
8984 ret = get_errno(umount(p));
8985 unlock_user(p, arg1, 0);
72eb7ea8 8986 return ret;
e5febef5 8987#endif
7a3148a9 8988#ifdef TARGET_NR_stime /* not on alpha */
31e31b8a
FB
8989 case TARGET_NR_stime:
8990 {
0f1f2d45
LV
8991 struct timespec ts;
8992 ts.tv_nsec = 0;
8993 if (get_user_sal(ts.tv_sec, arg1)) {
2852aafd 8994 return -TARGET_EFAULT;
0f1f2d45
LV
8995 }
8996 return get_errno(clock_settime(CLOCK_REALTIME, &ts));
31e31b8a 8997 }
7a3148a9 8998#endif
7a3148a9 8999#ifdef TARGET_NR_alarm /* not on alpha */
31e31b8a 9000 case TARGET_NR_alarm:
72eb7ea8 9001 return alarm(arg1);
7a3148a9 9002#endif
7a3148a9 9003#ifdef TARGET_NR_pause /* not on alpha */
31e31b8a 9004 case TARGET_NR_pause:
f59ec606
TB
9005 if (!block_signals()) {
9006 sigsuspend(&((TaskState *)cpu->opaque)->signal_mask);
9007 }
72eb7ea8 9008 return -TARGET_EINTR;
7a3148a9 9009#endif
e5febef5 9010#ifdef TARGET_NR_utime
31e31b8a 9011 case TARGET_NR_utime:
ebc05488 9012 {
53a5960a
PB
9013 struct utimbuf tbuf, *host_tbuf;
9014 struct target_utimbuf *target_tbuf;
9015 if (arg2) {
579a97f7 9016 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
2852aafd 9017 return -TARGET_EFAULT;
cbb21eed
MB
9018 tbuf.actime = tswapal(target_tbuf->actime);
9019 tbuf.modtime = tswapal(target_tbuf->modtime);
53a5960a
PB
9020 unlock_user_struct(target_tbuf, arg2, 0);
9021 host_tbuf = &tbuf;
f72e8ff4 9022 } else {
53a5960a 9023 host_tbuf = NULL;
f72e8ff4 9024 }
579a97f7 9025 if (!(p = lock_user_string(arg1)))
2852aafd 9026 return -TARGET_EFAULT;
53a5960a
PB
9027 ret = get_errno(utime(p, host_tbuf));
9028 unlock_user(p, arg1, 0);
ebc05488 9029 }
72eb7ea8 9030 return ret;
e5febef5 9031#endif
704eff6c 9032#ifdef TARGET_NR_utimes
978a66ff
FB
9033 case TARGET_NR_utimes:
9034 {
978a66ff 9035 struct timeval *tvp, tv[2];
53a5960a 9036 if (arg2) {
788f5ec4
TS
9037 if (copy_from_user_timeval(&tv[0], arg2)
9038 || copy_from_user_timeval(&tv[1],
9039 arg2 + sizeof(struct target_timeval)))
2852aafd 9040 return -TARGET_EFAULT;
978a66ff
FB
9041 tvp = tv;
9042 } else {
9043 tvp = NULL;
9044 }
579a97f7 9045 if (!(p = lock_user_string(arg1)))
2852aafd 9046 return -TARGET_EFAULT;
53a5960a
PB
9047 ret = get_errno(utimes(p, tvp));
9048 unlock_user(p, arg1, 0);
978a66ff 9049 }
72eb7ea8 9050 return ret;
704eff6c 9051#endif
c0d472b1 9052#if defined(TARGET_NR_futimesat)
ac8a6556
AZ
9053 case TARGET_NR_futimesat:
9054 {
9055 struct timeval *tvp, tv[2];
9056 if (arg3) {
9057 if (copy_from_user_timeval(&tv[0], arg3)
9058 || copy_from_user_timeval(&tv[1],
9059 arg3 + sizeof(struct target_timeval)))
2852aafd 9060 return -TARGET_EFAULT;
ac8a6556
AZ
9061 tvp = tv;
9062 } else {
9063 tvp = NULL;
9064 }
2852aafd
RH
9065 if (!(p = lock_user_string(arg2))) {
9066 return -TARGET_EFAULT;
9067 }
c0d472b1 9068 ret = get_errno(futimesat(arg1, path(p), tvp));
ac8a6556
AZ
9069 unlock_user(p, arg2, 0);
9070 }
72eb7ea8 9071 return ret;
ac8a6556 9072#endif
704eff6c 9073#ifdef TARGET_NR_access
31e31b8a 9074 case TARGET_NR_access:
2852aafd
RH
9075 if (!(p = lock_user_string(arg1))) {
9076 return -TARGET_EFAULT;
9077 }
719f908e 9078 ret = get_errno(access(path(p), arg2));
53a5960a 9079 unlock_user(p, arg1, 0);
72eb7ea8 9080 return ret;
704eff6c 9081#endif
92a34c10
TS
9082#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
9083 case TARGET_NR_faccessat:
2852aafd
RH
9084 if (!(p = lock_user_string(arg2))) {
9085 return -TARGET_EFAULT;
9086 }
c0d472b1 9087 ret = get_errno(faccessat(arg1, p, arg3, 0));
579a97f7 9088 unlock_user(p, arg2, 0);
72eb7ea8 9089 return ret;
92a34c10 9090#endif
7a3148a9 9091#ifdef TARGET_NR_nice /* not on alpha */
31e31b8a 9092 case TARGET_NR_nice:
72eb7ea8 9093 return get_errno(nice(arg1));
ebc05488 9094#endif
31e31b8a 9095 case TARGET_NR_sync:
04369ff2 9096 sync();
72eb7ea8 9097 return 0;
5a03cd00
AM
9098#if defined(TARGET_NR_syncfs) && defined(CONFIG_SYNCFS)
9099 case TARGET_NR_syncfs:
72eb7ea8 9100 return get_errno(syncfs(arg1));
5a03cd00 9101#endif
31e31b8a 9102 case TARGET_NR_kill:
72eb7ea8 9103 return get_errno(safe_kill(arg1, target_to_host_signal(arg2)));
704eff6c 9104#ifdef TARGET_NR_rename
31e31b8a 9105 case TARGET_NR_rename:
53a5960a
PB
9106 {
9107 void *p2;
9108 p = lock_user_string(arg1);
9109 p2 = lock_user_string(arg2);
579a97f7
FB
9110 if (!p || !p2)
9111 ret = -TARGET_EFAULT;
9112 else
9113 ret = get_errno(rename(p, p2));
53a5960a
PB
9114 unlock_user(p2, arg2, 0);
9115 unlock_user(p, arg1, 0);
9116 }
72eb7ea8 9117 return ret;
704eff6c 9118#endif
c0d472b1 9119#if defined(TARGET_NR_renameat)
722183f6 9120 case TARGET_NR_renameat:
722183f6 9121 {
579a97f7 9122 void *p2;
722183f6
TS
9123 p = lock_user_string(arg2);
9124 p2 = lock_user_string(arg4);
579a97f7 9125 if (!p || !p2)
0da46a6e 9126 ret = -TARGET_EFAULT;
722183f6 9127 else
c0d472b1 9128 ret = get_errno(renameat(arg1, p, arg3, p2));
579a97f7
FB
9129 unlock_user(p2, arg4, 0);
9130 unlock_user(p, arg2, 0);
722183f6 9131 }
72eb7ea8 9132 return ret;
95d0307c
AS
9133#endif
9134#if defined(TARGET_NR_renameat2)
9135 case TARGET_NR_renameat2:
9136 {
9137 void *p2;
9138 p = lock_user_string(arg2);
9139 p2 = lock_user_string(arg4);
9140 if (!p || !p2) {
9141 ret = -TARGET_EFAULT;
9142 } else {
9143 ret = get_errno(sys_renameat2(arg1, p, arg3, p2, arg5));
9144 }
9145 unlock_user(p2, arg4, 0);
9146 unlock_user(p, arg2, 0);
9147 }
72eb7ea8 9148 return ret;
722183f6 9149#endif
704eff6c 9150#ifdef TARGET_NR_mkdir
31e31b8a 9151 case TARGET_NR_mkdir:
579a97f7 9152 if (!(p = lock_user_string(arg1)))
2852aafd 9153 return -TARGET_EFAULT;
53a5960a
PB
9154 ret = get_errno(mkdir(p, arg2));
9155 unlock_user(p, arg1, 0);
72eb7ea8 9156 return ret;
704eff6c 9157#endif
c0d472b1 9158#if defined(TARGET_NR_mkdirat)
4472ad0d 9159 case TARGET_NR_mkdirat:
579a97f7 9160 if (!(p = lock_user_string(arg2)))
2852aafd 9161 return -TARGET_EFAULT;
c0d472b1 9162 ret = get_errno(mkdirat(arg1, p, arg3));
579a97f7 9163 unlock_user(p, arg2, 0);
72eb7ea8 9164 return ret;
4472ad0d 9165#endif
704eff6c 9166#ifdef TARGET_NR_rmdir
31e31b8a 9167 case TARGET_NR_rmdir:
579a97f7 9168 if (!(p = lock_user_string(arg1)))
2852aafd 9169 return -TARGET_EFAULT;
53a5960a
PB
9170 ret = get_errno(rmdir(p));
9171 unlock_user(p, arg1, 0);
72eb7ea8 9172 return ret;
704eff6c 9173#endif
31e31b8a
FB
9174 case TARGET_NR_dup:
9175 ret = get_errno(dup(arg1));
e36800c9
LV
9176 if (ret >= 0) {
9177 fd_trans_dup(arg1, ret);
9178 }
72eb7ea8 9179 return ret;
704eff6c 9180#ifdef TARGET_NR_pipe
31e31b8a 9181 case TARGET_NR_pipe:
72eb7ea8 9182 return do_pipe(cpu_env, arg1, 0, 0);
704eff6c 9183#endif
099d6b0f
RV
9184#ifdef TARGET_NR_pipe2
9185 case TARGET_NR_pipe2:
72eb7ea8
RH
9186 return do_pipe(cpu_env, arg1,
9187 target_to_host_bitmask(arg2, fcntl_flags_tbl), 1);
099d6b0f 9188#endif
31e31b8a 9189 case TARGET_NR_times:
32f36bce 9190 {
53a5960a 9191 struct target_tms *tmsp;
32f36bce
FB
9192 struct tms tms;
9193 ret = get_errno(times(&tms));
53a5960a 9194 if (arg1) {
579a97f7
FB
9195 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
9196 if (!tmsp)
2852aafd 9197 return -TARGET_EFAULT;
cbb21eed
MB
9198 tmsp->tms_utime = tswapal(host_to_target_clock_t(tms.tms_utime));
9199 tmsp->tms_stime = tswapal(host_to_target_clock_t(tms.tms_stime));
9200 tmsp->tms_cutime = tswapal(host_to_target_clock_t(tms.tms_cutime));
9201 tmsp->tms_cstime = tswapal(host_to_target_clock_t(tms.tms_cstime));
32f36bce 9202 }
c596ed17
FB
9203 if (!is_error(ret))
9204 ret = host_to_target_clock_t(ret);
32f36bce 9205 }
72eb7ea8 9206 return ret;
31e31b8a 9207 case TARGET_NR_acct:
38d840e6
AJ
9208 if (arg1 == 0) {
9209 ret = get_errno(acct(NULL));
9210 } else {
2852aafd
RH
9211 if (!(p = lock_user_string(arg1))) {
9212 return -TARGET_EFAULT;
9213 }
38d840e6
AJ
9214 ret = get_errno(acct(path(p)));
9215 unlock_user(p, arg1, 0);
9216 }
72eb7ea8 9217 return ret;
8070e7be 9218#ifdef TARGET_NR_umount2
31e31b8a 9219 case TARGET_NR_umount2:
579a97f7 9220 if (!(p = lock_user_string(arg1)))
2852aafd 9221 return -TARGET_EFAULT;
53a5960a
PB
9222 ret = get_errno(umount2(p, arg2));
9223 unlock_user(p, arg1, 0);
72eb7ea8 9224 return ret;
ebc05488 9225#endif
31e31b8a 9226 case TARGET_NR_ioctl:
72eb7ea8 9227 return do_ioctl(arg1, arg2, arg3);
47ae93cd 9228#ifdef TARGET_NR_fcntl
31e31b8a 9229 case TARGET_NR_fcntl:
72eb7ea8 9230 return do_fcntl(arg1, arg2, arg3);
ebc05488 9231#endif
31e31b8a 9232 case TARGET_NR_setpgid:
72eb7ea8 9233 return get_errno(setpgid(arg1, arg2));
31e31b8a 9234 case TARGET_NR_umask:
72eb7ea8 9235 return get_errno(umask(arg1));
31e31b8a 9236 case TARGET_NR_chroot:
579a97f7 9237 if (!(p = lock_user_string(arg1)))
2852aafd 9238 return -TARGET_EFAULT;
53a5960a
PB
9239 ret = get_errno(chroot(p));
9240 unlock_user(p, arg1, 0);
72eb7ea8 9241 return ret;
704eff6c 9242#ifdef TARGET_NR_dup2
31e31b8a
FB
9243 case TARGET_NR_dup2:
9244 ret = get_errno(dup2(arg1, arg2));
e36800c9
LV
9245 if (ret >= 0) {
9246 fd_trans_dup(arg1, arg2);
9247 }
72eb7ea8 9248 return ret;
704eff6c 9249#endif
d0927938
UH
9250#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
9251 case TARGET_NR_dup3:
10fa993a
PM
9252 {
9253 int host_flags;
9254
9255 if ((arg3 & ~TARGET_O_CLOEXEC) != 0) {
9256 return -EINVAL;
9257 }
9258 host_flags = target_to_host_bitmask(arg3, fcntl_flags_tbl);
9259 ret = get_errno(dup3(arg1, arg2, host_flags));
e36800c9
LV
9260 if (ret >= 0) {
9261 fd_trans_dup(arg1, arg2);
9262 }
72eb7ea8 9263 return ret;
10fa993a 9264 }
d0927938 9265#endif
7a3148a9 9266#ifdef TARGET_NR_getppid /* not on alpha */
31e31b8a 9267 case TARGET_NR_getppid:
72eb7ea8 9268 return get_errno(getppid());
7a3148a9 9269#endif
704eff6c 9270#ifdef TARGET_NR_getpgrp
31e31b8a 9271 case TARGET_NR_getpgrp:
72eb7ea8 9272 return get_errno(getpgrp());
704eff6c 9273#endif
31e31b8a 9274 case TARGET_NR_setsid:
72eb7ea8 9275 return get_errno(setsid());
e5febef5 9276#ifdef TARGET_NR_sigaction
31e31b8a 9277 case TARGET_NR_sigaction:
31e31b8a 9278 {
02d0de10 9279#if defined(TARGET_MIPS)
106ec879
FB
9280 struct target_sigaction act, oact, *pact, *old_act;
9281
9282 if (arg2) {
579a97f7 9283 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9284 return -TARGET_EFAULT;
106ec879
FB
9285 act._sa_handler = old_act->_sa_handler;
9286 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
9287 act.sa_flags = old_act->sa_flags;
9288 unlock_user_struct(old_act, arg2, 0);
9289 pact = &act;
9290 } else {
9291 pact = NULL;
9292 }
9293
02fb28e8 9294 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
106ec879
FB
9295
9296 if (!is_error(ret) && arg3) {
579a97f7 9297 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9298 return -TARGET_EFAULT;
106ec879
FB
9299 old_act->_sa_handler = oact._sa_handler;
9300 old_act->sa_flags = oact.sa_flags;
9301 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
9302 old_act->sa_mask.sig[1] = 0;
9303 old_act->sa_mask.sig[2] = 0;
9304 old_act->sa_mask.sig[3] = 0;
9305 unlock_user_struct(old_act, arg3, 1);
9306 }
6049f4f8
RH
9307#else
9308 struct target_old_sigaction *old_act;
9309 struct target_sigaction act, oact, *pact;
9310 if (arg2) {
9311 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
2852aafd 9312 return -TARGET_EFAULT;
6049f4f8
RH
9313 act._sa_handler = old_act->_sa_handler;
9314 target_siginitset(&act.sa_mask, old_act->sa_mask);
9315 act.sa_flags = old_act->sa_flags;
ca192277 9316#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9317 act.sa_restorer = old_act->sa_restorer;
ca192277 9318#endif
6049f4f8
RH
9319 unlock_user_struct(old_act, arg2, 0);
9320 pact = &act;
9321 } else {
9322 pact = NULL;
9323 }
02fb28e8 9324 ret = get_errno(do_sigaction(arg1, pact, &oact, 0));
6049f4f8
RH
9325 if (!is_error(ret) && arg3) {
9326 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
2852aafd 9327 return -TARGET_EFAULT;
6049f4f8
RH
9328 old_act->_sa_handler = oact._sa_handler;
9329 old_act->sa_mask = oact.sa_mask.sig[0];
9330 old_act->sa_flags = oact.sa_flags;
ca192277 9331#ifdef TARGET_ARCH_HAS_SA_RESTORER
6049f4f8 9332 old_act->sa_restorer = oact.sa_restorer;
ca192277 9333#endif
6049f4f8
RH
9334 unlock_user_struct(old_act, arg3, 1);
9335 }
388bb21a 9336#endif
31e31b8a 9337 }
72eb7ea8 9338 return ret;
e5febef5 9339#endif
66fb9763 9340 case TARGET_NR_rt_sigaction:
53a5960a 9341 {
0f6f9903
RH
9342 /*
9343 * For Alpha and SPARC this is a 5 argument syscall, with
78bfef72
PM
9344 * a 'restorer' parameter which must be copied into the
9345 * sa_restorer field of the sigaction struct.
9346 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
9347 * and arg5 is the sigsetsize.
78bfef72 9348 */
0f6f9903
RH
9349#if defined(TARGET_ALPHA)
9350 target_ulong sigsetsize = arg4;
9351 target_ulong restorer = arg5;
9352#elif defined(TARGET_SPARC)
78bfef72
PM
9353 target_ulong restorer = arg4;
9354 target_ulong sigsetsize = arg5;
9355#else
9356 target_ulong sigsetsize = arg4;
02fb28e8 9357 target_ulong restorer = 0;
78bfef72 9358#endif
fb80439b
RH
9359 struct target_sigaction *act = NULL;
9360 struct target_sigaction *oact = NULL;
53a5960a 9361
78bfef72 9362 if (sigsetsize != sizeof(target_sigset_t)) {
72eb7ea8 9363 return -TARGET_EINVAL;
c815701e 9364 }
fb80439b
RH
9365 if (arg2 && !lock_user_struct(VERIFY_READ, act, arg2, 1)) {
9366 return -TARGET_EFAULT;
78bfef72 9367 }
fb80439b
RH
9368 if (arg3 && !lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
9369 ret = -TARGET_EFAULT;
9370 } else {
9371 ret = get_errno(do_sigaction(arg1, act, oact, restorer));
9372 if (oact) {
9373 unlock_user_struct(oact, arg3, 1);
579a97f7 9374 }
fb80439b
RH
9375 }
9376 if (act) {
53a5960a 9377 unlock_user_struct(act, arg2, 0);
fb80439b 9378 }
53a5960a 9379 }
72eb7ea8 9380 return ret;
7a3148a9 9381#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 9382 case TARGET_NR_sgetmask:
66fb9763
FB
9383 {
9384 sigset_t cur_set;
992f48a0 9385 abi_ulong target_set;
3d3efba0
PM
9386 ret = do_sigprocmask(0, NULL, &cur_set);
9387 if (!ret) {
9388 host_to_target_old_sigset(&target_set, &cur_set);
9389 ret = target_set;
9390 }
66fb9763 9391 }
72eb7ea8 9392 return ret;
7a3148a9
JM
9393#endif
9394#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 9395 case TARGET_NR_ssetmask:
66fb9763 9396 {
a8617d8c 9397 sigset_t set, oset;
992f48a0 9398 abi_ulong target_set = arg1;
66fb9763 9399 target_to_host_old_sigset(&set, &target_set);
3d3efba0
PM
9400 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
9401 if (!ret) {
9402 host_to_target_old_sigset(&target_set, &oset);
9403 ret = target_set;
9404 }
66fb9763 9405 }
72eb7ea8 9406 return ret;
7a3148a9 9407#endif
e5febef5 9408#ifdef TARGET_NR_sigprocmask
66fb9763
FB
9409 case TARGET_NR_sigprocmask:
9410 {
a5b3b13b
RH
9411#if defined(TARGET_ALPHA)
9412 sigset_t set, oldset;
9413 abi_ulong mask;
9414 int how;
9415
9416 switch (arg1) {
9417 case TARGET_SIG_BLOCK:
9418 how = SIG_BLOCK;
9419 break;
9420 case TARGET_SIG_UNBLOCK:
9421 how = SIG_UNBLOCK;
9422 break;
9423 case TARGET_SIG_SETMASK:
9424 how = SIG_SETMASK;
9425 break;
9426 default:
259841c1 9427 return -TARGET_EINVAL;
a5b3b13b
RH
9428 }
9429 mask = arg2;
9430 target_to_host_old_sigset(&set, &mask);
9431
3d3efba0 9432 ret = do_sigprocmask(how, &set, &oldset);
a5b3b13b
RH
9433 if (!is_error(ret)) {
9434 host_to_target_old_sigset(&mask, &oldset);
9435 ret = mask;
0229f5a3 9436 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
9437 }
9438#else
66fb9763 9439 sigset_t set, oldset, *set_ptr;
a5b3b13b 9440 int how;
3b46e624 9441
53a5960a 9442 if (arg2) {
ebce1719
PV
9443 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9444 if (!p) {
9445 return -TARGET_EFAULT;
9446 }
9447 target_to_host_old_sigset(&set, p);
9448 unlock_user(p, arg2, 0);
9449 set_ptr = &set;
a5b3b13b 9450 switch (arg1) {
66fb9763
FB
9451 case TARGET_SIG_BLOCK:
9452 how = SIG_BLOCK;
9453 break;
9454 case TARGET_SIG_UNBLOCK:
9455 how = SIG_UNBLOCK;
9456 break;
9457 case TARGET_SIG_SETMASK:
9458 how = SIG_SETMASK;
9459 break;
9460 default:
259841c1 9461 return -TARGET_EINVAL;
66fb9763 9462 }
66fb9763
FB
9463 } else {
9464 how = 0;
9465 set_ptr = NULL;
9466 }
3d3efba0 9467 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9468 if (!is_error(ret) && arg3) {
c227f099 9469 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9470 return -TARGET_EFAULT;
53a5960a 9471 host_to_target_old_sigset(p, &oldset);
c227f099 9472 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 9473 }
a5b3b13b 9474#endif
66fb9763 9475 }
72eb7ea8 9476 return ret;
e5febef5 9477#endif
66fb9763
FB
9478 case TARGET_NR_rt_sigprocmask:
9479 {
9480 int how = arg1;
9481 sigset_t set, oldset, *set_ptr;
3b46e624 9482
c815701e 9483 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9484 return -TARGET_EINVAL;
c815701e
PM
9485 }
9486
53a5960a 9487 if (arg2) {
d3ced2a5
SCW
9488 p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1);
9489 if (!p) {
9490 return -TARGET_EFAULT;
9491 }
9492 target_to_host_sigset(&set, p);
9493 unlock_user(p, arg2, 0);
9494 set_ptr = &set;
66fb9763
FB
9495 switch(how) {
9496 case TARGET_SIG_BLOCK:
9497 how = SIG_BLOCK;
9498 break;
9499 case TARGET_SIG_UNBLOCK:
9500 how = SIG_UNBLOCK;
9501 break;
9502 case TARGET_SIG_SETMASK:
9503 how = SIG_SETMASK;
9504 break;
9505 default:
259841c1 9506 return -TARGET_EINVAL;
66fb9763 9507 }
66fb9763
FB
9508 } else {
9509 how = 0;
9510 set_ptr = NULL;
9511 }
3d3efba0 9512 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 9513 if (!is_error(ret) && arg3) {
c227f099 9514 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
2852aafd 9515 return -TARGET_EFAULT;
53a5960a 9516 host_to_target_sigset(p, &oldset);
c227f099 9517 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
9518 }
9519 }
72eb7ea8 9520 return ret;
e5febef5 9521#ifdef TARGET_NR_sigpending
66fb9763
FB
9522 case TARGET_NR_sigpending:
9523 {
9524 sigset_t set;
9525 ret = get_errno(sigpending(&set));
9526 if (!is_error(ret)) {
c227f099 9527 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9528 return -TARGET_EFAULT;
53a5960a 9529 host_to_target_old_sigset(p, &set);
c227f099 9530 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9531 }
9532 }
72eb7ea8 9533 return ret;
e5febef5 9534#endif
66fb9763
FB
9535 case TARGET_NR_rt_sigpending:
9536 {
9537 sigset_t set;
c815701e
PM
9538
9539 /* Yes, this check is >, not != like most. We follow the kernel's
9540 * logic and it does it like this because it implements
9541 * NR_sigpending through the same code path, and in that case
9542 * the old_sigset_t is smaller in size.
9543 */
9544 if (arg2 > sizeof(target_sigset_t)) {
72eb7ea8 9545 return -TARGET_EINVAL;
c815701e
PM
9546 }
9547
66fb9763
FB
9548 ret = get_errno(sigpending(&set));
9549 if (!is_error(ret)) {
c227f099 9550 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
2852aafd 9551 return -TARGET_EFAULT;
53a5960a 9552 host_to_target_sigset(p, &set);
c227f099 9553 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
9554 }
9555 }
72eb7ea8 9556 return ret;
e5febef5 9557#ifdef TARGET_NR_sigsuspend
66fb9763
FB
9558 case TARGET_NR_sigsuspend:
9559 {
3d3efba0 9560 TaskState *ts = cpu->opaque;
f43ce12b 9561#if defined(TARGET_ALPHA)
7fb5ef35
RH
9562 /* target_to_host_old_sigset will bswap back */
9563 abi_ulong mask = tswapal(arg1);
3d3efba0 9564 target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
f43ce12b 9565#else
c227f099 9566 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
2852aafd 9567 return -TARGET_EFAULT;
3d3efba0 9568 target_to_host_old_sigset(&ts->sigsuspend_mask, p);
53a5960a 9569 unlock_user(p, arg1, 0);
f43ce12b 9570#endif
3d3efba0
PM
9571 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
9572 SIGSET_T_SIZE));
af254a27 9573 if (ret != -QEMU_ERESTARTSYS) {
3d3efba0
PM
9574 ts->in_sigsuspend = 1;
9575 }
66fb9763 9576 }
72eb7ea8 9577 return ret;
e5febef5 9578#endif
66fb9763
FB
9579 case TARGET_NR_rt_sigsuspend:
9580 {
3d3efba0 9581 TaskState *ts = cpu->opaque;
c815701e
PM
9582
9583 if (arg2 != sizeof(target_sigset_t)) {
72eb7ea8 9584 return -TARGET_EINVAL;
c815701e 9585 }
c227f099 9586 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
2852aafd 9587 return -TARGET_EFAULT;
3d3efba0 9588 target_to_host_sigset(&ts->sigsuspend_mask, p);
53a5960a 9589 unlock_user(p, arg1, 0);
3d3efba0
PM
9590 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
9591 SIGSET_T_SIZE));
af254a27 9592 if (ret != -QEMU_ERESTARTSYS) {
3d3efba0
PM
9593 ts->in_sigsuspend = 1;
9594 }
66fb9763 9595 }
72eb7ea8 9596 return ret;
859e8a89 9597#ifdef TARGET_NR_rt_sigtimedwait
66fb9763
FB
9598 case TARGET_NR_rt_sigtimedwait:
9599 {
66fb9763
FB
9600 sigset_t set;
9601 struct timespec uts, *puts;
9602 siginfo_t uinfo;
3b46e624 9603
c815701e 9604 if (arg4 != sizeof(target_sigset_t)) {
72eb7ea8 9605 return -TARGET_EINVAL;
c815701e
PM
9606 }
9607
c227f099 9608 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
2852aafd 9609 return -TARGET_EFAULT;
53a5960a
PB
9610 target_to_host_sigset(&set, p);
9611 unlock_user(p, arg1, 0);
9612 if (arg3) {
66fb9763 9613 puts = &uts;
4d213001
FB
9614 if (target_to_host_timespec(puts, arg3)) {
9615 return -TARGET_EFAULT;
9616 }
66fb9763
FB
9617 } else {
9618 puts = NULL;
9619 }
b3f82330
PM
9620 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9621 SIGSET_T_SIZE));
974a196d
PJ
9622 if (!is_error(ret)) {
9623 if (arg2) {
9624 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
9625 0);
9626 if (!p) {
2852aafd 9627 return -TARGET_EFAULT;
974a196d
PJ
9628 }
9629 host_to_target_siginfo(p, &uinfo);
9630 unlock_user(p, arg2, sizeof(target_siginfo_t));
9631 }
9632 ret = host_to_target_signal(ret);
66fb9763
FB
9633 }
9634 }
72eb7ea8 9635 return ret;
ddcbde15
FB
9636#endif
9637#ifdef TARGET_NR_rt_sigtimedwait_time64
9638 case TARGET_NR_rt_sigtimedwait_time64:
9639 {
9640 sigset_t set;
9641 struct timespec uts, *puts;
9642 siginfo_t uinfo;
9643
9644 if (arg4 != sizeof(target_sigset_t)) {
9645 return -TARGET_EINVAL;
9646 }
9647
9648 p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1);
9649 if (!p) {
9650 return -TARGET_EFAULT;
9651 }
9652 target_to_host_sigset(&set, p);
9653 unlock_user(p, arg1, 0);
9654 if (arg3) {
9655 puts = &uts;
9656 if (target_to_host_timespec64(puts, arg3)) {
9657 return -TARGET_EFAULT;
9658 }
9659 } else {
9660 puts = NULL;
9661 }
9662 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
9663 SIGSET_T_SIZE));
9664 if (!is_error(ret)) {
9665 if (arg2) {
9666 p = lock_user(VERIFY_WRITE, arg2,
9667 sizeof(target_siginfo_t), 0);
9668 if (!p) {
9669 return -TARGET_EFAULT;
9670 }
9671 host_to_target_siginfo(p, &uinfo);
9672 unlock_user(p, arg2, sizeof(target_siginfo_t));
9673 }
9674 ret = host_to_target_signal(ret);
9675 }
9676 }
9677 return ret;
859e8a89 9678#endif
66fb9763
FB
9679 case TARGET_NR_rt_sigqueueinfo:
9680 {
9681 siginfo_t uinfo;
4debae6f
PM
9682
9683 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
9684 if (!p) {
2852aafd 9685 return -TARGET_EFAULT;
4debae6f 9686 }
53a5960a 9687 target_to_host_siginfo(&uinfo, p);
d8b6d892 9688 unlock_user(p, arg3, 0);
66fb9763
FB
9689 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
9690 }
72eb7ea8 9691 return ret;
cf8b8bfc
MS
9692 case TARGET_NR_rt_tgsigqueueinfo:
9693 {
9694 siginfo_t uinfo;
9695
9696 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
9697 if (!p) {
2852aafd 9698 return -TARGET_EFAULT;
cf8b8bfc
MS
9699 }
9700 target_to_host_siginfo(&uinfo, p);
9701 unlock_user(p, arg4, 0);
9702 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
9703 }
72eb7ea8 9704 return ret;
e5febef5 9705#ifdef TARGET_NR_sigreturn
66fb9763 9706 case TARGET_NR_sigreturn:
3d3efba0 9707 if (block_signals()) {
af254a27 9708 return -QEMU_ERESTARTSYS;
3d3efba0 9709 }
72eb7ea8 9710 return do_sigreturn(cpu_env);
e5febef5 9711#endif
66fb9763 9712 case TARGET_NR_rt_sigreturn:
3d3efba0 9713 if (block_signals()) {
af254a27 9714 return -QEMU_ERESTARTSYS;
3d3efba0 9715 }
72eb7ea8 9716 return do_rt_sigreturn(cpu_env);
31e31b8a 9717 case TARGET_NR_sethostname:
579a97f7 9718 if (!(p = lock_user_string(arg1)))
2852aafd 9719 return -TARGET_EFAULT;
53a5960a
PB
9720 ret = get_errno(sethostname(p, arg2));
9721 unlock_user(p, arg1, 0);
72eb7ea8 9722 return ret;
4f7f8924 9723#ifdef TARGET_NR_setrlimit
31e31b8a 9724 case TARGET_NR_setrlimit:
9de5e440 9725 {
e22b7015 9726 int resource = target_to_host_resource(arg1);
53a5960a 9727 struct target_rlimit *target_rlim;
9de5e440 9728 struct rlimit rlim;
579a97f7 9729 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
2852aafd 9730 return -TARGET_EFAULT;
81bbe906
TY
9731 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
9732 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 9733 unlock_user_struct(target_rlim, arg2, 0);
5dfa88f7
MF
9734 /*
9735 * If we just passed through resource limit settings for memory then
9736 * they would also apply to QEMU's own allocations, and QEMU will
9737 * crash or hang or die if its allocations fail. Ideally we would
9738 * track the guest allocations in QEMU and apply the limits ourselves.
9739 * For now, just tell the guest the call succeeded but don't actually
9740 * limit anything.
9741 */
9742 if (resource != RLIMIT_AS &&
9743 resource != RLIMIT_DATA &&
9744 resource != RLIMIT_STACK) {
9745 return get_errno(setrlimit(resource, &rlim));
9746 } else {
9747 return 0;
9748 }
9de5e440 9749 }
4f7f8924
AR
9750#endif
9751#ifdef TARGET_NR_getrlimit
31e31b8a 9752 case TARGET_NR_getrlimit:
9de5e440 9753 {
e22b7015 9754 int resource = target_to_host_resource(arg1);
53a5960a 9755 struct target_rlimit *target_rlim;
9de5e440 9756 struct rlimit rlim;
3b46e624 9757
9de5e440
FB
9758 ret = get_errno(getrlimit(resource, &rlim));
9759 if (!is_error(ret)) {
579a97f7 9760 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 9761 return -TARGET_EFAULT;
81bbe906
TY
9762 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
9763 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 9764 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
9765 }
9766 }
72eb7ea8 9767 return ret;
4f7f8924 9768#endif
31e31b8a 9769 case TARGET_NR_getrusage:
b409186b
FB
9770 {
9771 struct rusage rusage;
b409186b
FB
9772 ret = get_errno(getrusage(arg1, &rusage));
9773 if (!is_error(ret)) {
a39fb273 9774 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
9775 }
9776 }
72eb7ea8 9777 return ret;
859e8a89 9778#if defined(TARGET_NR_gettimeofday)
31e31b8a
FB
9779 case TARGET_NR_gettimeofday:
9780 {
31e31b8a 9781 struct timeval tv;
a52f5f87
RH
9782 struct timezone tz;
9783
9784 ret = get_errno(gettimeofday(&tv, &tz));
31e31b8a 9785 if (!is_error(ret)) {
a52f5f87
RH
9786 if (arg1 && copy_to_user_timeval(arg1, &tv)) {
9787 return -TARGET_EFAULT;
9788 }
9789 if (arg2 && copy_to_user_timezone(arg2, &tz)) {
2852aafd 9790 return -TARGET_EFAULT;
a52f5f87 9791 }
31e31b8a
FB
9792 }
9793 }
72eb7ea8 9794 return ret;
859e8a89
AF
9795#endif
9796#if defined(TARGET_NR_settimeofday)
31e31b8a
FB
9797 case TARGET_NR_settimeofday:
9798 {
b67d8031 9799 struct timeval tv, *ptv = NULL;
ef4467e9
PB
9800 struct timezone tz, *ptz = NULL;
9801
b67d8031
PB
9802 if (arg1) {
9803 if (copy_from_user_timeval(&tv, arg1)) {
2852aafd 9804 return -TARGET_EFAULT;
b67d8031
PB
9805 }
9806 ptv = &tv;
9807 }
ef4467e9
PB
9808
9809 if (arg2) {
9810 if (copy_from_user_timezone(&tz, arg2)) {
2852aafd 9811 return -TARGET_EFAULT;
ef4467e9
PB
9812 }
9813 ptz = &tz;
9814 }
9815
72eb7ea8 9816 return get_errno(settimeofday(ptv, ptz));
31e31b8a 9817 }
859e8a89 9818#endif
9468a5d4 9819#if defined(TARGET_NR_select)
31e31b8a 9820 case TARGET_NR_select:
5457dc9e
LV
9821#if defined(TARGET_WANT_NI_OLD_SELECT)
9822 /* some architectures used to have old_select here
9823 * but now ENOSYS it.
9824 */
9825 ret = -TARGET_ENOSYS;
9826#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9827 ret = do_old_select(arg1);
9468a5d4 9828#else
5457dc9e 9829 ret = do_select(arg1, arg2, arg3, arg4, arg5);
9468a5d4 9830#endif
72eb7ea8 9831 return ret;
9e42382f
RV
9832#endif
9833#ifdef TARGET_NR_pselect6
9834 case TARGET_NR_pselect6:
e5ce9688
FB
9835 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, false);
9836#endif
9837#ifdef TARGET_NR_pselect6_time64
9838 case TARGET_NR_pselect6_time64:
9839 return do_pselect6(arg1, arg2, arg3, arg4, arg5, arg6, true);
048f6b4d 9840#endif
704eff6c 9841#ifdef TARGET_NR_symlink
31e31b8a 9842 case TARGET_NR_symlink:
53a5960a
PB
9843 {
9844 void *p2;
9845 p = lock_user_string(arg1);
9846 p2 = lock_user_string(arg2);
579a97f7
FB
9847 if (!p || !p2)
9848 ret = -TARGET_EFAULT;
9849 else
9850 ret = get_errno(symlink(p, p2));
53a5960a
PB
9851 unlock_user(p2, arg2, 0);
9852 unlock_user(p, arg1, 0);
9853 }
72eb7ea8 9854 return ret;
704eff6c 9855#endif
c0d472b1 9856#if defined(TARGET_NR_symlinkat)
f0b6243d 9857 case TARGET_NR_symlinkat:
f0b6243d 9858 {
579a97f7 9859 void *p2;
f0b6243d
TS
9860 p = lock_user_string(arg1);
9861 p2 = lock_user_string(arg3);
579a97f7 9862 if (!p || !p2)
0da46a6e 9863 ret = -TARGET_EFAULT;
f0b6243d 9864 else
c0d472b1 9865 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
9866 unlock_user(p2, arg3, 0);
9867 unlock_user(p, arg1, 0);
f0b6243d 9868 }
72eb7ea8 9869 return ret;
f0b6243d 9870#endif
704eff6c 9871#ifdef TARGET_NR_readlink
31e31b8a 9872 case TARGET_NR_readlink:
53a5960a 9873 {
463d8e73 9874 void *p2;
53a5960a 9875 p = lock_user_string(arg1);
579a97f7 9876 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 9877 if (!p || !p2) {
579a97f7 9878 ret = -TARGET_EFAULT;
f17f4989
MF
9879 } else if (!arg3) {
9880 /* Short circuit this for the magic exe check. */
9881 ret = -TARGET_EINVAL;
463d8e73
AS
9882 } else if (is_proc_myself((const char *)p, "exe")) {
9883 char real[PATH_MAX], *temp;
9884 temp = realpath(exec_path, real);
f17f4989
MF
9885 /* Return value is # of bytes that we wrote to the buffer. */
9886 if (temp == NULL) {
9887 ret = get_errno(-1);
9888 } else {
9889 /* Don't worry about sign mismatch as earlier mapping
9890 * logic would have thrown a bad address error. */
9891 ret = MIN(strlen(real), arg3);
9892 /* We cannot NUL terminate the string. */
9893 memcpy(p2, real, ret);
9894 }
463d8e73
AS
9895 } else {
9896 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 9897 }
53a5960a
PB
9898 unlock_user(p2, arg2, ret);
9899 unlock_user(p, arg1, 0);
9900 }
72eb7ea8 9901 return ret;
704eff6c 9902#endif
c0d472b1 9903#if defined(TARGET_NR_readlinkat)
5e0ccb18 9904 case TARGET_NR_readlinkat:
5e0ccb18 9905 {
579a97f7 9906 void *p2;
5e0ccb18 9907 p = lock_user_string(arg2);
579a97f7 9908 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
9909 if (!p || !p2) {
9910 ret = -TARGET_EFAULT;
9911 } else if (is_proc_myself((const char *)p, "exe")) {
9912 char real[PATH_MAX], *temp;
9913 temp = realpath(exec_path, real);
9914 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
9915 snprintf((char *)p2, arg4, "%s", real);
9916 } else {
c0d472b1 9917 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 9918 }
579a97f7
FB
9919 unlock_user(p2, arg3, ret);
9920 unlock_user(p, arg2, 0);
5e0ccb18 9921 }
72eb7ea8 9922 return ret;
5e0ccb18 9923#endif
e5febef5 9924#ifdef TARGET_NR_swapon
31e31b8a 9925 case TARGET_NR_swapon:
579a97f7 9926 if (!(p = lock_user_string(arg1)))
2852aafd 9927 return -TARGET_EFAULT;
53a5960a
PB
9928 ret = get_errno(swapon(p, arg2));
9929 unlock_user(p, arg1, 0);
72eb7ea8 9930 return ret;
e5febef5 9931#endif
31e31b8a 9932 case TARGET_NR_reboot:
c07ecc68
LV
9933 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
9934 /* arg4 must be ignored in all other cases */
9935 p = lock_user_string(arg4);
9936 if (!p) {
2852aafd 9937 return -TARGET_EFAULT;
c07ecc68
LV
9938 }
9939 ret = get_errno(reboot(arg1, arg2, arg3, p));
9940 unlock_user(p, arg4, 0);
9941 } else {
9942 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
9943 }
72eb7ea8 9944 return ret;
e5febef5 9945#ifdef TARGET_NR_mmap
31e31b8a 9946 case TARGET_NR_mmap:
09701199
AG
9947#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
9948 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
9949 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
9950 || defined(TARGET_S390X)
31e31b8a 9951 {
992f48a0
BS
9952 abi_ulong *v;
9953 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7 9954 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
2852aafd 9955 return -TARGET_EFAULT;
cbb21eed
MB
9956 v1 = tswapal(v[0]);
9957 v2 = tswapal(v[1]);
9958 v3 = tswapal(v[2]);
9959 v4 = tswapal(v[3]);
9960 v5 = tswapal(v[4]);
9961 v6 = tswapal(v[5]);
53a5960a 9962 unlock_user(v, arg1, 0);
5fafdf24 9963 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
9964 target_to_host_bitmask(v4, mmap_flags_tbl),
9965 v5, v6));
31e31b8a 9966 }
31e31b8a 9967#else
ee1bf83d 9968 /* mmap pointers are always untagged */
5fafdf24
TS
9969 ret = get_errno(target_mmap(arg1, arg2, arg3,
9970 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
9971 arg5,
9972 arg6));
31e31b8a 9973#endif
72eb7ea8 9974 return ret;
e5febef5 9975#endif
a315a145 9976#ifdef TARGET_NR_mmap2
6fb883e8 9977 case TARGET_NR_mmap2:
bb7ec043 9978#ifndef MMAP_SHIFT
c573ff67 9979#define MMAP_SHIFT 12
c573ff67 9980#endif
72eb7ea8
RH
9981 ret = target_mmap(arg1, arg2, arg3,
9982 target_to_host_bitmask(arg4, mmap_flags_tbl),
9983 arg5, arg6 << MMAP_SHIFT);
9984 return get_errno(ret);
a315a145 9985#endif
31e31b8a 9986 case TARGET_NR_munmap:
ee1bf83d 9987 arg1 = cpu_untagged_addr(cpu, arg1);
72eb7ea8 9988 return get_errno(target_munmap(arg1, arg2));
9de5e440 9989 case TARGET_NR_mprotect:
ee1bf83d 9990 arg1 = cpu_untagged_addr(cpu, arg1);
97374d38 9991 {
0429a971 9992 TaskState *ts = cpu->opaque;
97374d38
PB
9993 /* Special hack to detect libc making the stack executable. */
9994 if ((arg3 & PROT_GROWSDOWN)
9995 && arg1 >= ts->info->stack_limit
9996 && arg1 <= ts->info->start_stack) {
9997 arg3 &= ~PROT_GROWSDOWN;
9998 arg2 = arg2 + arg1 - ts->info->stack_limit;
9999 arg1 = ts->info->stack_limit;
10000 }
10001 }
72eb7ea8 10002 return get_errno(target_mprotect(arg1, arg2, arg3));
e5febef5 10003#ifdef TARGET_NR_mremap
9de5e440 10004 case TARGET_NR_mremap:
ee1bf83d
RH
10005 arg1 = cpu_untagged_addr(cpu, arg1);
10006 /* mremap new_addr (arg5) is always untagged */
72eb7ea8 10007 return get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
e5febef5 10008#endif
53a5960a 10009 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 10010#ifdef TARGET_NR_msync
9de5e440 10011 case TARGET_NR_msync:
3e8f1628 10012 return get_errno(msync(g2h(cpu, arg1), arg2, arg3));
e5febef5
TS
10013#endif
10014#ifdef TARGET_NR_mlock
9de5e440 10015 case TARGET_NR_mlock:
3e8f1628 10016 return get_errno(mlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10017#endif
10018#ifdef TARGET_NR_munlock
9de5e440 10019 case TARGET_NR_munlock:
3e8f1628 10020 return get_errno(munlock(g2h(cpu, arg1), arg2));
e5febef5
TS
10021#endif
10022#ifdef TARGET_NR_mlockall
9de5e440 10023 case TARGET_NR_mlockall:
72eb7ea8 10024 return get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
e5febef5
TS
10025#endif
10026#ifdef TARGET_NR_munlockall
9de5e440 10027 case TARGET_NR_munlockall:
72eb7ea8 10028 return get_errno(munlockall());
e5febef5 10029#endif
4f7f8924 10030#ifdef TARGET_NR_truncate
31e31b8a 10031 case TARGET_NR_truncate:
579a97f7 10032 if (!(p = lock_user_string(arg1)))
2852aafd 10033 return -TARGET_EFAULT;
53a5960a
PB
10034 ret = get_errno(truncate(p, arg2));
10035 unlock_user(p, arg1, 0);
72eb7ea8 10036 return ret;
4f7f8924
AR
10037#endif
10038#ifdef TARGET_NR_ftruncate
31e31b8a 10039 case TARGET_NR_ftruncate:
72eb7ea8 10040 return get_errno(ftruncate(arg1, arg2));
4f7f8924 10041#endif
31e31b8a 10042 case TARGET_NR_fchmod:
72eb7ea8 10043 return get_errno(fchmod(arg1, arg2));
c0d472b1 10044#if defined(TARGET_NR_fchmodat)
814d7977 10045 case TARGET_NR_fchmodat:
579a97f7 10046 if (!(p = lock_user_string(arg2)))
2852aafd 10047 return -TARGET_EFAULT;
c0d472b1 10048 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 10049 unlock_user(p, arg2, 0);
72eb7ea8 10050 return ret;
814d7977 10051#endif
31e31b8a 10052 case TARGET_NR_getpriority:
95c09828
RH
10053 /* Note that negative values are valid for getpriority, so we must
10054 differentiate based on errno settings. */
10055 errno = 0;
10056 ret = getpriority(arg1, arg2);
10057 if (ret == -1 && errno != 0) {
72eb7ea8 10058 return -host_to_target_errno(errno);
95c09828
RH
10059 }
10060#ifdef TARGET_ALPHA
10061 /* Return value is the unbiased priority. Signal no error. */
10062 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
10063#else
10064 /* Return value is a biased priority to avoid negative numbers. */
10065 ret = 20 - ret;
10066#endif
72eb7ea8 10067 return ret;
31e31b8a 10068 case TARGET_NR_setpriority:
72eb7ea8 10069 return get_errno(setpriority(arg1, arg2, arg3));
4f7f8924 10070#ifdef TARGET_NR_statfs
31e31b8a 10071 case TARGET_NR_statfs:
2852aafd
RH
10072 if (!(p = lock_user_string(arg1))) {
10073 return -TARGET_EFAULT;
10074 }
53a5960a
PB
10075 ret = get_errno(statfs(path(p), &stfs));
10076 unlock_user(p, arg1, 0);
31e31b8a
FB
10077 convert_statfs:
10078 if (!is_error(ret)) {
53a5960a 10079 struct target_statfs *target_stfs;
3b46e624 10080
579a97f7 10081 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
2852aafd 10082 return -TARGET_EFAULT;
579a97f7
FB
10083 __put_user(stfs.f_type, &target_stfs->f_type);
10084 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10085 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10086 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10087 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10088 __put_user(stfs.f_files, &target_stfs->f_files);
10089 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10090 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10091 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10092 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10093 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
d4247ec2
SL
10094#ifdef _STATFS_F_FLAGS
10095 __put_user(stfs.f_flags, &target_stfs->f_flags);
10096#else
10097 __put_user(0, &target_stfs->f_flags);
10098#endif
229d3376 10099 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 10100 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a 10101 }
72eb7ea8 10102 return ret;
4f7f8924
AR
10103#endif
10104#ifdef TARGET_NR_fstatfs
31e31b8a 10105 case TARGET_NR_fstatfs:
56c8f68f 10106 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 10107 goto convert_statfs;
4f7f8924 10108#endif
56c8f68f
FB
10109#ifdef TARGET_NR_statfs64
10110 case TARGET_NR_statfs64:
2852aafd
RH
10111 if (!(p = lock_user_string(arg1))) {
10112 return -TARGET_EFAULT;
10113 }
53a5960a
PB
10114 ret = get_errno(statfs(path(p), &stfs));
10115 unlock_user(p, arg1, 0);
56c8f68f
FB
10116 convert_statfs64:
10117 if (!is_error(ret)) {
53a5960a 10118 struct target_statfs64 *target_stfs;
3b46e624 10119
579a97f7 10120 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
2852aafd 10121 return -TARGET_EFAULT;
579a97f7
FB
10122 __put_user(stfs.f_type, &target_stfs->f_type);
10123 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
10124 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
10125 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
10126 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
10127 __put_user(stfs.f_files, &target_stfs->f_files);
10128 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
10129 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
10130 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
10131 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376 10132 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
b94e2b4e
F
10133#ifdef _STATFS_F_FLAGS
10134 __put_user(stfs.f_flags, &target_stfs->f_flags);
10135#else
10136 __put_user(0, &target_stfs->f_flags);
10137#endif
229d3376 10138 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 10139 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f 10140 }
72eb7ea8 10141 return ret;
56c8f68f
FB
10142 case TARGET_NR_fstatfs64:
10143 ret = get_errno(fstatfs(arg1, &stfs));
10144 goto convert_statfs64;
10145#endif
e5febef5 10146#ifdef TARGET_NR_socketcall
31e31b8a 10147 case TARGET_NR_socketcall:
72eb7ea8 10148 return do_socketcall(arg1, arg2);
e5febef5 10149#endif
3532fa74
FB
10150#ifdef TARGET_NR_accept
10151 case TARGET_NR_accept:
72eb7ea8 10152 return do_accept4(arg1, arg2, arg3, 0);
a94b4987
PM
10153#endif
10154#ifdef TARGET_NR_accept4
10155 case TARGET_NR_accept4:
72eb7ea8 10156 return do_accept4(arg1, arg2, arg3, arg4);
3532fa74
FB
10157#endif
10158#ifdef TARGET_NR_bind
10159 case TARGET_NR_bind:
72eb7ea8 10160 return do_bind(arg1, arg2, arg3);
3532fa74
FB
10161#endif
10162#ifdef TARGET_NR_connect
10163 case TARGET_NR_connect:
72eb7ea8 10164 return do_connect(arg1, arg2, arg3);
3532fa74
FB
10165#endif
10166#ifdef TARGET_NR_getpeername
10167 case TARGET_NR_getpeername:
72eb7ea8 10168 return do_getpeername(arg1, arg2, arg3);
3532fa74
FB
10169#endif
10170#ifdef TARGET_NR_getsockname
10171 case TARGET_NR_getsockname:
72eb7ea8 10172 return do_getsockname(arg1, arg2, arg3);
3532fa74
FB
10173#endif
10174#ifdef TARGET_NR_getsockopt
10175 case TARGET_NR_getsockopt:
72eb7ea8 10176 return do_getsockopt(arg1, arg2, arg3, arg4, arg5);
3532fa74
FB
10177#endif
10178#ifdef TARGET_NR_listen
10179 case TARGET_NR_listen:
72eb7ea8 10180 return get_errno(listen(arg1, arg2));
3532fa74
FB
10181#endif
10182#ifdef TARGET_NR_recv
10183 case TARGET_NR_recv:
72eb7ea8 10184 return do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10185#endif
10186#ifdef TARGET_NR_recvfrom
10187 case TARGET_NR_recvfrom:
72eb7ea8 10188 return do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10189#endif
10190#ifdef TARGET_NR_recvmsg
10191 case TARGET_NR_recvmsg:
72eb7ea8 10192 return do_sendrecvmsg(arg1, arg2, arg3, 0);
3532fa74
FB
10193#endif
10194#ifdef TARGET_NR_send
10195 case TARGET_NR_send:
72eb7ea8 10196 return do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
10197#endif
10198#ifdef TARGET_NR_sendmsg
10199 case TARGET_NR_sendmsg:
72eb7ea8 10200 return do_sendrecvmsg(arg1, arg2, arg3, 1);
3532fa74 10201#endif
f19e00d7
AG
10202#ifdef TARGET_NR_sendmmsg
10203 case TARGET_NR_sendmmsg:
72eb7ea8 10204 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
859e8a89
AF
10205#endif
10206#ifdef TARGET_NR_recvmmsg
f19e00d7 10207 case TARGET_NR_recvmmsg:
72eb7ea8 10208 return do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
f19e00d7 10209#endif
3532fa74
FB
10210#ifdef TARGET_NR_sendto
10211 case TARGET_NR_sendto:
72eb7ea8 10212 return do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
10213#endif
10214#ifdef TARGET_NR_shutdown
10215 case TARGET_NR_shutdown:
72eb7ea8 10216 return get_errno(shutdown(arg1, arg2));
3532fa74 10217#endif
f894efd1
LV
10218#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
10219 case TARGET_NR_getrandom:
10220 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
10221 if (!p) {
2852aafd 10222 return -TARGET_EFAULT;
f894efd1
LV
10223 }
10224 ret = get_errno(getrandom(p, arg2, arg3));
10225 unlock_user(p, arg1, ret);
72eb7ea8 10226 return ret;
f894efd1 10227#endif
3532fa74
FB
10228#ifdef TARGET_NR_socket
10229 case TARGET_NR_socket:
72eb7ea8 10230 return do_socket(arg1, arg2, arg3);
3532fa74
FB
10231#endif
10232#ifdef TARGET_NR_socketpair
10233 case TARGET_NR_socketpair:
72eb7ea8 10234 return do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
10235#endif
10236#ifdef TARGET_NR_setsockopt
10237 case TARGET_NR_setsockopt:
72eb7ea8 10238 return do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
3532fa74 10239#endif
da2c8ad7 10240#if defined(TARGET_NR_syslog)
31e31b8a 10241 case TARGET_NR_syslog:
da2c8ad7
AM
10242 {
10243 int len = arg2;
7494b0f9 10244
da2c8ad7
AM
10245 switch (arg1) {
10246 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
10247 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
10248 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
10249 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
10250 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
10251 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
10252 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
10253 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
72eb7ea8 10254 return get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
da2c8ad7
AM
10255 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
10256 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
10257 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
10258 {
da2c8ad7 10259 if (len < 0) {
259841c1 10260 return -TARGET_EINVAL;
da2c8ad7 10261 }
da2c8ad7 10262 if (len == 0) {
72eb7ea8 10263 return 0;
da2c8ad7
AM
10264 }
10265 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10266 if (!p) {
259841c1 10267 return -TARGET_EFAULT;
da2c8ad7
AM
10268 }
10269 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
10270 unlock_user(p, arg2, arg3);
10271 }
72eb7ea8 10272 return ret;
da2c8ad7 10273 default:
72eb7ea8 10274 return -TARGET_EINVAL;
da2c8ad7
AM
10275 }
10276 }
10277 break;
10278#endif
31e31b8a 10279 case TARGET_NR_setitimer:
66fb9763 10280 {
66fb9763
FB
10281 struct itimerval value, ovalue, *pvalue;
10282
53a5960a 10283 if (arg2) {
66fb9763 10284 pvalue = &value;
788f5ec4
TS
10285 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
10286 || copy_from_user_timeval(&pvalue->it_value,
10287 arg2 + sizeof(struct target_timeval)))
2852aafd 10288 return -TARGET_EFAULT;
66fb9763
FB
10289 } else {
10290 pvalue = NULL;
10291 }
10292 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 10293 if (!is_error(ret) && arg3) {
788f5ec4
TS
10294 if (copy_to_user_timeval(arg3,
10295 &ovalue.it_interval)
10296 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
10297 &ovalue.it_value))
2852aafd 10298 return -TARGET_EFAULT;
66fb9763
FB
10299 }
10300 }
72eb7ea8 10301 return ret;
31e31b8a 10302 case TARGET_NR_getitimer:
66fb9763 10303 {
66fb9763 10304 struct itimerval value;
3b46e624 10305
66fb9763 10306 ret = get_errno(getitimer(arg1, &value));
53a5960a 10307 if (!is_error(ret) && arg2) {
788f5ec4
TS
10308 if (copy_to_user_timeval(arg2,
10309 &value.it_interval)
10310 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
10311 &value.it_value))
2852aafd 10312 return -TARGET_EFAULT;
66fb9763
FB
10313 }
10314 }
72eb7ea8 10315 return ret;
704eff6c 10316#ifdef TARGET_NR_stat
31e31b8a 10317 case TARGET_NR_stat:
2852aafd
RH
10318 if (!(p = lock_user_string(arg1))) {
10319 return -TARGET_EFAULT;
10320 }
53a5960a
PB
10321 ret = get_errno(stat(path(p), &st));
10322 unlock_user(p, arg1, 0);
31e31b8a 10323 goto do_stat;
704eff6c
CG
10324#endif
10325#ifdef TARGET_NR_lstat
31e31b8a 10326 case TARGET_NR_lstat:
2852aafd
RH
10327 if (!(p = lock_user_string(arg1))) {
10328 return -TARGET_EFAULT;
10329 }
53a5960a
PB
10330 ret = get_errno(lstat(path(p), &st));
10331 unlock_user(p, arg1, 0);
31e31b8a 10332 goto do_stat;
704eff6c 10333#endif
4f7f8924 10334#ifdef TARGET_NR_fstat
31e31b8a
FB
10335 case TARGET_NR_fstat:
10336 {
10337 ret = get_errno(fstat(arg1, &st));
704eff6c 10338#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
31e31b8a 10339 do_stat:
704eff6c 10340#endif
31e31b8a 10341 if (!is_error(ret)) {
53a5960a 10342 struct target_stat *target_st;
e3584658 10343
579a97f7 10344 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
2852aafd 10345 return -TARGET_EFAULT;
12727917 10346 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
10347 __put_user(st.st_dev, &target_st->st_dev);
10348 __put_user(st.st_ino, &target_st->st_ino);
10349 __put_user(st.st_mode, &target_st->st_mode);
10350 __put_user(st.st_uid, &target_st->st_uid);
10351 __put_user(st.st_gid, &target_st->st_gid);
10352 __put_user(st.st_nlink, &target_st->st_nlink);
10353 __put_user(st.st_rdev, &target_st->st_rdev);
10354 __put_user(st.st_size, &target_st->st_size);
10355 __put_user(st.st_blksize, &target_st->st_blksize);
10356 __put_user(st.st_blocks, &target_st->st_blocks);
10357 __put_user(st.st_atime, &target_st->target_st_atime);
10358 __put_user(st.st_mtime, &target_st->target_st_mtime);
10359 __put_user(st.st_ctime, &target_st->target_st_ctime);
febf6fad 10360#if defined(HAVE_STRUCT_STAT_ST_ATIM) && defined(TARGET_STAT_HAVE_NSEC)
5f992db6
CYT
10361 __put_user(st.st_atim.tv_nsec,
10362 &target_st->target_st_atime_nsec);
10363 __put_user(st.st_mtim.tv_nsec,
10364 &target_st->target_st_mtime_nsec);
10365 __put_user(st.st_ctim.tv_nsec,
10366 &target_st->target_st_ctime_nsec);
10367#endif
53a5960a 10368 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
10369 }
10370 }
72eb7ea8 10371 return ret;
ebc05488 10372#endif
31e31b8a 10373 case TARGET_NR_vhangup:
72eb7ea8 10374 return get_errno(vhangup());
42ad6ae9
FB
10375#ifdef TARGET_NR_syscall
10376 case TARGET_NR_syscall:
72eb7ea8
RH
10377 return do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
10378 arg6, arg7, arg8, 0);
ebc05488 10379#endif
859e8a89 10380#if defined(TARGET_NR_wait4)
31e31b8a
FB
10381 case TARGET_NR_wait4:
10382 {
10383 int status;
992f48a0 10384 abi_long status_ptr = arg2;
31e31b8a 10385 struct rusage rusage, *rusage_ptr;
992f48a0 10386 abi_ulong target_rusage = arg4;
a39fb273 10387 abi_long rusage_err;
31e31b8a
FB
10388 if (target_rusage)
10389 rusage_ptr = &rusage;
10390 else
10391 rusage_ptr = NULL;
4af80a37 10392 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
31e31b8a 10393 if (!is_error(ret)) {
5379557b 10394 if (status_ptr && ret) {
1d9d8b55 10395 status = host_to_target_waitstatus(status);
2f619698 10396 if (put_user_s32(status, status_ptr))
2852aafd 10397 return -TARGET_EFAULT;
31e31b8a 10398 }
a39fb273
PJ
10399 if (target_rusage) {
10400 rusage_err = host_to_target_rusage(target_rusage, &rusage);
10401 if (rusage_err) {
10402 ret = rusage_err;
10403 }
10404 }
31e31b8a
FB
10405 }
10406 }
72eb7ea8 10407 return ret;
859e8a89 10408#endif
e5febef5 10409#ifdef TARGET_NR_swapoff
31e31b8a 10410 case TARGET_NR_swapoff:
579a97f7 10411 if (!(p = lock_user_string(arg1)))
2852aafd 10412 return -TARGET_EFAULT;
53a5960a
PB
10413 ret = get_errno(swapoff(p));
10414 unlock_user(p, arg1, 0);
72eb7ea8 10415 return ret;
e5febef5 10416#endif
31e31b8a 10417 case TARGET_NR_sysinfo:
a5448a7d 10418 {
53a5960a 10419 struct target_sysinfo *target_value;
a5448a7d
FB
10420 struct sysinfo value;
10421 ret = get_errno(sysinfo(&value));
53a5960a 10422 if (!is_error(ret) && arg1)
a5448a7d 10423 {
579a97f7 10424 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
2852aafd 10425 return -TARGET_EFAULT;
a5448a7d
FB
10426 __put_user(value.uptime, &target_value->uptime);
10427 __put_user(value.loads[0], &target_value->loads[0]);
10428 __put_user(value.loads[1], &target_value->loads[1]);
10429 __put_user(value.loads[2], &target_value->loads[2]);
10430 __put_user(value.totalram, &target_value->totalram);
10431 __put_user(value.freeram, &target_value->freeram);
10432 __put_user(value.sharedram, &target_value->sharedram);
10433 __put_user(value.bufferram, &target_value->bufferram);
10434 __put_user(value.totalswap, &target_value->totalswap);
10435 __put_user(value.freeswap, &target_value->freeswap);
10436 __put_user(value.procs, &target_value->procs);
10437 __put_user(value.totalhigh, &target_value->totalhigh);
10438 __put_user(value.freehigh, &target_value->freehigh);
10439 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 10440 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
10441 }
10442 }
72eb7ea8 10443 return ret;
e5febef5 10444#ifdef TARGET_NR_ipc
31e31b8a 10445 case TARGET_NR_ipc:
72eb7ea8 10446 return do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
e5febef5 10447#endif
e5289087
AJ
10448#ifdef TARGET_NR_semget
10449 case TARGET_NR_semget:
72eb7ea8 10450 return get_errno(semget(arg1, arg2, arg3));
e5289087
AJ
10451#endif
10452#ifdef TARGET_NR_semop
10453 case TARGET_NR_semop:
cac46eb0 10454 return do_semtimedop(arg1, arg2, arg3, 0, false);
d8c08b1e
MK
10455#endif
10456#ifdef TARGET_NR_semtimedop
10457 case TARGET_NR_semtimedop:
cac46eb0
FB
10458 return do_semtimedop(arg1, arg2, arg3, arg4, false);
10459#endif
10460#ifdef TARGET_NR_semtimedop_time64
10461 case TARGET_NR_semtimedop_time64:
10462 return do_semtimedop(arg1, arg2, arg3, arg4, true);
e5289087
AJ
10463#endif
10464#ifdef TARGET_NR_semctl
10465 case TARGET_NR_semctl:
72eb7ea8 10466 return do_semctl(arg1, arg2, arg3, arg4);
e5289087 10467#endif
eeb438c1
AJ
10468#ifdef TARGET_NR_msgctl
10469 case TARGET_NR_msgctl:
72eb7ea8 10470 return do_msgctl(arg1, arg2, arg3);
eeb438c1
AJ
10471#endif
10472#ifdef TARGET_NR_msgget
10473 case TARGET_NR_msgget:
72eb7ea8 10474 return get_errno(msgget(arg1, arg2));
eeb438c1
AJ
10475#endif
10476#ifdef TARGET_NR_msgrcv
10477 case TARGET_NR_msgrcv:
72eb7ea8 10478 return do_msgrcv(arg1, arg2, arg3, arg4, arg5);
eeb438c1
AJ
10479#endif
10480#ifdef TARGET_NR_msgsnd
10481 case TARGET_NR_msgsnd:
72eb7ea8 10482 return do_msgsnd(arg1, arg2, arg3, arg4);
88a8c984
RV
10483#endif
10484#ifdef TARGET_NR_shmget
10485 case TARGET_NR_shmget:
72eb7ea8 10486 return get_errno(shmget(arg1, arg2, arg3));
88a8c984
RV
10487#endif
10488#ifdef TARGET_NR_shmctl
10489 case TARGET_NR_shmctl:
72eb7ea8 10490 return do_shmctl(arg1, arg2, arg3);
88a8c984
RV
10491#endif
10492#ifdef TARGET_NR_shmat
10493 case TARGET_NR_shmat:
72eb7ea8 10494 return do_shmat(cpu_env, arg1, arg2, arg3);
88a8c984
RV
10495#endif
10496#ifdef TARGET_NR_shmdt
10497 case TARGET_NR_shmdt:
72eb7ea8 10498 return do_shmdt(arg1);
eeb438c1 10499#endif
31e31b8a 10500 case TARGET_NR_fsync:
72eb7ea8 10501 return get_errno(fsync(arg1));
31e31b8a 10502 case TARGET_NR_clone:
4ce6243d
PM
10503 /* Linux manages to have three different orderings for its
10504 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
10505 * match the kernel's CONFIG_CLONE_* settings.
10506 * Microblaze is further special in that it uses a sixth
10507 * implicit argument to clone for the TLS pointer.
10508 */
10509#if defined(TARGET_MICROBLAZE)
a5b3bdcb 10510 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
10511#elif defined(TARGET_CLONE_BACKWARDS)
10512 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
10513#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 10514 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 10515#else
4ce6243d 10516 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 10517#endif
72eb7ea8 10518 return ret;
ec86b0fb
FB
10519#ifdef __NR_exit_group
10520 /* new thread calls */
10521 case TARGET_NR_exit_group:
708b6a64 10522 preexit_cleanup(cpu_env, arg1);
72eb7ea8 10523 return get_errno(exit_group(arg1));
ec86b0fb 10524#endif
31e31b8a 10525 case TARGET_NR_setdomainname:
579a97f7 10526 if (!(p = lock_user_string(arg1)))
2852aafd 10527 return -TARGET_EFAULT;
53a5960a
PB
10528 ret = get_errno(setdomainname(p, arg2));
10529 unlock_user(p, arg1, 0);
72eb7ea8 10530 return ret;
31e31b8a
FB
10531 case TARGET_NR_uname:
10532 /* no need to transcode because we use the linux syscall */
29e619b1
FB
10533 {
10534 struct new_utsname * buf;
3b46e624 10535
579a97f7 10536 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
2852aafd 10537 return -TARGET_EFAULT;
29e619b1
FB
10538 ret = get_errno(sys_uname(buf));
10539 if (!is_error(ret)) {
332c9781 10540 /* Overwrite the native machine name with whatever is being
29e619b1 10541 emulated. */
871f95c6
PMD
10542 g_strlcpy(buf->machine, cpu_to_uname_machine(cpu_env),
10543 sizeof(buf->machine));
c5937220 10544 /* Allow the user to override the reported release. */
332c9781
PM
10545 if (qemu_uname_release && *qemu_uname_release) {
10546 g_strlcpy(buf->release, qemu_uname_release,
10547 sizeof(buf->release));
10548 }
29e619b1 10549 }
53a5960a 10550 unlock_user_struct(buf, arg1, 1);
29e619b1 10551 }
72eb7ea8 10552 return ret;
6dbad63e 10553#ifdef TARGET_I386
31e31b8a 10554 case TARGET_NR_modify_ldt:
72eb7ea8 10555 return do_modify_ldt(cpu_env, arg1, arg2, arg3);
84409ddb 10556#if !defined(TARGET_X86_64)
5cd4393b 10557 case TARGET_NR_vm86:
72eb7ea8 10558 return do_vm86(cpu_env, arg1, arg2);
84409ddb 10559#endif
6dbad63e 10560#endif
859e8a89 10561#if defined(TARGET_NR_adjtimex)
31e31b8a 10562 case TARGET_NR_adjtimex:
19f59bce
AM
10563 {
10564 struct timex host_buf;
10565
10566 if (target_to_host_timex(&host_buf, arg1) != 0) {
2852aafd 10567 return -TARGET_EFAULT;
19f59bce
AM
10568 }
10569 ret = get_errno(adjtimex(&host_buf));
10570 if (!is_error(ret)) {
10571 if (host_to_target_timex(arg1, &host_buf) != 0) {
2852aafd 10572 return -TARGET_EFAULT;
19f59bce
AM
10573 }
10574 }
10575 }
72eb7ea8 10576 return ret;
859e8a89 10577#endif
38860a03
AM
10578#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
10579 case TARGET_NR_clock_adjtime:
10580 {
10581 struct timex htx, *phtx = &htx;
10582
10583 if (target_to_host_timex(phtx, arg2) != 0) {
2852aafd 10584 return -TARGET_EFAULT;
38860a03
AM
10585 }
10586 ret = get_errno(clock_adjtime(arg1, phtx));
10587 if (!is_error(ret) && phtx) {
10588 if (host_to_target_timex(arg2, phtx) != 0) {
2852aafd 10589 return -TARGET_EFAULT;
38860a03
AM
10590 }
10591 }
10592 }
72eb7ea8 10593 return ret;
6ac03b2c
FB
10594#endif
10595#if defined(TARGET_NR_clock_adjtime64) && defined(CONFIG_CLOCK_ADJTIME)
10596 case TARGET_NR_clock_adjtime64:
10597 {
10598 struct timex htx;
10599
10600 if (target_to_host_timex64(&htx, arg2) != 0) {
10601 return -TARGET_EFAULT;
10602 }
10603 ret = get_errno(clock_adjtime(arg1, &htx));
10604 if (!is_error(ret) && host_to_target_timex64(arg2, &htx)) {
10605 return -TARGET_EFAULT;
10606 }
10607 }
10608 return ret;
38860a03 10609#endif
31e31b8a 10610 case TARGET_NR_getpgid:
72eb7ea8 10611 return get_errno(getpgid(arg1));
31e31b8a 10612 case TARGET_NR_fchdir:
72eb7ea8 10613 return get_errno(fchdir(arg1));
31e31b8a 10614 case TARGET_NR_personality:
72eb7ea8 10615 return get_errno(personality(arg1));
7a3148a9 10616#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
10617 case TARGET_NR__llseek:
10618 {
0c1592d9 10619 int64_t res;
d35b261c 10620#if !defined(__NR_llseek)
9fea273c 10621 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
0c1592d9
PM
10622 if (res == -1) {
10623 ret = get_errno(res);
10624 } else {
10625 ret = 0;
10626 }
4f2ac237 10627#else
31e31b8a 10628 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 10629#endif
0c1592d9 10630 if ((ret == 0) && put_user_s64(res, arg4)) {
2852aafd 10631 return -TARGET_EFAULT;
0c1592d9 10632 }
31e31b8a 10633 }
72eb7ea8 10634 return ret;
7a3148a9 10635#endif
704eff6c 10636#ifdef TARGET_NR_getdents
31e31b8a 10637 case TARGET_NR_getdents:
fd08ddb9 10638 return do_getdents(arg1, arg2, arg3);
704eff6c 10639#endif /* TARGET_NR_getdents */
3ae43202 10640#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99 10641 case TARGET_NR_getdents64:
fd08ddb9 10642 return do_getdents64(arg1, arg2, arg3);
a541f297 10643#endif /* TARGET_NR_getdents64 */
9468a5d4 10644#if defined(TARGET_NR__newselect)
31e31b8a 10645 case TARGET_NR__newselect:
72eb7ea8 10646 return do_select(arg1, arg2, arg3, arg4, arg5);
e5febef5 10647#endif
e5ce9688 10648#ifdef TARGET_NR_poll
9de5e440 10649 case TARGET_NR_poll:
e5ce9688
FB
10650 return do_ppoll(arg1, arg2, arg3, arg4, arg5, false, false);
10651#endif
10652#ifdef TARGET_NR_ppoll
d8035d4c 10653 case TARGET_NR_ppoll:
e5ce9688
FB
10654 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, false);
10655#endif
10656#ifdef TARGET_NR_ppoll_time64
10657 case TARGET_NR_ppoll_time64:
10658 return do_ppoll(arg1, arg2, arg3, arg4, arg5, true, true);
e5febef5 10659#endif
31e31b8a 10660 case TARGET_NR_flock:
9de5e440
FB
10661 /* NOTE: the flock constant seems to be the same for every
10662 Linux platform */
72eb7ea8 10663 return get_errno(safe_flock(arg1, arg2));
31e31b8a
FB
10664 case TARGET_NR_readv:
10665 {
f287b2c2
RH
10666 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10667 if (vec != NULL) {
918c03ed 10668 ret = get_errno(safe_readv(arg1, vec, arg3));
f287b2c2
RH
10669 unlock_iovec(vec, arg2, arg3, 1);
10670 } else {
10671 ret = -host_to_target_errno(errno);
10672 }
31e31b8a 10673 }
72eb7ea8 10674 return ret;
31e31b8a
FB
10675 case TARGET_NR_writev:
10676 {
f287b2c2
RH
10677 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10678 if (vec != NULL) {
918c03ed 10679 ret = get_errno(safe_writev(arg1, vec, arg3));
f287b2c2
RH
10680 unlock_iovec(vec, arg2, arg3, 0);
10681 } else {
10682 ret = -host_to_target_errno(errno);
10683 }
31e31b8a 10684 }
72eb7ea8 10685 return ret;
0f26386c
DJ
10686#if defined(TARGET_NR_preadv)
10687 case TARGET_NR_preadv:
10688 {
10689 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10690 if (vec != NULL) {
9ac22517
MF
10691 unsigned long low, high;
10692
10693 target_to_host_low_high(arg4, arg5, &low, &high);
10694 ret = get_errno(safe_preadv(arg1, vec, arg3, low, high));
0f26386c
DJ
10695 unlock_iovec(vec, arg2, arg3, 1);
10696 } else {
10697 ret = -host_to_target_errno(errno);
f8d00fba
DJ
10698 }
10699 }
72eb7ea8 10700 return ret;
f8d00fba
DJ
10701#endif
10702#if defined(TARGET_NR_pwritev)
10703 case TARGET_NR_pwritev:
10704 {
10705 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10706 if (vec != NULL) {
9ac22517
MF
10707 unsigned long low, high;
10708
10709 target_to_host_low_high(arg4, arg5, &low, &high);
10710 ret = get_errno(safe_pwritev(arg1, vec, arg3, low, high));
f8d00fba
DJ
10711 unlock_iovec(vec, arg2, arg3, 0);
10712 } else {
10713 ret = -host_to_target_errno(errno);
0f26386c
DJ
10714 }
10715 }
72eb7ea8 10716 return ret;
0f26386c 10717#endif
31e31b8a 10718 case TARGET_NR_getsid:
72eb7ea8 10719 return get_errno(getsid(arg1));
7a3148a9 10720#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 10721 case TARGET_NR_fdatasync:
72eb7ea8 10722 return get_errno(fdatasync(arg1));
704eff6c 10723#endif
737de1d1
MF
10724 case TARGET_NR_sched_getaffinity:
10725 {
10726 unsigned int mask_size;
10727 unsigned long *mask;
10728
10729 /*
10730 * sched_getaffinity needs multiples of ulong, so need to take
10731 * care of mismatches between target ulong and host ulong sizes.
10732 */
10733 if (arg2 & (sizeof(abi_ulong) - 1)) {
72eb7ea8 10734 return -TARGET_EINVAL;
737de1d1
MF
10735 }
10736 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10737
10738 mask = alloca(mask_size);
2e0a8713 10739 memset(mask, 0, mask_size);
737de1d1
MF
10740 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10741
10742 if (!is_error(ret)) {
be3bd286
PM
10743 if (ret > arg2) {
10744 /* More data returned than the caller's buffer will fit.
10745 * This only happens if sizeof(abi_long) < sizeof(long)
10746 * and the caller passed us a buffer holding an odd number
10747 * of abi_longs. If the host kernel is actually using the
10748 * extra 4 bytes then fail EINVAL; otherwise we can just
10749 * ignore them and only copy the interesting part.
10750 */
10751 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10752 if (numcpus > arg2 * 8) {
72eb7ea8 10753 return -TARGET_EINVAL;
be3bd286
PM
10754 }
10755 ret = arg2;
10756 }
10757
5fdefcf8 10758 if (host_to_target_cpu_mask(mask, mask_size, arg3, ret)) {
2852aafd 10759 return -TARGET_EFAULT;
5fdefcf8 10760 }
737de1d1
MF
10761 }
10762 }
72eb7ea8 10763 return ret;
737de1d1
MF
10764 case TARGET_NR_sched_setaffinity:
10765 {
10766 unsigned int mask_size;
10767 unsigned long *mask;
10768
10769 /*
10770 * sched_setaffinity needs multiples of ulong, so need to take
10771 * care of mismatches between target ulong and host ulong sizes.
10772 */
10773 if (arg2 & (sizeof(abi_ulong) - 1)) {
72eb7ea8 10774 return -TARGET_EINVAL;
737de1d1
MF
10775 }
10776 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
737de1d1 10777 mask = alloca(mask_size);
2e0a8713
ST
10778
10779 ret = target_to_host_cpu_mask(mask, mask_size, arg3, arg2);
10780 if (ret) {
72eb7ea8 10781 return ret;
737de1d1 10782 }
737de1d1 10783
72eb7ea8 10784 return get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
737de1d1 10785 }
b827c3ed
ST
10786 case TARGET_NR_getcpu:
10787 {
10788 unsigned cpu, node;
10789 ret = get_errno(sys_getcpu(arg1 ? &cpu : NULL,
10790 arg2 ? &node : NULL,
10791 NULL));
10792 if (is_error(ret)) {
259841c1 10793 return ret;
b827c3ed
ST
10794 }
10795 if (arg1 && put_user_u32(cpu, arg1)) {
2852aafd 10796 return -TARGET_EFAULT;
b827c3ed
ST
10797 }
10798 if (arg2 && put_user_u32(node, arg2)) {
2852aafd 10799 return -TARGET_EFAULT;
b827c3ed
ST
10800 }
10801 }
72eb7ea8 10802 return ret;
31e31b8a 10803 case TARGET_NR_sched_setparam:
5cd4393b 10804 {
407a119b 10805 struct target_sched_param *target_schp;
5cd4393b 10806 struct sched_param schp;
53a5960a 10807
a1d5c5b2
TM
10808 if (arg2 == 0) {
10809 return -TARGET_EINVAL;
10810 }
407a119b 10811 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1)) {
2852aafd 10812 return -TARGET_EFAULT;
407a119b 10813 }
5cd4393b 10814 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10815 unlock_user_struct(target_schp, arg2, 0);
407a119b 10816 return get_errno(sys_sched_setparam(arg1, &schp));
5cd4393b 10817 }
31e31b8a 10818 case TARGET_NR_sched_getparam:
5cd4393b 10819 {
407a119b 10820 struct target_sched_param *target_schp;
5cd4393b 10821 struct sched_param schp;
a1d5c5b2
TM
10822
10823 if (arg2 == 0) {
10824 return -TARGET_EINVAL;
10825 }
407a119b 10826 ret = get_errno(sys_sched_getparam(arg1, &schp));
5cd4393b 10827 if (!is_error(ret)) {
407a119b 10828 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0)) {
2852aafd 10829 return -TARGET_EFAULT;
407a119b 10830 }
5cd4393b 10831 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 10832 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
10833 }
10834 }
72eb7ea8 10835 return ret;
31e31b8a 10836 case TARGET_NR_sched_setscheduler:
5cd4393b 10837 {
407a119b 10838 struct target_sched_param *target_schp;
5cd4393b 10839 struct sched_param schp;
a1d5c5b2
TM
10840 if (arg3 == 0) {
10841 return -TARGET_EINVAL;
10842 }
407a119b 10843 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1)) {
2852aafd 10844 return -TARGET_EFAULT;
407a119b 10845 }
5cd4393b 10846 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10847 unlock_user_struct(target_schp, arg3, 0);
407a119b 10848 return get_errno(sys_sched_setscheduler(arg1, arg2, &schp));
5cd4393b 10849 }
31e31b8a 10850 case TARGET_NR_sched_getscheduler:
407a119b 10851 return get_errno(sys_sched_getscheduler(arg1));
45ad761c
TT
10852 case TARGET_NR_sched_getattr:
10853 {
10854 struct target_sched_attr *target_scha;
10855 struct sched_attr scha;
10856 if (arg2 == 0) {
10857 return -TARGET_EINVAL;
10858 }
10859 if (arg3 > sizeof(scha)) {
10860 arg3 = sizeof(scha);
10861 }
10862 ret = get_errno(sys_sched_getattr(arg1, &scha, arg3, arg4));
10863 if (!is_error(ret)) {
10864 target_scha = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10865 if (!target_scha) {
10866 return -TARGET_EFAULT;
10867 }
10868 target_scha->size = tswap32(scha.size);
10869 target_scha->sched_policy = tswap32(scha.sched_policy);
10870 target_scha->sched_flags = tswap64(scha.sched_flags);
10871 target_scha->sched_nice = tswap32(scha.sched_nice);
10872 target_scha->sched_priority = tswap32(scha.sched_priority);
10873 target_scha->sched_runtime = tswap64(scha.sched_runtime);
10874 target_scha->sched_deadline = tswap64(scha.sched_deadline);
10875 target_scha->sched_period = tswap64(scha.sched_period);
10876 if (scha.size > offsetof(struct sched_attr, sched_util_min)) {
10877 target_scha->sched_util_min = tswap32(scha.sched_util_min);
10878 target_scha->sched_util_max = tswap32(scha.sched_util_max);
10879 }
10880 unlock_user(target_scha, arg2, arg3);
10881 }
10882 return ret;
10883 }
10884 case TARGET_NR_sched_setattr:
10885 {
10886 struct target_sched_attr *target_scha;
10887 struct sched_attr scha;
10888 uint32_t size;
10889 int zeroed;
10890 if (arg2 == 0) {
10891 return -TARGET_EINVAL;
10892 }
10893 if (get_user_u32(size, arg2)) {
10894 return -TARGET_EFAULT;
10895 }
10896 if (!size) {
10897 size = offsetof(struct target_sched_attr, sched_util_min);
10898 }
10899 if (size < offsetof(struct target_sched_attr, sched_util_min)) {
10900 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10901 return -TARGET_EFAULT;
10902 }
10903 return -TARGET_E2BIG;
10904 }
10905
10906 zeroed = check_zeroed_user(arg2, sizeof(struct target_sched_attr), size);
10907 if (zeroed < 0) {
10908 return zeroed;
10909 } else if (zeroed == 0) {
10910 if (put_user_u32(sizeof(struct target_sched_attr), arg2)) {
10911 return -TARGET_EFAULT;
10912 }
10913 return -TARGET_E2BIG;
10914 }
10915 if (size > sizeof(struct target_sched_attr)) {
10916 size = sizeof(struct target_sched_attr);
10917 }
10918
10919 target_scha = lock_user(VERIFY_READ, arg2, size, 1);
10920 if (!target_scha) {
10921 return -TARGET_EFAULT;
10922 }
10923 scha.size = size;
10924 scha.sched_policy = tswap32(target_scha->sched_policy);
10925 scha.sched_flags = tswap64(target_scha->sched_flags);
10926 scha.sched_nice = tswap32(target_scha->sched_nice);
10927 scha.sched_priority = tswap32(target_scha->sched_priority);
10928 scha.sched_runtime = tswap64(target_scha->sched_runtime);
10929 scha.sched_deadline = tswap64(target_scha->sched_deadline);
10930 scha.sched_period = tswap64(target_scha->sched_period);
10931 if (size > offsetof(struct target_sched_attr, sched_util_min)) {
10932 scha.sched_util_min = tswap32(target_scha->sched_util_min);
10933 scha.sched_util_max = tswap32(target_scha->sched_util_max);
10934 }
10935 unlock_user(target_scha, arg2, 0);
10936 return get_errno(sys_sched_setattr(arg1, &scha, arg3));
10937 }
31e31b8a 10938 case TARGET_NR_sched_yield:
72eb7ea8 10939 return get_errno(sched_yield());
31e31b8a 10940 case TARGET_NR_sched_get_priority_max:
72eb7ea8 10941 return get_errno(sched_get_priority_max(arg1));
31e31b8a 10942 case TARGET_NR_sched_get_priority_min:
72eb7ea8 10943 return get_errno(sched_get_priority_min(arg1));
859e8a89 10944#ifdef TARGET_NR_sched_rr_get_interval
31e31b8a 10945 case TARGET_NR_sched_rr_get_interval:
5cd4393b 10946 {
5cd4393b
FB
10947 struct timespec ts;
10948 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10949 if (!is_error(ret)) {
d4290c40 10950 ret = host_to_target_timespec(arg2, &ts);
5cd4393b
FB
10951 }
10952 }
72eb7ea8 10953 return ret;
859e8a89 10954#endif
ddcbde15
FB
10955#ifdef TARGET_NR_sched_rr_get_interval_time64
10956 case TARGET_NR_sched_rr_get_interval_time64:
10957 {
10958 struct timespec ts;
10959 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10960 if (!is_error(ret)) {
10961 ret = host_to_target_timespec64(arg2, &ts);
10962 }
10963 }
10964 return ret;
10965#endif
859e8a89 10966#if defined(TARGET_NR_nanosleep)
31e31b8a 10967 case TARGET_NR_nanosleep:
1b6b029e 10968 {
1b6b029e 10969 struct timespec req, rem;
53a5960a 10970 target_to_host_timespec(&req, arg1);
9e518226 10971 ret = get_errno(safe_nanosleep(&req, &rem));
53a5960a
PB
10972 if (is_error(ret) && arg2) {
10973 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
10974 }
10975 }
72eb7ea8 10976 return ret;
859e8a89 10977#endif
31e31b8a 10978 case TARGET_NR_prctl:
87e9bf23 10979 return do_prctl(cpu_env, arg1, arg2, arg3, arg4, arg5);
39b9aae1 10980 break;
d2fd1af7
FB
10981#ifdef TARGET_NR_arch_prctl
10982 case TARGET_NR_arch_prctl:
72eb7ea8 10983 return do_arch_prctl(cpu_env, arg1, arg2);
d2fd1af7 10984#endif
f2c7ba15
AJ
10985#ifdef TARGET_NR_pread64
10986 case TARGET_NR_pread64:
8bf8e9df 10987 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
10988 arg4 = arg5;
10989 arg5 = arg6;
10990 }
2bd3f899
PM
10991 if (arg2 == 0 && arg3 == 0) {
10992 /* Special-case NULL buffer and zero length, which should succeed */
10993 p = 0;
10994 } else {
10995 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
10996 if (!p) {
10997 return -TARGET_EFAULT;
10998 }
10999 }
f2c7ba15
AJ
11000 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
11001 unlock_user(p, arg2, ret);
72eb7ea8 11002 return ret;
f2c7ba15 11003 case TARGET_NR_pwrite64:
8bf8e9df 11004 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
11005 arg4 = arg5;
11006 arg5 = arg6;
11007 }
2bd3f899
PM
11008 if (arg2 == 0 && arg3 == 0) {
11009 /* Special-case NULL buffer and zero length, which should succeed */
11010 p = 0;
11011 } else {
11012 p = lock_user(VERIFY_READ, arg2, arg3, 1);
11013 if (!p) {
11014 return -TARGET_EFAULT;
11015 }
11016 }
f2c7ba15
AJ
11017 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
11018 unlock_user(p, arg2, 0);
72eb7ea8 11019 return ret;
67867308 11020#endif
31e31b8a 11021 case TARGET_NR_getcwd:
579a97f7 11022 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
2852aafd 11023 return -TARGET_EFAULT;
53a5960a
PB
11024 ret = get_errno(sys_getcwd1(p, arg2));
11025 unlock_user(p, arg1, ret);
72eb7ea8 11026 return ret;
31e31b8a
FB
11027 case TARGET_NR_capget:
11028 case TARGET_NR_capset:
e0eb210e
PM
11029 {
11030 struct target_user_cap_header *target_header;
11031 struct target_user_cap_data *target_data = NULL;
11032 struct __user_cap_header_struct header;
11033 struct __user_cap_data_struct data[2];
11034 struct __user_cap_data_struct *dataptr = NULL;
11035 int i, target_datalen;
11036 int data_items = 1;
11037
11038 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
2852aafd 11039 return -TARGET_EFAULT;
e0eb210e
PM
11040 }
11041 header.version = tswap32(target_header->version);
11042 header.pid = tswap32(target_header->pid);
11043
ec864874 11044 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
11045 /* Version 2 and up takes pointer to two user_data structs */
11046 data_items = 2;
11047 }
11048
11049 target_datalen = sizeof(*target_data) * data_items;
11050
11051 if (arg2) {
11052 if (num == TARGET_NR_capget) {
11053 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
11054 } else {
11055 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
11056 }
11057 if (!target_data) {
11058 unlock_user_struct(target_header, arg1, 0);
2852aafd 11059 return -TARGET_EFAULT;
e0eb210e
PM
11060 }
11061
11062 if (num == TARGET_NR_capset) {
11063 for (i = 0; i < data_items; i++) {
11064 data[i].effective = tswap32(target_data[i].effective);
11065 data[i].permitted = tswap32(target_data[i].permitted);
11066 data[i].inheritable = tswap32(target_data[i].inheritable);
11067 }
11068 }
11069
11070 dataptr = data;
11071 }
11072
11073 if (num == TARGET_NR_capget) {
11074 ret = get_errno(capget(&header, dataptr));
11075 } else {
11076 ret = get_errno(capset(&header, dataptr));
11077 }
11078
11079 /* The kernel always updates version for both capget and capset */
11080 target_header->version = tswap32(header.version);
11081 unlock_user_struct(target_header, arg1, 1);
11082
11083 if (arg2) {
11084 if (num == TARGET_NR_capget) {
11085 for (i = 0; i < data_items; i++) {
11086 target_data[i].effective = tswap32(data[i].effective);
11087 target_data[i].permitted = tswap32(data[i].permitted);
11088 target_data[i].inheritable = tswap32(data[i].inheritable);
11089 }
11090 unlock_user(target_data, arg2, target_datalen);
11091 } else {
11092 unlock_user(target_data, arg2, 0);
11093 }
11094 }
72eb7ea8 11095 return ret;
e0eb210e 11096 }
31e31b8a 11097 case TARGET_NR_sigaltstack:
6b208755 11098 return do_sigaltstack(arg1, arg2, cpu_env);
a8fd1aba
PM
11099
11100#ifdef CONFIG_SENDFILE
4f7f8924 11101#ifdef TARGET_NR_sendfile
a8fd1aba
PM
11102 case TARGET_NR_sendfile:
11103 {
11104 off_t *offp = NULL;
11105 off_t off;
11106 if (arg3) {
11107 ret = get_user_sal(off, arg3);
11108 if (is_error(ret)) {
72eb7ea8 11109 return ret;
a8fd1aba
PM
11110 }
11111 offp = &off;
11112 }
11113 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11114 if (!is_error(ret) && arg3) {
11115 abi_long ret2 = put_user_sal(off, arg3);
11116 if (is_error(ret2)) {
11117 ret = ret2;
11118 }
11119 }
72eb7ea8 11120 return ret;
a8fd1aba 11121 }
4f7f8924 11122#endif
a8fd1aba
PM
11123#ifdef TARGET_NR_sendfile64
11124 case TARGET_NR_sendfile64:
11125 {
11126 off_t *offp = NULL;
11127 off_t off;
11128 if (arg3) {
11129 ret = get_user_s64(off, arg3);
11130 if (is_error(ret)) {
72eb7ea8 11131 return ret;
a8fd1aba
PM
11132 }
11133 offp = &off;
11134 }
11135 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
11136 if (!is_error(ret) && arg3) {
11137 abi_long ret2 = put_user_s64(off, arg3);
11138 if (is_error(ret2)) {
11139 ret = ret2;
11140 }
11141 }
72eb7ea8 11142 return ret;
a8fd1aba
PM
11143 }
11144#endif
ebc05488 11145#endif
048f6b4d 11146#ifdef TARGET_NR_vfork
31e31b8a 11147 case TARGET_NR_vfork:
72eb7ea8
RH
11148 return get_errno(do_fork(cpu_env,
11149 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
11150 0, 0, 0, 0));
048f6b4d 11151#endif
ebc05488 11152#ifdef TARGET_NR_ugetrlimit
31e31b8a 11153 case TARGET_NR_ugetrlimit:
728584be
FB
11154 {
11155 struct rlimit rlim;
e22b7015
WT
11156 int resource = target_to_host_resource(arg1);
11157 ret = get_errno(getrlimit(resource, &rlim));
728584be 11158 if (!is_error(ret)) {
53a5960a 11159 struct target_rlimit *target_rlim;
579a97f7 11160 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
2852aafd 11161 return -TARGET_EFAULT;
81bbe906
TY
11162 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
11163 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 11164 unlock_user_struct(target_rlim, arg2, 1);
728584be 11165 }
72eb7ea8 11166 return ret;
728584be 11167 }
ebc05488 11168#endif
a315a145 11169#ifdef TARGET_NR_truncate64
31e31b8a 11170 case TARGET_NR_truncate64:
579a97f7 11171 if (!(p = lock_user_string(arg1)))
2852aafd 11172 return -TARGET_EFAULT;
53a5960a
PB
11173 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
11174 unlock_user(p, arg1, 0);
72eb7ea8 11175 return ret;
a315a145
FB
11176#endif
11177#ifdef TARGET_NR_ftruncate64
31e31b8a 11178 case TARGET_NR_ftruncate64:
72eb7ea8 11179 return target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
a315a145
FB
11180#endif
11181#ifdef TARGET_NR_stat64
31e31b8a 11182 case TARGET_NR_stat64:
2852aafd
RH
11183 if (!(p = lock_user_string(arg1))) {
11184 return -TARGET_EFAULT;
11185 }
53a5960a
PB
11186 ret = get_errno(stat(path(p), &st));
11187 unlock_user(p, arg1, 0);
6a24a778
AZ
11188 if (!is_error(ret))
11189 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11190 return ret;
a315a145
FB
11191#endif
11192#ifdef TARGET_NR_lstat64
31e31b8a 11193 case TARGET_NR_lstat64:
2852aafd
RH
11194 if (!(p = lock_user_string(arg1))) {
11195 return -TARGET_EFAULT;
11196 }
53a5960a
PB
11197 ret = get_errno(lstat(path(p), &st));
11198 unlock_user(p, arg1, 0);
6a24a778
AZ
11199 if (!is_error(ret))
11200 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11201 return ret;
a315a145
FB
11202#endif
11203#ifdef TARGET_NR_fstat64
31e31b8a 11204 case TARGET_NR_fstat64:
6a24a778
AZ
11205 ret = get_errno(fstat(arg1, &st));
11206 if (!is_error(ret))
11207 ret = host_to_target_stat64(cpu_env, arg2, &st);
72eb7ea8 11208 return ret;
ce4defa0 11209#endif
c0d472b1 11210#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 11211#ifdef TARGET_NR_fstatat64
6a24a778 11212 case TARGET_NR_fstatat64:
9d33b76b
AJ
11213#endif
11214#ifdef TARGET_NR_newfstatat
11215 case TARGET_NR_newfstatat:
11216#endif
2852aafd
RH
11217 if (!(p = lock_user_string(arg2))) {
11218 return -TARGET_EFAULT;
11219 }
c0d472b1 11220 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
2852aafd 11221 unlock_user(p, arg2, 0);
6a24a778
AZ
11222 if (!is_error(ret))
11223 ret = host_to_target_stat64(cpu_env, arg3, &st);
72eb7ea8 11224 return ret;
a315a145 11225#endif
efa92184
AR
11226#if defined(TARGET_NR_statx)
11227 case TARGET_NR_statx:
11228 {
11229 struct target_statx *target_stx;
11230 int dirfd = arg1;
11231 int flags = arg3;
11232
11233 p = lock_user_string(arg2);
11234 if (p == NULL) {
11235 return -TARGET_EFAULT;
11236 }
11237#if defined(__NR_statx)
11238 {
11239 /*
11240 * It is assumed that struct statx is architecture independent.
11241 */
11242 struct target_statx host_stx;
11243 int mask = arg4;
11244
11245 ret = get_errno(sys_statx(dirfd, p, flags, mask, &host_stx));
11246 if (!is_error(ret)) {
11247 if (host_to_target_statx(&host_stx, arg5) != 0) {
11248 unlock_user(p, arg2, 0);
11249 return -TARGET_EFAULT;
11250 }
11251 }
11252
11253 if (ret != -TARGET_ENOSYS) {
11254 unlock_user(p, arg2, 0);
11255 return ret;
11256 }
11257 }
11258#endif
11259 ret = get_errno(fstatat(dirfd, path(p), &st, flags));
11260 unlock_user(p, arg2, 0);
11261
11262 if (!is_error(ret)) {
11263 if (!lock_user_struct(VERIFY_WRITE, target_stx, arg5, 0)) {
11264 return -TARGET_EFAULT;
11265 }
11266 memset(target_stx, 0, sizeof(*target_stx));
11267 __put_user(major(st.st_dev), &target_stx->stx_dev_major);
11268 __put_user(minor(st.st_dev), &target_stx->stx_dev_minor);
11269 __put_user(st.st_ino, &target_stx->stx_ino);
11270 __put_user(st.st_mode, &target_stx->stx_mode);
11271 __put_user(st.st_uid, &target_stx->stx_uid);
11272 __put_user(st.st_gid, &target_stx->stx_gid);
11273 __put_user(st.st_nlink, &target_stx->stx_nlink);
11274 __put_user(major(st.st_rdev), &target_stx->stx_rdev_major);
11275 __put_user(minor(st.st_rdev), &target_stx->stx_rdev_minor);
11276 __put_user(st.st_size, &target_stx->stx_size);
11277 __put_user(st.st_blksize, &target_stx->stx_blksize);
11278 __put_user(st.st_blocks, &target_stx->stx_blocks);
11279 __put_user(st.st_atime, &target_stx->stx_atime.tv_sec);
11280 __put_user(st.st_mtime, &target_stx->stx_mtime.tv_sec);
11281 __put_user(st.st_ctime, &target_stx->stx_ctime.tv_sec);
11282 unlock_user_struct(target_stx, arg5, 1);
11283 }
11284 }
11285 return ret;
11286#endif
704eff6c 11287#ifdef TARGET_NR_lchown
67867308 11288 case TARGET_NR_lchown:
579a97f7 11289 if (!(p = lock_user_string(arg1)))
2852aafd 11290 return -TARGET_EFAULT;
53a5960a
PB
11291 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
11292 unlock_user(p, arg1, 0);
72eb7ea8 11293 return ret;
704eff6c 11294#endif
0c866a7e 11295#ifdef TARGET_NR_getuid
67867308 11296 case TARGET_NR_getuid:
72eb7ea8 11297 return get_errno(high2lowuid(getuid()));
0c866a7e
RV
11298#endif
11299#ifdef TARGET_NR_getgid
67867308 11300 case TARGET_NR_getgid:
72eb7ea8 11301 return get_errno(high2lowgid(getgid()));
0c866a7e
RV
11302#endif
11303#ifdef TARGET_NR_geteuid
67867308 11304 case TARGET_NR_geteuid:
72eb7ea8 11305 return get_errno(high2lowuid(geteuid()));
0c866a7e
RV
11306#endif
11307#ifdef TARGET_NR_getegid
67867308 11308 case TARGET_NR_getegid:
72eb7ea8 11309 return get_errno(high2lowgid(getegid()));
0c866a7e 11310#endif
67867308 11311 case TARGET_NR_setreuid:
72eb7ea8 11312 return get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
67867308 11313 case TARGET_NR_setregid:
72eb7ea8 11314 return get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
67867308
FB
11315 case TARGET_NR_getgroups:
11316 {
11317 int gidsetsize = arg1;
0c866a7e 11318 target_id *target_grouplist;
67867308
FB
11319 gid_t *grouplist;
11320 int i;
11321
11322 grouplist = alloca(gidsetsize * sizeof(gid_t));
11323 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11324 if (gidsetsize == 0)
72eb7ea8 11325 return ret;
67867308 11326 if (!is_error(ret)) {
03903ffc 11327 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7 11328 if (!target_grouplist)
2852aafd 11329 return -TARGET_EFAULT;
a2155fcc 11330 for(i = 0;i < ret; i++)
0c866a7e 11331 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 11332 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
11333 }
11334 }
72eb7ea8 11335 return ret;
67867308
FB
11336 case TARGET_NR_setgroups:
11337 {
11338 int gidsetsize = arg1;
0c866a7e 11339 target_id *target_grouplist;
f2b79ce9 11340 gid_t *grouplist = NULL;
67867308 11341 int i;
f2b79ce9
DA
11342 if (gidsetsize) {
11343 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 11344 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9 11345 if (!target_grouplist) {
259841c1 11346 return -TARGET_EFAULT;
f2b79ce9
DA
11347 }
11348 for (i = 0; i < gidsetsize; i++) {
11349 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
11350 }
11351 unlock_user(target_grouplist, arg2, 0);
579a97f7 11352 }
72eb7ea8 11353 return get_errno(setgroups(gidsetsize, grouplist));
67867308 11354 }
67867308 11355 case TARGET_NR_fchown:
72eb7ea8 11356 return get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
c0d472b1 11357#if defined(TARGET_NR_fchownat)
ccfa72b7 11358 case TARGET_NR_fchownat:
579a97f7 11359 if (!(p = lock_user_string(arg2)))
2852aafd 11360 return -TARGET_EFAULT;
c0d472b1
PM
11361 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
11362 low2highgid(arg4), arg5));
579a97f7 11363 unlock_user(p, arg2, 0);
72eb7ea8 11364 return ret;
ccfa72b7 11365#endif
67867308
FB
11366#ifdef TARGET_NR_setresuid
11367 case TARGET_NR_setresuid:
72eb7ea8
RH
11368 return get_errno(sys_setresuid(low2highuid(arg1),
11369 low2highuid(arg2),
11370 low2highuid(arg3)));
67867308
FB
11371#endif
11372#ifdef TARGET_NR_getresuid
11373 case TARGET_NR_getresuid:
11374 {
53a5960a 11375 uid_t ruid, euid, suid;
67867308
FB
11376 ret = get_errno(getresuid(&ruid, &euid, &suid));
11377 if (!is_error(ret)) {
76ca310a
PM
11378 if (put_user_id(high2lowuid(ruid), arg1)
11379 || put_user_id(high2lowuid(euid), arg2)
11380 || put_user_id(high2lowuid(suid), arg3))
2852aafd 11381 return -TARGET_EFAULT;
67867308
FB
11382 }
11383 }
72eb7ea8 11384 return ret;
67867308
FB
11385#endif
11386#ifdef TARGET_NR_getresgid
11387 case TARGET_NR_setresgid:
72eb7ea8
RH
11388 return get_errno(sys_setresgid(low2highgid(arg1),
11389 low2highgid(arg2),
11390 low2highgid(arg3)));
67867308
FB
11391#endif
11392#ifdef TARGET_NR_getresgid
11393 case TARGET_NR_getresgid:
11394 {
53a5960a 11395 gid_t rgid, egid, sgid;
67867308
FB
11396 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11397 if (!is_error(ret)) {
76ca310a
PM
11398 if (put_user_id(high2lowgid(rgid), arg1)
11399 || put_user_id(high2lowgid(egid), arg2)
11400 || put_user_id(high2lowgid(sgid), arg3))
2852aafd 11401 return -TARGET_EFAULT;
67867308
FB
11402 }
11403 }
72eb7ea8 11404 return ret;
67867308 11405#endif
704eff6c 11406#ifdef TARGET_NR_chown
67867308 11407 case TARGET_NR_chown:
579a97f7 11408 if (!(p = lock_user_string(arg1)))
2852aafd 11409 return -TARGET_EFAULT;
53a5960a
PB
11410 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
11411 unlock_user(p, arg1, 0);
72eb7ea8 11412 return ret;
704eff6c 11413#endif
67867308 11414 case TARGET_NR_setuid:
72eb7ea8 11415 return get_errno(sys_setuid(low2highuid(arg1)));
67867308 11416 case TARGET_NR_setgid:
72eb7ea8 11417 return get_errno(sys_setgid(low2highgid(arg1)));
67867308 11418 case TARGET_NR_setfsuid:
72eb7ea8 11419 return get_errno(setfsuid(arg1));
67867308 11420 case TARGET_NR_setfsgid:
72eb7ea8 11421 return get_errno(setfsgid(arg1));
67867308 11422
a315a145 11423#ifdef TARGET_NR_lchown32
31e31b8a 11424 case TARGET_NR_lchown32:
579a97f7 11425 if (!(p = lock_user_string(arg1)))
2852aafd 11426 return -TARGET_EFAULT;
53a5960a
PB
11427 ret = get_errno(lchown(p, arg2, arg3));
11428 unlock_user(p, arg1, 0);
72eb7ea8 11429 return ret;
a315a145
FB
11430#endif
11431#ifdef TARGET_NR_getuid32
31e31b8a 11432 case TARGET_NR_getuid32:
72eb7ea8 11433 return get_errno(getuid());
a315a145 11434#endif
64b4d28c
AJ
11435
11436#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
11437 /* Alpha specific */
11438 case TARGET_NR_getxuid:
ba0e276d
RH
11439 {
11440 uid_t euid;
11441 euid=geteuid();
11442 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
11443 }
72eb7ea8 11444 return get_errno(getuid());
64b4d28c
AJ
11445#endif
11446#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
11447 /* Alpha specific */
11448 case TARGET_NR_getxgid:
ba0e276d
RH
11449 {
11450 uid_t egid;
11451 egid=getegid();
11452 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
11453 }
72eb7ea8 11454 return get_errno(getgid());
64b4d28c 11455#endif
ba0e276d
RH
11456#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
11457 /* Alpha specific */
11458 case TARGET_NR_osf_getsysinfo:
11459 ret = -TARGET_EOPNOTSUPP;
11460 switch (arg1) {
11461 case TARGET_GSI_IEEE_FP_CONTROL:
11462 {
21ba8564
RH
11463 uint64_t fpcr = cpu_alpha_load_fpcr(cpu_env);
11464 uint64_t swcr = ((CPUAlphaState *)cpu_env)->swcr;
11465
11466 swcr &= ~SWCR_STATUS_MASK;
11467 swcr |= (fpcr >> 35) & SWCR_STATUS_MASK;
ba0e276d
RH
11468
11469 if (put_user_u64 (swcr, arg2))
2852aafd 11470 return -TARGET_EFAULT;
ba0e276d
RH
11471 ret = 0;
11472 }
11473 break;
11474
11475 /* case GSI_IEEE_STATE_AT_SIGNAL:
11476 -- Not implemented in linux kernel.
11477 case GSI_UACPROC:
11478 -- Retrieves current unaligned access state; not much used.
11479 case GSI_PROC_TYPE:
11480 -- Retrieves implver information; surely not used.
11481 case GSI_GET_HWRPB:
11482 -- Grabs a copy of the HWRPB; surely not used.
11483 */
11484 }
72eb7ea8 11485 return ret;
ba0e276d
RH
11486#endif
11487#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11488 /* Alpha specific */
11489 case TARGET_NR_osf_setsysinfo:
11490 ret = -TARGET_EOPNOTSUPP;
11491 switch (arg1) {
11492 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d 11493 {
21ba8564 11494 uint64_t swcr, fpcr;
ba0e276d 11495
6e06d515 11496 if (get_user_u64 (swcr, arg2)) {
2852aafd 11497 return -TARGET_EFAULT;
6e06d515 11498 }
ba0e276d 11499
21ba8564
RH
11500 /*
11501 * The kernel calls swcr_update_status to update the
11502 * status bits from the fpcr at every point that it
11503 * could be queried. Therefore, we store the status
11504 * bits only in FPCR.
11505 */
11506 ((CPUAlphaState *)cpu_env)->swcr
11507 = swcr & (SWCR_TRAP_ENABLE_MASK | SWCR_MAP_MASK);
11508
11509 fpcr = cpu_alpha_load_fpcr(cpu_env);
11510 fpcr &= ((uint64_t)FPCR_DYN_MASK << 32);
11511 fpcr |= alpha_ieee_swcr_to_fpcr(swcr);
6e06d515 11512 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 11513 ret = 0;
6e06d515
RH
11514 }
11515 break;
11516
11517 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11518 {
21ba8564 11519 uint64_t exc, fpcr, fex;
6e06d515
RH
11520
11521 if (get_user_u64(exc, arg2)) {
2852aafd 11522 return -TARGET_EFAULT;
6e06d515 11523 }
21ba8564
RH
11524 exc &= SWCR_STATUS_MASK;
11525 fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 11526
21ba8564
RH
11527 /* Old exceptions are not signaled. */
11528 fex = alpha_ieee_fpcr_to_swcr(fpcr);
11529 fex = exc & ~fex;
11530 fex >>= SWCR_STATUS_TO_EXCSUM_SHIFT;
11531 fex &= ((CPUArchState *)cpu_env)->swcr;
6e06d515 11532
21ba8564
RH
11533 /* Update the hardware fpcr. */
11534 fpcr |= alpha_ieee_swcr_to_fpcr(exc);
6e06d515 11535 cpu_alpha_store_fpcr(cpu_env, fpcr);
6e06d515 11536
21ba8564
RH
11537 if (fex) {
11538 int si_code = TARGET_FPE_FLTUNK;
6e06d515 11539 target_siginfo_t info;
21ba8564
RH
11540
11541 if (fex & SWCR_TRAP_ENABLE_DNO) {
11542 si_code = TARGET_FPE_FLTUND;
11543 }
11544 if (fex & SWCR_TRAP_ENABLE_INE) {
11545 si_code = TARGET_FPE_FLTRES;
11546 }
11547 if (fex & SWCR_TRAP_ENABLE_UNF) {
11548 si_code = TARGET_FPE_FLTUND;
11549 }
11550 if (fex & SWCR_TRAP_ENABLE_OVF) {
11551 si_code = TARGET_FPE_FLTOVF;
11552 }
11553 if (fex & SWCR_TRAP_ENABLE_DZE) {
11554 si_code = TARGET_FPE_FLTDIV;
11555 }
11556 if (fex & SWCR_TRAP_ENABLE_INV) {
11557 si_code = TARGET_FPE_FLTINV;
11558 }
11559
6e06d515
RH
11560 info.si_signo = SIGFPE;
11561 info.si_errno = 0;
11562 info.si_code = si_code;
11563 info._sifields._sigfault._addr
11564 = ((CPUArchState *)cpu_env)->pc;
9d2803f7
PM
11565 queue_signal((CPUArchState *)cpu_env, info.si_signo,
11566 QEMU_SI_FAULT, &info);
ba0e276d 11567 }
21ba8564 11568 ret = 0;
ba0e276d
RH
11569 }
11570 break;
11571
11572 /* case SSI_NVPAIRS:
11573 -- Used with SSIN_UACPROC to enable unaligned accesses.
11574 case SSI_IEEE_STATE_AT_SIGNAL:
11575 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11576 -- Not implemented in linux kernel
11577 */
11578 }
72eb7ea8 11579 return ret;
ba0e276d
RH
11580#endif
11581#ifdef TARGET_NR_osf_sigprocmask
11582 /* Alpha specific. */
11583 case TARGET_NR_osf_sigprocmask:
11584 {
11585 abi_ulong mask;
bc088ba1 11586 int how;
ba0e276d
RH
11587 sigset_t set, oldset;
11588
11589 switch(arg1) {
11590 case TARGET_SIG_BLOCK:
11591 how = SIG_BLOCK;
11592 break;
11593 case TARGET_SIG_UNBLOCK:
11594 how = SIG_UNBLOCK;
11595 break;
11596 case TARGET_SIG_SETMASK:
11597 how = SIG_SETMASK;
11598 break;
11599 default:
259841c1 11600 return -TARGET_EINVAL;
ba0e276d
RH
11601 }
11602 mask = arg2;
11603 target_to_host_old_sigset(&set, &mask);
3d3efba0
PM
11604 ret = do_sigprocmask(how, &set, &oldset);
11605 if (!ret) {
11606 host_to_target_old_sigset(&mask, &oldset);
11607 ret = mask;
11608 }
ba0e276d 11609 }
72eb7ea8 11610 return ret;
ba0e276d 11611#endif
64b4d28c 11612
a315a145 11613#ifdef TARGET_NR_getgid32
31e31b8a 11614 case TARGET_NR_getgid32:
72eb7ea8 11615 return get_errno(getgid());
a315a145
FB
11616#endif
11617#ifdef TARGET_NR_geteuid32
31e31b8a 11618 case TARGET_NR_geteuid32:
72eb7ea8 11619 return get_errno(geteuid());
a315a145
FB
11620#endif
11621#ifdef TARGET_NR_getegid32
31e31b8a 11622 case TARGET_NR_getegid32:
72eb7ea8 11623 return get_errno(getegid());
a315a145
FB
11624#endif
11625#ifdef TARGET_NR_setreuid32
31e31b8a 11626 case TARGET_NR_setreuid32:
72eb7ea8 11627 return get_errno(setreuid(arg1, arg2));
a315a145
FB
11628#endif
11629#ifdef TARGET_NR_setregid32
31e31b8a 11630 case TARGET_NR_setregid32:
72eb7ea8 11631 return get_errno(setregid(arg1, arg2));
a315a145
FB
11632#endif
11633#ifdef TARGET_NR_getgroups32
31e31b8a 11634 case TARGET_NR_getgroups32:
99c475ab
FB
11635 {
11636 int gidsetsize = arg1;
53a5960a 11637 uint32_t *target_grouplist;
99c475ab
FB
11638 gid_t *grouplist;
11639 int i;
11640
11641 grouplist = alloca(gidsetsize * sizeof(gid_t));
11642 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233 11643 if (gidsetsize == 0)
72eb7ea8 11644 return ret;
99c475ab 11645 if (!is_error(ret)) {
579a97f7
FB
11646 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11647 if (!target_grouplist) {
259841c1 11648 return -TARGET_EFAULT;
579a97f7 11649 }
a2155fcc 11650 for(i = 0;i < ret; i++)
53a5960a
PB
11651 target_grouplist[i] = tswap32(grouplist[i]);
11652 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
11653 }
11654 }
72eb7ea8 11655 return ret;
a315a145
FB
11656#endif
11657#ifdef TARGET_NR_setgroups32
31e31b8a 11658 case TARGET_NR_setgroups32:
99c475ab
FB
11659 {
11660 int gidsetsize = arg1;
53a5960a 11661 uint32_t *target_grouplist;
99c475ab
FB
11662 gid_t *grouplist;
11663 int i;
3b46e624 11664
99c475ab 11665 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
11666 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11667 if (!target_grouplist) {
259841c1 11668 return -TARGET_EFAULT;
579a97f7 11669 }
99c475ab 11670 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
11671 grouplist[i] = tswap32(target_grouplist[i]);
11672 unlock_user(target_grouplist, arg2, 0);
72eb7ea8 11673 return get_errno(setgroups(gidsetsize, grouplist));
99c475ab 11674 }
a315a145
FB
11675#endif
11676#ifdef TARGET_NR_fchown32
31e31b8a 11677 case TARGET_NR_fchown32:
72eb7ea8 11678 return get_errno(fchown(arg1, arg2, arg3));
a315a145
FB
11679#endif
11680#ifdef TARGET_NR_setresuid32
31e31b8a 11681 case TARGET_NR_setresuid32:
72eb7ea8 11682 return get_errno(sys_setresuid(arg1, arg2, arg3));
a315a145
FB
11683#endif
11684#ifdef TARGET_NR_getresuid32
31e31b8a 11685 case TARGET_NR_getresuid32:
b03c60f3 11686 {
53a5960a 11687 uid_t ruid, euid, suid;
b03c60f3
FB
11688 ret = get_errno(getresuid(&ruid, &euid, &suid));
11689 if (!is_error(ret)) {
2f619698
FB
11690 if (put_user_u32(ruid, arg1)
11691 || put_user_u32(euid, arg2)
11692 || put_user_u32(suid, arg3))
2852aafd 11693 return -TARGET_EFAULT;
b03c60f3
FB
11694 }
11695 }
72eb7ea8 11696 return ret;
a315a145
FB
11697#endif
11698#ifdef TARGET_NR_setresgid32
31e31b8a 11699 case TARGET_NR_setresgid32:
72eb7ea8 11700 return get_errno(sys_setresgid(arg1, arg2, arg3));
a315a145
FB
11701#endif
11702#ifdef TARGET_NR_getresgid32
31e31b8a 11703 case TARGET_NR_getresgid32:
b03c60f3 11704 {
53a5960a 11705 gid_t rgid, egid, sgid;
b03c60f3
FB
11706 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11707 if (!is_error(ret)) {
2f619698
FB
11708 if (put_user_u32(rgid, arg1)
11709 || put_user_u32(egid, arg2)
11710 || put_user_u32(sgid, arg3))
2852aafd 11711 return -TARGET_EFAULT;
b03c60f3
FB
11712 }
11713 }
72eb7ea8 11714 return ret;
a315a145
FB
11715#endif
11716#ifdef TARGET_NR_chown32
31e31b8a 11717 case TARGET_NR_chown32:
579a97f7 11718 if (!(p = lock_user_string(arg1)))
2852aafd 11719 return -TARGET_EFAULT;
53a5960a
PB
11720 ret = get_errno(chown(p, arg2, arg3));
11721 unlock_user(p, arg1, 0);
72eb7ea8 11722 return ret;
a315a145
FB
11723#endif
11724#ifdef TARGET_NR_setuid32
31e31b8a 11725 case TARGET_NR_setuid32:
72eb7ea8 11726 return get_errno(sys_setuid(arg1));
a315a145
FB
11727#endif
11728#ifdef TARGET_NR_setgid32
31e31b8a 11729 case TARGET_NR_setgid32:
72eb7ea8 11730 return get_errno(sys_setgid(arg1));
a315a145
FB
11731#endif
11732#ifdef TARGET_NR_setfsuid32
31e31b8a 11733 case TARGET_NR_setfsuid32:
72eb7ea8 11734 return get_errno(setfsuid(arg1));
a315a145
FB
11735#endif
11736#ifdef TARGET_NR_setfsgid32
31e31b8a 11737 case TARGET_NR_setfsgid32:
72eb7ea8 11738 return get_errno(setfsgid(arg1));
a315a145 11739#endif
ffa65c3b 11740#ifdef TARGET_NR_mincore
31e31b8a 11741 case TARGET_NR_mincore:
04bb9ace 11742 {
259841c1 11743 void *a = lock_user(VERIFY_READ, arg1, arg2, 0);
98a3331a 11744 if (!a) {
259841c1 11745 return -TARGET_ENOMEM;
98a3331a 11746 }
98a3331a
FSM
11747 p = lock_user_string(arg3);
11748 if (!p) {
259841c1
RH
11749 ret = -TARGET_EFAULT;
11750 } else {
11751 ret = get_errno(mincore(a, arg2, p));
11752 unlock_user(p, arg3, ret);
98a3331a 11753 }
04bb9ace
AJ
11754 unlock_user(a, arg1, 0);
11755 }
72eb7ea8 11756 return ret;
ffa65c3b 11757#endif
408321b6
AJ
11758#ifdef TARGET_NR_arm_fadvise64_64
11759 case TARGET_NR_arm_fadvise64_64:
e0156a9d
PM
11760 /* arm_fadvise64_64 looks like fadvise64_64 but
11761 * with different argument order: fd, advice, offset, len
11762 * rather than the usual fd, offset, len, advice.
11763 * Note that offset and len are both 64-bit so appear as
11764 * pairs of 32-bit registers.
11765 */
11766 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11767 target_offset64(arg5, arg6), arg2);
72eb7ea8 11768 return -host_to_target_errno(ret);
408321b6 11769#endif
badd3cd8
PM
11770
11771#if TARGET_ABI_BITS == 32
11772
11773#ifdef TARGET_NR_fadvise64_64
11774 case TARGET_NR_fadvise64_64:
64a563dd 11775#if defined(TARGET_PPC) || defined(TARGET_XTENSA)
43046b5a
LV
11776 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11777 ret = arg2;
11778 arg2 = arg3;
11779 arg3 = arg4;
11780 arg4 = arg5;
11781 arg5 = arg6;
11782 arg6 = ret;
11783#else
badd3cd8 11784 /* 6 args: fd, offset (high, low), len (high, low), advice */
8bf8e9df 11785 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11786 /* offset is in (3,4), len in (5,6) and advice in 7 */
11787 arg2 = arg3;
11788 arg3 = arg4;
11789 arg4 = arg5;
11790 arg5 = arg6;
11791 arg6 = arg7;
11792 }
43046b5a 11793#endif
72eb7ea8
RH
11794 ret = posix_fadvise(arg1, target_offset64(arg2, arg3),
11795 target_offset64(arg4, arg5), arg6);
11796 return -host_to_target_errno(ret);
badd3cd8
PM
11797#endif
11798
11799#ifdef TARGET_NR_fadvise64
11800 case TARGET_NR_fadvise64:
11801 /* 5 args: fd, offset (high, low), len, advice */
8bf8e9df 11802 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11803 /* offset is in (3,4), len in 5 and advice in 6 */
11804 arg2 = arg3;
11805 arg3 = arg4;
11806 arg4 = arg5;
11807 arg5 = arg6;
11808 }
72eb7ea8
RH
11809 ret = posix_fadvise(arg1, target_offset64(arg2, arg3), arg4, arg5);
11810 return -host_to_target_errno(ret);
408321b6 11811#endif
badd3cd8
PM
11812
11813#else /* not a 32-bit ABI */
e0156a9d 11814#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
11815#ifdef TARGET_NR_fadvise64_64
11816 case TARGET_NR_fadvise64_64:
11817#endif
e72d2cc7
UH
11818#ifdef TARGET_NR_fadvise64
11819 case TARGET_NR_fadvise64:
11820#endif
11821#ifdef TARGET_S390X
11822 switch (arg4) {
11823 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11824 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11825 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11826 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11827 default: break;
11828 }
11829#endif
72eb7ea8 11830 return -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
408321b6 11831#endif
badd3cd8
PM
11832#endif /* end of 64-bit ABI fadvise handling */
11833
ffa65c3b 11834#ifdef TARGET_NR_madvise
31e31b8a 11835 case TARGET_NR_madvise:
24836689 11836 /* A straight passthrough may not be safe because qemu sometimes
d2d6b857 11837 turns private file-backed mappings into anonymous mappings.
24836689
PB
11838 This will break MADV_DONTNEED.
11839 This is a hint, so ignoring and returning success is ok. */
72eb7ea8 11840 return 0;
ffa65c3b 11841#endif
bbf5f2a1 11842#ifdef TARGET_NR_fcntl64
31e31b8a 11843 case TARGET_NR_fcntl64:
77e4672d 11844 {
bbf5f2a1
AB
11845 int cmd;
11846 struct flock64 fl;
213d3e9e
PM
11847 from_flock64_fn *copyfrom = copy_from_user_flock64;
11848 to_flock64_fn *copyto = copy_to_user_flock64;
11849
ce4defa0 11850#ifdef TARGET_ARM
7f254c5c
LV
11851 if (!((CPUARMState *)cpu_env)->eabi) {
11852 copyfrom = copy_from_user_oabi_flock64;
11853 copyto = copy_to_user_oabi_flock64;
213d3e9e 11854 }
ce4defa0 11855#endif
77e4672d 11856
bbf5f2a1 11857 cmd = target_to_host_fcntl_cmd(arg2);
31b63193 11858 if (cmd == -TARGET_EINVAL) {
72eb7ea8 11859 return cmd;
31b63193 11860 }
b1e341eb 11861
60cd49d5 11862 switch(arg2) {
b1e341eb 11863 case TARGET_F_GETLK64:
213d3e9e
PM
11864 ret = copyfrom(&fl, arg3);
11865 if (ret) {
11866 break;
5813427b 11867 }
af8ab2bf 11868 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
213d3e9e
PM
11869 if (ret == 0) {
11870 ret = copyto(arg3, &fl);
11871 }
77e4672d
FB
11872 break;
11873
b1e341eb
TS
11874 case TARGET_F_SETLK64:
11875 case TARGET_F_SETLKW64:
213d3e9e
PM
11876 ret = copyfrom(&fl, arg3);
11877 if (ret) {
11878 break;
ce4defa0 11879 }
435da5e7 11880 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
77e4672d 11881 break;
60cd49d5 11882 default:
5f106811 11883 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
11884 break;
11885 }
72eb7ea8 11886 return ret;
77e4672d 11887 }
60cd49d5 11888#endif
7d600c80
TS
11889#ifdef TARGET_NR_cacheflush
11890 case TARGET_NR_cacheflush:
11891 /* self-modifying code is handled automatically, so nothing needed */
72eb7ea8 11892 return 0;
7d600c80 11893#endif
c573ff67
FB
11894#ifdef TARGET_NR_getpagesize
11895 case TARGET_NR_getpagesize:
72eb7ea8 11896 return TARGET_PAGE_SIZE;
ebc05488 11897#endif
31e31b8a 11898 case TARGET_NR_gettid:
71ba74f6 11899 return get_errno(sys_gettid());
e5febef5 11900#ifdef TARGET_NR_readahead
31e31b8a 11901 case TARGET_NR_readahead:
2054ac9b 11902#if TARGET_ABI_BITS == 32
8bf8e9df 11903 if (regpairs_aligned(cpu_env, num)) {
2054ac9b
AJ
11904 arg2 = arg3;
11905 arg3 = arg4;
11906 arg4 = arg5;
11907 }
77c6850f 11908 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
2054ac9b
AJ
11909#else
11910 ret = get_errno(readahead(arg1, arg2, arg3));
11911#endif
72eb7ea8 11912 return ret;
e5febef5 11913#endif
a790ae38 11914#ifdef CONFIG_ATTR
ebc05488 11915#ifdef TARGET_NR_setxattr
31e31b8a
FB
11916 case TARGET_NR_listxattr:
11917 case TARGET_NR_llistxattr:
fb5590f7
PM
11918 {
11919 void *p, *b = 0;
11920 if (arg2) {
11921 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11922 if (!b) {
72eb7ea8 11923 return -TARGET_EFAULT;
fb5590f7
PM
11924 }
11925 }
11926 p = lock_user_string(arg1);
11927 if (p) {
11928 if (num == TARGET_NR_listxattr) {
11929 ret = get_errno(listxattr(p, b, arg3));
11930 } else {
11931 ret = get_errno(llistxattr(p, b, arg3));
11932 }
11933 } else {
11934 ret = -TARGET_EFAULT;
11935 }
11936 unlock_user(p, arg1, 0);
11937 unlock_user(b, arg2, arg3);
72eb7ea8 11938 return ret;
fb5590f7 11939 }
31e31b8a 11940 case TARGET_NR_flistxattr:
fb5590f7
PM
11941 {
11942 void *b = 0;
11943 if (arg2) {
11944 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11945 if (!b) {
72eb7ea8 11946 return -TARGET_EFAULT;
fb5590f7
PM
11947 }
11948 }
11949 ret = get_errno(flistxattr(arg1, b, arg3));
11950 unlock_user(b, arg2, arg3);
72eb7ea8 11951 return ret;
fb5590f7 11952 }
a790ae38 11953 case TARGET_NR_setxattr:
30297b55 11954 case TARGET_NR_lsetxattr:
a790ae38 11955 {
e3c33ec6
PM
11956 void *p, *n, *v = 0;
11957 if (arg3) {
11958 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11959 if (!v) {
72eb7ea8 11960 return -TARGET_EFAULT;
e3c33ec6
PM
11961 }
11962 }
a790ae38
ACH
11963 p = lock_user_string(arg1);
11964 n = lock_user_string(arg2);
e3c33ec6 11965 if (p && n) {
30297b55
PM
11966 if (num == TARGET_NR_setxattr) {
11967 ret = get_errno(setxattr(p, n, v, arg4, arg5));
11968 } else {
11969 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
11970 }
a790ae38
ACH
11971 } else {
11972 ret = -TARGET_EFAULT;
11973 }
11974 unlock_user(p, arg1, 0);
11975 unlock_user(n, arg2, 0);
11976 unlock_user(v, arg3, 0);
11977 }
72eb7ea8 11978 return ret;
30297b55
PM
11979 case TARGET_NR_fsetxattr:
11980 {
11981 void *n, *v = 0;
11982 if (arg3) {
11983 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11984 if (!v) {
72eb7ea8 11985 return -TARGET_EFAULT;
30297b55
PM
11986 }
11987 }
11988 n = lock_user_string(arg2);
11989 if (n) {
11990 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
11991 } else {
11992 ret = -TARGET_EFAULT;
11993 }
11994 unlock_user(n, arg2, 0);
11995 unlock_user(v, arg3, 0);
11996 }
72eb7ea8 11997 return ret;
a790ae38 11998 case TARGET_NR_getxattr:
30297b55 11999 case TARGET_NR_lgetxattr:
a790ae38 12000 {
e3c33ec6
PM
12001 void *p, *n, *v = 0;
12002 if (arg3) {
12003 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12004 if (!v) {
72eb7ea8 12005 return -TARGET_EFAULT;
e3c33ec6
PM
12006 }
12007 }
a790ae38
ACH
12008 p = lock_user_string(arg1);
12009 n = lock_user_string(arg2);
e3c33ec6 12010 if (p && n) {
30297b55
PM
12011 if (num == TARGET_NR_getxattr) {
12012 ret = get_errno(getxattr(p, n, v, arg4));
12013 } else {
12014 ret = get_errno(lgetxattr(p, n, v, arg4));
12015 }
a790ae38
ACH
12016 } else {
12017 ret = -TARGET_EFAULT;
12018 }
12019 unlock_user(p, arg1, 0);
12020 unlock_user(n, arg2, 0);
12021 unlock_user(v, arg3, arg4);
12022 }
72eb7ea8 12023 return ret;
30297b55
PM
12024 case TARGET_NR_fgetxattr:
12025 {
12026 void *n, *v = 0;
12027 if (arg3) {
12028 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
12029 if (!v) {
72eb7ea8 12030 return -TARGET_EFAULT;
30297b55
PM
12031 }
12032 }
12033 n = lock_user_string(arg2);
12034 if (n) {
12035 ret = get_errno(fgetxattr(arg1, n, v, arg4));
12036 } else {
12037 ret = -TARGET_EFAULT;
12038 }
12039 unlock_user(n, arg2, 0);
12040 unlock_user(v, arg3, arg4);
12041 }
72eb7ea8 12042 return ret;
a790ae38 12043 case TARGET_NR_removexattr:
30297b55 12044 case TARGET_NR_lremovexattr:
a790ae38
ACH
12045 {
12046 void *p, *n;
12047 p = lock_user_string(arg1);
12048 n = lock_user_string(arg2);
12049 if (p && n) {
30297b55
PM
12050 if (num == TARGET_NR_removexattr) {
12051 ret = get_errno(removexattr(p, n));
12052 } else {
12053 ret = get_errno(lremovexattr(p, n));
12054 }
a790ae38
ACH
12055 } else {
12056 ret = -TARGET_EFAULT;
12057 }
12058 unlock_user(p, arg1, 0);
12059 unlock_user(n, arg2, 0);
12060 }
72eb7ea8 12061 return ret;
30297b55
PM
12062 case TARGET_NR_fremovexattr:
12063 {
12064 void *n;
12065 n = lock_user_string(arg2);
12066 if (n) {
12067 ret = get_errno(fremovexattr(arg1, n));
12068 } else {
12069 ret = -TARGET_EFAULT;
12070 }
12071 unlock_user(n, arg2, 0);
12072 }
72eb7ea8 12073 return ret;
ebc05488 12074#endif
a790ae38 12075#endif /* CONFIG_ATTR */
ebc05488 12076#ifdef TARGET_NR_set_thread_area
5cd4393b 12077 case TARGET_NR_set_thread_area:
8d18e893 12078#if defined(TARGET_MIPS)
d279279e 12079 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
72eb7ea8 12080 return 0;
ef96779b
EI
12081#elif defined(TARGET_CRIS)
12082 if (arg1 & 0xff)
12083 ret = -TARGET_EINVAL;
12084 else {
12085 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
12086 ret = 0;
12087 }
72eb7ea8 12088 return ret;
8d18e893 12089#elif defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12090 return do_set_thread_area(cpu_env, arg1);
1ccd9374
PM
12091#elif defined(TARGET_M68K)
12092 {
0429a971 12093 TaskState *ts = cpu->opaque;
1ccd9374 12094 ts->tp_value = arg1;
72eb7ea8 12095 return 0;
1ccd9374 12096 }
6f5b89a0 12097#else
10f45d98 12098 return -TARGET_ENOSYS;
6f5b89a0
TS
12099#endif
12100#endif
12101#ifdef TARGET_NR_get_thread_area
5cd4393b 12102 case TARGET_NR_get_thread_area:
8d18e893 12103#if defined(TARGET_I386) && defined(TARGET_ABI32)
72eb7ea8 12104 return do_get_thread_area(cpu_env, arg1);
1ccd9374
PM
12105#elif defined(TARGET_M68K)
12106 {
0429a971 12107 TaskState *ts = cpu->opaque;
72eb7ea8 12108 return ts->tp_value;
1ccd9374 12109 }
8d18e893 12110#else
10f45d98 12111 return -TARGET_ENOSYS;
48dc41eb 12112#endif
8d18e893 12113#endif
48dc41eb
FB
12114#ifdef TARGET_NR_getdomainname
12115 case TARGET_NR_getdomainname:
10f45d98 12116 return -TARGET_ENOSYS;
ebc05488 12117#endif
6f5b89a0 12118
12e3340c
MF
12119#ifdef TARGET_NR_clock_settime
12120 case TARGET_NR_clock_settime:
12121 {
12122 struct timespec ts;
12123
12124 ret = target_to_host_timespec(&ts, arg2);
12125 if (!is_error(ret)) {
12126 ret = get_errno(clock_settime(arg1, &ts));
12127 }
72eb7ea8 12128 return ret;
12e3340c
MF
12129 }
12130#endif
c6c8d102
AF
12131#ifdef TARGET_NR_clock_settime64
12132 case TARGET_NR_clock_settime64:
12133 {
12134 struct timespec ts;
12135
12136 ret = target_to_host_timespec64(&ts, arg2);
12137 if (!is_error(ret)) {
12138 ret = get_errno(clock_settime(arg1, &ts));
12139 }
12140 return ret;
12141 }
12142#endif
b5906f95
TS
12143#ifdef TARGET_NR_clock_gettime
12144 case TARGET_NR_clock_gettime:
12145 {
12146 struct timespec ts;
12147 ret = get_errno(clock_gettime(arg1, &ts));
12148 if (!is_error(ret)) {
b9f9908e 12149 ret = host_to_target_timespec(arg2, &ts);
b5906f95 12150 }
72eb7ea8 12151 return ret;
b5906f95
TS
12152 }
12153#endif
c6c8d102
AF
12154#ifdef TARGET_NR_clock_gettime64
12155 case TARGET_NR_clock_gettime64:
12156 {
12157 struct timespec ts;
12158 ret = get_errno(clock_gettime(arg1, &ts));
12159 if (!is_error(ret)) {
12160 ret = host_to_target_timespec64(arg2, &ts);
12161 }
12162 return ret;
12163 }
12164#endif
b5906f95
TS
12165#ifdef TARGET_NR_clock_getres
12166 case TARGET_NR_clock_getres:
12167 {
12168 struct timespec ts;
12169 ret = get_errno(clock_getres(arg1, &ts));
12170 if (!is_error(ret)) {
12171 host_to_target_timespec(arg2, &ts);
12172 }
72eb7ea8 12173 return ret;
b5906f95
TS
12174 }
12175#endif
828cb3a1
FB
12176#ifdef TARGET_NR_clock_getres_time64
12177 case TARGET_NR_clock_getres_time64:
12178 {
12179 struct timespec ts;
12180 ret = get_errno(clock_getres(arg1, &ts));
12181 if (!is_error(ret)) {
12182 host_to_target_timespec64(arg2, &ts);
12183 }
12184 return ret;
12185 }
12186#endif
63d7651b
PB
12187#ifdef TARGET_NR_clock_nanosleep
12188 case TARGET_NR_clock_nanosleep:
12189 {
12190 struct timespec ts;
b09d6406
FB
12191 if (target_to_host_timespec(&ts, arg3)) {
12192 return -TARGET_EFAULT;
12193 }
9e518226
PM
12194 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12195 &ts, arg4 ? &ts : NULL));
8ec68a0a
LV
12196 /*
12197 * if the call is interrupted by a signal handler, it fails
12198 * with error -TARGET_EINTR and if arg4 is not NULL and arg2 is not
12199 * TIMER_ABSTIME, it returns the remaining unslept time in arg4.
12200 */
b09d6406
FB
12201 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12202 host_to_target_timespec(arg4, &ts)) {
12203 return -TARGET_EFAULT;
8ec68a0a 12204 }
8fbe8fdf 12205
72eb7ea8 12206 return ret;
63d7651b
PB
12207 }
12208#endif
6ac03b2c
FB
12209#ifdef TARGET_NR_clock_nanosleep_time64
12210 case TARGET_NR_clock_nanosleep_time64:
12211 {
12212 struct timespec ts;
12213
12214 if (target_to_host_timespec64(&ts, arg3)) {
12215 return -TARGET_EFAULT;
12216 }
12217
12218 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
12219 &ts, arg4 ? &ts : NULL));
12220
12221 if (ret == -TARGET_EINTR && arg4 && arg2 != TIMER_ABSTIME &&
12222 host_to_target_timespec64(arg4, &ts)) {
12223 return -TARGET_EFAULT;
12224 }
12225 return ret;
12226 }
12227#endif
b5906f95 12228
6f5b89a0
TS
12229#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
12230 case TARGET_NR_set_tid_address:
3e8f1628 12231 return get_errno(set_tid_address((int *)g2h(cpu, arg1)));
6f5b89a0
TS
12232#endif
12233
4cae1d16 12234 case TARGET_NR_tkill:
72eb7ea8 12235 return get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16 12236
71455574 12237 case TARGET_NR_tgkill:
72eb7ea8
RH
12238 return get_errno(safe_tgkill((int)arg1, (int)arg2,
12239 target_to_host_signal(arg3)));
71455574 12240
4f2b1fe8
TS
12241#ifdef TARGET_NR_set_robust_list
12242 case TARGET_NR_set_robust_list:
e9a970a8
PM
12243 case TARGET_NR_get_robust_list:
12244 /* The ABI for supporting robust futexes has userspace pass
12245 * the kernel a pointer to a linked list which is updated by
12246 * userspace after the syscall; the list is walked by the kernel
12247 * when the thread exits. Since the linked list in QEMU guest
12248 * memory isn't a valid linked list for the host and we have
12249 * no way to reliably intercept the thread-death event, we can't
12250 * support these. Silently return ENOSYS so that guest userspace
12251 * falls back to a non-robust futex implementation (which should
12252 * be OK except in the corner case of the guest crashing while
12253 * holding a mutex that is shared with another process via
12254 * shared memory).
12255 */
10f45d98 12256 return -TARGET_ENOSYS;
4f2b1fe8
TS
12257#endif
12258
1acae9f2 12259#if defined(TARGET_NR_utimensat)
9007f0ef
TS
12260 case TARGET_NR_utimensat:
12261 {
ebc996f3
RV
12262 struct timespec *tsp, ts[2];
12263 if (!arg3) {
12264 tsp = NULL;
12265 } else {
b3a3af70
FB
12266 if (target_to_host_timespec(ts, arg3)) {
12267 return -TARGET_EFAULT;
12268 }
12269 if (target_to_host_timespec(ts + 1, arg3 +
12270 sizeof(struct target_timespec))) {
12271 return -TARGET_EFAULT;
12272 }
ebc996f3
RV
12273 tsp = ts;
12274 }
9007f0ef 12275 if (!arg2)
ebc996f3 12276 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 12277 else {
579a97f7 12278 if (!(p = lock_user_string(arg2))) {
259841c1 12279 return -TARGET_EFAULT;
579a97f7 12280 }
ebc996f3 12281 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 12282 unlock_user(p, arg2, 0);
cac46eb0
FB
12283 }
12284 }
12285 return ret;
12286#endif
12287#ifdef TARGET_NR_utimensat_time64
12288 case TARGET_NR_utimensat_time64:
12289 {
12290 struct timespec *tsp, ts[2];
12291 if (!arg3) {
12292 tsp = NULL;
12293 } else {
12294 if (target_to_host_timespec64(ts, arg3)) {
12295 return -TARGET_EFAULT;
12296 }
12297 if (target_to_host_timespec64(ts + 1, arg3 +
12298 sizeof(struct target__kernel_timespec))) {
12299 return -TARGET_EFAULT;
12300 }
12301 tsp = ts;
12302 }
12303 if (!arg2)
12304 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
12305 else {
12306 p = lock_user_string(arg2);
12307 if (!p) {
12308 return -TARGET_EFAULT;
12309 }
12310 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
12311 unlock_user(p, arg2, 0);
9007f0ef
TS
12312 }
12313 }
72eb7ea8 12314 return ret;
9007f0ef 12315#endif
859e8a89 12316#ifdef TARGET_NR_futex
bd0c5661 12317 case TARGET_NR_futex:
3e8f1628 12318 return do_futex(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
859e8a89 12319#endif
14690296
AF
12320#ifdef TARGET_NR_futex_time64
12321 case TARGET_NR_futex_time64:
3e8f1628 12322 return do_futex_time64(cpu, arg1, arg2, arg3, arg4, arg5, arg6);
14690296 12323#endif
33f53ac5
PB
12324#ifdef CONFIG_INOTIFY
12325#if defined(TARGET_NR_inotify_init)
39b59763 12326 case TARGET_NR_inotify_init:
33f53ac5 12327 ret = get_errno(inotify_init());
b929f7e5
PMD
12328 if (ret >= 0) {
12329 fd_trans_register(ret, &target_inotify_trans);
12330 }
72eb7ea8 12331 return ret;
39b59763 12332#endif
33f53ac5 12333#if defined(TARGET_NR_inotify_init1) && defined(CONFIG_INOTIFY1)
c05c7a73 12334 case TARGET_NR_inotify_init1:
33f53ac5 12335 ret = get_errno(inotify_init1(target_to_host_bitmask(arg1,
fea243e9 12336 fcntl_flags_tbl)));
b929f7e5
PMD
12337 if (ret >= 0) {
12338 fd_trans_register(ret, &target_inotify_trans);
12339 }
72eb7ea8 12340 return ret;
c05c7a73 12341#endif
33f53ac5 12342#if defined(TARGET_NR_inotify_add_watch)
39b59763
AJ
12343 case TARGET_NR_inotify_add_watch:
12344 p = lock_user_string(arg2);
33f53ac5 12345 ret = get_errno(inotify_add_watch(arg1, path(p), arg3));
39b59763 12346 unlock_user(p, arg2, 0);
72eb7ea8 12347 return ret;
39b59763 12348#endif
33f53ac5 12349#if defined(TARGET_NR_inotify_rm_watch)
39b59763 12350 case TARGET_NR_inotify_rm_watch:
33f53ac5
PB
12351 return get_errno(inotify_rm_watch(arg1, arg2));
12352#endif
39b59763 12353#endif
9007f0ef 12354
8ec9cf89 12355#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
12356 case TARGET_NR_mq_open:
12357 {
c7536ab6 12358 struct mq_attr posix_mq_attr;
26400775 12359 struct mq_attr *pposix_mq_attr;
c7536ab6 12360 int host_flags;
24e1003a 12361
c7536ab6 12362 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
26400775
LD
12363 pposix_mq_attr = NULL;
12364 if (arg4) {
12365 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
2852aafd 12366 return -TARGET_EFAULT;
26400775
LD
12367 }
12368 pposix_mq_attr = &posix_mq_attr;
c7536ab6 12369 }
24e1003a 12370 p = lock_user_string(arg1 - 1);
c7536ab6 12371 if (!p) {
2852aafd 12372 return -TARGET_EFAULT;
b6ce1f6b 12373 }
26400775 12374 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
24e1003a
AJ
12375 unlock_user (p, arg1, 0);
12376 }
72eb7ea8 12377 return ret;
24e1003a
AJ
12378
12379 case TARGET_NR_mq_unlink:
12380 p = lock_user_string(arg1 - 1);
3211215e 12381 if (!p) {
72eb7ea8 12382 return -TARGET_EFAULT;
3211215e 12383 }
24e1003a
AJ
12384 ret = get_errno(mq_unlink(p));
12385 unlock_user (p, arg1, 0);
72eb7ea8 12386 return ret;
24e1003a 12387
859e8a89 12388#ifdef TARGET_NR_mq_timedsend
24e1003a
AJ
12389 case TARGET_NR_mq_timedsend:
12390 {
12391 struct timespec ts;
12392
12393 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12394 if (arg5 != 0) {
dcbcf5cf
FB
12395 if (target_to_host_timespec(&ts, arg5)) {
12396 return -TARGET_EFAULT;
12397 }
d40ecd66 12398 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
dcbcf5cf
FB
12399 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12400 return -TARGET_EFAULT;
12401 }
d40ecd66
PM
12402 } else {
12403 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
24e1003a 12404 }
24e1003a
AJ
12405 unlock_user (p, arg2, arg3);
12406 }
72eb7ea8 12407 return ret;
859e8a89 12408#endif
d107e375
FB
12409#ifdef TARGET_NR_mq_timedsend_time64
12410 case TARGET_NR_mq_timedsend_time64:
12411 {
12412 struct timespec ts;
12413
12414 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12415 if (arg5 != 0) {
12416 if (target_to_host_timespec64(&ts, arg5)) {
12417 return -TARGET_EFAULT;
12418 }
12419 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
12420 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12421 return -TARGET_EFAULT;
12422 }
12423 } else {
12424 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
12425 }
12426 unlock_user(p, arg2, arg3);
12427 }
12428 return ret;
12429#endif
24e1003a 12430
859e8a89 12431#ifdef TARGET_NR_mq_timedreceive
24e1003a
AJ
12432 case TARGET_NR_mq_timedreceive:
12433 {
12434 struct timespec ts;
12435 unsigned int prio;
12436
12437 p = lock_user (VERIFY_READ, arg2, arg3, 1);
12438 if (arg5 != 0) {
dcbcf5cf
FB
12439 if (target_to_host_timespec(&ts, arg5)) {
12440 return -TARGET_EFAULT;
12441 }
d40ecd66
PM
12442 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12443 &prio, &ts));
dcbcf5cf
FB
12444 if (!is_error(ret) && host_to_target_timespec(arg5, &ts)) {
12445 return -TARGET_EFAULT;
12446 }
d40ecd66
PM
12447 } else {
12448 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12449 &prio, NULL));
24e1003a 12450 }
24e1003a
AJ
12451 unlock_user (p, arg2, arg3);
12452 if (arg4 != 0)
12453 put_user_u32(prio, arg4);
12454 }
72eb7ea8 12455 return ret;
859e8a89 12456#endif
d107e375
FB
12457#ifdef TARGET_NR_mq_timedreceive_time64
12458 case TARGET_NR_mq_timedreceive_time64:
12459 {
12460 struct timespec ts;
12461 unsigned int prio;
12462
12463 p = lock_user(VERIFY_READ, arg2, arg3, 1);
12464 if (arg5 != 0) {
12465 if (target_to_host_timespec64(&ts, arg5)) {
12466 return -TARGET_EFAULT;
12467 }
12468 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12469 &prio, &ts));
12470 if (!is_error(ret) && host_to_target_timespec64(arg5, &ts)) {
12471 return -TARGET_EFAULT;
12472 }
12473 } else {
12474 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
12475 &prio, NULL));
12476 }
12477 unlock_user(p, arg2, arg3);
12478 if (arg4 != 0) {
12479 put_user_u32(prio, arg4);
12480 }
12481 }
12482 return ret;
12483#endif
24e1003a
AJ
12484
12485 /* Not implemented for now... */
12486/* case TARGET_NR_mq_notify: */
12487/* break; */
12488
12489 case TARGET_NR_mq_getsetattr:
12490 {
12491 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
12492 ret = 0;
24e1003a
AJ
12493 if (arg2 != 0) {
12494 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
a23ea409
MF
12495 ret = get_errno(mq_setattr(arg1, &posix_mq_attr_in,
12496 &posix_mq_attr_out));
12497 } else if (arg3 != 0) {
12498 ret = get_errno(mq_getattr(arg1, &posix_mq_attr_out));
12499 }
12500 if (ret == 0 && arg3 != 0) {
12501 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
24e1003a 12502 }
24e1003a 12503 }
72eb7ea8 12504 return ret;
24e1003a
AJ
12505#endif
12506
3ce34dfb
VS
12507#ifdef CONFIG_SPLICE
12508#ifdef TARGET_NR_tee
12509 case TARGET_NR_tee:
12510 {
12511 ret = get_errno(tee(arg1,arg2,arg3,arg4));
12512 }
72eb7ea8 12513 return ret;
3ce34dfb
VS
12514#endif
12515#ifdef TARGET_NR_splice
12516 case TARGET_NR_splice:
12517 {
12518 loff_t loff_in, loff_out;
12519 loff_t *ploff_in = NULL, *ploff_out = NULL;
17644b36
AS
12520 if (arg2) {
12521 if (get_user_u64(loff_in, arg2)) {
2852aafd 12522 return -TARGET_EFAULT;
17644b36 12523 }
3ce34dfb
VS
12524 ploff_in = &loff_in;
12525 }
17644b36
AS
12526 if (arg4) {
12527 if (get_user_u64(loff_out, arg4)) {
2852aafd 12528 return -TARGET_EFAULT;
17644b36 12529 }
3ce34dfb
VS
12530 ploff_out = &loff_out;
12531 }
12532 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
17644b36
AS
12533 if (arg2) {
12534 if (put_user_u64(loff_in, arg2)) {
2852aafd 12535 return -TARGET_EFAULT;
17644b36
AS
12536 }
12537 }
12538 if (arg4) {
12539 if (put_user_u64(loff_out, arg4)) {
2852aafd 12540 return -TARGET_EFAULT;
17644b36
AS
12541 }
12542 }
3ce34dfb 12543 }
72eb7ea8 12544 return ret;
3ce34dfb
VS
12545#endif
12546#ifdef TARGET_NR_vmsplice
12547 case TARGET_NR_vmsplice:
12548 {
f287b2c2
RH
12549 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
12550 if (vec != NULL) {
12551 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
12552 unlock_iovec(vec, arg2, arg3, 0);
12553 } else {
12554 ret = -host_to_target_errno(errno);
12555 }
3ce34dfb 12556 }
72eb7ea8 12557 return ret;
3ce34dfb
VS
12558#endif
12559#endif /* CONFIG_SPLICE */
c2882b96
RV
12560#ifdef CONFIG_EVENTFD
12561#if defined(TARGET_NR_eventfd)
12562 case TARGET_NR_eventfd:
12563 ret = get_errno(eventfd(arg1, 0));
b929f7e5
PMD
12564 if (ret >= 0) {
12565 fd_trans_register(ret, &target_eventfd_trans);
12566 }
72eb7ea8 12567 return ret;
c2882b96
RV
12568#endif
12569#if defined(TARGET_NR_eventfd2)
12570 case TARGET_NR_eventfd2:
5947c697 12571 {
78721301 12572 int host_flags = arg2 & (~(TARGET_O_NONBLOCK_MASK | TARGET_O_CLOEXEC));
5947c697
PJ
12573 if (arg2 & TARGET_O_NONBLOCK) {
12574 host_flags |= O_NONBLOCK;
12575 }
12576 if (arg2 & TARGET_O_CLOEXEC) {
12577 host_flags |= O_CLOEXEC;
12578 }
12579 ret = get_errno(eventfd(arg1, host_flags));
b929f7e5
PMD
12580 if (ret >= 0) {
12581 fd_trans_register(ret, &target_eventfd_trans);
12582 }
72eb7ea8 12583 return ret;
5947c697 12584 }
c2882b96
RV
12585#endif
12586#endif /* CONFIG_EVENTFD */
d0927938
UH
12587#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
12588 case TARGET_NR_fallocate:
20249ae1
AG
12589#if TARGET_ABI_BITS == 32
12590 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12591 target_offset64(arg5, arg6)));
12592#else
d0927938 12593 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 12594#endif
72eb7ea8 12595 return ret;
c727f47d
PM
12596#endif
12597#if defined(CONFIG_SYNC_FILE_RANGE)
12598#if defined(TARGET_NR_sync_file_range)
12599 case TARGET_NR_sync_file_range:
12600#if TARGET_ABI_BITS == 32
bfcedc57
RV
12601#if defined(TARGET_MIPS)
12602 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12603 target_offset64(arg5, arg6), arg7));
12604#else
c727f47d
PM
12605 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12606 target_offset64(arg4, arg5), arg6));
bfcedc57 12607#endif /* !TARGET_MIPS */
c727f47d
PM
12608#else
12609 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12610#endif
72eb7ea8 12611 return ret;
c727f47d 12612#endif
5bcb4986
LV
12613#if defined(TARGET_NR_sync_file_range2) || \
12614 defined(TARGET_NR_arm_sync_file_range)
c727f47d
PM
12615#if defined(TARGET_NR_sync_file_range2)
12616 case TARGET_NR_sync_file_range2:
5bcb4986
LV
12617#endif
12618#if defined(TARGET_NR_arm_sync_file_range)
12619 case TARGET_NR_arm_sync_file_range:
12620#endif
c727f47d
PM
12621 /* This is like sync_file_range but the arguments are reordered */
12622#if TARGET_ABI_BITS == 32
12623 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12624 target_offset64(arg5, arg6), arg2));
12625#else
12626 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12627#endif
72eb7ea8 12628 return ret;
c727f47d 12629#endif
3b6edd16 12630#endif
e36800c9
LV
12631#if defined(TARGET_NR_signalfd4)
12632 case TARGET_NR_signalfd4:
72eb7ea8 12633 return do_signalfd4(arg1, arg2, arg4);
e36800c9
LV
12634#endif
12635#if defined(TARGET_NR_signalfd)
12636 case TARGET_NR_signalfd:
72eb7ea8 12637 return do_signalfd4(arg1, arg2, 0);
e36800c9 12638#endif
3b6edd16
PM
12639#if defined(CONFIG_EPOLL)
12640#if defined(TARGET_NR_epoll_create)
12641 case TARGET_NR_epoll_create:
72eb7ea8 12642 return get_errno(epoll_create(arg1));
3b6edd16
PM
12643#endif
12644#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12645 case TARGET_NR_epoll_create1:
386d3865 12646 return get_errno(epoll_create1(target_to_host_bitmask(arg1, fcntl_flags_tbl)));
3b6edd16
PM
12647#endif
12648#if defined(TARGET_NR_epoll_ctl)
12649 case TARGET_NR_epoll_ctl:
12650 {
12651 struct epoll_event ep;
12652 struct epoll_event *epp = 0;
12653 if (arg4) {
c7811022
L
12654 if (arg2 != EPOLL_CTL_DEL) {
12655 struct target_epoll_event *target_ep;
12656 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12657 return -TARGET_EFAULT;
12658 }
12659 ep.events = tswap32(target_ep->events);
12660 /*
12661 * The epoll_data_t union is just opaque data to the kernel,
12662 * so we transfer all 64 bits across and need not worry what
12663 * actual data type it is.
12664 */
12665 ep.data.u64 = tswap64(target_ep->data.u64);
12666 unlock_user_struct(target_ep, arg4, 0);
3b6edd16 12667 }
c7811022
L
12668 /*
12669 * before kernel 2.6.9, EPOLL_CTL_DEL operation required a
12670 * non-null pointer, even though this argument is ignored.
12671 *
3b6edd16 12672 */
3b6edd16
PM
12673 epp = &ep;
12674 }
72eb7ea8 12675 return get_errno(epoll_ctl(arg1, arg2, arg3, epp));
3b6edd16
PM
12676 }
12677#endif
12678
227f0214 12679#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12680#if defined(TARGET_NR_epoll_wait)
12681 case TARGET_NR_epoll_wait:
12682#endif
227f0214 12683#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12684 case TARGET_NR_epoll_pwait:
12685#endif
12686 {
12687 struct target_epoll_event *target_ep;
12688 struct epoll_event *ep;
12689 int epfd = arg1;
12690 int maxevents = arg3;
12691 int timeout = arg4;
12692
2ba7fae3 12693 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
72eb7ea8 12694 return -TARGET_EINVAL;
2ba7fae3
PM
12695 }
12696
3b6edd16
PM
12697 target_ep = lock_user(VERIFY_WRITE, arg2,
12698 maxevents * sizeof(struct target_epoll_event), 1);
12699 if (!target_ep) {
2852aafd 12700 return -TARGET_EFAULT;
3b6edd16
PM
12701 }
12702
04c95f4d
PM
12703 ep = g_try_new(struct epoll_event, maxevents);
12704 if (!ep) {
12705 unlock_user(target_ep, arg2, 0);
72eb7ea8 12706 return -TARGET_ENOMEM;
04c95f4d 12707 }
3b6edd16
PM
12708
12709 switch (num) {
227f0214 12710#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12711 case TARGET_NR_epoll_pwait:
12712 {
12713 target_sigset_t *target_set;
12714 sigset_t _set, *set = &_set;
12715
12716 if (arg5) {
c815701e
PM
12717 if (arg6 != sizeof(target_sigset_t)) {
12718 ret = -TARGET_EINVAL;
12719 break;
12720 }
12721
3b6edd16
PM
12722 target_set = lock_user(VERIFY_READ, arg5,
12723 sizeof(target_sigset_t), 1);
12724 if (!target_set) {
04c95f4d
PM
12725 ret = -TARGET_EFAULT;
12726 break;
3b6edd16
PM
12727 }
12728 target_to_host_sigset(set, target_set);
12729 unlock_user(target_set, arg5, 0);
12730 } else {
12731 set = NULL;
12732 }
12733
227f0214
PM
12734 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12735 set, SIGSET_T_SIZE));
3b6edd16
PM
12736 break;
12737 }
12738#endif
12739#if defined(TARGET_NR_epoll_wait)
12740 case TARGET_NR_epoll_wait:
227f0214
PM
12741 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12742 NULL, 0));
3b6edd16
PM
12743 break;
12744#endif
12745 default:
12746 ret = -TARGET_ENOSYS;
12747 }
12748 if (!is_error(ret)) {
12749 int i;
12750 for (i = 0; i < ret; i++) {
12751 target_ep[i].events = tswap32(ep[i].events);
12752 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12753 }
04c95f4d
PM
12754 unlock_user(target_ep, arg2,
12755 ret * sizeof(struct target_epoll_event));
12756 } else {
12757 unlock_user(target_ep, arg2, 0);
3b6edd16 12758 }
04c95f4d 12759 g_free(ep);
72eb7ea8 12760 return ret;
3b6edd16
PM
12761 }
12762#endif
163a05a8
PM
12763#endif
12764#ifdef TARGET_NR_prlimit64
12765 case TARGET_NR_prlimit64:
12766 {
12767 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12768 struct target_rlimit64 *target_rnew, *target_rold;
12769 struct host_rlimit64 rnew, rold, *rnewp = 0;
95018018 12770 int resource = target_to_host_resource(arg2);
055d92f8
TK
12771
12772 if (arg3 && (resource != RLIMIT_AS &&
12773 resource != RLIMIT_DATA &&
12774 resource != RLIMIT_STACK)) {
163a05a8 12775 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
2852aafd 12776 return -TARGET_EFAULT;
163a05a8
PM
12777 }
12778 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12779 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12780 unlock_user_struct(target_rnew, arg3, 0);
12781 rnewp = &rnew;
12782 }
12783
95018018 12784 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
163a05a8
PM
12785 if (!is_error(ret) && arg4) {
12786 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
2852aafd 12787 return -TARGET_EFAULT;
163a05a8
PM
12788 }
12789 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12790 target_rold->rlim_max = tswap64(rold.rlim_max);
12791 unlock_user_struct(target_rold, arg4, 1);
12792 }
72eb7ea8 12793 return ret;
163a05a8 12794 }
3d21d29c
RH
12795#endif
12796#ifdef TARGET_NR_gethostname
12797 case TARGET_NR_gethostname:
12798 {
12799 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12800 if (name) {
12801 ret = get_errno(gethostname(name, arg2));
12802 unlock_user(name, arg1, arg2);
12803 } else {
12804 ret = -TARGET_EFAULT;
12805 }
72eb7ea8 12806 return ret;
3d21d29c 12807 }
89aaf1a6
RV
12808#endif
12809#ifdef TARGET_NR_atomic_cmpxchg_32
12810 case TARGET_NR_atomic_cmpxchg_32:
12811 {
12812 /* should use start_exclusive from main.c */
12813 abi_ulong mem_value;
12814 if (get_user_u32(mem_value, arg6)) {
12815 target_siginfo_t info;
12816 info.si_signo = SIGSEGV;
12817 info.si_errno = 0;
12818 info.si_code = TARGET_SEGV_MAPERR;
12819 info._sifields._sigfault._addr = arg6;
9d2803f7
PM
12820 queue_signal((CPUArchState *)cpu_env, info.si_signo,
12821 QEMU_SI_FAULT, &info);
89aaf1a6
RV
12822 ret = 0xdeadbeef;
12823
12824 }
12825 if (mem_value == arg2)
12826 put_user_u32(arg1, arg6);
72eb7ea8 12827 return mem_value;
89aaf1a6
RV
12828 }
12829#endif
12830#ifdef TARGET_NR_atomic_barrier
12831 case TARGET_NR_atomic_barrier:
72eb7ea8
RH
12832 /* Like the kernel implementation and the
12833 qemu arm barrier, no-op this? */
12834 return 0;
d0927938 12835#endif
f4f1e10a
ECL
12836
12837#ifdef TARGET_NR_timer_create
12838 case TARGET_NR_timer_create:
12839 {
12840 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12841
12842 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
f4f1e10a
ECL
12843
12844 int clkid = arg1;
12845 int timer_index = next_free_host_timer();
12846
12847 if (timer_index < 0) {
12848 ret = -TARGET_EAGAIN;
12849 } else {
12850 timer_t *phtimer = g_posix_timers + timer_index;
12851
12852 if (arg2) {
f4f1e10a 12853 phost_sevp = &host_sevp;
c065976f
PM
12854 ret = target_to_host_sigevent(phost_sevp, arg2);
12855 if (ret != 0) {
72eb7ea8 12856 return ret;
c065976f 12857 }
f4f1e10a
ECL
12858 }
12859
12860 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12861 if (ret) {
12862 phtimer = NULL;
12863 } else {
aecc8861 12864 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
2852aafd 12865 return -TARGET_EFAULT;
f4f1e10a 12866 }
f4f1e10a
ECL
12867 }
12868 }
72eb7ea8 12869 return ret;
f4f1e10a
ECL
12870 }
12871#endif
12872
12873#ifdef TARGET_NR_timer_settime
12874 case TARGET_NR_timer_settime:
12875 {
12876 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12877 * struct itimerspec * old_value */
aecc8861 12878 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12879
aecc8861
AG
12880 if (timerid < 0) {
12881 ret = timerid;
12882 } else if (arg3 == 0) {
f4f1e10a
ECL
12883 ret = -TARGET_EINVAL;
12884 } else {
e52a99f7 12885 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12886 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12887
40c80b5e 12888 if (target_to_host_itimerspec(&hspec_new, arg3)) {
2852aafd 12889 return -TARGET_EFAULT;
40c80b5e 12890 }
f4f1e10a
ECL
12891 ret = get_errno(
12892 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
40c80b5e 12893 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
2852aafd 12894 return -TARGET_EFAULT;
40c80b5e 12895 }
f4f1e10a 12896 }
72eb7ea8 12897 return ret;
f4f1e10a
ECL
12898 }
12899#endif
12900
828cb3a1
FB
12901#ifdef TARGET_NR_timer_settime64
12902 case TARGET_NR_timer_settime64:
12903 {
12904 target_timer_t timerid = get_timer_id(arg1);
12905
12906 if (timerid < 0) {
12907 ret = timerid;
12908 } else if (arg3 == 0) {
12909 ret = -TARGET_EINVAL;
12910 } else {
12911 timer_t htimer = g_posix_timers[timerid];
12912 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12913
12914 if (target_to_host_itimerspec64(&hspec_new, arg3)) {
12915 return -TARGET_EFAULT;
12916 }
12917 ret = get_errno(
12918 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
12919 if (arg4 && host_to_target_itimerspec64(arg4, &hspec_old)) {
12920 return -TARGET_EFAULT;
12921 }
12922 }
12923 return ret;
12924 }
12925#endif
12926
f4f1e10a
ECL
12927#ifdef TARGET_NR_timer_gettime
12928 case TARGET_NR_timer_gettime:
12929 {
12930 /* args: timer_t timerid, struct itimerspec *curr_value */
aecc8861 12931 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12932
aecc8861
AG
12933 if (timerid < 0) {
12934 ret = timerid;
12935 } else if (!arg2) {
12936 ret = -TARGET_EFAULT;
f4f1e10a 12937 } else {
e52a99f7 12938 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12939 struct itimerspec hspec;
12940 ret = get_errno(timer_gettime(htimer, &hspec));
12941
12942 if (host_to_target_itimerspec(arg2, &hspec)) {
12943 ret = -TARGET_EFAULT;
12944 }
12945 }
72eb7ea8 12946 return ret;
f4f1e10a
ECL
12947 }
12948#endif
12949
828cb3a1
FB
12950#ifdef TARGET_NR_timer_gettime64
12951 case TARGET_NR_timer_gettime64:
12952 {
12953 /* args: timer_t timerid, struct itimerspec64 *curr_value */
12954 target_timer_t timerid = get_timer_id(arg1);
12955
12956 if (timerid < 0) {
12957 ret = timerid;
12958 } else if (!arg2) {
12959 ret = -TARGET_EFAULT;
12960 } else {
12961 timer_t htimer = g_posix_timers[timerid];
12962 struct itimerspec hspec;
12963 ret = get_errno(timer_gettime(htimer, &hspec));
12964
12965 if (host_to_target_itimerspec64(arg2, &hspec)) {
12966 ret = -TARGET_EFAULT;
12967 }
12968 }
12969 return ret;
12970 }
12971#endif
12972
f4f1e10a
ECL
12973#ifdef TARGET_NR_timer_getoverrun
12974 case TARGET_NR_timer_getoverrun:
12975 {
12976 /* args: timer_t timerid */
aecc8861 12977 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12978
aecc8861
AG
12979 if (timerid < 0) {
12980 ret = timerid;
f4f1e10a 12981 } else {
e52a99f7 12982 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12983 ret = get_errno(timer_getoverrun(htimer));
12984 }
72eb7ea8 12985 return ret;
f4f1e10a
ECL
12986 }
12987#endif
12988
12989#ifdef TARGET_NR_timer_delete
12990 case TARGET_NR_timer_delete:
12991 {
12992 /* args: timer_t timerid */
aecc8861 12993 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12994
aecc8861
AG
12995 if (timerid < 0) {
12996 ret = timerid;
f4f1e10a 12997 } else {
e52a99f7 12998 timer_t htimer = g_posix_timers[timerid];
f4f1e10a 12999 ret = get_errno(timer_delete(htimer));
e52a99f7 13000 g_posix_timers[timerid] = 0;
f4f1e10a 13001 }
72eb7ea8 13002 return ret;
f4f1e10a
ECL
13003 }
13004#endif
13005
51834341
RV
13006#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
13007 case TARGET_NR_timerfd_create:
72eb7ea8
RH
13008 return get_errno(timerfd_create(arg1,
13009 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
51834341
RV
13010#endif
13011
13012#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
13013 case TARGET_NR_timerfd_gettime:
13014 {
13015 struct itimerspec its_curr;
13016
13017 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13018
13019 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
2852aafd 13020 return -TARGET_EFAULT;
51834341
RV
13021 }
13022 }
72eb7ea8 13023 return ret;
51834341
RV
13024#endif
13025
828cb3a1
FB
13026#if defined(TARGET_NR_timerfd_gettime64) && defined(CONFIG_TIMERFD)
13027 case TARGET_NR_timerfd_gettime64:
13028 {
13029 struct itimerspec its_curr;
13030
13031 ret = get_errno(timerfd_gettime(arg1, &its_curr));
13032
13033 if (arg2 && host_to_target_itimerspec64(arg2, &its_curr)) {
13034 return -TARGET_EFAULT;
13035 }
13036 }
13037 return ret;
13038#endif
13039
51834341
RV
13040#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
13041 case TARGET_NR_timerfd_settime:
13042 {
13043 struct itimerspec its_new, its_old, *p_new;
13044
13045 if (arg3) {
13046 if (target_to_host_itimerspec(&its_new, arg3)) {
2852aafd 13047 return -TARGET_EFAULT;
51834341
RV
13048 }
13049 p_new = &its_new;
13050 } else {
13051 p_new = NULL;
13052 }
13053
13054 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13055
13056 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
2852aafd 13057 return -TARGET_EFAULT;
51834341
RV
13058 }
13059 }
72eb7ea8 13060 return ret;
51834341
RV
13061#endif
13062
828cb3a1
FB
13063#if defined(TARGET_NR_timerfd_settime64) && defined(CONFIG_TIMERFD)
13064 case TARGET_NR_timerfd_settime64:
13065 {
13066 struct itimerspec its_new, its_old, *p_new;
13067
13068 if (arg3) {
13069 if (target_to_host_itimerspec64(&its_new, arg3)) {
13070 return -TARGET_EFAULT;
13071 }
13072 p_new = &its_new;
13073 } else {
13074 p_new = NULL;
13075 }
13076
13077 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
13078
13079 if (arg4 && host_to_target_itimerspec64(arg4, &its_old)) {
13080 return -TARGET_EFAULT;
13081 }
13082 }
13083 return ret;
13084#endif
13085
ab31cda3
PB
13086#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
13087 case TARGET_NR_ioprio_get:
72eb7ea8 13088 return get_errno(ioprio_get(arg1, arg2));
ab31cda3
PB
13089#endif
13090
13091#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
13092 case TARGET_NR_ioprio_set:
72eb7ea8 13093 return get_errno(ioprio_set(arg1, arg2, arg3));
ab31cda3
PB
13094#endif
13095
9af5c906
RV
13096#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
13097 case TARGET_NR_setns:
72eb7ea8 13098 return get_errno(setns(arg1, arg2));
9af5c906
RV
13099#endif
13100#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
13101 case TARGET_NR_unshare:
72eb7ea8 13102 return get_errno(unshare(arg1));
9af5c906 13103#endif
2f14788c
LV
13104#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
13105 case TARGET_NR_kcmp:
72eb7ea8 13106 return get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
2f14788c 13107#endif
fa97e38e
RH
13108#ifdef TARGET_NR_swapcontext
13109 case TARGET_NR_swapcontext:
13110 /* PowerPC specific. */
72eb7ea8 13111 return do_swapcontext(cpu_env, arg1, arg2, arg3);
fa97e38e 13112#endif
9bdfa4d2
SCW
13113#ifdef TARGET_NR_memfd_create
13114 case TARGET_NR_memfd_create:
13115 p = lock_user_string(arg1);
13116 if (!p) {
13117 return -TARGET_EFAULT;
13118 }
13119 ret = get_errno(memfd_create(p, arg2));
13120 fd_trans_unregister(ret);
13121 unlock_user(p, arg1, 0);
13122 return ret;
13123#endif
8500476f
AS
13124#if defined TARGET_NR_membarrier && defined __NR_membarrier
13125 case TARGET_NR_membarrier:
13126 return get_errno(membarrier(arg1, arg2));
13127#endif
9af5c906 13128
84946457
AS
13129#if defined(TARGET_NR_copy_file_range) && defined(__NR_copy_file_range)
13130 case TARGET_NR_copy_file_range:
13131 {
13132 loff_t inoff, outoff;
13133 loff_t *pinoff = NULL, *poutoff = NULL;
13134
13135 if (arg2) {
13136 if (get_user_u64(inoff, arg2)) {
13137 return -TARGET_EFAULT;
13138 }
13139 pinoff = &inoff;
13140 }
13141 if (arg4) {
13142 if (get_user_u64(outoff, arg4)) {
13143 return -TARGET_EFAULT;
13144 }
13145 poutoff = &outoff;
13146 }
0fa259dd 13147 /* Do not sign-extend the count parameter. */
84946457 13148 ret = get_errno(safe_copy_file_range(arg1, pinoff, arg3, poutoff,
0fa259dd 13149 (abi_ulong)arg5, arg6));
84946457
AS
13150 if (!is_error(ret) && ret > 0) {
13151 if (arg2) {
13152 if (put_user_u64(inoff, arg2)) {
13153 return -TARGET_EFAULT;
13154 }
13155 }
13156 if (arg4) {
13157 if (put_user_u64(outoff, arg4)) {
13158 return -TARGET_EFAULT;
13159 }
13160 }
13161 }
13162 }
13163 return ret;
13164#endif
13165
e10fbe8f
YT
13166#if defined(TARGET_NR_pivot_root)
13167 case TARGET_NR_pivot_root:
13168 {
13169 void *p2;
13170 p = lock_user_string(arg1); /* new_root */
13171 p2 = lock_user_string(arg2); /* put_old */
13172 if (!p || !p2) {
13173 ret = -TARGET_EFAULT;
13174 } else {
13175 ret = get_errno(pivot_root(p, p2));
13176 }
13177 unlock_user(p2, arg2, 0);
13178 unlock_user(p, arg1, 0);
13179 }
13180 return ret;
13181#endif
13182
31e31b8a 13183 default:
122f9c83 13184 qemu_log_mask(LOG_UNIMP, "Unsupported syscall: %d\n", num);
72eb7ea8 13185 return -TARGET_ENOSYS;
31e31b8a 13186 }
31e31b8a
FB
13187 return ret;
13188}
dc1ce18b
RH
13189
13190abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
13191 abi_long arg2, abi_long arg3, abi_long arg4,
13192 abi_long arg5, abi_long arg6, abi_long arg7,
13193 abi_long arg8)
13194{
29a0af61 13195 CPUState *cpu = env_cpu(cpu_env);
dc1ce18b
RH
13196 abi_long ret;
13197
13198#ifdef DEBUG_ERESTARTSYS
13199 /* Debug-only code for exercising the syscall-restart code paths
13200 * in the per-architecture cpu main loops: restart every syscall
13201 * the guest makes once before letting it through.
13202 */
13203 {
13204 static bool flag;
13205 flag = !flag;
13206 if (flag) {
af254a27 13207 return -QEMU_ERESTARTSYS;
dc1ce18b
RH
13208 }
13209 }
13210#endif
13211
c36f7a64
EC
13212 record_syscall_start(cpu, num, arg1,
13213 arg2, arg3, arg4, arg5, arg6, arg7, arg8);
dc1ce18b 13214
4b25a506 13215 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119 13216 print_syscall(cpu_env, num, arg1, arg2, arg3, arg4, arg5, arg6);
4b25a506
JK
13217 }
13218
13219 ret = do_syscall1(cpu_env, num, arg1, arg2, arg3, arg4,
13220 arg5, arg6, arg7, arg8);
13221
13222 if (unlikely(qemu_loglevel_mask(LOG_STRACE))) {
e400e119
FB
13223 print_syscall_ret(cpu_env, num, ret, arg1, arg2,
13224 arg3, arg4, arg5, arg6);
dc1ce18b
RH
13225 }
13226
c36f7a64 13227 record_syscall_return(cpu, num, ret);
dc1ce18b
RH
13228 return ret;
13229}