]> Git Repo - qemu.git/blame - linux-user/syscall.c
linux-user: wrap fork() in a start/end exclusive section
[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);
a4dd3d51 6261 /* Wait until the parent has finished initializing the tls state. */
d865bab5
PB
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 8581#if defined(TARGET_ALPHA)
78bfef72
PM
8582 /* For Alpha and SPARC this is a 5 argument syscall, with
8583 * a 'restorer' parameter which must be copied into the
8584 * sa_restorer field of the sigaction struct.
8585 * For Alpha that 'restorer' is arg5; for SPARC it is arg4,
8586 * and arg5 is the sigsetsize.
8587 * Alpha also has a separate rt_sigaction struct that it uses
8588 * here; SPARC uses the usual sigaction struct.
8589 */
6049f4f8 8590 struct target_rt_sigaction *rt_act;
78bfef72 8591 struct target_sigaction act, oact, *pact = 0;
c815701e
PM
8592
8593 if (arg4 != sizeof(target_sigset_t)) {
8594 ret = -TARGET_EINVAL;
8595 break;
8596 }
6049f4f8
RH
8597 if (arg2) {
8598 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
8599 goto efault;
8600 act._sa_handler = rt_act->_sa_handler;
8601 act.sa_mask = rt_act->sa_mask;
8602 act.sa_flags = rt_act->sa_flags;
8603 act.sa_restorer = arg5;
8604 unlock_user_struct(rt_act, arg2, 0);
8605 pact = &act;
8606 }
8607 ret = get_errno(do_sigaction(arg1, pact, &oact));
8608 if (!is_error(ret) && arg3) {
8609 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
8610 goto efault;
8611 rt_act->_sa_handler = oact._sa_handler;
8612 rt_act->sa_mask = oact.sa_mask;
8613 rt_act->sa_flags = oact.sa_flags;
8614 unlock_user_struct(rt_act, arg3, 1);
8615 }
8616#else
78bfef72
PM
8617#ifdef TARGET_SPARC
8618 target_ulong restorer = arg4;
8619 target_ulong sigsetsize = arg5;
8620#else
8621 target_ulong sigsetsize = arg4;
8622#endif
53a5960a
PB
8623 struct target_sigaction *act;
8624 struct target_sigaction *oact;
8625
78bfef72 8626 if (sigsetsize != sizeof(target_sigset_t)) {
c815701e
PM
8627 ret = -TARGET_EINVAL;
8628 break;
8629 }
579a97f7 8630 if (arg2) {
78bfef72 8631 if (!lock_user_struct(VERIFY_READ, act, arg2, 1)) {
579a97f7 8632 goto efault;
78bfef72
PM
8633 }
8634#ifdef TARGET_SPARC
8635 act->sa_restorer = restorer;
8636#endif
8637 } else {
53a5960a 8638 act = NULL;
78bfef72 8639 }
579a97f7
FB
8640 if (arg3) {
8641 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
8642 ret = -TARGET_EFAULT;
8643 goto rt_sigaction_fail;
8644 }
8645 } else
53a5960a
PB
8646 oact = NULL;
8647 ret = get_errno(do_sigaction(arg1, act, oact));
579a97f7
FB
8648 rt_sigaction_fail:
8649 if (act)
53a5960a 8650 unlock_user_struct(act, arg2, 0);
579a97f7 8651 if (oact)
53a5960a 8652 unlock_user_struct(oact, arg3, 1);
6049f4f8 8653#endif
53a5960a 8654 }
66fb9763 8655 break;
7a3148a9 8656#ifdef TARGET_NR_sgetmask /* not on alpha */
31e31b8a 8657 case TARGET_NR_sgetmask:
66fb9763
FB
8658 {
8659 sigset_t cur_set;
992f48a0 8660 abi_ulong target_set;
3d3efba0
PM
8661 ret = do_sigprocmask(0, NULL, &cur_set);
8662 if (!ret) {
8663 host_to_target_old_sigset(&target_set, &cur_set);
8664 ret = target_set;
8665 }
66fb9763
FB
8666 }
8667 break;
7a3148a9
JM
8668#endif
8669#ifdef TARGET_NR_ssetmask /* not on alpha */
31e31b8a 8670 case TARGET_NR_ssetmask:
66fb9763 8671 {
a8617d8c 8672 sigset_t set, oset;
992f48a0 8673 abi_ulong target_set = arg1;
66fb9763 8674 target_to_host_old_sigset(&set, &target_set);
3d3efba0
PM
8675 ret = do_sigprocmask(SIG_SETMASK, &set, &oset);
8676 if (!ret) {
8677 host_to_target_old_sigset(&target_set, &oset);
8678 ret = target_set;
8679 }
66fb9763
FB
8680 }
8681 break;
7a3148a9 8682#endif
e5febef5 8683#ifdef TARGET_NR_sigprocmask
66fb9763
FB
8684 case TARGET_NR_sigprocmask:
8685 {
a5b3b13b
RH
8686#if defined(TARGET_ALPHA)
8687 sigset_t set, oldset;
8688 abi_ulong mask;
8689 int how;
8690
8691 switch (arg1) {
8692 case TARGET_SIG_BLOCK:
8693 how = SIG_BLOCK;
8694 break;
8695 case TARGET_SIG_UNBLOCK:
8696 how = SIG_UNBLOCK;
8697 break;
8698 case TARGET_SIG_SETMASK:
8699 how = SIG_SETMASK;
8700 break;
8701 default:
8702 ret = -TARGET_EINVAL;
8703 goto fail;
8704 }
8705 mask = arg2;
8706 target_to_host_old_sigset(&set, &mask);
8707
3d3efba0 8708 ret = do_sigprocmask(how, &set, &oldset);
a5b3b13b
RH
8709 if (!is_error(ret)) {
8710 host_to_target_old_sigset(&mask, &oldset);
8711 ret = mask;
0229f5a3 8712 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0; /* force no error */
a5b3b13b
RH
8713 }
8714#else
66fb9763 8715 sigset_t set, oldset, *set_ptr;
a5b3b13b 8716 int how;
3b46e624 8717
53a5960a 8718 if (arg2) {
a5b3b13b 8719 switch (arg1) {
66fb9763
FB
8720 case TARGET_SIG_BLOCK:
8721 how = SIG_BLOCK;
8722 break;
8723 case TARGET_SIG_UNBLOCK:
8724 how = SIG_UNBLOCK;
8725 break;
8726 case TARGET_SIG_SETMASK:
8727 how = SIG_SETMASK;
8728 break;
8729 default:
0da46a6e 8730 ret = -TARGET_EINVAL;
66fb9763
FB
8731 goto fail;
8732 }
c227f099 8733 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 8734 goto efault;
53a5960a
PB
8735 target_to_host_old_sigset(&set, p);
8736 unlock_user(p, arg2, 0);
66fb9763
FB
8737 set_ptr = &set;
8738 } else {
8739 how = 0;
8740 set_ptr = NULL;
8741 }
3d3efba0 8742 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 8743 if (!is_error(ret) && arg3) {
c227f099 8744 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 8745 goto efault;
53a5960a 8746 host_to_target_old_sigset(p, &oldset);
c227f099 8747 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763 8748 }
a5b3b13b 8749#endif
66fb9763
FB
8750 }
8751 break;
e5febef5 8752#endif
66fb9763
FB
8753 case TARGET_NR_rt_sigprocmask:
8754 {
8755 int how = arg1;
8756 sigset_t set, oldset, *set_ptr;
3b46e624 8757
c815701e
PM
8758 if (arg4 != sizeof(target_sigset_t)) {
8759 ret = -TARGET_EINVAL;
8760 break;
8761 }
8762
53a5960a 8763 if (arg2) {
66fb9763
FB
8764 switch(how) {
8765 case TARGET_SIG_BLOCK:
8766 how = SIG_BLOCK;
8767 break;
8768 case TARGET_SIG_UNBLOCK:
8769 how = SIG_UNBLOCK;
8770 break;
8771 case TARGET_SIG_SETMASK:
8772 how = SIG_SETMASK;
8773 break;
8774 default:
0da46a6e 8775 ret = -TARGET_EINVAL;
66fb9763
FB
8776 goto fail;
8777 }
c227f099 8778 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
579a97f7 8779 goto efault;
53a5960a
PB
8780 target_to_host_sigset(&set, p);
8781 unlock_user(p, arg2, 0);
66fb9763
FB
8782 set_ptr = &set;
8783 } else {
8784 how = 0;
8785 set_ptr = NULL;
8786 }
3d3efba0 8787 ret = do_sigprocmask(how, set_ptr, &oldset);
53a5960a 8788 if (!is_error(ret) && arg3) {
c227f099 8789 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
579a97f7 8790 goto efault;
53a5960a 8791 host_to_target_sigset(p, &oldset);
c227f099 8792 unlock_user(p, arg3, sizeof(target_sigset_t));
66fb9763
FB
8793 }
8794 }
8795 break;
e5febef5 8796#ifdef TARGET_NR_sigpending
66fb9763
FB
8797 case TARGET_NR_sigpending:
8798 {
8799 sigset_t set;
8800 ret = get_errno(sigpending(&set));
8801 if (!is_error(ret)) {
c227f099 8802 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 8803 goto efault;
53a5960a 8804 host_to_target_old_sigset(p, &set);
c227f099 8805 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
8806 }
8807 }
8808 break;
e5febef5 8809#endif
66fb9763
FB
8810 case TARGET_NR_rt_sigpending:
8811 {
8812 sigset_t set;
c815701e
PM
8813
8814 /* Yes, this check is >, not != like most. We follow the kernel's
8815 * logic and it does it like this because it implements
8816 * NR_sigpending through the same code path, and in that case
8817 * the old_sigset_t is smaller in size.
8818 */
8819 if (arg2 > sizeof(target_sigset_t)) {
8820 ret = -TARGET_EINVAL;
8821 break;
8822 }
8823
66fb9763
FB
8824 ret = get_errno(sigpending(&set));
8825 if (!is_error(ret)) {
c227f099 8826 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
579a97f7 8827 goto efault;
53a5960a 8828 host_to_target_sigset(p, &set);
c227f099 8829 unlock_user(p, arg1, sizeof(target_sigset_t));
66fb9763
FB
8830 }
8831 }
8832 break;
e5febef5 8833#ifdef TARGET_NR_sigsuspend
66fb9763
FB
8834 case TARGET_NR_sigsuspend:
8835 {
3d3efba0 8836 TaskState *ts = cpu->opaque;
f43ce12b
RH
8837#if defined(TARGET_ALPHA)
8838 abi_ulong mask = arg1;
3d3efba0 8839 target_to_host_old_sigset(&ts->sigsuspend_mask, &mask);
f43ce12b 8840#else
c227f099 8841 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 8842 goto efault;
3d3efba0 8843 target_to_host_old_sigset(&ts->sigsuspend_mask, p);
53a5960a 8844 unlock_user(p, arg1, 0);
f43ce12b 8845#endif
3d3efba0
PM
8846 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8847 SIGSET_T_SIZE));
8848 if (ret != -TARGET_ERESTARTSYS) {
8849 ts->in_sigsuspend = 1;
8850 }
66fb9763
FB
8851 }
8852 break;
e5febef5 8853#endif
66fb9763
FB
8854 case TARGET_NR_rt_sigsuspend:
8855 {
3d3efba0 8856 TaskState *ts = cpu->opaque;
c815701e
PM
8857
8858 if (arg2 != sizeof(target_sigset_t)) {
8859 ret = -TARGET_EINVAL;
8860 break;
8861 }
c227f099 8862 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 8863 goto efault;
3d3efba0 8864 target_to_host_sigset(&ts->sigsuspend_mask, p);
53a5960a 8865 unlock_user(p, arg1, 0);
3d3efba0
PM
8866 ret = get_errno(safe_rt_sigsuspend(&ts->sigsuspend_mask,
8867 SIGSET_T_SIZE));
8868 if (ret != -TARGET_ERESTARTSYS) {
8869 ts->in_sigsuspend = 1;
8870 }
66fb9763
FB
8871 }
8872 break;
8873 case TARGET_NR_rt_sigtimedwait:
8874 {
66fb9763
FB
8875 sigset_t set;
8876 struct timespec uts, *puts;
8877 siginfo_t uinfo;
3b46e624 8878
c815701e
PM
8879 if (arg4 != sizeof(target_sigset_t)) {
8880 ret = -TARGET_EINVAL;
8881 break;
8882 }
8883
c227f099 8884 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
579a97f7 8885 goto efault;
53a5960a
PB
8886 target_to_host_sigset(&set, p);
8887 unlock_user(p, arg1, 0);
8888 if (arg3) {
66fb9763 8889 puts = &uts;
53a5960a 8890 target_to_host_timespec(puts, arg3);
66fb9763
FB
8891 } else {
8892 puts = NULL;
8893 }
b3f82330
PM
8894 ret = get_errno(safe_rt_sigtimedwait(&set, &uinfo, puts,
8895 SIGSET_T_SIZE));
974a196d
PJ
8896 if (!is_error(ret)) {
8897 if (arg2) {
8898 p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t),
8899 0);
8900 if (!p) {
8901 goto efault;
8902 }
8903 host_to_target_siginfo(p, &uinfo);
8904 unlock_user(p, arg2, sizeof(target_siginfo_t));
8905 }
8906 ret = host_to_target_signal(ret);
66fb9763
FB
8907 }
8908 }
8909 break;
8910 case TARGET_NR_rt_sigqueueinfo:
8911 {
8912 siginfo_t uinfo;
4debae6f
PM
8913
8914 p = lock_user(VERIFY_READ, arg3, sizeof(target_siginfo_t), 1);
8915 if (!p) {
579a97f7 8916 goto efault;
4debae6f 8917 }
53a5960a 8918 target_to_host_siginfo(&uinfo, p);
d8b6d892 8919 unlock_user(p, arg3, 0);
66fb9763
FB
8920 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
8921 }
8922 break;
cf8b8bfc
MS
8923 case TARGET_NR_rt_tgsigqueueinfo:
8924 {
8925 siginfo_t uinfo;
8926
8927 p = lock_user(VERIFY_READ, arg4, sizeof(target_siginfo_t), 1);
8928 if (!p) {
8929 goto efault;
8930 }
8931 target_to_host_siginfo(&uinfo, p);
8932 unlock_user(p, arg4, 0);
8933 ret = get_errno(sys_rt_tgsigqueueinfo(arg1, arg2, arg3, &uinfo));
8934 }
8935 break;
e5febef5 8936#ifdef TARGET_NR_sigreturn
66fb9763 8937 case TARGET_NR_sigreturn:
3d3efba0
PM
8938 if (block_signals()) {
8939 ret = -TARGET_ERESTARTSYS;
8940 } else {
8941 ret = do_sigreturn(cpu_env);
8942 }
66fb9763 8943 break;
e5febef5 8944#endif
66fb9763 8945 case TARGET_NR_rt_sigreturn:
3d3efba0
PM
8946 if (block_signals()) {
8947 ret = -TARGET_ERESTARTSYS;
8948 } else {
8949 ret = do_rt_sigreturn(cpu_env);
8950 }
66fb9763 8951 break;
31e31b8a 8952 case TARGET_NR_sethostname:
579a97f7
FB
8953 if (!(p = lock_user_string(arg1)))
8954 goto efault;
53a5960a
PB
8955 ret = get_errno(sethostname(p, arg2));
8956 unlock_user(p, arg1, 0);
31e31b8a
FB
8957 break;
8958 case TARGET_NR_setrlimit:
9de5e440 8959 {
e22b7015 8960 int resource = target_to_host_resource(arg1);
53a5960a 8961 struct target_rlimit *target_rlim;
9de5e440 8962 struct rlimit rlim;
579a97f7
FB
8963 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
8964 goto efault;
81bbe906
TY
8965 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
8966 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
53a5960a 8967 unlock_user_struct(target_rlim, arg2, 0);
9de5e440
FB
8968 ret = get_errno(setrlimit(resource, &rlim));
8969 }
8970 break;
31e31b8a 8971 case TARGET_NR_getrlimit:
9de5e440 8972 {
e22b7015 8973 int resource = target_to_host_resource(arg1);
53a5960a 8974 struct target_rlimit *target_rlim;
9de5e440 8975 struct rlimit rlim;
3b46e624 8976
9de5e440
FB
8977 ret = get_errno(getrlimit(resource, &rlim));
8978 if (!is_error(ret)) {
579a97f7
FB
8979 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
8980 goto efault;
81bbe906
TY
8981 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
8982 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 8983 unlock_user_struct(target_rlim, arg2, 1);
9de5e440
FB
8984 }
8985 }
8986 break;
31e31b8a 8987 case TARGET_NR_getrusage:
b409186b
FB
8988 {
8989 struct rusage rusage;
b409186b
FB
8990 ret = get_errno(getrusage(arg1, &rusage));
8991 if (!is_error(ret)) {
a39fb273 8992 ret = host_to_target_rusage(arg2, &rusage);
b409186b
FB
8993 }
8994 }
8995 break;
31e31b8a
FB
8996 case TARGET_NR_gettimeofday:
8997 {
31e31b8a
FB
8998 struct timeval tv;
8999 ret = get_errno(gettimeofday(&tv, NULL));
9000 if (!is_error(ret)) {
788f5ec4
TS
9001 if (copy_to_user_timeval(arg1, &tv))
9002 goto efault;
31e31b8a
FB
9003 }
9004 }
9005 break;
9006 case TARGET_NR_settimeofday:
9007 {
b67d8031 9008 struct timeval tv, *ptv = NULL;
ef4467e9
PB
9009 struct timezone tz, *ptz = NULL;
9010
b67d8031
PB
9011 if (arg1) {
9012 if (copy_from_user_timeval(&tv, arg1)) {
9013 goto efault;
9014 }
9015 ptv = &tv;
9016 }
ef4467e9
PB
9017
9018 if (arg2) {
9019 if (copy_from_user_timezone(&tz, arg2)) {
9020 goto efault;
9021 }
9022 ptz = &tz;
9023 }
9024
b67d8031 9025 ret = get_errno(settimeofday(ptv, ptz));
31e31b8a
FB
9026 }
9027 break;
9468a5d4 9028#if defined(TARGET_NR_select)
31e31b8a 9029 case TARGET_NR_select:
5457dc9e
LV
9030#if defined(TARGET_WANT_NI_OLD_SELECT)
9031 /* some architectures used to have old_select here
9032 * but now ENOSYS it.
9033 */
9034 ret = -TARGET_ENOSYS;
9035#elif defined(TARGET_WANT_OLD_SYS_SELECT)
9036 ret = do_old_select(arg1);
9468a5d4 9037#else
5457dc9e 9038 ret = do_select(arg1, arg2, arg3, arg4, arg5);
9468a5d4 9039#endif
f2674e31 9040 break;
9e42382f
RV
9041#endif
9042#ifdef TARGET_NR_pselect6
9043 case TARGET_NR_pselect6:
055e0906
MF
9044 {
9045 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
9046 fd_set rfds, wfds, efds;
9047 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
9048 struct timespec ts, *ts_ptr;
9049
9050 /*
9051 * The 6th arg is actually two args smashed together,
9052 * so we cannot use the C library.
9053 */
9054 sigset_t set;
9055 struct {
9056 sigset_t *set;
9057 size_t size;
9058 } sig, *sig_ptr;
9059
9060 abi_ulong arg_sigset, arg_sigsize, *arg7;
9061 target_sigset_t *target_sigset;
9062
9063 n = arg1;
9064 rfd_addr = arg2;
9065 wfd_addr = arg3;
9066 efd_addr = arg4;
9067 ts_addr = arg5;
9068
9069 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
9070 if (ret) {
9071 goto fail;
9072 }
9073 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
9074 if (ret) {
9075 goto fail;
9076 }
9077 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
9078 if (ret) {
9079 goto fail;
9080 }
9081
9082 /*
9083 * This takes a timespec, and not a timeval, so we cannot
9084 * use the do_select() helper ...
9085 */
9086 if (ts_addr) {
9087 if (target_to_host_timespec(&ts, ts_addr)) {
9088 goto efault;
9089 }
9090 ts_ptr = &ts;
9091 } else {
9092 ts_ptr = NULL;
9093 }
9094
9095 /* Extract the two packed args for the sigset */
9096 if (arg6) {
9097 sig_ptr = &sig;
b28a1f33 9098 sig.size = SIGSET_T_SIZE;
055e0906
MF
9099
9100 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
9101 if (!arg7) {
9102 goto efault;
9103 }
cbb21eed
MB
9104 arg_sigset = tswapal(arg7[0]);
9105 arg_sigsize = tswapal(arg7[1]);
055e0906
MF
9106 unlock_user(arg7, arg6, 0);
9107
9108 if (arg_sigset) {
9109 sig.set = &set;
8f04eeb3
PM
9110 if (arg_sigsize != sizeof(*target_sigset)) {
9111 /* Like the kernel, we enforce correct size sigsets */
9112 ret = -TARGET_EINVAL;
9113 goto fail;
9114 }
055e0906
MF
9115 target_sigset = lock_user(VERIFY_READ, arg_sigset,
9116 sizeof(*target_sigset), 1);
9117 if (!target_sigset) {
9118 goto efault;
9119 }
9120 target_to_host_sigset(&set, target_sigset);
9121 unlock_user(target_sigset, arg_sigset, 0);
9122 } else {
9123 sig.set = NULL;
9124 }
9125 } else {
9126 sig_ptr = NULL;
9127 }
9128
6df9d38d
PM
9129 ret = get_errno(safe_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
9130 ts_ptr, sig_ptr));
055e0906
MF
9131
9132 if (!is_error(ret)) {
9133 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
9134 goto efault;
9135 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
9136 goto efault;
9137 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
9138 goto efault;
9139
9140 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
9141 goto efault;
9142 }
9143 }
9144 break;
048f6b4d 9145#endif
704eff6c 9146#ifdef TARGET_NR_symlink
31e31b8a 9147 case TARGET_NR_symlink:
53a5960a
PB
9148 {
9149 void *p2;
9150 p = lock_user_string(arg1);
9151 p2 = lock_user_string(arg2);
579a97f7
FB
9152 if (!p || !p2)
9153 ret = -TARGET_EFAULT;
9154 else
9155 ret = get_errno(symlink(p, p2));
53a5960a
PB
9156 unlock_user(p2, arg2, 0);
9157 unlock_user(p, arg1, 0);
9158 }
31e31b8a 9159 break;
704eff6c 9160#endif
c0d472b1 9161#if defined(TARGET_NR_symlinkat)
f0b6243d 9162 case TARGET_NR_symlinkat:
f0b6243d 9163 {
579a97f7 9164 void *p2;
f0b6243d
TS
9165 p = lock_user_string(arg1);
9166 p2 = lock_user_string(arg3);
579a97f7 9167 if (!p || !p2)
0da46a6e 9168 ret = -TARGET_EFAULT;
f0b6243d 9169 else
c0d472b1 9170 ret = get_errno(symlinkat(p, arg2, p2));
579a97f7
FB
9171 unlock_user(p2, arg3, 0);
9172 unlock_user(p, arg1, 0);
f0b6243d
TS
9173 }
9174 break;
9175#endif
ebc05488 9176#ifdef TARGET_NR_oldlstat
31e31b8a
FB
9177 case TARGET_NR_oldlstat:
9178 goto unimplemented;
ebc05488 9179#endif
704eff6c 9180#ifdef TARGET_NR_readlink
31e31b8a 9181 case TARGET_NR_readlink:
53a5960a 9182 {
463d8e73 9183 void *p2;
53a5960a 9184 p = lock_user_string(arg1);
579a97f7 9185 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
463d8e73 9186 if (!p || !p2) {
579a97f7 9187 ret = -TARGET_EFAULT;
f17f4989
MF
9188 } else if (!arg3) {
9189 /* Short circuit this for the magic exe check. */
9190 ret = -TARGET_EINVAL;
463d8e73
AS
9191 } else if (is_proc_myself((const char *)p, "exe")) {
9192 char real[PATH_MAX], *temp;
9193 temp = realpath(exec_path, real);
f17f4989
MF
9194 /* Return value is # of bytes that we wrote to the buffer. */
9195 if (temp == NULL) {
9196 ret = get_errno(-1);
9197 } else {
9198 /* Don't worry about sign mismatch as earlier mapping
9199 * logic would have thrown a bad address error. */
9200 ret = MIN(strlen(real), arg3);
9201 /* We cannot NUL terminate the string. */
9202 memcpy(p2, real, ret);
9203 }
463d8e73
AS
9204 } else {
9205 ret = get_errno(readlink(path(p), p2, arg3));
d088d664 9206 }
53a5960a
PB
9207 unlock_user(p2, arg2, ret);
9208 unlock_user(p, arg1, 0);
9209 }
31e31b8a 9210 break;
704eff6c 9211#endif
c0d472b1 9212#if defined(TARGET_NR_readlinkat)
5e0ccb18 9213 case TARGET_NR_readlinkat:
5e0ccb18 9214 {
579a97f7 9215 void *p2;
5e0ccb18 9216 p = lock_user_string(arg2);
579a97f7 9217 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
463d8e73
AS
9218 if (!p || !p2) {
9219 ret = -TARGET_EFAULT;
9220 } else if (is_proc_myself((const char *)p, "exe")) {
9221 char real[PATH_MAX], *temp;
9222 temp = realpath(exec_path, real);
9223 ret = temp == NULL ? get_errno(-1) : strlen(real) ;
9224 snprintf((char *)p2, arg4, "%s", real);
9225 } else {
c0d472b1 9226 ret = get_errno(readlinkat(arg1, path(p), p2, arg4));
463d8e73 9227 }
579a97f7
FB
9228 unlock_user(p2, arg3, ret);
9229 unlock_user(p, arg2, 0);
5e0ccb18
TS
9230 }
9231 break;
9232#endif
e5febef5 9233#ifdef TARGET_NR_uselib
31e31b8a
FB
9234 case TARGET_NR_uselib:
9235 goto unimplemented;
e5febef5
TS
9236#endif
9237#ifdef TARGET_NR_swapon
31e31b8a 9238 case TARGET_NR_swapon:
579a97f7
FB
9239 if (!(p = lock_user_string(arg1)))
9240 goto efault;
53a5960a
PB
9241 ret = get_errno(swapon(p, arg2));
9242 unlock_user(p, arg1, 0);
31e31b8a 9243 break;
e5febef5 9244#endif
31e31b8a 9245 case TARGET_NR_reboot:
c07ecc68
LV
9246 if (arg3 == LINUX_REBOOT_CMD_RESTART2) {
9247 /* arg4 must be ignored in all other cases */
9248 p = lock_user_string(arg4);
9249 if (!p) {
9250 goto efault;
9251 }
9252 ret = get_errno(reboot(arg1, arg2, arg3, p));
9253 unlock_user(p, arg4, 0);
9254 } else {
9255 ret = get_errno(reboot(arg1, arg2, arg3, NULL));
9256 }
0f6b4d21 9257 break;
e5febef5 9258#ifdef TARGET_NR_readdir
31e31b8a
FB
9259 case TARGET_NR_readdir:
9260 goto unimplemented;
e5febef5
TS
9261#endif
9262#ifdef TARGET_NR_mmap
31e31b8a 9263 case TARGET_NR_mmap:
09701199
AG
9264#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || \
9265 (defined(TARGET_ARM) && defined(TARGET_ABI32)) || \
a4c075f1
UH
9266 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
9267 || defined(TARGET_S390X)
31e31b8a 9268 {
992f48a0
BS
9269 abi_ulong *v;
9270 abi_ulong v1, v2, v3, v4, v5, v6;
579a97f7
FB
9271 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
9272 goto efault;
cbb21eed
MB
9273 v1 = tswapal(v[0]);
9274 v2 = tswapal(v[1]);
9275 v3 = tswapal(v[2]);
9276 v4 = tswapal(v[3]);
9277 v5 = tswapal(v[4]);
9278 v6 = tswapal(v[5]);
53a5960a 9279 unlock_user(v, arg1, 0);
5fafdf24 9280 ret = get_errno(target_mmap(v1, v2, v3,
5286db75
FB
9281 target_to_host_bitmask(v4, mmap_flags_tbl),
9282 v5, v6));
31e31b8a 9283 }
31e31b8a 9284#else
5fafdf24
TS
9285 ret = get_errno(target_mmap(arg1, arg2, arg3,
9286 target_to_host_bitmask(arg4, mmap_flags_tbl),
6fb883e8
FB
9287 arg5,
9288 arg6));
31e31b8a 9289#endif
6fb883e8 9290 break;
e5febef5 9291#endif
a315a145 9292#ifdef TARGET_NR_mmap2
6fb883e8 9293 case TARGET_NR_mmap2:
bb7ec043 9294#ifndef MMAP_SHIFT
c573ff67 9295#define MMAP_SHIFT 12
c573ff67 9296#endif
5fafdf24
TS
9297 ret = get_errno(target_mmap(arg1, arg2, arg3,
9298 target_to_host_bitmask(arg4, mmap_flags_tbl),
5286db75 9299 arg5,
c573ff67 9300 arg6 << MMAP_SHIFT));
31e31b8a 9301 break;
a315a145 9302#endif
31e31b8a 9303 case TARGET_NR_munmap:
54936004 9304 ret = get_errno(target_munmap(arg1, arg2));
31e31b8a 9305 break;
9de5e440 9306 case TARGET_NR_mprotect:
97374d38 9307 {
0429a971 9308 TaskState *ts = cpu->opaque;
97374d38
PB
9309 /* Special hack to detect libc making the stack executable. */
9310 if ((arg3 & PROT_GROWSDOWN)
9311 && arg1 >= ts->info->stack_limit
9312 && arg1 <= ts->info->start_stack) {
9313 arg3 &= ~PROT_GROWSDOWN;
9314 arg2 = arg2 + arg1 - ts->info->stack_limit;
9315 arg1 = ts->info->stack_limit;
9316 }
9317 }
54936004 9318 ret = get_errno(target_mprotect(arg1, arg2, arg3));
9de5e440 9319 break;
e5febef5 9320#ifdef TARGET_NR_mremap
9de5e440 9321 case TARGET_NR_mremap:
54936004 9322 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
9de5e440 9323 break;
e5febef5 9324#endif
53a5960a 9325 /* ??? msync/mlock/munlock are broken for softmmu. */
e5febef5 9326#ifdef TARGET_NR_msync
9de5e440 9327 case TARGET_NR_msync:
53a5960a 9328 ret = get_errno(msync(g2h(arg1), arg2, arg3));
9de5e440 9329 break;
e5febef5
TS
9330#endif
9331#ifdef TARGET_NR_mlock
9de5e440 9332 case TARGET_NR_mlock:
53a5960a 9333 ret = get_errno(mlock(g2h(arg1), arg2));
9de5e440 9334 break;
e5febef5
TS
9335#endif
9336#ifdef TARGET_NR_munlock
9de5e440 9337 case TARGET_NR_munlock:
53a5960a 9338 ret = get_errno(munlock(g2h(arg1), arg2));
9de5e440 9339 break;
e5febef5
TS
9340#endif
9341#ifdef TARGET_NR_mlockall
9de5e440 9342 case TARGET_NR_mlockall:
6f6a4032 9343 ret = get_errno(mlockall(target_to_host_mlockall_arg(arg1)));
9de5e440 9344 break;
e5febef5
TS
9345#endif
9346#ifdef TARGET_NR_munlockall
9de5e440
FB
9347 case TARGET_NR_munlockall:
9348 ret = get_errno(munlockall());
9349 break;
e5febef5 9350#endif
31e31b8a 9351 case TARGET_NR_truncate:
579a97f7
FB
9352 if (!(p = lock_user_string(arg1)))
9353 goto efault;
53a5960a
PB
9354 ret = get_errno(truncate(p, arg2));
9355 unlock_user(p, arg1, 0);
31e31b8a
FB
9356 break;
9357 case TARGET_NR_ftruncate:
9358 ret = get_errno(ftruncate(arg1, arg2));
9359 break;
9360 case TARGET_NR_fchmod:
9361 ret = get_errno(fchmod(arg1, arg2));
9362 break;
c0d472b1 9363#if defined(TARGET_NR_fchmodat)
814d7977 9364 case TARGET_NR_fchmodat:
579a97f7
FB
9365 if (!(p = lock_user_string(arg2)))
9366 goto efault;
c0d472b1 9367 ret = get_errno(fchmodat(arg1, p, arg3, 0));
579a97f7 9368 unlock_user(p, arg2, 0);
814d7977
TS
9369 break;
9370#endif
31e31b8a 9371 case TARGET_NR_getpriority:
95c09828
RH
9372 /* Note that negative values are valid for getpriority, so we must
9373 differentiate based on errno settings. */
9374 errno = 0;
9375 ret = getpriority(arg1, arg2);
9376 if (ret == -1 && errno != 0) {
9377 ret = -host_to_target_errno(errno);
9378 break;
9379 }
9380#ifdef TARGET_ALPHA
9381 /* Return value is the unbiased priority. Signal no error. */
9382 ((CPUAlphaState *)cpu_env)->ir[IR_V0] = 0;
9383#else
9384 /* Return value is a biased priority to avoid negative numbers. */
9385 ret = 20 - ret;
9386#endif
31e31b8a
FB
9387 break;
9388 case TARGET_NR_setpriority:
9389 ret = get_errno(setpriority(arg1, arg2, arg3));
9390 break;
ebc05488 9391#ifdef TARGET_NR_profil
31e31b8a
FB
9392 case TARGET_NR_profil:
9393 goto unimplemented;
ebc05488 9394#endif
31e31b8a 9395 case TARGET_NR_statfs:
579a97f7
FB
9396 if (!(p = lock_user_string(arg1)))
9397 goto efault;
53a5960a
PB
9398 ret = get_errno(statfs(path(p), &stfs));
9399 unlock_user(p, arg1, 0);
31e31b8a
FB
9400 convert_statfs:
9401 if (!is_error(ret)) {
53a5960a 9402 struct target_statfs *target_stfs;
3b46e624 9403
579a97f7
FB
9404 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
9405 goto efault;
9406 __put_user(stfs.f_type, &target_stfs->f_type);
9407 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
9408 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
9409 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
9410 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
9411 __put_user(stfs.f_files, &target_stfs->f_files);
9412 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
9413 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
9414 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
9415 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
9416 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
9417 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
53a5960a 9418 unlock_user_struct(target_stfs, arg2, 1);
31e31b8a
FB
9419 }
9420 break;
9421 case TARGET_NR_fstatfs:
56c8f68f 9422 ret = get_errno(fstatfs(arg1, &stfs));
31e31b8a 9423 goto convert_statfs;
56c8f68f
FB
9424#ifdef TARGET_NR_statfs64
9425 case TARGET_NR_statfs64:
579a97f7
FB
9426 if (!(p = lock_user_string(arg1)))
9427 goto efault;
53a5960a
PB
9428 ret = get_errno(statfs(path(p), &stfs));
9429 unlock_user(p, arg1, 0);
56c8f68f
FB
9430 convert_statfs64:
9431 if (!is_error(ret)) {
53a5960a 9432 struct target_statfs64 *target_stfs;
3b46e624 9433
579a97f7
FB
9434 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
9435 goto efault;
9436 __put_user(stfs.f_type, &target_stfs->f_type);
9437 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
9438 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
9439 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
9440 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
9441 __put_user(stfs.f_files, &target_stfs->f_files);
9442 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
9443 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
9444 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
9445 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
229d3376
AG
9446 __put_user(stfs.f_frsize, &target_stfs->f_frsize);
9447 memset(target_stfs->f_spare, 0, sizeof(target_stfs->f_spare));
579a97f7 9448 unlock_user_struct(target_stfs, arg3, 1);
56c8f68f
FB
9449 }
9450 break;
9451 case TARGET_NR_fstatfs64:
9452 ret = get_errno(fstatfs(arg1, &stfs));
9453 goto convert_statfs64;
9454#endif
ebc05488 9455#ifdef TARGET_NR_ioperm
31e31b8a
FB
9456 case TARGET_NR_ioperm:
9457 goto unimplemented;
ebc05488 9458#endif
e5febef5 9459#ifdef TARGET_NR_socketcall
31e31b8a 9460 case TARGET_NR_socketcall:
53a5960a 9461 ret = do_socketcall(arg1, arg2);
31e31b8a 9462 break;
e5febef5 9463#endif
3532fa74
FB
9464#ifdef TARGET_NR_accept
9465 case TARGET_NR_accept:
a94b4987
PM
9466 ret = do_accept4(arg1, arg2, arg3, 0);
9467 break;
9468#endif
9469#ifdef TARGET_NR_accept4
9470 case TARGET_NR_accept4:
a94b4987 9471 ret = do_accept4(arg1, arg2, arg3, arg4);
3532fa74
FB
9472 break;
9473#endif
9474#ifdef TARGET_NR_bind
9475 case TARGET_NR_bind:
9476 ret = do_bind(arg1, arg2, arg3);
9477 break;
9478#endif
9479#ifdef TARGET_NR_connect
9480 case TARGET_NR_connect:
9481 ret = do_connect(arg1, arg2, arg3);
9482 break;
9483#endif
9484#ifdef TARGET_NR_getpeername
9485 case TARGET_NR_getpeername:
1be9e1dc 9486 ret = do_getpeername(arg1, arg2, arg3);
3532fa74
FB
9487 break;
9488#endif
9489#ifdef TARGET_NR_getsockname
9490 case TARGET_NR_getsockname:
1be9e1dc 9491 ret = do_getsockname(arg1, arg2, arg3);
3532fa74
FB
9492 break;
9493#endif
9494#ifdef TARGET_NR_getsockopt
9495 case TARGET_NR_getsockopt:
9496 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
9497 break;
9498#endif
9499#ifdef TARGET_NR_listen
9500 case TARGET_NR_listen:
1be9e1dc 9501 ret = get_errno(listen(arg1, arg2));
3532fa74
FB
9502 break;
9503#endif
9504#ifdef TARGET_NR_recv
9505 case TARGET_NR_recv:
214201bd 9506 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
9507 break;
9508#endif
9509#ifdef TARGET_NR_recvfrom
9510 case TARGET_NR_recvfrom:
214201bd 9511 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
9512 break;
9513#endif
9514#ifdef TARGET_NR_recvmsg
9515 case TARGET_NR_recvmsg:
9516 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
9517 break;
9518#endif
9519#ifdef TARGET_NR_send
9520 case TARGET_NR_send:
1be9e1dc 9521 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
3532fa74
FB
9522 break;
9523#endif
9524#ifdef TARGET_NR_sendmsg
9525 case TARGET_NR_sendmsg:
9526 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
9527 break;
9528#endif
f19e00d7
AG
9529#ifdef TARGET_NR_sendmmsg
9530 case TARGET_NR_sendmmsg:
9531 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 1);
9532 break;
9533 case TARGET_NR_recvmmsg:
9534 ret = do_sendrecvmmsg(arg1, arg2, arg3, arg4, 0);
9535 break;
9536#endif
3532fa74
FB
9537#ifdef TARGET_NR_sendto
9538 case TARGET_NR_sendto:
1be9e1dc 9539 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
3532fa74
FB
9540 break;
9541#endif
9542#ifdef TARGET_NR_shutdown
9543 case TARGET_NR_shutdown:
1be9e1dc 9544 ret = get_errno(shutdown(arg1, arg2));
3532fa74
FB
9545 break;
9546#endif
f894efd1
LV
9547#if defined(TARGET_NR_getrandom) && defined(__NR_getrandom)
9548 case TARGET_NR_getrandom:
9549 p = lock_user(VERIFY_WRITE, arg1, arg2, 0);
9550 if (!p) {
9551 goto efault;
9552 }
9553 ret = get_errno(getrandom(p, arg2, arg3));
9554 unlock_user(p, arg1, ret);
9555 break;
9556#endif
3532fa74
FB
9557#ifdef TARGET_NR_socket
9558 case TARGET_NR_socket:
9559 ret = do_socket(arg1, arg2, arg3);
9560 break;
9561#endif
9562#ifdef TARGET_NR_socketpair
9563 case TARGET_NR_socketpair:
1be9e1dc 9564 ret = do_socketpair(arg1, arg2, arg3, arg4);
3532fa74
FB
9565 break;
9566#endif
9567#ifdef TARGET_NR_setsockopt
9568 case TARGET_NR_setsockopt:
9569 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
9570 break;
9571#endif
da2c8ad7 9572#if defined(TARGET_NR_syslog)
31e31b8a 9573 case TARGET_NR_syslog:
da2c8ad7
AM
9574 {
9575 int len = arg2;
7494b0f9 9576
da2c8ad7
AM
9577 switch (arg1) {
9578 case TARGET_SYSLOG_ACTION_CLOSE: /* Close log */
9579 case TARGET_SYSLOG_ACTION_OPEN: /* Open log */
9580 case TARGET_SYSLOG_ACTION_CLEAR: /* Clear ring buffer */
9581 case TARGET_SYSLOG_ACTION_CONSOLE_OFF: /* Disable logging */
9582 case TARGET_SYSLOG_ACTION_CONSOLE_ON: /* Enable logging */
9583 case TARGET_SYSLOG_ACTION_CONSOLE_LEVEL: /* Set messages level */
9584 case TARGET_SYSLOG_ACTION_SIZE_UNREAD: /* Number of chars */
9585 case TARGET_SYSLOG_ACTION_SIZE_BUFFER: /* Size of the buffer */
9586 {
9587 ret = get_errno(sys_syslog((int)arg1, NULL, (int)arg3));
9588 }
9589 break;
9590 case TARGET_SYSLOG_ACTION_READ: /* Read from log */
9591 case TARGET_SYSLOG_ACTION_READ_CLEAR: /* Read/clear msgs */
9592 case TARGET_SYSLOG_ACTION_READ_ALL: /* Read last messages */
9593 {
9594 ret = -TARGET_EINVAL;
9595 if (len < 0) {
9596 goto fail;
9597 }
9598 ret = 0;
9599 if (len == 0) {
9600 break;
9601 }
9602 p = lock_user(VERIFY_WRITE, arg2, arg3, 0);
9603 if (!p) {
9604 ret = -TARGET_EFAULT;
9605 goto fail;
9606 }
9607 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
9608 unlock_user(p, arg2, arg3);
9609 }
9610 break;
9611 default:
9612 ret = -EINVAL;
9613 break;
9614 }
9615 }
9616 break;
9617#endif
31e31b8a 9618 case TARGET_NR_setitimer:
66fb9763 9619 {
66fb9763
FB
9620 struct itimerval value, ovalue, *pvalue;
9621
53a5960a 9622 if (arg2) {
66fb9763 9623 pvalue = &value;
788f5ec4
TS
9624 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
9625 || copy_from_user_timeval(&pvalue->it_value,
9626 arg2 + sizeof(struct target_timeval)))
9627 goto efault;
66fb9763
FB
9628 } else {
9629 pvalue = NULL;
9630 }
9631 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
53a5960a 9632 if (!is_error(ret) && arg3) {
788f5ec4
TS
9633 if (copy_to_user_timeval(arg3,
9634 &ovalue.it_interval)
9635 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
9636 &ovalue.it_value))
9637 goto efault;
66fb9763
FB
9638 }
9639 }
9640 break;
31e31b8a 9641 case TARGET_NR_getitimer:
66fb9763 9642 {
66fb9763 9643 struct itimerval value;
3b46e624 9644
66fb9763 9645 ret = get_errno(getitimer(arg1, &value));
53a5960a 9646 if (!is_error(ret) && arg2) {
788f5ec4
TS
9647 if (copy_to_user_timeval(arg2,
9648 &value.it_interval)
9649 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
9650 &value.it_value))
9651 goto efault;
66fb9763
FB
9652 }
9653 }
9654 break;
704eff6c 9655#ifdef TARGET_NR_stat
31e31b8a 9656 case TARGET_NR_stat:
579a97f7
FB
9657 if (!(p = lock_user_string(arg1)))
9658 goto efault;
53a5960a
PB
9659 ret = get_errno(stat(path(p), &st));
9660 unlock_user(p, arg1, 0);
31e31b8a 9661 goto do_stat;
704eff6c
CG
9662#endif
9663#ifdef TARGET_NR_lstat
31e31b8a 9664 case TARGET_NR_lstat:
579a97f7
FB
9665 if (!(p = lock_user_string(arg1)))
9666 goto efault;
53a5960a
PB
9667 ret = get_errno(lstat(path(p), &st));
9668 unlock_user(p, arg1, 0);
31e31b8a 9669 goto do_stat;
704eff6c 9670#endif
31e31b8a
FB
9671 case TARGET_NR_fstat:
9672 {
9673 ret = get_errno(fstat(arg1, &st));
704eff6c 9674#if defined(TARGET_NR_stat) || defined(TARGET_NR_lstat)
31e31b8a 9675 do_stat:
704eff6c 9676#endif
31e31b8a 9677 if (!is_error(ret)) {
53a5960a 9678 struct target_stat *target_st;
e3584658 9679
579a97f7
FB
9680 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
9681 goto efault;
12727917 9682 memset(target_st, 0, sizeof(*target_st));
d2fd1af7
FB
9683 __put_user(st.st_dev, &target_st->st_dev);
9684 __put_user(st.st_ino, &target_st->st_ino);
9685 __put_user(st.st_mode, &target_st->st_mode);
9686 __put_user(st.st_uid, &target_st->st_uid);
9687 __put_user(st.st_gid, &target_st->st_gid);
9688 __put_user(st.st_nlink, &target_st->st_nlink);
9689 __put_user(st.st_rdev, &target_st->st_rdev);
9690 __put_user(st.st_size, &target_st->st_size);
9691 __put_user(st.st_blksize, &target_st->st_blksize);
9692 __put_user(st.st_blocks, &target_st->st_blocks);
9693 __put_user(st.st_atime, &target_st->target_st_atime);
9694 __put_user(st.st_mtime, &target_st->target_st_mtime);
9695 __put_user(st.st_ctime, &target_st->target_st_ctime);
53a5960a 9696 unlock_user_struct(target_st, arg2, 1);
31e31b8a
FB
9697 }
9698 }
9699 break;
ebc05488 9700#ifdef TARGET_NR_olduname
31e31b8a
FB
9701 case TARGET_NR_olduname:
9702 goto unimplemented;
ebc05488
FB
9703#endif
9704#ifdef TARGET_NR_iopl
31e31b8a
FB
9705 case TARGET_NR_iopl:
9706 goto unimplemented;
ebc05488 9707#endif
31e31b8a
FB
9708 case TARGET_NR_vhangup:
9709 ret = get_errno(vhangup());
9710 break;
ebc05488 9711#ifdef TARGET_NR_idle
31e31b8a
FB
9712 case TARGET_NR_idle:
9713 goto unimplemented;
42ad6ae9
FB
9714#endif
9715#ifdef TARGET_NR_syscall
9716 case TARGET_NR_syscall:
5945cfcb
PM
9717 ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
9718 arg6, arg7, arg8, 0);
9719 break;
ebc05488 9720#endif
31e31b8a
FB
9721 case TARGET_NR_wait4:
9722 {
9723 int status;
992f48a0 9724 abi_long status_ptr = arg2;
31e31b8a 9725 struct rusage rusage, *rusage_ptr;
992f48a0 9726 abi_ulong target_rusage = arg4;
a39fb273 9727 abi_long rusage_err;
31e31b8a
FB
9728 if (target_rusage)
9729 rusage_ptr = &rusage;
9730 else
9731 rusage_ptr = NULL;
4af80a37 9732 ret = get_errno(safe_wait4(arg1, &status, arg3, rusage_ptr));
31e31b8a 9733 if (!is_error(ret)) {
5379557b 9734 if (status_ptr && ret) {
1d9d8b55 9735 status = host_to_target_waitstatus(status);
2f619698
FB
9736 if (put_user_s32(status, status_ptr))
9737 goto efault;
31e31b8a 9738 }
a39fb273
PJ
9739 if (target_rusage) {
9740 rusage_err = host_to_target_rusage(target_rusage, &rusage);
9741 if (rusage_err) {
9742 ret = rusage_err;
9743 }
9744 }
31e31b8a
FB
9745 }
9746 }
9747 break;
e5febef5 9748#ifdef TARGET_NR_swapoff
31e31b8a 9749 case TARGET_NR_swapoff:
579a97f7
FB
9750 if (!(p = lock_user_string(arg1)))
9751 goto efault;
53a5960a
PB
9752 ret = get_errno(swapoff(p));
9753 unlock_user(p, arg1, 0);
31e31b8a 9754 break;
e5febef5 9755#endif
31e31b8a 9756 case TARGET_NR_sysinfo:
a5448a7d 9757 {
53a5960a 9758 struct target_sysinfo *target_value;
a5448a7d
FB
9759 struct sysinfo value;
9760 ret = get_errno(sysinfo(&value));
53a5960a 9761 if (!is_error(ret) && arg1)
a5448a7d 9762 {
579a97f7
FB
9763 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
9764 goto efault;
a5448a7d
FB
9765 __put_user(value.uptime, &target_value->uptime);
9766 __put_user(value.loads[0], &target_value->loads[0]);
9767 __put_user(value.loads[1], &target_value->loads[1]);
9768 __put_user(value.loads[2], &target_value->loads[2]);
9769 __put_user(value.totalram, &target_value->totalram);
9770 __put_user(value.freeram, &target_value->freeram);
9771 __put_user(value.sharedram, &target_value->sharedram);
9772 __put_user(value.bufferram, &target_value->bufferram);
9773 __put_user(value.totalswap, &target_value->totalswap);
9774 __put_user(value.freeswap, &target_value->freeswap);
9775 __put_user(value.procs, &target_value->procs);
9776 __put_user(value.totalhigh, &target_value->totalhigh);
9777 __put_user(value.freehigh, &target_value->freehigh);
9778 __put_user(value.mem_unit, &target_value->mem_unit);
53a5960a 9779 unlock_user_struct(target_value, arg1, 1);
a5448a7d
FB
9780 }
9781 }
9782 break;
e5febef5 9783#ifdef TARGET_NR_ipc
31e31b8a 9784 case TARGET_NR_ipc:
ee8e7614
PM
9785 ret = do_ipc(cpu_env, arg1, arg2, arg3, arg4, arg5, arg6);
9786 break;
e5febef5 9787#endif
e5289087
AJ
9788#ifdef TARGET_NR_semget
9789 case TARGET_NR_semget:
9790 ret = get_errno(semget(arg1, arg2, arg3));
9791 break;
9792#endif
9793#ifdef TARGET_NR_semop
9794 case TARGET_NR_semop:
c7128c9f 9795 ret = do_semop(arg1, arg2, arg3);
e5289087
AJ
9796 break;
9797#endif
9798#ifdef TARGET_NR_semctl
9799 case TARGET_NR_semctl:
d1c002b6 9800 ret = do_semctl(arg1, arg2, arg3, arg4);
e5289087
AJ
9801 break;
9802#endif
eeb438c1
AJ
9803#ifdef TARGET_NR_msgctl
9804 case TARGET_NR_msgctl:
9805 ret = do_msgctl(arg1, arg2, arg3);
9806 break;
9807#endif
9808#ifdef TARGET_NR_msgget
9809 case TARGET_NR_msgget:
9810 ret = get_errno(msgget(arg1, arg2));
9811 break;
9812#endif
9813#ifdef TARGET_NR_msgrcv
9814 case TARGET_NR_msgrcv:
9815 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
9816 break;
9817#endif
9818#ifdef TARGET_NR_msgsnd
9819 case TARGET_NR_msgsnd:
9820 ret = do_msgsnd(arg1, arg2, arg3, arg4);
9821 break;
88a8c984
RV
9822#endif
9823#ifdef TARGET_NR_shmget
9824 case TARGET_NR_shmget:
9825 ret = get_errno(shmget(arg1, arg2, arg3));
9826 break;
9827#endif
9828#ifdef TARGET_NR_shmctl
9829 case TARGET_NR_shmctl:
9830 ret = do_shmctl(arg1, arg2, arg3);
9831 break;
9832#endif
9833#ifdef TARGET_NR_shmat
9834 case TARGET_NR_shmat:
ee8e7614 9835 ret = do_shmat(cpu_env, arg1, arg2, arg3);
88a8c984
RV
9836 break;
9837#endif
9838#ifdef TARGET_NR_shmdt
9839 case TARGET_NR_shmdt:
9840 ret = do_shmdt(arg1);
9841 break;
eeb438c1 9842#endif
31e31b8a
FB
9843 case TARGET_NR_fsync:
9844 ret = get_errno(fsync(arg1));
9845 break;
31e31b8a 9846 case TARGET_NR_clone:
4ce6243d
PM
9847 /* Linux manages to have three different orderings for its
9848 * arguments to clone(); the BACKWARDS and BACKWARDS2 defines
9849 * match the kernel's CONFIG_CLONE_* settings.
9850 * Microblaze is further special in that it uses a sixth
9851 * implicit argument to clone for the TLS pointer.
9852 */
9853#if defined(TARGET_MICROBLAZE)
a5b3bdcb 9854 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg4, arg6, arg5));
4ce6243d
PM
9855#elif defined(TARGET_CLONE_BACKWARDS)
9856 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
9857#elif defined(TARGET_CLONE_BACKWARDS2)
a4c075f1 9858 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
0b6d3ae0 9859#else
4ce6243d 9860 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
0b6d3ae0 9861#endif
1b6b029e 9862 break;
ec86b0fb
FB
9863#ifdef __NR_exit_group
9864 /* new thread calls */
9865 case TARGET_NR_exit_group:
9788c9ca 9866#ifdef TARGET_GPROF
6d946cda
AJ
9867 _mcleanup();
9868#endif
e9009676 9869 gdb_exit(cpu_env, arg1);
ec86b0fb
FB
9870 ret = get_errno(exit_group(arg1));
9871 break;
9872#endif
31e31b8a 9873 case TARGET_NR_setdomainname:
579a97f7
FB
9874 if (!(p = lock_user_string(arg1)))
9875 goto efault;
53a5960a
PB
9876 ret = get_errno(setdomainname(p, arg2));
9877 unlock_user(p, arg1, 0);
31e31b8a
FB
9878 break;
9879 case TARGET_NR_uname:
9880 /* no need to transcode because we use the linux syscall */
29e619b1
FB
9881 {
9882 struct new_utsname * buf;
3b46e624 9883
579a97f7
FB
9884 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
9885 goto efault;
29e619b1
FB
9886 ret = get_errno(sys_uname(buf));
9887 if (!is_error(ret)) {
332c9781 9888 /* Overwrite the native machine name with whatever is being
29e619b1 9889 emulated. */
da79030f 9890 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
c5937220 9891 /* Allow the user to override the reported release. */
332c9781
PM
9892 if (qemu_uname_release && *qemu_uname_release) {
9893 g_strlcpy(buf->release, qemu_uname_release,
9894 sizeof(buf->release));
9895 }
29e619b1 9896 }
53a5960a 9897 unlock_user_struct(buf, arg1, 1);
29e619b1 9898 }
31e31b8a 9899 break;
6dbad63e 9900#ifdef TARGET_I386
31e31b8a 9901 case TARGET_NR_modify_ldt:
03acab66 9902 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
5cd4393b 9903 break;
84409ddb 9904#if !defined(TARGET_X86_64)
5cd4393b
FB
9905 case TARGET_NR_vm86old:
9906 goto unimplemented;
9907 case TARGET_NR_vm86:
53a5960a 9908 ret = do_vm86(cpu_env, arg1, arg2);
6dbad63e 9909 break;
84409ddb 9910#endif
6dbad63e 9911#endif
31e31b8a 9912 case TARGET_NR_adjtimex:
19f59bce
AM
9913 {
9914 struct timex host_buf;
9915
9916 if (target_to_host_timex(&host_buf, arg1) != 0) {
9917 goto efault;
9918 }
9919 ret = get_errno(adjtimex(&host_buf));
9920 if (!is_error(ret)) {
9921 if (host_to_target_timex(arg1, &host_buf) != 0) {
9922 goto efault;
9923 }
9924 }
9925 }
9926 break;
38860a03
AM
9927#if defined(TARGET_NR_clock_adjtime) && defined(CONFIG_CLOCK_ADJTIME)
9928 case TARGET_NR_clock_adjtime:
9929 {
9930 struct timex htx, *phtx = &htx;
9931
9932 if (target_to_host_timex(phtx, arg2) != 0) {
9933 goto efault;
9934 }
9935 ret = get_errno(clock_adjtime(arg1, phtx));
9936 if (!is_error(ret) && phtx) {
9937 if (host_to_target_timex(arg2, phtx) != 0) {
9938 goto efault;
9939 }
9940 }
9941 }
9942 break;
9943#endif
e5febef5 9944#ifdef TARGET_NR_create_module
31e31b8a 9945 case TARGET_NR_create_module:
e5febef5 9946#endif
31e31b8a
FB
9947 case TARGET_NR_init_module:
9948 case TARGET_NR_delete_module:
e5febef5 9949#ifdef TARGET_NR_get_kernel_syms
31e31b8a 9950 case TARGET_NR_get_kernel_syms:
e5febef5 9951#endif
31e31b8a
FB
9952 goto unimplemented;
9953 case TARGET_NR_quotactl:
9954 goto unimplemented;
9955 case TARGET_NR_getpgid:
9956 ret = get_errno(getpgid(arg1));
9957 break;
9958 case TARGET_NR_fchdir:
9959 ret = get_errno(fchdir(arg1));
9960 break;
84409ddb 9961#ifdef TARGET_NR_bdflush /* not on x86_64 */
31e31b8a
FB
9962 case TARGET_NR_bdflush:
9963 goto unimplemented;
84409ddb 9964#endif
e5febef5 9965#ifdef TARGET_NR_sysfs
31e31b8a
FB
9966 case TARGET_NR_sysfs:
9967 goto unimplemented;
e5febef5 9968#endif
31e31b8a 9969 case TARGET_NR_personality:
1b6b029e 9970 ret = get_errno(personality(arg1));
31e31b8a 9971 break;
e5febef5 9972#ifdef TARGET_NR_afs_syscall
31e31b8a
FB
9973 case TARGET_NR_afs_syscall:
9974 goto unimplemented;
e5febef5 9975#endif
7a3148a9 9976#ifdef TARGET_NR__llseek /* Not on alpha */
31e31b8a
FB
9977 case TARGET_NR__llseek:
9978 {
0c1592d9 9979 int64_t res;
d35b261c 9980#if !defined(__NR_llseek)
9fea273c 9981 res = lseek(arg1, ((uint64_t)arg2 << 32) | (abi_ulong)arg3, arg5);
0c1592d9
PM
9982 if (res == -1) {
9983 ret = get_errno(res);
9984 } else {
9985 ret = 0;
9986 }
4f2ac237 9987#else
31e31b8a 9988 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
4f2ac237 9989#endif
0c1592d9
PM
9990 if ((ret == 0) && put_user_s64(res, arg4)) {
9991 goto efault;
9992 }
31e31b8a
FB
9993 }
9994 break;
7a3148a9 9995#endif
704eff6c 9996#ifdef TARGET_NR_getdents
31e31b8a 9997 case TARGET_NR_getdents:
3307e236 9998#ifdef __NR_getdents
d83c8733 9999#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
4add45b4 10000 {
53a5960a 10001 struct target_dirent *target_dirp;
6556a833 10002 struct linux_dirent *dirp;
992f48a0 10003 abi_long count = arg3;
4add45b4 10004
0e173b24
HK
10005 dirp = g_try_malloc(count);
10006 if (!dirp) {
579a97f7 10007 ret = -TARGET_ENOMEM;
0da46a6e
TS
10008 goto fail;
10009 }
3b46e624 10010
4add45b4
FB
10011 ret = get_errno(sys_getdents(arg1, dirp, count));
10012 if (!is_error(ret)) {
6556a833 10013 struct linux_dirent *de;
4add45b4
FB
10014 struct target_dirent *tde;
10015 int len = ret;
10016 int reclen, treclen;
10017 int count1, tnamelen;
10018
10019 count1 = 0;
10020 de = dirp;
579a97f7
FB
10021 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
10022 goto efault;
4add45b4
FB
10023 tde = target_dirp;
10024 while (len > 0) {
10025 reclen = de->d_reclen;
333858b7
DL
10026 tnamelen = reclen - offsetof(struct linux_dirent, d_name);
10027 assert(tnamelen >= 0);
10028 treclen = tnamelen + offsetof(struct target_dirent, d_name);
10029 assert(count1 + treclen <= count);
4add45b4 10030 tde->d_reclen = tswap16(treclen);
cbb21eed
MB
10031 tde->d_ino = tswapal(de->d_ino);
10032 tde->d_off = tswapal(de->d_off);
333858b7 10033 memcpy(tde->d_name, de->d_name, tnamelen);
6556a833 10034 de = (struct linux_dirent *)((char *)de + reclen);
4add45b4 10035 len -= reclen;
1c5bf3bf 10036 tde = (struct target_dirent *)((char *)tde + treclen);
4add45b4
FB
10037 count1 += treclen;
10038 }
10039 ret = count1;
579a97f7 10040 unlock_user(target_dirp, arg2, ret);
4add45b4 10041 }
0e173b24 10042 g_free(dirp);
4add45b4
FB
10043 }
10044#else
31e31b8a 10045 {
6556a833 10046 struct linux_dirent *dirp;
992f48a0 10047 abi_long count = arg3;
dab2ed99 10048
579a97f7
FB
10049 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
10050 goto efault;
72f03900 10051 ret = get_errno(sys_getdents(arg1, dirp, count));
31e31b8a 10052 if (!is_error(ret)) {
6556a833 10053 struct linux_dirent *de;
31e31b8a
FB
10054 int len = ret;
10055 int reclen;
10056 de = dirp;
10057 while (len > 0) {
8083a3e5 10058 reclen = de->d_reclen;
31e31b8a
FB
10059 if (reclen > len)
10060 break;
8083a3e5 10061 de->d_reclen = tswap16(reclen);
31e31b8a
FB
10062 tswapls(&de->d_ino);
10063 tswapls(&de->d_off);
6556a833 10064 de = (struct linux_dirent *)((char *)de + reclen);
31e31b8a
FB
10065 len -= reclen;
10066 }
10067 }
53a5960a 10068 unlock_user(dirp, arg2, ret);
3307e236
PM
10069 }
10070#endif
10071#else
10072 /* Implement getdents in terms of getdents64 */
10073 {
10074 struct linux_dirent64 *dirp;
10075 abi_long count = arg3;
10076
10077 dirp = lock_user(VERIFY_WRITE, arg2, count, 0);
10078 if (!dirp) {
10079 goto efault;
10080 }
10081 ret = get_errno(sys_getdents64(arg1, dirp, count));
10082 if (!is_error(ret)) {
10083 /* Convert the dirent64 structs to target dirent. We do this
10084 * in-place, since we can guarantee that a target_dirent is no
10085 * larger than a dirent64; however this means we have to be
10086 * careful to read everything before writing in the new format.
10087 */
10088 struct linux_dirent64 *de;
10089 struct target_dirent *tde;
10090 int len = ret;
10091 int tlen = 0;
10092
10093 de = dirp;
10094 tde = (struct target_dirent *)dirp;
10095 while (len > 0) {
10096 int namelen, treclen;
10097 int reclen = de->d_reclen;
10098 uint64_t ino = de->d_ino;
10099 int64_t off = de->d_off;
10100 uint8_t type = de->d_type;
10101
10102 namelen = strlen(de->d_name);
10103 treclen = offsetof(struct target_dirent, d_name)
10104 + namelen + 2;
10105 treclen = QEMU_ALIGN_UP(treclen, sizeof(abi_long));
10106
10107 memmove(tde->d_name, de->d_name, namelen + 1);
10108 tde->d_ino = tswapal(ino);
10109 tde->d_off = tswapal(off);
10110 tde->d_reclen = tswap16(treclen);
10111 /* The target_dirent type is in what was formerly a padding
10112 * byte at the end of the structure:
10113 */
10114 *(((char *)tde) + treclen - 1) = type;
10115
10116 de = (struct linux_dirent64 *)((char *)de + reclen);
10117 tde = (struct target_dirent *)((char *)tde + treclen);
10118 len -= reclen;
10119 tlen += treclen;
10120 }
10121 ret = tlen;
10122 }
10123 unlock_user(dirp, arg2, ret);
31e31b8a 10124 }
4add45b4 10125#endif
31e31b8a 10126 break;
704eff6c 10127#endif /* TARGET_NR_getdents */
3ae43202 10128#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
dab2ed99
FB
10129 case TARGET_NR_getdents64:
10130 {
6556a833 10131 struct linux_dirent64 *dirp;
992f48a0 10132 abi_long count = arg3;
579a97f7
FB
10133 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
10134 goto efault;
dab2ed99
FB
10135 ret = get_errno(sys_getdents64(arg1, dirp, count));
10136 if (!is_error(ret)) {
6556a833 10137 struct linux_dirent64 *de;
dab2ed99
FB
10138 int len = ret;
10139 int reclen;
10140 de = dirp;
10141 while (len > 0) {
8083a3e5 10142 reclen = de->d_reclen;
dab2ed99
FB
10143 if (reclen > len)
10144 break;
8083a3e5 10145 de->d_reclen = tswap16(reclen);
8582a53a
FB
10146 tswap64s((uint64_t *)&de->d_ino);
10147 tswap64s((uint64_t *)&de->d_off);
6556a833 10148 de = (struct linux_dirent64 *)((char *)de + reclen);
dab2ed99
FB
10149 len -= reclen;
10150 }
10151 }
53a5960a 10152 unlock_user(dirp, arg2, ret);
dab2ed99
FB
10153 }
10154 break;
a541f297 10155#endif /* TARGET_NR_getdents64 */
9468a5d4 10156#if defined(TARGET_NR__newselect)
31e31b8a 10157 case TARGET_NR__newselect:
53a5960a 10158 ret = do_select(arg1, arg2, arg3, arg4, arg5);
31e31b8a 10159 break;
e5febef5 10160#endif
d8035d4c
MF
10161#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
10162# ifdef TARGET_NR_poll
9de5e440 10163 case TARGET_NR_poll:
d8035d4c
MF
10164# endif
10165# ifdef TARGET_NR_ppoll
10166 case TARGET_NR_ppoll:
10167# endif
9de5e440 10168 {
53a5960a 10169 struct target_pollfd *target_pfd;
9de5e440 10170 unsigned int nfds = arg2;
9de5e440 10171 struct pollfd *pfd;
7854b056 10172 unsigned int i;
9de5e440 10173
3e24bb3f
LV
10174 pfd = NULL;
10175 target_pfd = NULL;
10176 if (nfds) {
ce9c139d
PM
10177 if (nfds > (INT_MAX / sizeof(struct target_pollfd))) {
10178 ret = -TARGET_EINVAL;
10179 break;
10180 }
10181
3e24bb3f
LV
10182 target_pfd = lock_user(VERIFY_WRITE, arg1,
10183 sizeof(struct target_pollfd) * nfds, 1);
10184 if (!target_pfd) {
10185 goto efault;
10186 }
d8035d4c 10187
3e24bb3f
LV
10188 pfd = alloca(sizeof(struct pollfd) * nfds);
10189 for (i = 0; i < nfds; i++) {
10190 pfd[i].fd = tswap32(target_pfd[i].fd);
10191 pfd[i].events = tswap16(target_pfd[i].events);
10192 }
9de5e440 10193 }
d8035d4c 10194
a6130237 10195 switch (num) {
d8035d4c 10196# ifdef TARGET_NR_ppoll
a6130237
PM
10197 case TARGET_NR_ppoll:
10198 {
d8035d4c
MF
10199 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
10200 target_sigset_t *target_set;
10201 sigset_t _set, *set = &_set;
10202
10203 if (arg3) {
10204 if (target_to_host_timespec(timeout_ts, arg3)) {
10205 unlock_user(target_pfd, arg1, 0);
10206 goto efault;
10207 }
10208 } else {
10209 timeout_ts = NULL;
10210 }
10211
10212 if (arg4) {
c815701e
PM
10213 if (arg5 != sizeof(target_sigset_t)) {
10214 unlock_user(target_pfd, arg1, 0);
10215 ret = -TARGET_EINVAL;
10216 break;
10217 }
10218
d8035d4c
MF
10219 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
10220 if (!target_set) {
10221 unlock_user(target_pfd, arg1, 0);
10222 goto efault;
10223 }
10224 target_to_host_sigset(set, target_set);
10225 } else {
10226 set = NULL;
10227 }
10228
a6130237
PM
10229 ret = get_errno(safe_ppoll(pfd, nfds, timeout_ts,
10230 set, SIGSET_T_SIZE));
d8035d4c
MF
10231
10232 if (!is_error(ret) && arg3) {
10233 host_to_target_timespec(arg3, timeout_ts);
10234 }
10235 if (arg4) {
10236 unlock_user(target_set, arg4, 0);
10237 }
a6130237
PM
10238 break;
10239 }
d8035d4c 10240# endif
a6130237
PM
10241# ifdef TARGET_NR_poll
10242 case TARGET_NR_poll:
10243 {
10244 struct timespec ts, *pts;
10245
10246 if (arg3 >= 0) {
10247 /* Convert ms to secs, ns */
10248 ts.tv_sec = arg3 / 1000;
10249 ts.tv_nsec = (arg3 % 1000) * 1000000LL;
10250 pts = &ts;
10251 } else {
10252 /* -ve poll() timeout means "infinite" */
10253 pts = NULL;
10254 }
10255 ret = get_errno(safe_ppoll(pfd, nfds, pts, NULL, 0));
10256 break;
10257 }
d8035d4c 10258# endif
a6130237
PM
10259 default:
10260 g_assert_not_reached();
10261 }
d8035d4c 10262
9de5e440
FB
10263 if (!is_error(ret)) {
10264 for(i = 0; i < nfds; i++) {
5cd4393b 10265 target_pfd[i].revents = tswap16(pfd[i].revents);
9de5e440
FB
10266 }
10267 }
30cb4cde 10268 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
9de5e440
FB
10269 }
10270 break;
e5febef5 10271#endif
31e31b8a 10272 case TARGET_NR_flock:
9de5e440
FB
10273 /* NOTE: the flock constant seems to be the same for every
10274 Linux platform */
2a845989 10275 ret = get_errno(safe_flock(arg1, arg2));
31e31b8a
FB
10276 break;
10277 case TARGET_NR_readv:
10278 {
f287b2c2
RH
10279 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10280 if (vec != NULL) {
918c03ed 10281 ret = get_errno(safe_readv(arg1, vec, arg3));
f287b2c2
RH
10282 unlock_iovec(vec, arg2, arg3, 1);
10283 } else {
10284 ret = -host_to_target_errno(errno);
10285 }
31e31b8a
FB
10286 }
10287 break;
10288 case TARGET_NR_writev:
10289 {
f287b2c2
RH
10290 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10291 if (vec != NULL) {
918c03ed 10292 ret = get_errno(safe_writev(arg1, vec, arg3));
f287b2c2
RH
10293 unlock_iovec(vec, arg2, arg3, 0);
10294 } else {
10295 ret = -host_to_target_errno(errno);
10296 }
31e31b8a
FB
10297 }
10298 break;
0f26386c
DJ
10299#if defined(TARGET_NR_preadv)
10300 case TARGET_NR_preadv:
10301 {
10302 struct iovec *vec = lock_iovec(VERIFY_WRITE, arg2, arg3, 0);
10303 if (vec != NULL) {
10304 ret = get_errno(safe_preadv(arg1, vec, arg3, arg4, arg5));
10305 unlock_iovec(vec, arg2, arg3, 1);
10306 } else {
10307 ret = -host_to_target_errno(errno);
f8d00fba
DJ
10308 }
10309 }
10310 break;
10311#endif
10312#if defined(TARGET_NR_pwritev)
10313 case TARGET_NR_pwritev:
10314 {
10315 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
10316 if (vec != NULL) {
10317 ret = get_errno(safe_pwritev(arg1, vec, arg3, arg4, arg5));
10318 unlock_iovec(vec, arg2, arg3, 0);
10319 } else {
10320 ret = -host_to_target_errno(errno);
0f26386c
DJ
10321 }
10322 }
10323 break;
10324#endif
31e31b8a
FB
10325 case TARGET_NR_getsid:
10326 ret = get_errno(getsid(arg1));
10327 break;
7a3148a9 10328#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
31e31b8a 10329 case TARGET_NR_fdatasync:
5cd4393b
FB
10330 ret = get_errno(fdatasync(arg1));
10331 break;
7a3148a9 10332#endif
704eff6c 10333#ifdef TARGET_NR__sysctl
31e31b8a 10334 case TARGET_NR__sysctl:
0da46a6e 10335 /* We don't implement this, but ENOTDIR is always a safe
29e619b1 10336 return value. */
0da46a6e
TS
10337 ret = -TARGET_ENOTDIR;
10338 break;
704eff6c 10339#endif
737de1d1
MF
10340 case TARGET_NR_sched_getaffinity:
10341 {
10342 unsigned int mask_size;
10343 unsigned long *mask;
10344
10345 /*
10346 * sched_getaffinity needs multiples of ulong, so need to take
10347 * care of mismatches between target ulong and host ulong sizes.
10348 */
10349 if (arg2 & (sizeof(abi_ulong) - 1)) {
10350 ret = -TARGET_EINVAL;
10351 break;
10352 }
10353 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10354
10355 mask = alloca(mask_size);
10356 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
10357
10358 if (!is_error(ret)) {
be3bd286
PM
10359 if (ret > arg2) {
10360 /* More data returned than the caller's buffer will fit.
10361 * This only happens if sizeof(abi_long) < sizeof(long)
10362 * and the caller passed us a buffer holding an odd number
10363 * of abi_longs. If the host kernel is actually using the
10364 * extra 4 bytes then fail EINVAL; otherwise we can just
10365 * ignore them and only copy the interesting part.
10366 */
10367 int numcpus = sysconf(_SC_NPROCESSORS_CONF);
10368 if (numcpus > arg2 * 8) {
10369 ret = -TARGET_EINVAL;
10370 break;
10371 }
10372 ret = arg2;
10373 }
10374
cd18f05e 10375 if (copy_to_user(arg3, mask, ret)) {
737de1d1
MF
10376 goto efault;
10377 }
737de1d1
MF
10378 }
10379 }
10380 break;
10381 case TARGET_NR_sched_setaffinity:
10382 {
10383 unsigned int mask_size;
10384 unsigned long *mask;
10385
10386 /*
10387 * sched_setaffinity needs multiples of ulong, so need to take
10388 * care of mismatches between target ulong and host ulong sizes.
10389 */
10390 if (arg2 & (sizeof(abi_ulong) - 1)) {
10391 ret = -TARGET_EINVAL;
10392 break;
10393 }
10394 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
10395
10396 mask = alloca(mask_size);
10397 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
10398 goto efault;
10399 }
10400 memcpy(mask, p, arg2);
10401 unlock_user_struct(p, arg2, 0);
10402
10403 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
10404 }
10405 break;
31e31b8a 10406 case TARGET_NR_sched_setparam:
5cd4393b 10407 {
53a5960a 10408 struct sched_param *target_schp;
5cd4393b 10409 struct sched_param schp;
53a5960a 10410
a1d5c5b2
TM
10411 if (arg2 == 0) {
10412 return -TARGET_EINVAL;
10413 }
579a97f7
FB
10414 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
10415 goto efault;
5cd4393b 10416 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10417 unlock_user_struct(target_schp, arg2, 0);
5cd4393b
FB
10418 ret = get_errno(sched_setparam(arg1, &schp));
10419 }
10420 break;
31e31b8a 10421 case TARGET_NR_sched_getparam:
5cd4393b 10422 {
53a5960a 10423 struct sched_param *target_schp;
5cd4393b 10424 struct sched_param schp;
a1d5c5b2
TM
10425
10426 if (arg2 == 0) {
10427 return -TARGET_EINVAL;
10428 }
5cd4393b
FB
10429 ret = get_errno(sched_getparam(arg1, &schp));
10430 if (!is_error(ret)) {
579a97f7
FB
10431 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
10432 goto efault;
5cd4393b 10433 target_schp->sched_priority = tswap32(schp.sched_priority);
53a5960a 10434 unlock_user_struct(target_schp, arg2, 1);
5cd4393b
FB
10435 }
10436 }
10437 break;
31e31b8a 10438 case TARGET_NR_sched_setscheduler:
5cd4393b 10439 {
53a5960a 10440 struct sched_param *target_schp;
5cd4393b 10441 struct sched_param schp;
a1d5c5b2
TM
10442 if (arg3 == 0) {
10443 return -TARGET_EINVAL;
10444 }
579a97f7
FB
10445 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
10446 goto efault;
5cd4393b 10447 schp.sched_priority = tswap32(target_schp->sched_priority);
53a5960a 10448 unlock_user_struct(target_schp, arg3, 0);
5cd4393b
FB
10449 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
10450 }
10451 break;
31e31b8a 10452 case TARGET_NR_sched_getscheduler:
5cd4393b
FB
10453 ret = get_errno(sched_getscheduler(arg1));
10454 break;
31e31b8a
FB
10455 case TARGET_NR_sched_yield:
10456 ret = get_errno(sched_yield());
10457 break;
10458 case TARGET_NR_sched_get_priority_max:
5cd4393b
FB
10459 ret = get_errno(sched_get_priority_max(arg1));
10460 break;
31e31b8a 10461 case TARGET_NR_sched_get_priority_min:
5cd4393b
FB
10462 ret = get_errno(sched_get_priority_min(arg1));
10463 break;
31e31b8a 10464 case TARGET_NR_sched_rr_get_interval:
5cd4393b 10465 {
5cd4393b
FB
10466 struct timespec ts;
10467 ret = get_errno(sched_rr_get_interval(arg1, &ts));
10468 if (!is_error(ret)) {
d4290c40 10469 ret = host_to_target_timespec(arg2, &ts);
5cd4393b
FB
10470 }
10471 }
10472 break;
31e31b8a 10473 case TARGET_NR_nanosleep:
1b6b029e 10474 {
1b6b029e 10475 struct timespec req, rem;
53a5960a 10476 target_to_host_timespec(&req, arg1);
9e518226 10477 ret = get_errno(safe_nanosleep(&req, &rem));
53a5960a
PB
10478 if (is_error(ret) && arg2) {
10479 host_to_target_timespec(arg2, &rem);
1b6b029e
FB
10480 }
10481 }
10482 break;
e5febef5 10483#ifdef TARGET_NR_query_module
31e31b8a 10484 case TARGET_NR_query_module:
5cd4393b 10485 goto unimplemented;
e5febef5
TS
10486#endif
10487#ifdef TARGET_NR_nfsservctl
31e31b8a 10488 case TARGET_NR_nfsservctl:
5cd4393b 10489 goto unimplemented;
e5febef5 10490#endif
31e31b8a 10491 case TARGET_NR_prctl:
1e6722f8
PM
10492 switch (arg1) {
10493 case PR_GET_PDEATHSIG:
10494 {
10495 int deathsig;
10496 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
10497 if (!is_error(ret) && arg2
10498 && put_user_ual(deathsig, arg2)) {
10499 goto efault;
e5574487 10500 }
1e6722f8
PM
10501 break;
10502 }
db9526b1
PM
10503#ifdef PR_GET_NAME
10504 case PR_GET_NAME:
10505 {
10506 void *name = lock_user(VERIFY_WRITE, arg2, 16, 1);
10507 if (!name) {
10508 goto efault;
10509 }
10510 ret = get_errno(prctl(arg1, (unsigned long)name,
10511 arg3, arg4, arg5));
10512 unlock_user(name, arg2, 16);
10513 break;
10514 }
10515 case PR_SET_NAME:
10516 {
10517 void *name = lock_user(VERIFY_READ, arg2, 16, 1);
10518 if (!name) {
10519 goto efault;
10520 }
10521 ret = get_errno(prctl(arg1, (unsigned long)name,
10522 arg3, arg4, arg5));
10523 unlock_user(name, arg2, 0);
10524 break;
10525 }
10526#endif
a8b154a6
JC
10527 case PR_GET_SECCOMP:
10528 case PR_SET_SECCOMP:
10529 /* Disable seccomp to prevent the target disabling syscalls we
10530 * need. */
10531 ret = -TARGET_EINVAL;
10532 break;
1e6722f8
PM
10533 default:
10534 /* Most prctl options have no pointer arguments */
10535 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
10536 break;
10537 }
39b9aae1 10538 break;
d2fd1af7
FB
10539#ifdef TARGET_NR_arch_prctl
10540 case TARGET_NR_arch_prctl:
10541#if defined(TARGET_I386) && !defined(TARGET_ABI32)
10542 ret = do_arch_prctl(cpu_env, arg1, arg2);
10543 break;
10544#else
10545 goto unimplemented;
10546#endif
10547#endif
f2c7ba15
AJ
10548#ifdef TARGET_NR_pread64
10549 case TARGET_NR_pread64:
8bf8e9df 10550 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
10551 arg4 = arg5;
10552 arg5 = arg6;
10553 }
f2c7ba15
AJ
10554 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
10555 goto efault;
10556 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
10557 unlock_user(p, arg2, ret);
10558 break;
10559 case TARGET_NR_pwrite64:
8bf8e9df 10560 if (regpairs_aligned(cpu_env, num)) {
ae017a5b
AG
10561 arg4 = arg5;
10562 arg5 = arg6;
10563 }
f2c7ba15
AJ
10564 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
10565 goto efault;
10566 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
10567 unlock_user(p, arg2, 0);
10568 break;
67867308 10569#endif
31e31b8a 10570 case TARGET_NR_getcwd:
579a97f7
FB
10571 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
10572 goto efault;
53a5960a
PB
10573 ret = get_errno(sys_getcwd1(p, arg2));
10574 unlock_user(p, arg1, ret);
31e31b8a
FB
10575 break;
10576 case TARGET_NR_capget:
10577 case TARGET_NR_capset:
e0eb210e
PM
10578 {
10579 struct target_user_cap_header *target_header;
10580 struct target_user_cap_data *target_data = NULL;
10581 struct __user_cap_header_struct header;
10582 struct __user_cap_data_struct data[2];
10583 struct __user_cap_data_struct *dataptr = NULL;
10584 int i, target_datalen;
10585 int data_items = 1;
10586
10587 if (!lock_user_struct(VERIFY_WRITE, target_header, arg1, 1)) {
10588 goto efault;
10589 }
10590 header.version = tswap32(target_header->version);
10591 header.pid = tswap32(target_header->pid);
10592
ec864874 10593 if (header.version != _LINUX_CAPABILITY_VERSION) {
e0eb210e
PM
10594 /* Version 2 and up takes pointer to two user_data structs */
10595 data_items = 2;
10596 }
10597
10598 target_datalen = sizeof(*target_data) * data_items;
10599
10600 if (arg2) {
10601 if (num == TARGET_NR_capget) {
10602 target_data = lock_user(VERIFY_WRITE, arg2, target_datalen, 0);
10603 } else {
10604 target_data = lock_user(VERIFY_READ, arg2, target_datalen, 1);
10605 }
10606 if (!target_data) {
10607 unlock_user_struct(target_header, arg1, 0);
10608 goto efault;
10609 }
10610
10611 if (num == TARGET_NR_capset) {
10612 for (i = 0; i < data_items; i++) {
10613 data[i].effective = tswap32(target_data[i].effective);
10614 data[i].permitted = tswap32(target_data[i].permitted);
10615 data[i].inheritable = tswap32(target_data[i].inheritable);
10616 }
10617 }
10618
10619 dataptr = data;
10620 }
10621
10622 if (num == TARGET_NR_capget) {
10623 ret = get_errno(capget(&header, dataptr));
10624 } else {
10625 ret = get_errno(capset(&header, dataptr));
10626 }
10627
10628 /* The kernel always updates version for both capget and capset */
10629 target_header->version = tswap32(header.version);
10630 unlock_user_struct(target_header, arg1, 1);
10631
10632 if (arg2) {
10633 if (num == TARGET_NR_capget) {
10634 for (i = 0; i < data_items; i++) {
10635 target_data[i].effective = tswap32(data[i].effective);
10636 target_data[i].permitted = tswap32(data[i].permitted);
10637 target_data[i].inheritable = tswap32(data[i].inheritable);
10638 }
10639 unlock_user(target_data, arg2, target_datalen);
10640 } else {
10641 unlock_user(target_data, arg2, 0);
10642 }
10643 }
10644 break;
10645 }
31e31b8a 10646 case TARGET_NR_sigaltstack:
9349b4f9 10647 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUArchState *)cpu_env));
a04e134a 10648 break;
a8fd1aba
PM
10649
10650#ifdef CONFIG_SENDFILE
10651 case TARGET_NR_sendfile:
10652 {
10653 off_t *offp = NULL;
10654 off_t off;
10655 if (arg3) {
10656 ret = get_user_sal(off, arg3);
10657 if (is_error(ret)) {
10658 break;
10659 }
10660 offp = &off;
10661 }
10662 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
10663 if (!is_error(ret) && arg3) {
10664 abi_long ret2 = put_user_sal(off, arg3);
10665 if (is_error(ret2)) {
10666 ret = ret2;
10667 }
10668 }
10669 break;
10670 }
10671#ifdef TARGET_NR_sendfile64
10672 case TARGET_NR_sendfile64:
10673 {
10674 off_t *offp = NULL;
10675 off_t off;
10676 if (arg3) {
10677 ret = get_user_s64(off, arg3);
10678 if (is_error(ret)) {
10679 break;
10680 }
10681 offp = &off;
10682 }
10683 ret = get_errno(sendfile(arg1, arg2, offp, arg4));
10684 if (!is_error(ret) && arg3) {
10685 abi_long ret2 = put_user_s64(off, arg3);
10686 if (is_error(ret2)) {
10687 ret = ret2;
10688 }
10689 }
10690 break;
10691 }
10692#endif
10693#else
31e31b8a 10694 case TARGET_NR_sendfile:
7edd2cf1 10695#ifdef TARGET_NR_sendfile64
a8fd1aba
PM
10696 case TARGET_NR_sendfile64:
10697#endif
5cd4393b 10698 goto unimplemented;
a8fd1aba
PM
10699#endif
10700
ebc05488 10701#ifdef TARGET_NR_getpmsg
31e31b8a 10702 case TARGET_NR_getpmsg:
5cd4393b 10703 goto unimplemented;
ebc05488
FB
10704#endif
10705#ifdef TARGET_NR_putpmsg
31e31b8a 10706 case TARGET_NR_putpmsg:
5cd4393b 10707 goto unimplemented;
ebc05488 10708#endif
048f6b4d 10709#ifdef TARGET_NR_vfork
31e31b8a 10710 case TARGET_NR_vfork:
7eddb5dd
LV
10711 ret = get_errno(do_fork(cpu_env,
10712 CLONE_VFORK | CLONE_VM | TARGET_SIGCHLD,
d865bab5 10713 0, 0, 0, 0));
31e31b8a 10714 break;
048f6b4d 10715#endif
ebc05488 10716#ifdef TARGET_NR_ugetrlimit
31e31b8a 10717 case TARGET_NR_ugetrlimit:
728584be
FB
10718 {
10719 struct rlimit rlim;
e22b7015
WT
10720 int resource = target_to_host_resource(arg1);
10721 ret = get_errno(getrlimit(resource, &rlim));
728584be 10722 if (!is_error(ret)) {
53a5960a 10723 struct target_rlimit *target_rlim;
579a97f7
FB
10724 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
10725 goto efault;
81bbe906
TY
10726 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
10727 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
53a5960a 10728 unlock_user_struct(target_rlim, arg2, 1);
728584be
FB
10729 }
10730 break;
10731 }
ebc05488 10732#endif
a315a145 10733#ifdef TARGET_NR_truncate64
31e31b8a 10734 case TARGET_NR_truncate64:
579a97f7
FB
10735 if (!(p = lock_user_string(arg1)))
10736 goto efault;
53a5960a
PB
10737 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
10738 unlock_user(p, arg1, 0);
667f38b1 10739 break;
a315a145
FB
10740#endif
10741#ifdef TARGET_NR_ftruncate64
31e31b8a 10742 case TARGET_NR_ftruncate64:
ce4defa0 10743 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
667f38b1 10744 break;
a315a145
FB
10745#endif
10746#ifdef TARGET_NR_stat64
31e31b8a 10747 case TARGET_NR_stat64:
579a97f7
FB
10748 if (!(p = lock_user_string(arg1)))
10749 goto efault;
53a5960a
PB
10750 ret = get_errno(stat(path(p), &st));
10751 unlock_user(p, arg1, 0);
6a24a778
AZ
10752 if (!is_error(ret))
10753 ret = host_to_target_stat64(cpu_env, arg2, &st);
10754 break;
a315a145
FB
10755#endif
10756#ifdef TARGET_NR_lstat64
31e31b8a 10757 case TARGET_NR_lstat64:
579a97f7
FB
10758 if (!(p = lock_user_string(arg1)))
10759 goto efault;
53a5960a
PB
10760 ret = get_errno(lstat(path(p), &st));
10761 unlock_user(p, arg1, 0);
6a24a778
AZ
10762 if (!is_error(ret))
10763 ret = host_to_target_stat64(cpu_env, arg2, &st);
10764 break;
a315a145
FB
10765#endif
10766#ifdef TARGET_NR_fstat64
31e31b8a 10767 case TARGET_NR_fstat64:
6a24a778
AZ
10768 ret = get_errno(fstat(arg1, &st));
10769 if (!is_error(ret))
10770 ret = host_to_target_stat64(cpu_env, arg2, &st);
10771 break;
ce4defa0 10772#endif
c0d472b1 10773#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat))
9d33b76b 10774#ifdef TARGET_NR_fstatat64
6a24a778 10775 case TARGET_NR_fstatat64:
9d33b76b
AJ
10776#endif
10777#ifdef TARGET_NR_newfstatat
10778 case TARGET_NR_newfstatat:
10779#endif
6a24a778
AZ
10780 if (!(p = lock_user_string(arg2)))
10781 goto efault;
c0d472b1 10782 ret = get_errno(fstatat(arg1, path(p), &st, arg4));
6a24a778
AZ
10783 if (!is_error(ret))
10784 ret = host_to_target_stat64(cpu_env, arg3, &st);
60cd49d5 10785 break;
a315a145 10786#endif
704eff6c 10787#ifdef TARGET_NR_lchown
67867308 10788 case TARGET_NR_lchown:
579a97f7
FB
10789 if (!(p = lock_user_string(arg1)))
10790 goto efault;
53a5960a
PB
10791 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
10792 unlock_user(p, arg1, 0);
67867308 10793 break;
704eff6c 10794#endif
0c866a7e 10795#ifdef TARGET_NR_getuid
67867308
FB
10796 case TARGET_NR_getuid:
10797 ret = get_errno(high2lowuid(getuid()));
10798 break;
0c866a7e
RV
10799#endif
10800#ifdef TARGET_NR_getgid
67867308
FB
10801 case TARGET_NR_getgid:
10802 ret = get_errno(high2lowgid(getgid()));
10803 break;
0c866a7e
RV
10804#endif
10805#ifdef TARGET_NR_geteuid
67867308
FB
10806 case TARGET_NR_geteuid:
10807 ret = get_errno(high2lowuid(geteuid()));
10808 break;
0c866a7e
RV
10809#endif
10810#ifdef TARGET_NR_getegid
67867308
FB
10811 case TARGET_NR_getegid:
10812 ret = get_errno(high2lowgid(getegid()));
10813 break;
0c866a7e 10814#endif
67867308
FB
10815 case TARGET_NR_setreuid:
10816 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
10817 break;
10818 case TARGET_NR_setregid:
10819 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
10820 break;
10821 case TARGET_NR_getgroups:
10822 {
10823 int gidsetsize = arg1;
0c866a7e 10824 target_id *target_grouplist;
67867308
FB
10825 gid_t *grouplist;
10826 int i;
10827
10828 grouplist = alloca(gidsetsize * sizeof(gid_t));
10829 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
10830 if (gidsetsize == 0)
10831 break;
67867308 10832 if (!is_error(ret)) {
03903ffc 10833 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * sizeof(target_id), 0);
579a97f7
FB
10834 if (!target_grouplist)
10835 goto efault;
a2155fcc 10836 for(i = 0;i < ret; i++)
0c866a7e 10837 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
03903ffc 10838 unlock_user(target_grouplist, arg2, gidsetsize * sizeof(target_id));
67867308
FB
10839 }
10840 }
10841 break;
10842 case TARGET_NR_setgroups:
10843 {
10844 int gidsetsize = arg1;
0c866a7e 10845 target_id *target_grouplist;
f2b79ce9 10846 gid_t *grouplist = NULL;
67867308 10847 int i;
f2b79ce9
DA
10848 if (gidsetsize) {
10849 grouplist = alloca(gidsetsize * sizeof(gid_t));
03903ffc 10850 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * sizeof(target_id), 1);
f2b79ce9
DA
10851 if (!target_grouplist) {
10852 ret = -TARGET_EFAULT;
10853 goto fail;
10854 }
10855 for (i = 0; i < gidsetsize; i++) {
10856 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
10857 }
10858 unlock_user(target_grouplist, arg2, 0);
579a97f7 10859 }
67867308
FB
10860 ret = get_errno(setgroups(gidsetsize, grouplist));
10861 }
10862 break;
10863 case TARGET_NR_fchown:
10864 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
10865 break;
c0d472b1 10866#if defined(TARGET_NR_fchownat)
ccfa72b7 10867 case TARGET_NR_fchownat:
579a97f7
FB
10868 if (!(p = lock_user_string(arg2)))
10869 goto efault;
c0d472b1
PM
10870 ret = get_errno(fchownat(arg1, p, low2highuid(arg3),
10871 low2highgid(arg4), arg5));
579a97f7 10872 unlock_user(p, arg2, 0);
ccfa72b7
TS
10873 break;
10874#endif
67867308
FB
10875#ifdef TARGET_NR_setresuid
10876 case TARGET_NR_setresuid:
fd6f7798
PM
10877 ret = get_errno(sys_setresuid(low2highuid(arg1),
10878 low2highuid(arg2),
10879 low2highuid(arg3)));
67867308
FB
10880 break;
10881#endif
10882#ifdef TARGET_NR_getresuid
10883 case TARGET_NR_getresuid:
10884 {
53a5960a 10885 uid_t ruid, euid, suid;
67867308
FB
10886 ret = get_errno(getresuid(&ruid, &euid, &suid));
10887 if (!is_error(ret)) {
76ca310a
PM
10888 if (put_user_id(high2lowuid(ruid), arg1)
10889 || put_user_id(high2lowuid(euid), arg2)
10890 || put_user_id(high2lowuid(suid), arg3))
2f619698 10891 goto efault;
67867308
FB
10892 }
10893 }
10894 break;
10895#endif
10896#ifdef TARGET_NR_getresgid
10897 case TARGET_NR_setresgid:
fd6f7798
PM
10898 ret = get_errno(sys_setresgid(low2highgid(arg1),
10899 low2highgid(arg2),
10900 low2highgid(arg3)));
67867308
FB
10901 break;
10902#endif
10903#ifdef TARGET_NR_getresgid
10904 case TARGET_NR_getresgid:
10905 {
53a5960a 10906 gid_t rgid, egid, sgid;
67867308
FB
10907 ret = get_errno(getresgid(&rgid, &egid, &sgid));
10908 if (!is_error(ret)) {
76ca310a
PM
10909 if (put_user_id(high2lowgid(rgid), arg1)
10910 || put_user_id(high2lowgid(egid), arg2)
10911 || put_user_id(high2lowgid(sgid), arg3))
2f619698 10912 goto efault;
67867308
FB
10913 }
10914 }
10915 break;
10916#endif
704eff6c 10917#ifdef TARGET_NR_chown
67867308 10918 case TARGET_NR_chown:
579a97f7
FB
10919 if (!(p = lock_user_string(arg1)))
10920 goto efault;
53a5960a
PB
10921 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
10922 unlock_user(p, arg1, 0);
67867308 10923 break;
704eff6c 10924#endif
67867308 10925 case TARGET_NR_setuid:
fd6f7798 10926 ret = get_errno(sys_setuid(low2highuid(arg1)));
67867308
FB
10927 break;
10928 case TARGET_NR_setgid:
fd6f7798 10929 ret = get_errno(sys_setgid(low2highgid(arg1)));
67867308
FB
10930 break;
10931 case TARGET_NR_setfsuid:
10932 ret = get_errno(setfsuid(arg1));
10933 break;
10934 case TARGET_NR_setfsgid:
10935 ret = get_errno(setfsgid(arg1));
10936 break;
67867308 10937
a315a145 10938#ifdef TARGET_NR_lchown32
31e31b8a 10939 case TARGET_NR_lchown32:
579a97f7
FB
10940 if (!(p = lock_user_string(arg1)))
10941 goto efault;
53a5960a
PB
10942 ret = get_errno(lchown(p, arg2, arg3));
10943 unlock_user(p, arg1, 0);
b03c60f3 10944 break;
a315a145
FB
10945#endif
10946#ifdef TARGET_NR_getuid32
31e31b8a 10947 case TARGET_NR_getuid32:
b03c60f3
FB
10948 ret = get_errno(getuid());
10949 break;
a315a145 10950#endif
64b4d28c
AJ
10951
10952#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
10953 /* Alpha specific */
10954 case TARGET_NR_getxuid:
ba0e276d
RH
10955 {
10956 uid_t euid;
10957 euid=geteuid();
10958 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
10959 }
64b4d28c
AJ
10960 ret = get_errno(getuid());
10961 break;
10962#endif
10963#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
10964 /* Alpha specific */
10965 case TARGET_NR_getxgid:
ba0e276d
RH
10966 {
10967 uid_t egid;
10968 egid=getegid();
10969 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
10970 }
64b4d28c
AJ
10971 ret = get_errno(getgid());
10972 break;
10973#endif
ba0e276d
RH
10974#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
10975 /* Alpha specific */
10976 case TARGET_NR_osf_getsysinfo:
10977 ret = -TARGET_EOPNOTSUPP;
10978 switch (arg1) {
10979 case TARGET_GSI_IEEE_FP_CONTROL:
10980 {
10981 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
10982
10983 /* Copied from linux ieee_fpcr_to_swcr. */
10984 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
10985 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
10986 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
10987 | SWCR_TRAP_ENABLE_DZE
10988 | SWCR_TRAP_ENABLE_OVF);
10989 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
10990 | SWCR_TRAP_ENABLE_INE);
10991 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
10992 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
10993
10994 if (put_user_u64 (swcr, arg2))
10995 goto efault;
10996 ret = 0;
10997 }
10998 break;
10999
11000 /* case GSI_IEEE_STATE_AT_SIGNAL:
11001 -- Not implemented in linux kernel.
11002 case GSI_UACPROC:
11003 -- Retrieves current unaligned access state; not much used.
11004 case GSI_PROC_TYPE:
11005 -- Retrieves implver information; surely not used.
11006 case GSI_GET_HWRPB:
11007 -- Grabs a copy of the HWRPB; surely not used.
11008 */
11009 }
11010 break;
11011#endif
11012#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
11013 /* Alpha specific */
11014 case TARGET_NR_osf_setsysinfo:
11015 ret = -TARGET_EOPNOTSUPP;
11016 switch (arg1) {
11017 case TARGET_SSI_IEEE_FP_CONTROL:
ba0e276d
RH
11018 {
11019 uint64_t swcr, fpcr, orig_fpcr;
11020
6e06d515 11021 if (get_user_u64 (swcr, arg2)) {
ba0e276d 11022 goto efault;
6e06d515
RH
11023 }
11024 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d
RH
11025 fpcr = orig_fpcr & FPCR_DYN_MASK;
11026
11027 /* Copied from linux ieee_swcr_to_fpcr. */
11028 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
11029 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
11030 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
11031 | SWCR_TRAP_ENABLE_DZE
11032 | SWCR_TRAP_ENABLE_OVF)) << 48;
11033 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
11034 | SWCR_TRAP_ENABLE_INE)) << 57;
11035 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
11036 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
11037
6e06d515 11038 cpu_alpha_store_fpcr(cpu_env, fpcr);
ba0e276d 11039 ret = 0;
6e06d515
RH
11040 }
11041 break;
11042
11043 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
11044 {
11045 uint64_t exc, fpcr, orig_fpcr;
11046 int si_code;
11047
11048 if (get_user_u64(exc, arg2)) {
11049 goto efault;
11050 }
ba0e276d 11051
6e06d515 11052 orig_fpcr = cpu_alpha_load_fpcr(cpu_env);
ba0e276d 11053
6e06d515
RH
11054 /* We only add to the exception status here. */
11055 fpcr = orig_fpcr | ((exc & SWCR_STATUS_MASK) << 35);
11056
11057 cpu_alpha_store_fpcr(cpu_env, fpcr);
11058 ret = 0;
11059
11060 /* Old exceptions are not signaled. */
11061 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
11062
11063 /* If any exceptions set by this call,
11064 and are unmasked, send a signal. */
11065 si_code = 0;
11066 if ((fpcr & (FPCR_INE | FPCR_INED)) == FPCR_INE) {
11067 si_code = TARGET_FPE_FLTRES;
11068 }
11069 if ((fpcr & (FPCR_UNF | FPCR_UNFD)) == FPCR_UNF) {
11070 si_code = TARGET_FPE_FLTUND;
11071 }
11072 if ((fpcr & (FPCR_OVF | FPCR_OVFD)) == FPCR_OVF) {
11073 si_code = TARGET_FPE_FLTOVF;
11074 }
11075 if ((fpcr & (FPCR_DZE | FPCR_DZED)) == FPCR_DZE) {
11076 si_code = TARGET_FPE_FLTDIV;
11077 }
11078 if ((fpcr & (FPCR_INV | FPCR_INVD)) == FPCR_INV) {
11079 si_code = TARGET_FPE_FLTINV;
11080 }
11081 if (si_code != 0) {
11082 target_siginfo_t info;
11083 info.si_signo = SIGFPE;
11084 info.si_errno = 0;
11085 info.si_code = si_code;
11086 info._sifields._sigfault._addr
11087 = ((CPUArchState *)cpu_env)->pc;
9d2803f7
PM
11088 queue_signal((CPUArchState *)cpu_env, info.si_signo,
11089 QEMU_SI_FAULT, &info);
ba0e276d
RH
11090 }
11091 }
11092 break;
11093
11094 /* case SSI_NVPAIRS:
11095 -- Used with SSIN_UACPROC to enable unaligned accesses.
11096 case SSI_IEEE_STATE_AT_SIGNAL:
11097 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
11098 -- Not implemented in linux kernel
11099 */
11100 }
11101 break;
11102#endif
11103#ifdef TARGET_NR_osf_sigprocmask
11104 /* Alpha specific. */
11105 case TARGET_NR_osf_sigprocmask:
11106 {
11107 abi_ulong mask;
bc088ba1 11108 int how;
ba0e276d
RH
11109 sigset_t set, oldset;
11110
11111 switch(arg1) {
11112 case TARGET_SIG_BLOCK:
11113 how = SIG_BLOCK;
11114 break;
11115 case TARGET_SIG_UNBLOCK:
11116 how = SIG_UNBLOCK;
11117 break;
11118 case TARGET_SIG_SETMASK:
11119 how = SIG_SETMASK;
11120 break;
11121 default:
11122 ret = -TARGET_EINVAL;
11123 goto fail;
11124 }
11125 mask = arg2;
11126 target_to_host_old_sigset(&set, &mask);
3d3efba0
PM
11127 ret = do_sigprocmask(how, &set, &oldset);
11128 if (!ret) {
11129 host_to_target_old_sigset(&mask, &oldset);
11130 ret = mask;
11131 }
ba0e276d
RH
11132 }
11133 break;
11134#endif
64b4d28c 11135
a315a145 11136#ifdef TARGET_NR_getgid32
31e31b8a 11137 case TARGET_NR_getgid32:
b03c60f3
FB
11138 ret = get_errno(getgid());
11139 break;
a315a145
FB
11140#endif
11141#ifdef TARGET_NR_geteuid32
31e31b8a 11142 case TARGET_NR_geteuid32:
b03c60f3
FB
11143 ret = get_errno(geteuid());
11144 break;
a315a145
FB
11145#endif
11146#ifdef TARGET_NR_getegid32
31e31b8a 11147 case TARGET_NR_getegid32:
b03c60f3
FB
11148 ret = get_errno(getegid());
11149 break;
a315a145
FB
11150#endif
11151#ifdef TARGET_NR_setreuid32
31e31b8a 11152 case TARGET_NR_setreuid32:
b03c60f3
FB
11153 ret = get_errno(setreuid(arg1, arg2));
11154 break;
a315a145
FB
11155#endif
11156#ifdef TARGET_NR_setregid32
31e31b8a 11157 case TARGET_NR_setregid32:
b03c60f3
FB
11158 ret = get_errno(setregid(arg1, arg2));
11159 break;
a315a145
FB
11160#endif
11161#ifdef TARGET_NR_getgroups32
31e31b8a 11162 case TARGET_NR_getgroups32:
99c475ab
FB
11163 {
11164 int gidsetsize = arg1;
53a5960a 11165 uint32_t *target_grouplist;
99c475ab
FB
11166 gid_t *grouplist;
11167 int i;
11168
11169 grouplist = alloca(gidsetsize * sizeof(gid_t));
11170 ret = get_errno(getgroups(gidsetsize, grouplist));
cb3bc233
AZ
11171 if (gidsetsize == 0)
11172 break;
99c475ab 11173 if (!is_error(ret)) {
579a97f7
FB
11174 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
11175 if (!target_grouplist) {
11176 ret = -TARGET_EFAULT;
11177 goto fail;
11178 }
a2155fcc 11179 for(i = 0;i < ret; i++)
53a5960a
PB
11180 target_grouplist[i] = tswap32(grouplist[i]);
11181 unlock_user(target_grouplist, arg2, gidsetsize * 4);
99c475ab
FB
11182 }
11183 }
11184 break;
a315a145
FB
11185#endif
11186#ifdef TARGET_NR_setgroups32
31e31b8a 11187 case TARGET_NR_setgroups32:
99c475ab
FB
11188 {
11189 int gidsetsize = arg1;
53a5960a 11190 uint32_t *target_grouplist;
99c475ab
FB
11191 gid_t *grouplist;
11192 int i;
3b46e624 11193
99c475ab 11194 grouplist = alloca(gidsetsize * sizeof(gid_t));
579a97f7
FB
11195 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
11196 if (!target_grouplist) {
11197 ret = -TARGET_EFAULT;
11198 goto fail;
11199 }
99c475ab 11200 for(i = 0;i < gidsetsize; i++)
53a5960a
PB
11201 grouplist[i] = tswap32(target_grouplist[i]);
11202 unlock_user(target_grouplist, arg2, 0);
99c475ab
FB
11203 ret = get_errno(setgroups(gidsetsize, grouplist));
11204 }
11205 break;
a315a145
FB
11206#endif
11207#ifdef TARGET_NR_fchown32
31e31b8a 11208 case TARGET_NR_fchown32:
b03c60f3
FB
11209 ret = get_errno(fchown(arg1, arg2, arg3));
11210 break;
a315a145
FB
11211#endif
11212#ifdef TARGET_NR_setresuid32
31e31b8a 11213 case TARGET_NR_setresuid32:
fd6f7798 11214 ret = get_errno(sys_setresuid(arg1, arg2, arg3));
b03c60f3 11215 break;
a315a145
FB
11216#endif
11217#ifdef TARGET_NR_getresuid32
31e31b8a 11218 case TARGET_NR_getresuid32:
b03c60f3 11219 {
53a5960a 11220 uid_t ruid, euid, suid;
b03c60f3
FB
11221 ret = get_errno(getresuid(&ruid, &euid, &suid));
11222 if (!is_error(ret)) {
2f619698
FB
11223 if (put_user_u32(ruid, arg1)
11224 || put_user_u32(euid, arg2)
11225 || put_user_u32(suid, arg3))
11226 goto efault;
b03c60f3
FB
11227 }
11228 }
11229 break;
a315a145
FB
11230#endif
11231#ifdef TARGET_NR_setresgid32
31e31b8a 11232 case TARGET_NR_setresgid32:
fd6f7798 11233 ret = get_errno(sys_setresgid(arg1, arg2, arg3));
b03c60f3 11234 break;
a315a145
FB
11235#endif
11236#ifdef TARGET_NR_getresgid32
31e31b8a 11237 case TARGET_NR_getresgid32:
b03c60f3 11238 {
53a5960a 11239 gid_t rgid, egid, sgid;
b03c60f3
FB
11240 ret = get_errno(getresgid(&rgid, &egid, &sgid));
11241 if (!is_error(ret)) {
2f619698
FB
11242 if (put_user_u32(rgid, arg1)
11243 || put_user_u32(egid, arg2)
11244 || put_user_u32(sgid, arg3))
11245 goto efault;
b03c60f3
FB
11246 }
11247 }
11248 break;
a315a145
FB
11249#endif
11250#ifdef TARGET_NR_chown32
31e31b8a 11251 case TARGET_NR_chown32:
579a97f7
FB
11252 if (!(p = lock_user_string(arg1)))
11253 goto efault;
53a5960a
PB
11254 ret = get_errno(chown(p, arg2, arg3));
11255 unlock_user(p, arg1, 0);
b03c60f3 11256 break;
a315a145
FB
11257#endif
11258#ifdef TARGET_NR_setuid32
31e31b8a 11259 case TARGET_NR_setuid32:
fd6f7798 11260 ret = get_errno(sys_setuid(arg1));
b03c60f3 11261 break;
a315a145
FB
11262#endif
11263#ifdef TARGET_NR_setgid32
31e31b8a 11264 case TARGET_NR_setgid32:
fd6f7798 11265 ret = get_errno(sys_setgid(arg1));
b03c60f3 11266 break;
a315a145
FB
11267#endif
11268#ifdef TARGET_NR_setfsuid32
31e31b8a 11269 case TARGET_NR_setfsuid32:
b03c60f3
FB
11270 ret = get_errno(setfsuid(arg1));
11271 break;
a315a145
FB
11272#endif
11273#ifdef TARGET_NR_setfsgid32
31e31b8a 11274 case TARGET_NR_setfsgid32:
b03c60f3
FB
11275 ret = get_errno(setfsgid(arg1));
11276 break;
a315a145 11277#endif
67867308 11278
31e31b8a 11279 case TARGET_NR_pivot_root:
b03c60f3 11280 goto unimplemented;
ffa65c3b 11281#ifdef TARGET_NR_mincore
31e31b8a 11282 case TARGET_NR_mincore:
04bb9ace
AJ
11283 {
11284 void *a;
98a3331a
FSM
11285 ret = -TARGET_ENOMEM;
11286 a = lock_user(VERIFY_READ, arg1, arg2, 0);
11287 if (!a) {
11288 goto fail;
11289 }
04bb9ace 11290 ret = -TARGET_EFAULT;
98a3331a
FSM
11291 p = lock_user_string(arg3);
11292 if (!p) {
04bb9ace 11293 goto mincore_fail;
98a3331a 11294 }
04bb9ace
AJ
11295 ret = get_errno(mincore(a, arg2, p));
11296 unlock_user(p, arg3, ret);
11297 mincore_fail:
11298 unlock_user(a, arg1, 0);
11299 }
11300 break;
ffa65c3b 11301#endif
408321b6
AJ
11302#ifdef TARGET_NR_arm_fadvise64_64
11303 case TARGET_NR_arm_fadvise64_64:
e0156a9d
PM
11304 /* arm_fadvise64_64 looks like fadvise64_64 but
11305 * with different argument order: fd, advice, offset, len
11306 * rather than the usual fd, offset, len, advice.
11307 * Note that offset and len are both 64-bit so appear as
11308 * pairs of 32-bit registers.
11309 */
11310 ret = posix_fadvise(arg1, target_offset64(arg3, arg4),
11311 target_offset64(arg5, arg6), arg2);
11312 ret = -host_to_target_errno(ret);
11313 break;
408321b6 11314#endif
badd3cd8
PM
11315
11316#if TARGET_ABI_BITS == 32
11317
11318#ifdef TARGET_NR_fadvise64_64
11319 case TARGET_NR_fadvise64_64:
43046b5a
LV
11320#if defined(TARGET_PPC)
11321 /* 6 args: fd, advice, offset (high, low), len (high, low) */
11322 ret = arg2;
11323 arg2 = arg3;
11324 arg3 = arg4;
11325 arg4 = arg5;
11326 arg5 = arg6;
11327 arg6 = ret;
11328#else
badd3cd8 11329 /* 6 args: fd, offset (high, low), len (high, low), advice */
8bf8e9df 11330 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11331 /* offset is in (3,4), len in (5,6) and advice in 7 */
11332 arg2 = arg3;
11333 arg3 = arg4;
11334 arg4 = arg5;
11335 arg5 = arg6;
11336 arg6 = arg7;
11337 }
43046b5a 11338#endif
badd3cd8
PM
11339 ret = -host_to_target_errno(posix_fadvise(arg1,
11340 target_offset64(arg2, arg3),
11341 target_offset64(arg4, arg5),
11342 arg6));
11343 break;
11344#endif
11345
11346#ifdef TARGET_NR_fadvise64
11347 case TARGET_NR_fadvise64:
11348 /* 5 args: fd, offset (high, low), len, advice */
8bf8e9df 11349 if (regpairs_aligned(cpu_env, num)) {
badd3cd8
PM
11350 /* offset is in (3,4), len in 5 and advice in 6 */
11351 arg2 = arg3;
11352 arg3 = arg4;
11353 arg4 = arg5;
11354 arg5 = arg6;
11355 }
11356 ret = -host_to_target_errno(posix_fadvise(arg1,
11357 target_offset64(arg2, arg3),
11358 arg4, arg5));
11359 break;
408321b6 11360#endif
badd3cd8
PM
11361
11362#else /* not a 32-bit ABI */
e0156a9d 11363#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_fadvise64)
408321b6
AJ
11364#ifdef TARGET_NR_fadvise64_64
11365 case TARGET_NR_fadvise64_64:
11366#endif
e72d2cc7
UH
11367#ifdef TARGET_NR_fadvise64
11368 case TARGET_NR_fadvise64:
11369#endif
11370#ifdef TARGET_S390X
11371 switch (arg4) {
11372 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
11373 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
11374 case 6: arg4 = POSIX_FADV_DONTNEED; break;
11375 case 7: arg4 = POSIX_FADV_NOREUSE; break;
11376 default: break;
11377 }
11378#endif
977d8241
PM
11379 ret = -host_to_target_errno(posix_fadvise(arg1, arg2, arg3, arg4));
11380 break;
408321b6 11381#endif
badd3cd8
PM
11382#endif /* end of 64-bit ABI fadvise handling */
11383
ffa65c3b 11384#ifdef TARGET_NR_madvise
31e31b8a 11385 case TARGET_NR_madvise:
24836689 11386 /* A straight passthrough may not be safe because qemu sometimes
d2d6b857 11387 turns private file-backed mappings into anonymous mappings.
24836689
PB
11388 This will break MADV_DONTNEED.
11389 This is a hint, so ignoring and returning success is ok. */
11390 ret = get_errno(0);
11391 break;
ffa65c3b 11392#endif
992f48a0 11393#if TARGET_ABI_BITS == 32
31e31b8a 11394 case TARGET_NR_fcntl64:
77e4672d 11395 {
b1e341eb 11396 int cmd;
77e4672d 11397 struct flock64 fl;
213d3e9e
PM
11398 from_flock64_fn *copyfrom = copy_from_user_flock64;
11399 to_flock64_fn *copyto = copy_to_user_flock64;
11400
ce4defa0 11401#ifdef TARGET_ARM
213d3e9e
PM
11402 if (((CPUARMState *)cpu_env)->eabi) {
11403 copyfrom = copy_from_user_eabi_flock64;
11404 copyto = copy_to_user_eabi_flock64;
11405 }
ce4defa0 11406#endif
77e4672d 11407
5f106811 11408 cmd = target_to_host_fcntl_cmd(arg2);
31b63193
PM
11409 if (cmd == -TARGET_EINVAL) {
11410 ret = cmd;
11411 break;
11412 }
b1e341eb 11413
60cd49d5 11414 switch(arg2) {
b1e341eb 11415 case TARGET_F_GETLK64:
213d3e9e
PM
11416 ret = copyfrom(&fl, arg3);
11417 if (ret) {
11418 break;
5813427b 11419 }
b1e341eb 11420 ret = get_errno(fcntl(arg1, cmd, &fl));
213d3e9e
PM
11421 if (ret == 0) {
11422 ret = copyto(arg3, &fl);
11423 }
77e4672d
FB
11424 break;
11425
b1e341eb
TS
11426 case TARGET_F_SETLK64:
11427 case TARGET_F_SETLKW64:
213d3e9e
PM
11428 ret = copyfrom(&fl, arg3);
11429 if (ret) {
11430 break;
ce4defa0 11431 }
435da5e7 11432 ret = get_errno(safe_fcntl(arg1, cmd, &fl));
77e4672d 11433 break;
60cd49d5 11434 default:
5f106811 11435 ret = do_fcntl(arg1, arg2, arg3);
60cd49d5
FB
11436 break;
11437 }
77e4672d
FB
11438 break;
11439 }
60cd49d5 11440#endif
7d600c80
TS
11441#ifdef TARGET_NR_cacheflush
11442 case TARGET_NR_cacheflush:
11443 /* self-modifying code is handled automatically, so nothing needed */
11444 ret = 0;
11445 break;
11446#endif
ebc05488 11447#ifdef TARGET_NR_security
31e31b8a
FB
11448 case TARGET_NR_security:
11449 goto unimplemented;
c573ff67
FB
11450#endif
11451#ifdef TARGET_NR_getpagesize
11452 case TARGET_NR_getpagesize:
11453 ret = TARGET_PAGE_SIZE;
11454 break;
ebc05488 11455#endif
31e31b8a
FB
11456 case TARGET_NR_gettid:
11457 ret = get_errno(gettid());
11458 break;
e5febef5 11459#ifdef TARGET_NR_readahead
31e31b8a 11460 case TARGET_NR_readahead:
2054ac9b 11461#if TARGET_ABI_BITS == 32
8bf8e9df 11462 if (regpairs_aligned(cpu_env, num)) {
2054ac9b
AJ
11463 arg2 = arg3;
11464 arg3 = arg4;
11465 arg4 = arg5;
11466 }
77c6850f 11467 ret = get_errno(readahead(arg1, target_offset64(arg2, arg3) , arg4));
2054ac9b
AJ
11468#else
11469 ret = get_errno(readahead(arg1, arg2, arg3));
11470#endif
11471 break;
e5febef5 11472#endif
a790ae38 11473#ifdef CONFIG_ATTR
ebc05488 11474#ifdef TARGET_NR_setxattr
31e31b8a
FB
11475 case TARGET_NR_listxattr:
11476 case TARGET_NR_llistxattr:
fb5590f7
PM
11477 {
11478 void *p, *b = 0;
11479 if (arg2) {
11480 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11481 if (!b) {
11482 ret = -TARGET_EFAULT;
11483 break;
11484 }
11485 }
11486 p = lock_user_string(arg1);
11487 if (p) {
11488 if (num == TARGET_NR_listxattr) {
11489 ret = get_errno(listxattr(p, b, arg3));
11490 } else {
11491 ret = get_errno(llistxattr(p, b, arg3));
11492 }
11493 } else {
11494 ret = -TARGET_EFAULT;
11495 }
11496 unlock_user(p, arg1, 0);
11497 unlock_user(b, arg2, arg3);
11498 break;
11499 }
31e31b8a 11500 case TARGET_NR_flistxattr:
fb5590f7
PM
11501 {
11502 void *b = 0;
11503 if (arg2) {
11504 b = lock_user(VERIFY_WRITE, arg2, arg3, 0);
11505 if (!b) {
11506 ret = -TARGET_EFAULT;
11507 break;
11508 }
11509 }
11510 ret = get_errno(flistxattr(arg1, b, arg3));
11511 unlock_user(b, arg2, arg3);
6f932f91 11512 break;
fb5590f7 11513 }
a790ae38 11514 case TARGET_NR_setxattr:
30297b55 11515 case TARGET_NR_lsetxattr:
a790ae38 11516 {
e3c33ec6
PM
11517 void *p, *n, *v = 0;
11518 if (arg3) {
11519 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11520 if (!v) {
11521 ret = -TARGET_EFAULT;
11522 break;
11523 }
11524 }
a790ae38
ACH
11525 p = lock_user_string(arg1);
11526 n = lock_user_string(arg2);
e3c33ec6 11527 if (p && n) {
30297b55
PM
11528 if (num == TARGET_NR_setxattr) {
11529 ret = get_errno(setxattr(p, n, v, arg4, arg5));
11530 } else {
11531 ret = get_errno(lsetxattr(p, n, v, arg4, arg5));
11532 }
a790ae38
ACH
11533 } else {
11534 ret = -TARGET_EFAULT;
11535 }
11536 unlock_user(p, arg1, 0);
11537 unlock_user(n, arg2, 0);
11538 unlock_user(v, arg3, 0);
11539 }
11540 break;
30297b55
PM
11541 case TARGET_NR_fsetxattr:
11542 {
11543 void *n, *v = 0;
11544 if (arg3) {
11545 v = lock_user(VERIFY_READ, arg3, arg4, 1);
11546 if (!v) {
11547 ret = -TARGET_EFAULT;
11548 break;
11549 }
11550 }
11551 n = lock_user_string(arg2);
11552 if (n) {
11553 ret = get_errno(fsetxattr(arg1, n, v, arg4, arg5));
11554 } else {
11555 ret = -TARGET_EFAULT;
11556 }
11557 unlock_user(n, arg2, 0);
11558 unlock_user(v, arg3, 0);
11559 }
11560 break;
a790ae38 11561 case TARGET_NR_getxattr:
30297b55 11562 case TARGET_NR_lgetxattr:
a790ae38 11563 {
e3c33ec6
PM
11564 void *p, *n, *v = 0;
11565 if (arg3) {
11566 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11567 if (!v) {
11568 ret = -TARGET_EFAULT;
11569 break;
11570 }
11571 }
a790ae38
ACH
11572 p = lock_user_string(arg1);
11573 n = lock_user_string(arg2);
e3c33ec6 11574 if (p && n) {
30297b55
PM
11575 if (num == TARGET_NR_getxattr) {
11576 ret = get_errno(getxattr(p, n, v, arg4));
11577 } else {
11578 ret = get_errno(lgetxattr(p, n, v, arg4));
11579 }
a790ae38
ACH
11580 } else {
11581 ret = -TARGET_EFAULT;
11582 }
11583 unlock_user(p, arg1, 0);
11584 unlock_user(n, arg2, 0);
11585 unlock_user(v, arg3, arg4);
11586 }
11587 break;
30297b55
PM
11588 case TARGET_NR_fgetxattr:
11589 {
11590 void *n, *v = 0;
11591 if (arg3) {
11592 v = lock_user(VERIFY_WRITE, arg3, arg4, 0);
11593 if (!v) {
11594 ret = -TARGET_EFAULT;
11595 break;
11596 }
11597 }
11598 n = lock_user_string(arg2);
11599 if (n) {
11600 ret = get_errno(fgetxattr(arg1, n, v, arg4));
11601 } else {
11602 ret = -TARGET_EFAULT;
11603 }
11604 unlock_user(n, arg2, 0);
11605 unlock_user(v, arg3, arg4);
11606 }
11607 break;
a790ae38 11608 case TARGET_NR_removexattr:
30297b55 11609 case TARGET_NR_lremovexattr:
a790ae38
ACH
11610 {
11611 void *p, *n;
11612 p = lock_user_string(arg1);
11613 n = lock_user_string(arg2);
11614 if (p && n) {
30297b55
PM
11615 if (num == TARGET_NR_removexattr) {
11616 ret = get_errno(removexattr(p, n));
11617 } else {
11618 ret = get_errno(lremovexattr(p, n));
11619 }
a790ae38
ACH
11620 } else {
11621 ret = -TARGET_EFAULT;
11622 }
11623 unlock_user(p, arg1, 0);
11624 unlock_user(n, arg2, 0);
11625 }
11626 break;
30297b55
PM
11627 case TARGET_NR_fremovexattr:
11628 {
11629 void *n;
11630 n = lock_user_string(arg2);
11631 if (n) {
11632 ret = get_errno(fremovexattr(arg1, n));
11633 } else {
11634 ret = -TARGET_EFAULT;
11635 }
11636 unlock_user(n, arg2, 0);
11637 }
11638 break;
ebc05488 11639#endif
a790ae38 11640#endif /* CONFIG_ATTR */
ebc05488 11641#ifdef TARGET_NR_set_thread_area
5cd4393b 11642 case TARGET_NR_set_thread_area:
8d18e893 11643#if defined(TARGET_MIPS)
d279279e 11644 ((CPUMIPSState *) cpu_env)->active_tc.CP0_UserLocal = arg1;
6f5b89a0
TS
11645 ret = 0;
11646 break;
ef96779b
EI
11647#elif defined(TARGET_CRIS)
11648 if (arg1 & 0xff)
11649 ret = -TARGET_EINVAL;
11650 else {
11651 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
11652 ret = 0;
11653 }
11654 break;
8d18e893
FB
11655#elif defined(TARGET_I386) && defined(TARGET_ABI32)
11656 ret = do_set_thread_area(cpu_env, arg1);
11657 break;
1ccd9374
PM
11658#elif defined(TARGET_M68K)
11659 {
0429a971 11660 TaskState *ts = cpu->opaque;
1ccd9374 11661 ts->tp_value = arg1;
95c1eb19 11662 ret = 0;
1ccd9374
PM
11663 break;
11664 }
6f5b89a0
TS
11665#else
11666 goto unimplemented_nowarn;
11667#endif
11668#endif
11669#ifdef TARGET_NR_get_thread_area
5cd4393b 11670 case TARGET_NR_get_thread_area:
8d18e893
FB
11671#if defined(TARGET_I386) && defined(TARGET_ABI32)
11672 ret = do_get_thread_area(cpu_env, arg1);
d312bbe1 11673 break;
1ccd9374
PM
11674#elif defined(TARGET_M68K)
11675 {
0429a971 11676 TaskState *ts = cpu->opaque;
1ccd9374
PM
11677 ret = ts->tp_value;
11678 break;
11679 }
8d18e893 11680#else
5cd4393b 11681 goto unimplemented_nowarn;
48dc41eb 11682#endif
8d18e893 11683#endif
48dc41eb
FB
11684#ifdef TARGET_NR_getdomainname
11685 case TARGET_NR_getdomainname:
11686 goto unimplemented_nowarn;
ebc05488 11687#endif
6f5b89a0 11688
b5906f95
TS
11689#ifdef TARGET_NR_clock_gettime
11690 case TARGET_NR_clock_gettime:
11691 {
11692 struct timespec ts;
11693 ret = get_errno(clock_gettime(arg1, &ts));
11694 if (!is_error(ret)) {
11695 host_to_target_timespec(arg2, &ts);
11696 }
11697 break;
11698 }
11699#endif
11700#ifdef TARGET_NR_clock_getres
11701 case TARGET_NR_clock_getres:
11702 {
11703 struct timespec ts;
11704 ret = get_errno(clock_getres(arg1, &ts));
11705 if (!is_error(ret)) {
11706 host_to_target_timespec(arg2, &ts);
11707 }
11708 break;
11709 }
11710#endif
63d7651b
PB
11711#ifdef TARGET_NR_clock_nanosleep
11712 case TARGET_NR_clock_nanosleep:
11713 {
11714 struct timespec ts;
11715 target_to_host_timespec(&ts, arg3);
9e518226
PM
11716 ret = get_errno(safe_clock_nanosleep(arg1, arg2,
11717 &ts, arg4 ? &ts : NULL));
63d7651b
PB
11718 if (arg4)
11719 host_to_target_timespec(arg4, &ts);
8fbe8fdf
TM
11720
11721#if defined(TARGET_PPC)
11722 /* clock_nanosleep is odd in that it returns positive errno values.
11723 * On PPC, CR0 bit 3 should be set in such a situation. */
9e518226 11724 if (ret && ret != -TARGET_ERESTARTSYS) {
8fbe8fdf
TM
11725 ((CPUPPCState *)cpu_env)->crf[0] |= 1;
11726 }
11727#endif
63d7651b
PB
11728 break;
11729 }
11730#endif
b5906f95 11731
6f5b89a0
TS
11732#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
11733 case TARGET_NR_set_tid_address:
579a97f7
FB
11734 ret = get_errno(set_tid_address((int *)g2h(arg1)));
11735 break;
6f5b89a0
TS
11736#endif
11737
4cae1d16 11738 case TARGET_NR_tkill:
bef653d9 11739 ret = get_errno(safe_tkill((int)arg1, target_to_host_signal(arg2)));
4cae1d16 11740 break;
4cae1d16 11741
71455574 11742 case TARGET_NR_tgkill:
bef653d9 11743 ret = get_errno(safe_tgkill((int)arg1, (int)arg2,
4cb05961 11744 target_to_host_signal(arg3)));
bef653d9 11745 break;
71455574 11746
4f2b1fe8
TS
11747#ifdef TARGET_NR_set_robust_list
11748 case TARGET_NR_set_robust_list:
e9a970a8
PM
11749 case TARGET_NR_get_robust_list:
11750 /* The ABI for supporting robust futexes has userspace pass
11751 * the kernel a pointer to a linked list which is updated by
11752 * userspace after the syscall; the list is walked by the kernel
11753 * when the thread exits. Since the linked list in QEMU guest
11754 * memory isn't a valid linked list for the host and we have
11755 * no way to reliably intercept the thread-death event, we can't
11756 * support these. Silently return ENOSYS so that guest userspace
11757 * falls back to a non-robust futex implementation (which should
11758 * be OK except in the corner case of the guest crashing while
11759 * holding a mutex that is shared with another process via
11760 * shared memory).
11761 */
11762 goto unimplemented_nowarn;
4f2b1fe8
TS
11763#endif
11764
1acae9f2 11765#if defined(TARGET_NR_utimensat)
9007f0ef
TS
11766 case TARGET_NR_utimensat:
11767 {
ebc996f3
RV
11768 struct timespec *tsp, ts[2];
11769 if (!arg3) {
11770 tsp = NULL;
11771 } else {
11772 target_to_host_timespec(ts, arg3);
11773 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
11774 tsp = ts;
11775 }
9007f0ef 11776 if (!arg2)
ebc996f3 11777 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
9007f0ef 11778 else {
579a97f7 11779 if (!(p = lock_user_string(arg2))) {
0da46a6e 11780 ret = -TARGET_EFAULT;
579a97f7
FB
11781 goto fail;
11782 }
ebc996f3 11783 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
579a97f7 11784 unlock_user(p, arg2, 0);
9007f0ef
TS
11785 }
11786 }
11787 break;
11788#endif
bd0c5661
PB
11789 case TARGET_NR_futex:
11790 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
11791 break;
dbfe4c36 11792#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
39b59763
AJ
11793 case TARGET_NR_inotify_init:
11794 ret = get_errno(sys_inotify_init());
b929f7e5
PMD
11795 if (ret >= 0) {
11796 fd_trans_register(ret, &target_inotify_trans);
11797 }
39b59763
AJ
11798 break;
11799#endif
a1606b0b 11800#ifdef CONFIG_INOTIFY1
c05c7a73
RV
11801#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
11802 case TARGET_NR_inotify_init1:
fea243e9
LD
11803 ret = get_errno(sys_inotify_init1(target_to_host_bitmask(arg1,
11804 fcntl_flags_tbl)));
b929f7e5
PMD
11805 if (ret >= 0) {
11806 fd_trans_register(ret, &target_inotify_trans);
11807 }
c05c7a73
RV
11808 break;
11809#endif
a1606b0b 11810#endif
dbfe4c36 11811#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
39b59763
AJ
11812 case TARGET_NR_inotify_add_watch:
11813 p = lock_user_string(arg2);
11814 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
11815 unlock_user(p, arg2, 0);
11816 break;
11817#endif
dbfe4c36 11818#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
39b59763
AJ
11819 case TARGET_NR_inotify_rm_watch:
11820 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
11821 break;
11822#endif
9007f0ef 11823
8ec9cf89 11824#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
24e1003a
AJ
11825 case TARGET_NR_mq_open:
11826 {
c7536ab6 11827 struct mq_attr posix_mq_attr;
26400775 11828 struct mq_attr *pposix_mq_attr;
c7536ab6 11829 int host_flags;
24e1003a 11830
c7536ab6 11831 host_flags = target_to_host_bitmask(arg2, fcntl_flags_tbl);
26400775
LD
11832 pposix_mq_attr = NULL;
11833 if (arg4) {
11834 if (copy_from_user_mq_attr(&posix_mq_attr, arg4) != 0) {
11835 goto efault;
11836 }
11837 pposix_mq_attr = &posix_mq_attr;
c7536ab6 11838 }
24e1003a 11839 p = lock_user_string(arg1 - 1);
c7536ab6
AM
11840 if (!p) {
11841 goto efault;
b6ce1f6b 11842 }
26400775 11843 ret = get_errno(mq_open(p, host_flags, arg3, pposix_mq_attr));
24e1003a
AJ
11844 unlock_user (p, arg1, 0);
11845 }
11846 break;
11847
11848 case TARGET_NR_mq_unlink:
11849 p = lock_user_string(arg1 - 1);
3211215e
PM
11850 if (!p) {
11851 ret = -TARGET_EFAULT;
11852 break;
11853 }
24e1003a
AJ
11854 ret = get_errno(mq_unlink(p));
11855 unlock_user (p, arg1, 0);
11856 break;
11857
11858 case TARGET_NR_mq_timedsend:
11859 {
11860 struct timespec ts;
11861
11862 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11863 if (arg5 != 0) {
11864 target_to_host_timespec(&ts, arg5);
d40ecd66 11865 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, &ts));
24e1003a 11866 host_to_target_timespec(arg5, &ts);
d40ecd66
PM
11867 } else {
11868 ret = get_errno(safe_mq_timedsend(arg1, p, arg3, arg4, NULL));
24e1003a 11869 }
24e1003a
AJ
11870 unlock_user (p, arg2, arg3);
11871 }
11872 break;
11873
11874 case TARGET_NR_mq_timedreceive:
11875 {
11876 struct timespec ts;
11877 unsigned int prio;
11878
11879 p = lock_user (VERIFY_READ, arg2, arg3, 1);
11880 if (arg5 != 0) {
11881 target_to_host_timespec(&ts, arg5);
d40ecd66
PM
11882 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11883 &prio, &ts));
24e1003a 11884 host_to_target_timespec(arg5, &ts);
d40ecd66
PM
11885 } else {
11886 ret = get_errno(safe_mq_timedreceive(arg1, p, arg3,
11887 &prio, NULL));
24e1003a 11888 }
24e1003a
AJ
11889 unlock_user (p, arg2, arg3);
11890 if (arg4 != 0)
11891 put_user_u32(prio, arg4);
11892 }
11893 break;
11894
11895 /* Not implemented for now... */
11896/* case TARGET_NR_mq_notify: */
11897/* break; */
11898
11899 case TARGET_NR_mq_getsetattr:
11900 {
11901 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
11902 ret = 0;
11903 if (arg3 != 0) {
11904 ret = mq_getattr(arg1, &posix_mq_attr_out);
11905 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
11906 }
11907 if (arg2 != 0) {
11908 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
11909 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
11910 }
11911
11912 }
11913 break;
11914#endif
11915
3ce34dfb
VS
11916#ifdef CONFIG_SPLICE
11917#ifdef TARGET_NR_tee
11918 case TARGET_NR_tee:
11919 {
11920 ret = get_errno(tee(arg1,arg2,arg3,arg4));
11921 }
11922 break;
11923#endif
11924#ifdef TARGET_NR_splice
11925 case TARGET_NR_splice:
11926 {
11927 loff_t loff_in, loff_out;
11928 loff_t *ploff_in = NULL, *ploff_out = NULL;
17644b36
AS
11929 if (arg2) {
11930 if (get_user_u64(loff_in, arg2)) {
11931 goto efault;
11932 }
3ce34dfb
VS
11933 ploff_in = &loff_in;
11934 }
17644b36
AS
11935 if (arg4) {
11936 if (get_user_u64(loff_out, arg4)) {
11937 goto efault;
11938 }
3ce34dfb
VS
11939 ploff_out = &loff_out;
11940 }
11941 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
17644b36
AS
11942 if (arg2) {
11943 if (put_user_u64(loff_in, arg2)) {
11944 goto efault;
11945 }
11946 }
11947 if (arg4) {
11948 if (put_user_u64(loff_out, arg4)) {
11949 goto efault;
11950 }
11951 }
3ce34dfb
VS
11952 }
11953 break;
11954#endif
11955#ifdef TARGET_NR_vmsplice
11956 case TARGET_NR_vmsplice:
11957 {
f287b2c2
RH
11958 struct iovec *vec = lock_iovec(VERIFY_READ, arg2, arg3, 1);
11959 if (vec != NULL) {
11960 ret = get_errno(vmsplice(arg1, vec, arg3, arg4));
11961 unlock_iovec(vec, arg2, arg3, 0);
11962 } else {
11963 ret = -host_to_target_errno(errno);
11964 }
3ce34dfb
VS
11965 }
11966 break;
11967#endif
11968#endif /* CONFIG_SPLICE */
c2882b96
RV
11969#ifdef CONFIG_EVENTFD
11970#if defined(TARGET_NR_eventfd)
11971 case TARGET_NR_eventfd:
11972 ret = get_errno(eventfd(arg1, 0));
b929f7e5
PMD
11973 if (ret >= 0) {
11974 fd_trans_register(ret, &target_eventfd_trans);
11975 }
c2882b96
RV
11976 break;
11977#endif
11978#if defined(TARGET_NR_eventfd2)
11979 case TARGET_NR_eventfd2:
5947c697
PJ
11980 {
11981 int host_flags = arg2 & (~(TARGET_O_NONBLOCK | TARGET_O_CLOEXEC));
11982 if (arg2 & TARGET_O_NONBLOCK) {
11983 host_flags |= O_NONBLOCK;
11984 }
11985 if (arg2 & TARGET_O_CLOEXEC) {
11986 host_flags |= O_CLOEXEC;
11987 }
11988 ret = get_errno(eventfd(arg1, host_flags));
b929f7e5
PMD
11989 if (ret >= 0) {
11990 fd_trans_register(ret, &target_eventfd_trans);
11991 }
c2882b96 11992 break;
5947c697 11993 }
c2882b96
RV
11994#endif
11995#endif /* CONFIG_EVENTFD */
d0927938
UH
11996#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
11997 case TARGET_NR_fallocate:
20249ae1
AG
11998#if TARGET_ABI_BITS == 32
11999 ret = get_errno(fallocate(arg1, arg2, target_offset64(arg3, arg4),
12000 target_offset64(arg5, arg6)));
12001#else
d0927938 12002 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
20249ae1 12003#endif
d0927938 12004 break;
c727f47d
PM
12005#endif
12006#if defined(CONFIG_SYNC_FILE_RANGE)
12007#if defined(TARGET_NR_sync_file_range)
12008 case TARGET_NR_sync_file_range:
12009#if TARGET_ABI_BITS == 32
bfcedc57
RV
12010#if defined(TARGET_MIPS)
12011 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12012 target_offset64(arg5, arg6), arg7));
12013#else
c727f47d
PM
12014 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
12015 target_offset64(arg4, arg5), arg6));
bfcedc57 12016#endif /* !TARGET_MIPS */
c727f47d
PM
12017#else
12018 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
12019#endif
12020 break;
12021#endif
12022#if defined(TARGET_NR_sync_file_range2)
12023 case TARGET_NR_sync_file_range2:
12024 /* This is like sync_file_range but the arguments are reordered */
12025#if TARGET_ABI_BITS == 32
12026 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
12027 target_offset64(arg5, arg6), arg2));
12028#else
12029 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
12030#endif
12031 break;
12032#endif
3b6edd16 12033#endif
e36800c9
LV
12034#if defined(TARGET_NR_signalfd4)
12035 case TARGET_NR_signalfd4:
12036 ret = do_signalfd4(arg1, arg2, arg4);
12037 break;
12038#endif
12039#if defined(TARGET_NR_signalfd)
12040 case TARGET_NR_signalfd:
12041 ret = do_signalfd4(arg1, arg2, 0);
12042 break;
12043#endif
3b6edd16
PM
12044#if defined(CONFIG_EPOLL)
12045#if defined(TARGET_NR_epoll_create)
12046 case TARGET_NR_epoll_create:
12047 ret = get_errno(epoll_create(arg1));
12048 break;
12049#endif
12050#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
12051 case TARGET_NR_epoll_create1:
12052 ret = get_errno(epoll_create1(arg1));
12053 break;
12054#endif
12055#if defined(TARGET_NR_epoll_ctl)
12056 case TARGET_NR_epoll_ctl:
12057 {
12058 struct epoll_event ep;
12059 struct epoll_event *epp = 0;
12060 if (arg4) {
12061 struct target_epoll_event *target_ep;
12062 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
12063 goto efault;
12064 }
12065 ep.events = tswap32(target_ep->events);
12066 /* The epoll_data_t union is just opaque data to the kernel,
12067 * so we transfer all 64 bits across and need not worry what
12068 * actual data type it is.
12069 */
12070 ep.data.u64 = tswap64(target_ep->data.u64);
12071 unlock_user_struct(target_ep, arg4, 0);
12072 epp = &ep;
12073 }
12074 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
12075 break;
12076 }
12077#endif
12078
227f0214 12079#if defined(TARGET_NR_epoll_wait) || defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12080#if defined(TARGET_NR_epoll_wait)
12081 case TARGET_NR_epoll_wait:
12082#endif
227f0214 12083#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12084 case TARGET_NR_epoll_pwait:
12085#endif
12086 {
12087 struct target_epoll_event *target_ep;
12088 struct epoll_event *ep;
12089 int epfd = arg1;
12090 int maxevents = arg3;
12091 int timeout = arg4;
12092
2ba7fae3
PM
12093 if (maxevents <= 0 || maxevents > TARGET_EP_MAX_EVENTS) {
12094 ret = -TARGET_EINVAL;
12095 break;
12096 }
12097
3b6edd16
PM
12098 target_ep = lock_user(VERIFY_WRITE, arg2,
12099 maxevents * sizeof(struct target_epoll_event), 1);
12100 if (!target_ep) {
12101 goto efault;
12102 }
12103
04c95f4d
PM
12104 ep = g_try_new(struct epoll_event, maxevents);
12105 if (!ep) {
12106 unlock_user(target_ep, arg2, 0);
12107 ret = -TARGET_ENOMEM;
12108 break;
12109 }
3b6edd16
PM
12110
12111 switch (num) {
227f0214 12112#if defined(TARGET_NR_epoll_pwait)
3b6edd16
PM
12113 case TARGET_NR_epoll_pwait:
12114 {
12115 target_sigset_t *target_set;
12116 sigset_t _set, *set = &_set;
12117
12118 if (arg5) {
c815701e
PM
12119 if (arg6 != sizeof(target_sigset_t)) {
12120 ret = -TARGET_EINVAL;
12121 break;
12122 }
12123
3b6edd16
PM
12124 target_set = lock_user(VERIFY_READ, arg5,
12125 sizeof(target_sigset_t), 1);
12126 if (!target_set) {
04c95f4d
PM
12127 ret = -TARGET_EFAULT;
12128 break;
3b6edd16
PM
12129 }
12130 target_to_host_sigset(set, target_set);
12131 unlock_user(target_set, arg5, 0);
12132 } else {
12133 set = NULL;
12134 }
12135
227f0214
PM
12136 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12137 set, SIGSET_T_SIZE));
3b6edd16
PM
12138 break;
12139 }
12140#endif
12141#if defined(TARGET_NR_epoll_wait)
12142 case TARGET_NR_epoll_wait:
227f0214
PM
12143 ret = get_errno(safe_epoll_pwait(epfd, ep, maxevents, timeout,
12144 NULL, 0));
3b6edd16
PM
12145 break;
12146#endif
12147 default:
12148 ret = -TARGET_ENOSYS;
12149 }
12150 if (!is_error(ret)) {
12151 int i;
12152 for (i = 0; i < ret; i++) {
12153 target_ep[i].events = tswap32(ep[i].events);
12154 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
12155 }
04c95f4d
PM
12156 unlock_user(target_ep, arg2,
12157 ret * sizeof(struct target_epoll_event));
12158 } else {
12159 unlock_user(target_ep, arg2, 0);
3b6edd16 12160 }
04c95f4d 12161 g_free(ep);
3b6edd16
PM
12162 break;
12163 }
12164#endif
163a05a8
PM
12165#endif
12166#ifdef TARGET_NR_prlimit64
12167 case TARGET_NR_prlimit64:
12168 {
12169 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
12170 struct target_rlimit64 *target_rnew, *target_rold;
12171 struct host_rlimit64 rnew, rold, *rnewp = 0;
95018018 12172 int resource = target_to_host_resource(arg2);
163a05a8
PM
12173 if (arg3) {
12174 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
12175 goto efault;
12176 }
12177 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
12178 rnew.rlim_max = tswap64(target_rnew->rlim_max);
12179 unlock_user_struct(target_rnew, arg3, 0);
12180 rnewp = &rnew;
12181 }
12182
95018018 12183 ret = get_errno(sys_prlimit64(arg1, resource, rnewp, arg4 ? &rold : 0));
163a05a8
PM
12184 if (!is_error(ret) && arg4) {
12185 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
12186 goto efault;
12187 }
12188 target_rold->rlim_cur = tswap64(rold.rlim_cur);
12189 target_rold->rlim_max = tswap64(rold.rlim_max);
12190 unlock_user_struct(target_rold, arg4, 1);
12191 }
12192 break;
12193 }
3d21d29c
RH
12194#endif
12195#ifdef TARGET_NR_gethostname
12196 case TARGET_NR_gethostname:
12197 {
12198 char *name = lock_user(VERIFY_WRITE, arg1, arg2, 0);
12199 if (name) {
12200 ret = get_errno(gethostname(name, arg2));
12201 unlock_user(name, arg1, arg2);
12202 } else {
12203 ret = -TARGET_EFAULT;
12204 }
12205 break;
12206 }
89aaf1a6
RV
12207#endif
12208#ifdef TARGET_NR_atomic_cmpxchg_32
12209 case TARGET_NR_atomic_cmpxchg_32:
12210 {
12211 /* should use start_exclusive from main.c */
12212 abi_ulong mem_value;
12213 if (get_user_u32(mem_value, arg6)) {
12214 target_siginfo_t info;
12215 info.si_signo = SIGSEGV;
12216 info.si_errno = 0;
12217 info.si_code = TARGET_SEGV_MAPERR;
12218 info._sifields._sigfault._addr = arg6;
9d2803f7
PM
12219 queue_signal((CPUArchState *)cpu_env, info.si_signo,
12220 QEMU_SI_FAULT, &info);
89aaf1a6
RV
12221 ret = 0xdeadbeef;
12222
12223 }
12224 if (mem_value == arg2)
12225 put_user_u32(arg1, arg6);
12226 ret = mem_value;
12227 break;
12228 }
12229#endif
12230#ifdef TARGET_NR_atomic_barrier
12231 case TARGET_NR_atomic_barrier:
12232 {
12233 /* Like the kernel implementation and the qemu arm barrier, no-op this? */
3b899ea7 12234 ret = 0;
89aaf1a6
RV
12235 break;
12236 }
d0927938 12237#endif
f4f1e10a
ECL
12238
12239#ifdef TARGET_NR_timer_create
12240 case TARGET_NR_timer_create:
12241 {
12242 /* args: clockid_t clockid, struct sigevent *sevp, timer_t *timerid */
12243
12244 struct sigevent host_sevp = { {0}, }, *phost_sevp = NULL;
f4f1e10a
ECL
12245
12246 int clkid = arg1;
12247 int timer_index = next_free_host_timer();
12248
12249 if (timer_index < 0) {
12250 ret = -TARGET_EAGAIN;
12251 } else {
12252 timer_t *phtimer = g_posix_timers + timer_index;
12253
12254 if (arg2) {
f4f1e10a 12255 phost_sevp = &host_sevp;
c065976f
PM
12256 ret = target_to_host_sigevent(phost_sevp, arg2);
12257 if (ret != 0) {
12258 break;
12259 }
f4f1e10a
ECL
12260 }
12261
12262 ret = get_errno(timer_create(clkid, phost_sevp, phtimer));
12263 if (ret) {
12264 phtimer = NULL;
12265 } else {
aecc8861 12266 if (put_user(TIMER_MAGIC | timer_index, arg3, target_timer_t)) {
f4f1e10a
ECL
12267 goto efault;
12268 }
f4f1e10a
ECL
12269 }
12270 }
12271 break;
12272 }
12273#endif
12274
12275#ifdef TARGET_NR_timer_settime
12276 case TARGET_NR_timer_settime:
12277 {
12278 /* args: timer_t timerid, int flags, const struct itimerspec *new_value,
12279 * struct itimerspec * old_value */
aecc8861 12280 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12281
aecc8861
AG
12282 if (timerid < 0) {
12283 ret = timerid;
12284 } else if (arg3 == 0) {
f4f1e10a
ECL
12285 ret = -TARGET_EINVAL;
12286 } else {
e52a99f7 12287 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12288 struct itimerspec hspec_new = {{0},}, hspec_old = {{0},};
12289
40c80b5e
MAL
12290 if (target_to_host_itimerspec(&hspec_new, arg3)) {
12291 goto efault;
12292 }
f4f1e10a
ECL
12293 ret = get_errno(
12294 timer_settime(htimer, arg2, &hspec_new, &hspec_old));
40c80b5e
MAL
12295 if (arg4 && host_to_target_itimerspec(arg4, &hspec_old)) {
12296 goto efault;
12297 }
f4f1e10a
ECL
12298 }
12299 break;
12300 }
12301#endif
12302
12303#ifdef TARGET_NR_timer_gettime
12304 case TARGET_NR_timer_gettime:
12305 {
12306 /* args: timer_t timerid, struct itimerspec *curr_value */
aecc8861 12307 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12308
aecc8861
AG
12309 if (timerid < 0) {
12310 ret = timerid;
12311 } else if (!arg2) {
12312 ret = -TARGET_EFAULT;
f4f1e10a 12313 } else {
e52a99f7 12314 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12315 struct itimerspec hspec;
12316 ret = get_errno(timer_gettime(htimer, &hspec));
12317
12318 if (host_to_target_itimerspec(arg2, &hspec)) {
12319 ret = -TARGET_EFAULT;
12320 }
12321 }
12322 break;
12323 }
12324#endif
12325
12326#ifdef TARGET_NR_timer_getoverrun
12327 case TARGET_NR_timer_getoverrun:
12328 {
12329 /* args: timer_t timerid */
aecc8861 12330 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12331
aecc8861
AG
12332 if (timerid < 0) {
12333 ret = timerid;
f4f1e10a 12334 } else {
e52a99f7 12335 timer_t htimer = g_posix_timers[timerid];
f4f1e10a
ECL
12336 ret = get_errno(timer_getoverrun(htimer));
12337 }
e36800c9 12338 fd_trans_unregister(ret);
f4f1e10a
ECL
12339 break;
12340 }
12341#endif
12342
12343#ifdef TARGET_NR_timer_delete
12344 case TARGET_NR_timer_delete:
12345 {
12346 /* args: timer_t timerid */
aecc8861 12347 target_timer_t timerid = get_timer_id(arg1);
e52a99f7 12348
aecc8861
AG
12349 if (timerid < 0) {
12350 ret = timerid;
f4f1e10a 12351 } else {
e52a99f7 12352 timer_t htimer = g_posix_timers[timerid];
f4f1e10a 12353 ret = get_errno(timer_delete(htimer));
e52a99f7 12354 g_posix_timers[timerid] = 0;
f4f1e10a
ECL
12355 }
12356 break;
12357 }
12358#endif
12359
51834341
RV
12360#if defined(TARGET_NR_timerfd_create) && defined(CONFIG_TIMERFD)
12361 case TARGET_NR_timerfd_create:
12362 ret = get_errno(timerfd_create(arg1,
12363 target_to_host_bitmask(arg2, fcntl_flags_tbl)));
12364 break;
12365#endif
12366
12367#if defined(TARGET_NR_timerfd_gettime) && defined(CONFIG_TIMERFD)
12368 case TARGET_NR_timerfd_gettime:
12369 {
12370 struct itimerspec its_curr;
12371
12372 ret = get_errno(timerfd_gettime(arg1, &its_curr));
12373
12374 if (arg2 && host_to_target_itimerspec(arg2, &its_curr)) {
12375 goto efault;
12376 }
12377 }
12378 break;
12379#endif
12380
12381#if defined(TARGET_NR_timerfd_settime) && defined(CONFIG_TIMERFD)
12382 case TARGET_NR_timerfd_settime:
12383 {
12384 struct itimerspec its_new, its_old, *p_new;
12385
12386 if (arg3) {
12387 if (target_to_host_itimerspec(&its_new, arg3)) {
12388 goto efault;
12389 }
12390 p_new = &its_new;
12391 } else {
12392 p_new = NULL;
12393 }
12394
12395 ret = get_errno(timerfd_settime(arg1, arg2, p_new, &its_old));
12396
12397 if (arg4 && host_to_target_itimerspec(arg4, &its_old)) {
12398 goto efault;
12399 }
12400 }
12401 break;
12402#endif
12403
ab31cda3
PB
12404#if defined(TARGET_NR_ioprio_get) && defined(__NR_ioprio_get)
12405 case TARGET_NR_ioprio_get:
12406 ret = get_errno(ioprio_get(arg1, arg2));
12407 break;
12408#endif
12409
12410#if defined(TARGET_NR_ioprio_set) && defined(__NR_ioprio_set)
12411 case TARGET_NR_ioprio_set:
12412 ret = get_errno(ioprio_set(arg1, arg2, arg3));
12413 break;
12414#endif
12415
9af5c906
RV
12416#if defined(TARGET_NR_setns) && defined(CONFIG_SETNS)
12417 case TARGET_NR_setns:
12418 ret = get_errno(setns(arg1, arg2));
12419 break;
12420#endif
12421#if defined(TARGET_NR_unshare) && defined(CONFIG_SETNS)
12422 case TARGET_NR_unshare:
12423 ret = get_errno(unshare(arg1));
12424 break;
12425#endif
2f14788c
LV
12426#if defined(TARGET_NR_kcmp) && defined(__NR_kcmp)
12427 case TARGET_NR_kcmp:
12428 ret = get_errno(kcmp(arg1, arg2, arg3, arg4, arg5));
12429 break;
12430#endif
9af5c906 12431
31e31b8a
FB
12432 default:
12433 unimplemented:
5cd4393b 12434 gemu_log("qemu: Unsupported syscall: %d\n", num);
4f2b1fe8 12435#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
5cd4393b 12436 unimplemented_nowarn:
80a9d035 12437#endif
0da46a6e 12438 ret = -TARGET_ENOSYS;
31e31b8a
FB
12439 break;
12440 }
579a97f7 12441fail:
c573ff67 12442#ifdef DEBUG
0bf9e31a 12443 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
c573ff67 12444#endif
b92c47c1
TS
12445 if(do_strace)
12446 print_syscall_ret(num, ret);
9c15e700 12447 trace_guest_user_syscall_ret(cpu, num, ret);
31e31b8a 12448 return ret;
579a97f7
FB
12449efault:
12450 ret = -TARGET_EFAULT;
12451 goto fail;
31e31b8a 12452}
This page took 3.100006 seconds and 4 git commands to generate.