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