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