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