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