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