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