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