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