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