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