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