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