blob: 90f6789e5f0c2be0b9b06256d68e69bb0ca7440a [file] [log] [blame]
bellard31e31b82003-02-18 22:55:36 +00001/*
2 * Linux syscalls
ths5fafdf22007-09-16 21:08:06 +00003 *
bellard31e31b82003-02-18 22:55:36 +00004 * 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
Blue Swirl8167ee82009-07-16 20:47:01 +000017 * along with this program; if not, see <http://www.gnu.org/licenses/>.
bellard31e31b82003-02-18 22:55:36 +000018 */
Eduardo Habkostd5b3a9b2009-06-09 18:26:31 -030019#define _ATFILE_SOURCE
bellard31e31b82003-02-18 22:55:36 +000020#include <stdlib.h>
21#include <stdio.h>
22#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000023#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000024#include <elf.h>
25#include <endian.h>
26#include <errno.h>
27#include <unistd.h>
28#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000029#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000030#include <limits.h>
bellard31e31b82003-02-18 22:55:36 +000031#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000032#include <sys/ipc.h>
33#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000034#include <sys/wait.h>
35#include <sys/time.h>
36#include <sys/stat.h>
37#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000038#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000039#include <sys/resource.h>
40#include <sys/mman.h>
41#include <sys/swap.h>
42#include <signal.h>
43#include <sched.h>
Aurelien Jarno60e99242010-03-29 02:12:51 +020044#ifdef __ia64__
45int __clone2(int (*fn)(void *), void *child_stack_base,
46 size_t stack_size, int flags, void *arg, ...);
47#endif
bellard31e31b82003-02-18 22:55:36 +000048#include <sys/socket.h>
aurel32607175e2009-04-15 16:11:59 +000049#include <sys/un.h>
bellard31e31b82003-02-18 22:55:36 +000050#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000051#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000052#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000053#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000054#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000055#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000056#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000057#include <sys/sysinfo.h>
aurel323b3f24a2009-04-15 16:12:13 +000058#include <sys/utsname.h>
bellard72f03902003-02-18 23:33:18 +000059//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000060#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000061#include <netinet/tcp.h>
Laurent Vivier86fcd942011-03-30 01:35:23 +020062#include <linux/wireless.h>
aurel320b6d3ae2008-09-15 07:43:43 +000063#include <qemu-common.h>
Juan Quintela9788c9c2009-07-27 16:13:02 +020064#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +000065#include <sys/gmon.h>
66#endif
Riku Voipioc2882b92009-08-12 15:08:24 +030067#ifdef CONFIG_EVENTFD
68#include <sys/eventfd.h>
69#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +000070#ifdef CONFIG_EPOLL
71#include <sys/epoll.h>
72#endif
bellard31e31b82003-02-18 22:55:36 +000073
74#define termios host_termios
75#define winsize host_winsize
76#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000077#define sgttyb host_sgttyb /* same as target */
78#define tchars host_tchars /* same as target */
79#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000080
81#include <linux/termios.h>
82#include <linux/unistd.h>
83#include <linux/utsname.h>
84#include <linux/cdrom.h>
85#include <linux/hdreg.h>
86#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000087#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000088#include <linux/mtio.h>
Martin Mohring350d1772009-05-04 21:21:41 +030089#include <linux/fs.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000090#if defined(CONFIG_FIEMAP)
Peter Maydell285da2b2011-01-06 15:04:18 +000091#include <linux/fiemap.h>
Peter Maydelldace20d2011-01-10 13:11:24 +000092#endif
Ulrich Hechtf7680a52009-10-16 17:00:44 +020093#include <linux/fb.h>
94#include <linux/vt.h>
pbrookd7e40362008-05-23 16:06:43 +000095#include "linux_loop.h"
Loïc Minierda790302009-12-29 22:06:13 +010096#include "cpu-uname.h"
bellard31e31b82003-02-18 22:55:36 +000097
bellard3ef693a2003-03-23 20:17:16 +000098#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000099#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +0000100
Juan Quintela2f7bb872009-07-27 16:13:24 +0200101#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +0000102#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
103 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
104#else
105/* XXX: Hardcode the above values. */
106#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +0000107#endif
108
bellard72f03902003-02-18 23:33:18 +0000109//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +0000110
bellard1a9353d2003-03-16 20:28:50 +0000111//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000112#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
113#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000114
bellard70a194b2003-08-11 22:20:16 +0000115
bellard70a194b2003-08-11 22:20:16 +0000116#undef _syscall0
117#undef _syscall1
118#undef _syscall2
119#undef _syscall3
120#undef _syscall4
121#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000122#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000123
bellard83fcb512006-06-14 13:37:16 +0000124#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000125static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000126{ \
127 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000128}
129
bellard83fcb512006-06-14 13:37:16 +0000130#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000131static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000132{ \
133 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000134}
135
bellard83fcb512006-06-14 13:37:16 +0000136#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000137static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000138{ \
139 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000140}
141
bellard83fcb512006-06-14 13:37:16 +0000142#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000143static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000144{ \
145 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000146}
147
bellard83fcb512006-06-14 13:37:16 +0000148#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000149static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000150{ \
151 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000152}
153
bellard83fcb512006-06-14 13:37:16 +0000154#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
155 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000156static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000157{ \
158 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000159}
bellard83fcb512006-06-14 13:37:16 +0000160
161
162#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
163 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000164static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
165 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000166{ \
167 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
168}
169
bellard70a194b2003-08-11 22:20:16 +0000170
bellard31e31b82003-02-18 22:55:36 +0000171#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000172#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000173#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000174#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000175#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000176#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000177#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000178#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000179#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000180#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000181#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000182#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000183#define __NR_sys_mknodat __NR_mknodat
aurel329d33b762009-04-08 23:07:05 +0000184#define __NR_sys_newfstatat __NR_newfstatat
ths82424832007-09-24 09:21:55 +0000185#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000186#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000187#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000188#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000189#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000190#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000191#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000192#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000193#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000194#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000195#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000196#define __NR_sys_inotify_init __NR_inotify_init
197#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
198#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000199
Alexander Graf42a39fb2011-04-15 17:32:45 +0200200#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) || \
201 defined(__s390x__)
bellard9af9eaa2003-04-07 21:34:41 +0000202#define __NR__llseek __NR_lseek
203#endif
204
bellard72f03902003-02-18 23:33:18 +0000205#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000206_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000207#else
ths0da46a62007-10-20 20:23:07 +0000208/* This is a replacement for the host gettid() and must return a host
209 errno. */
bellard72f03902003-02-18 23:33:18 +0000210static int gettid(void) {
211 return -ENOSYS;
212}
213#endif
aurel323b3f24a2009-04-15 16:12:13 +0000214_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
aurel323b3f24a2009-04-15 16:12:13 +0000215#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
216_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
217#endif
218_syscall2(int, sys_getpriority, int, which, int, who);
Richard Hendersond35b2612010-06-04 12:14:10 -0700219#if defined(TARGET_NR__llseek) && defined(__NR_llseek)
aurel323b3f24a2009-04-15 16:12:13 +0000220_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
221 loff_t *, res, uint, wh);
222#endif
223_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
224_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
225#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
226_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
227#endif
228#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
229_syscall2(int,sys_tkill,int,tid,int,sig)
230#endif
231#ifdef __NR_exit_group
232_syscall1(int,exit_group,int,error_code)
233#endif
234#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
235_syscall1(int,set_tid_address,int *,tidptr)
236#endif
Juan Quintela2f7bb872009-07-27 16:13:24 +0200237#if defined(CONFIG_USE_NPTL)
aurel323b3f24a2009-04-15 16:12:13 +0000238#if defined(TARGET_NR_futex) && defined(__NR_futex)
239_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
240 const struct timespec *,timeout,int *,uaddr2,int,val3)
241#endif
242#endif
Mike Frysinger737de1d2011-02-07 01:05:55 -0500243#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
244_syscall3(int, sys_sched_getaffinity, pid_t, pid, unsigned int, len,
245 unsigned long *, user_mask_ptr);
246#define __NR_sys_sched_setaffinity __NR_sched_setaffinity
247_syscall3(int, sys_sched_setaffinity, pid_t, pid, unsigned int, len,
248 unsigned long *, user_mask_ptr);
aurel323b3f24a2009-04-15 16:12:13 +0000249
250static bitmask_transtbl fcntl_flags_tbl[] = {
251 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
252 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
253 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
254 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
255 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
256 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
257 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
258 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
259 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
260 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
261 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
262 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
263 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
264#if defined(O_DIRECT)
265 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
266#endif
267 { 0, 0, 0, 0 }
268};
269
270#define COPY_UTSNAME_FIELD(dest, src) \
271 do { \
272 /* __NEW_UTS_LEN doesn't include terminating null */ \
273 (void) strncpy((dest), (src), __NEW_UTS_LEN); \
274 (dest)[__NEW_UTS_LEN] = '\0'; \
275 } while (0)
276
277static int sys_uname(struct new_utsname *buf)
278{
279 struct utsname uts_buf;
280
281 if (uname(&uts_buf) < 0)
282 return (-1);
283
284 /*
285 * Just in case these have some differences, we
286 * translate utsname to new_utsname (which is the
287 * struct linux kernel uses).
288 */
289
Stefan Weil67bd9ed2011-05-07 22:32:25 +0200290 memset(buf, 0, sizeof(*buf));
aurel323b3f24a2009-04-15 16:12:13 +0000291 COPY_UTSNAME_FIELD(buf->sysname, uts_buf.sysname);
292 COPY_UTSNAME_FIELD(buf->nodename, uts_buf.nodename);
293 COPY_UTSNAME_FIELD(buf->release, uts_buf.release);
294 COPY_UTSNAME_FIELD(buf->version, uts_buf.version);
295 COPY_UTSNAME_FIELD(buf->machine, uts_buf.machine);
296#ifdef _GNU_SOURCE
297 COPY_UTSNAME_FIELD(buf->domainname, uts_buf.domainname);
298#endif
299 return (0);
300
301#undef COPY_UTSNAME_FIELD
302}
303
304static int sys_getcwd1(char *buf, size_t size)
305{
306 if (getcwd(buf, size) == NULL) {
307 /* getcwd() sets errno */
308 return (-1);
309 }
aurel32aaf4ad32009-04-16 14:17:14 +0000310 return strlen(buf)+1;
aurel323b3f24a2009-04-15 16:12:13 +0000311}
312
313#ifdef CONFIG_ATFILE
314/*
315 * Host system seems to have atfile syscall stubs available. We
316 * now enable them one by one as specified by target syscall_nr.h.
317 */
318
319#ifdef TARGET_NR_faccessat
aurel32465c9f02009-04-19 08:52:17 +0000320static int sys_faccessat(int dirfd, const char *pathname, int mode)
aurel323b3f24a2009-04-15 16:12:13 +0000321{
aurel32465c9f02009-04-19 08:52:17 +0000322 return (faccessat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000323}
324#endif
325#ifdef TARGET_NR_fchmodat
aurel32465c9f02009-04-19 08:52:17 +0000326static int sys_fchmodat(int dirfd, const char *pathname, mode_t mode)
aurel323b3f24a2009-04-15 16:12:13 +0000327{
aurel32465c9f02009-04-19 08:52:17 +0000328 return (fchmodat(dirfd, pathname, mode, 0));
aurel323b3f24a2009-04-15 16:12:13 +0000329}
330#endif
Riku Voipio0c866a72011-04-18 15:23:06 +0300331#if defined(TARGET_NR_fchownat)
aurel323b3f24a2009-04-15 16:12:13 +0000332static int sys_fchownat(int dirfd, const char *pathname, uid_t owner,
333 gid_t group, int flags)
334{
335 return (fchownat(dirfd, pathname, owner, group, flags));
336}
337#endif
338#ifdef __NR_fstatat64
339static int sys_fstatat64(int dirfd, const char *pathname, struct stat *buf,
340 int flags)
341{
342 return (fstatat(dirfd, pathname, buf, flags));
343}
344#endif
345#ifdef __NR_newfstatat
346static int sys_newfstatat(int dirfd, const char *pathname, struct stat *buf,
347 int flags)
348{
349 return (fstatat(dirfd, pathname, buf, flags));
350}
351#endif
352#ifdef TARGET_NR_futimesat
353static int sys_futimesat(int dirfd, const char *pathname,
354 const struct timeval times[2])
355{
356 return (futimesat(dirfd, pathname, times));
357}
358#endif
359#ifdef TARGET_NR_linkat
360static int sys_linkat(int olddirfd, const char *oldpath,
361 int newdirfd, const char *newpath, int flags)
362{
363 return (linkat(olddirfd, oldpath, newdirfd, newpath, flags));
364}
365#endif
366#ifdef TARGET_NR_mkdirat
367static int sys_mkdirat(int dirfd, const char *pathname, mode_t mode)
368{
369 return (mkdirat(dirfd, pathname, mode));
370}
371#endif
372#ifdef TARGET_NR_mknodat
373static int sys_mknodat(int dirfd, const char *pathname, mode_t mode,
374 dev_t dev)
375{
376 return (mknodat(dirfd, pathname, mode, dev));
377}
378#endif
379#ifdef TARGET_NR_openat
380static int sys_openat(int dirfd, const char *pathname, int flags, ...)
381{
382 /*
383 * open(2) has extra parameter 'mode' when called with
384 * flag O_CREAT.
385 */
386 if ((flags & O_CREAT) != 0) {
387 va_list ap;
388 mode_t mode;
389
390 /*
391 * Get the 'mode' parameter and translate it to
392 * host bits.
393 */
394 va_start(ap, flags);
395 mode = va_arg(ap, mode_t);
396 mode = target_to_host_bitmask(mode, fcntl_flags_tbl);
397 va_end(ap);
398
399 return (openat(dirfd, pathname, flags, mode));
400 }
401 return (openat(dirfd, pathname, flags));
402}
403#endif
404#ifdef TARGET_NR_readlinkat
405static int sys_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz)
406{
407 return (readlinkat(dirfd, pathname, buf, bufsiz));
408}
409#endif
410#ifdef TARGET_NR_renameat
411static int sys_renameat(int olddirfd, const char *oldpath,
412 int newdirfd, const char *newpath)
413{
414 return (renameat(olddirfd, oldpath, newdirfd, newpath));
415}
416#endif
417#ifdef TARGET_NR_symlinkat
418static int sys_symlinkat(const char *oldpath, int newdirfd, const char *newpath)
419{
420 return (symlinkat(oldpath, newdirfd, newpath));
421}
422#endif
423#ifdef TARGET_NR_unlinkat
424static int sys_unlinkat(int dirfd, const char *pathname, int flags)
425{
426 return (unlinkat(dirfd, pathname, flags));
427}
428#endif
aurel323b3f24a2009-04-15 16:12:13 +0000429#else /* !CONFIG_ATFILE */
430
431/*
432 * Try direct syscalls instead
433 */
ths92a34c12007-09-24 09:27:49 +0000434#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
aurel32465c9f02009-04-19 08:52:17 +0000435_syscall3(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode)
ths92a34c12007-09-24 09:27:49 +0000436#endif
ths814d7972007-09-24 09:26:51 +0000437#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
aurel32465c9f02009-04-19 08:52:17 +0000438_syscall3(int,sys_fchmodat,int,dirfd,const char *,pathname, mode_t,mode)
ths814d7972007-09-24 09:26:51 +0000439#endif
Riku Voipio0c866a72011-04-18 15:23:06 +0300440#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
thsccfa72b2007-09-24 09:23:34 +0000441_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
442 uid_t,owner,gid_t,group,int,flags)
443#endif
aurel329d33b762009-04-08 23:07:05 +0000444#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
445 defined(__NR_fstatat64)
balrog6a24a772008-09-20 02:23:36 +0000446_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
447 struct stat *,buf,int,flags)
448#endif
balrogac8a6552008-09-20 02:25:39 +0000449#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
450_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
451 const struct timeval *,times)
452#endif
aurel323b3f24a2009-04-15 16:12:13 +0000453#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \
454 defined(__NR_newfstatat)
455_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname,
456 struct stat *,buf,int,flags)
blueswir18fcd3692008-08-17 20:26:25 +0000457#endif
ths64f0ce42007-09-24 09:25:06 +0000458#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
459_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
aurel323b3f24a2009-04-15 16:12:13 +0000460 int,newdirfd,const char *,newpath,int,flags)
ths64f0ce42007-09-24 09:25:06 +0000461#endif
ths4472ad02007-09-24 09:22:32 +0000462#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
463_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
464#endif
ths75ac37a2007-09-24 09:23:05 +0000465#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
466_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
467 mode_t,mode,dev_t,dev)
468#endif
ths82424832007-09-24 09:21:55 +0000469#if defined(TARGET_NR_openat) && defined(__NR_openat)
470_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
471#endif
ths5e0ccb12007-09-24 09:26:10 +0000472#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
473_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
474 char *,buf,size_t,bufsize)
475#endif
ths722183f2007-09-24 09:24:37 +0000476#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
477_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
478 int,newdirfd,const char *,newpath)
479#endif
thsb51eaa82007-09-25 16:09:22 +0000480#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000481_syscall3(int,sys_symlinkat,const char *,oldpath,
482 int,newdirfd,const char *,newpath)
483#endif
ths8170f562007-09-24 09:24:11 +0000484#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
485_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
486#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300487
488#endif /* CONFIG_ATFILE */
489
490#ifdef CONFIG_UTIMENSAT
491static int sys_utimensat(int dirfd, const char *pathname,
492 const struct timespec times[2], int flags)
493{
494 if (pathname == NULL)
495 return futimens(dirfd, times);
496 else
497 return utimensat(dirfd, pathname, times, flags);
498}
499#else
ths9007f0e2007-09-25 17:50:37 +0000500#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
501_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
502 const struct timespec *,tsp,int,flags)
503#endif
Riku Voipioebc996f2009-04-21 15:01:51 +0300504#endif /* CONFIG_UTIMENSAT */
aurel323b3f24a2009-04-15 16:12:13 +0000505
506#ifdef CONFIG_INOTIFY
aurel328690e422009-04-17 13:50:32 +0000507#include <sys/inotify.h>
aurel323b3f24a2009-04-15 16:12:13 +0000508
aurel3239b59762008-10-01 21:46:50 +0000509#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel323b3f24a2009-04-15 16:12:13 +0000510static int sys_inotify_init(void)
511{
512 return (inotify_init());
513}
aurel3239b59762008-10-01 21:46:50 +0000514#endif
515#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000516static int sys_inotify_add_watch(int fd,const char *pathname, int32_t mask)
517{
518 return (inotify_add_watch(fd, pathname, mask));
519}
aurel3239b59762008-10-01 21:46:50 +0000520#endif
521#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel323b3f24a2009-04-15 16:12:13 +0000522static int sys_inotify_rm_watch(int fd, int32_t wd)
523{
aurel328690e422009-04-17 13:50:32 +0000524 return (inotify_rm_watch(fd, wd));
aurel323b3f24a2009-04-15 16:12:13 +0000525}
aurel3239b59762008-10-01 21:46:50 +0000526#endif
Riku Voipioc05c7a72010-03-26 15:25:11 +0000527#ifdef CONFIG_INOTIFY1
528#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
529static int sys_inotify_init1(int flags)
530{
531 return (inotify_init1(flags));
532}
533#endif
534#endif
aurel323b3f24a2009-04-15 16:12:13 +0000535#else
536/* Userspace can usually survive runtime without inotify */
537#undef TARGET_NR_inotify_init
Riku Voipioc05c7a72010-03-26 15:25:11 +0000538#undef TARGET_NR_inotify_init1
aurel323b3f24a2009-04-15 16:12:13 +0000539#undef TARGET_NR_inotify_add_watch
540#undef TARGET_NR_inotify_rm_watch
541#endif /* CONFIG_INOTIFY */
542
Mike Frysingerd8035d42011-02-07 01:05:51 -0500543#if defined(TARGET_NR_ppoll)
544#ifndef __NR_ppoll
545# define __NR_ppoll -1
546#endif
547#define __NR_sys_ppoll __NR_ppoll
548_syscall5(int, sys_ppoll, struct pollfd *, fds, nfds_t, nfds,
549 struct timespec *, timeout, const __sigset_t *, sigmask,
550 size_t, sigsetsize)
551#endif
bellard66fb9762003-03-23 01:06:05 +0000552
Mike Frysinger055e0902011-06-03 17:01:49 -0400553#if defined(TARGET_NR_pselect6)
554#ifndef __NR_pselect6
555# define __NR_pselect6 -1
556#endif
557#define __NR_sys_pselect6 __NR_pselect6
558_syscall6(int, sys_pselect6, int, nfds, fd_set *, readfds, fd_set *, writefds,
559 fd_set *, exceptfds, struct timespec *, timeout, void *, sig);
560#endif
561
Peter Maydell163a05a2011-06-27 17:44:52 +0100562#if defined(TARGET_NR_prlimit64)
563#ifndef __NR_prlimit64
564# define __NR_prlimit64 -1
565#endif
566#define __NR_sys_prlimit64 __NR_prlimit64
567/* The glibc rlimit structure may not be that used by the underlying syscall */
568struct host_rlimit64 {
569 uint64_t rlim_cur;
570 uint64_t rlim_max;
571};
572_syscall4(int, sys_prlimit64, pid_t, pid, int, resource,
573 const struct host_rlimit64 *, new_limit,
574 struct host_rlimit64 *, old_limit)
575#endif
576
bellard66fb9762003-03-23 01:06:05 +0000577extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000578extern int flock(int, int);
579extern int setfsuid(int);
580extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000581extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000582
thsb92c47c2007-11-01 00:07:38 +0000583#define ERRNO_TABLE_SIZE 1200
584
585/* target_to_host_errno_table[] is initialized from
586 * host_to_target_errno_table[] in syscall_init(). */
587static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
588};
589
ths637947f2007-06-01 12:09:19 +0000590/*
thsfe8f0962007-07-12 10:59:21 +0000591 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000592 * minus the errnos that are not actually generic to all archs.
593 */
thsb92c47c2007-11-01 00:07:38 +0000594static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000595 [EIDRM] = TARGET_EIDRM,
596 [ECHRNG] = TARGET_ECHRNG,
597 [EL2NSYNC] = TARGET_EL2NSYNC,
598 [EL3HLT] = TARGET_EL3HLT,
599 [EL3RST] = TARGET_EL3RST,
600 [ELNRNG] = TARGET_ELNRNG,
601 [EUNATCH] = TARGET_EUNATCH,
602 [ENOCSI] = TARGET_ENOCSI,
603 [EL2HLT] = TARGET_EL2HLT,
604 [EDEADLK] = TARGET_EDEADLK,
605 [ENOLCK] = TARGET_ENOLCK,
606 [EBADE] = TARGET_EBADE,
607 [EBADR] = TARGET_EBADR,
608 [EXFULL] = TARGET_EXFULL,
609 [ENOANO] = TARGET_ENOANO,
610 [EBADRQC] = TARGET_EBADRQC,
611 [EBADSLT] = TARGET_EBADSLT,
612 [EBFONT] = TARGET_EBFONT,
613 [ENOSTR] = TARGET_ENOSTR,
614 [ENODATA] = TARGET_ENODATA,
615 [ETIME] = TARGET_ETIME,
616 [ENOSR] = TARGET_ENOSR,
617 [ENONET] = TARGET_ENONET,
618 [ENOPKG] = TARGET_ENOPKG,
619 [EREMOTE] = TARGET_EREMOTE,
620 [ENOLINK] = TARGET_ENOLINK,
621 [EADV] = TARGET_EADV,
622 [ESRMNT] = TARGET_ESRMNT,
623 [ECOMM] = TARGET_ECOMM,
624 [EPROTO] = TARGET_EPROTO,
625 [EDOTDOT] = TARGET_EDOTDOT,
626 [EMULTIHOP] = TARGET_EMULTIHOP,
627 [EBADMSG] = TARGET_EBADMSG,
628 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
629 [EOVERFLOW] = TARGET_EOVERFLOW,
630 [ENOTUNIQ] = TARGET_ENOTUNIQ,
631 [EBADFD] = TARGET_EBADFD,
632 [EREMCHG] = TARGET_EREMCHG,
633 [ELIBACC] = TARGET_ELIBACC,
634 [ELIBBAD] = TARGET_ELIBBAD,
635 [ELIBSCN] = TARGET_ELIBSCN,
636 [ELIBMAX] = TARGET_ELIBMAX,
637 [ELIBEXEC] = TARGET_ELIBEXEC,
638 [EILSEQ] = TARGET_EILSEQ,
639 [ENOSYS] = TARGET_ENOSYS,
640 [ELOOP] = TARGET_ELOOP,
641 [ERESTART] = TARGET_ERESTART,
642 [ESTRPIPE] = TARGET_ESTRPIPE,
643 [ENOTEMPTY] = TARGET_ENOTEMPTY,
644 [EUSERS] = TARGET_EUSERS,
645 [ENOTSOCK] = TARGET_ENOTSOCK,
646 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
647 [EMSGSIZE] = TARGET_EMSGSIZE,
648 [EPROTOTYPE] = TARGET_EPROTOTYPE,
649 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
650 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
651 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
652 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
653 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
654 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
655 [EADDRINUSE] = TARGET_EADDRINUSE,
656 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
657 [ENETDOWN] = TARGET_ENETDOWN,
658 [ENETUNREACH] = TARGET_ENETUNREACH,
659 [ENETRESET] = TARGET_ENETRESET,
660 [ECONNABORTED] = TARGET_ECONNABORTED,
661 [ECONNRESET] = TARGET_ECONNRESET,
662 [ENOBUFS] = TARGET_ENOBUFS,
663 [EISCONN] = TARGET_EISCONN,
664 [ENOTCONN] = TARGET_ENOTCONN,
665 [EUCLEAN] = TARGET_EUCLEAN,
666 [ENOTNAM] = TARGET_ENOTNAM,
667 [ENAVAIL] = TARGET_ENAVAIL,
668 [EISNAM] = TARGET_EISNAM,
669 [EREMOTEIO] = TARGET_EREMOTEIO,
670 [ESHUTDOWN] = TARGET_ESHUTDOWN,
671 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
672 [ETIMEDOUT] = TARGET_ETIMEDOUT,
673 [ECONNREFUSED] = TARGET_ECONNREFUSED,
674 [EHOSTDOWN] = TARGET_EHOSTDOWN,
675 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
676 [EALREADY] = TARGET_EALREADY,
677 [EINPROGRESS] = TARGET_EINPROGRESS,
678 [ESTALE] = TARGET_ESTALE,
679 [ECANCELED] = TARGET_ECANCELED,
680 [ENOMEDIUM] = TARGET_ENOMEDIUM,
681 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000682#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000683 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000684#endif
685#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000686 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000687#endif
688#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000689 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000690#endif
691#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000692 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000693#endif
694#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000695 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000696#endif
697#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000698 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000699#endif
thsb92c47c2007-11-01 00:07:38 +0000700};
ths637947f2007-06-01 12:09:19 +0000701
702static inline int host_to_target_errno(int err)
703{
704 if(host_to_target_errno_table[err])
705 return host_to_target_errno_table[err];
706 return err;
707}
708
thsb92c47c2007-11-01 00:07:38 +0000709static inline int target_to_host_errno(int err)
710{
711 if (target_to_host_errno_table[err])
712 return target_to_host_errno_table[err];
713 return err;
714}
715
blueswir1992f48a2007-10-14 16:27:31 +0000716static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000717{
718 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000719 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000720 else
721 return ret;
722}
723
blueswir1992f48a2007-10-14 16:27:31 +0000724static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000725{
blueswir1992f48a2007-10-14 16:27:31 +0000726 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000727}
728
thsb92c47c2007-11-01 00:07:38 +0000729char *target_strerror(int err)
730{
731 return strerror(target_to_host_errno(err));
732}
733
blueswir1992f48a2007-10-14 16:27:31 +0000734static abi_ulong target_brk;
735static abi_ulong target_original_brk;
vincent4d1de872011-06-14 21:56:33 +0000736static abi_ulong brk_page;
bellard31e31b82003-02-18 22:55:36 +0000737
blueswir1992f48a2007-10-14 16:27:31 +0000738void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000739{
blueswir14c1de732007-07-07 20:45:44 +0000740 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
vincent4d1de872011-06-14 21:56:33 +0000741 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000742}
743
vincent4d1de872011-06-14 21:56:33 +0000744//#define DEBUGF_BRK(message, args...) do { fprintf(stderr, (message), ## args); } while (0)
745#define DEBUGF_BRK(message, args...)
746
ths0da46a62007-10-20 20:23:07 +0000747/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000748abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000749{
blueswir1992f48a2007-10-14 16:27:31 +0000750 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000751 int new_alloc_size;
752
vincent4d1de872011-06-14 21:56:33 +0000753 DEBUGF_BRK("do_brk(%#010x) -> ", new_brk);
ths3b46e622007-09-17 08:09:54 +0000754
vincent4d1de872011-06-14 21:56:33 +0000755 if (!new_brk) {
756 DEBUGF_BRK("%#010x (!new_brk)\n", target_brk);
757 return target_brk;
758 }
759 if (new_brk < target_original_brk) {
760 DEBUGF_BRK("%#010x (new_brk < target_original_brk)\n", target_brk);
761 return target_brk;
762 }
bellard31e31b82003-02-18 22:55:36 +0000763
vincent4d1de872011-06-14 21:56:33 +0000764 /* If the new brk is less than the highest page reserved to the
765 * target heap allocation, set it and we're almost done... */
766 if (new_brk <= brk_page) {
767 /* Heap contents are initialized to zero, as for anonymous
768 * mapped pages. */
769 if (new_brk > target_brk) {
770 memset(g2h(target_brk), 0, new_brk - target_brk);
771 }
bellard31e31b82003-02-18 22:55:36 +0000772 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000773 DEBUGF_BRK("%#010x (new_brk <= brk_page)\n", target_brk);
pbrook53a59602006-03-25 19:31:22 +0000774 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000775 }
776
Peter Maydell00faf082011-04-18 16:34:24 +0100777 /* We need to allocate more memory after the brk... Note that
778 * we don't use MAP_FIXED because that will map over the top of
779 * any existing mapping (like the one with the host libc or qemu
780 * itself); instead we treat "mapped but at wrong address" as
781 * a failure and unmap again.
782 */
vincent4d1de872011-06-14 21:56:33 +0000783 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page);
ths5fafdf22007-09-16 21:08:06 +0000784 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000785 PROT_READ|PROT_WRITE,
Peter Maydell00faf082011-04-18 16:34:24 +0100786 MAP_ANON|MAP_PRIVATE, 0, 0));
787
788 if (mapped_addr == brk_page) {
789 target_brk = new_brk;
vincent4d1de872011-06-14 21:56:33 +0000790 brk_page = HOST_PAGE_ALIGN(target_brk);
791 DEBUGF_BRK("%#010x (mapped_addr == brk_page)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100792 return target_brk;
793 } else if (mapped_addr != -1) {
794 /* Mapped but at wrong address, meaning there wasn't actually
795 * enough space for this brk.
796 */
797 target_munmap(mapped_addr, new_alloc_size);
798 mapped_addr = -1;
vincent4d1de872011-06-14 21:56:33 +0000799 DEBUGF_BRK("%#010x (mapped_addr != -1)\n", target_brk);
800 }
801 else {
802 DEBUGF_BRK("%#010x (otherwise)\n", target_brk);
Peter Maydell00faf082011-04-18 16:34:24 +0100803 }
balrog7ab240a2008-04-26 12:17:34 +0000804
Richard Henderson7dd46c02010-05-03 10:07:49 -0700805#if defined(TARGET_ALPHA)
806 /* We (partially) emulate OSF/1 on Alpha, which requires we
807 return a proper errno, not an unchanged brk value. */
Peter Maydell00faf082011-04-18 16:34:24 +0100808 return -TARGET_ENOMEM;
Richard Henderson7dd46c02010-05-03 10:07:49 -0700809#endif
Peter Maydell00faf082011-04-18 16:34:24 +0100810 /* For everything else, return the previous break. */
balrog7ab240a2008-04-26 12:17:34 +0000811 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000812}
813
ths26edcf42007-12-09 02:25:24 +0000814static inline abi_long copy_from_user_fdset(fd_set *fds,
815 abi_ulong target_fds_addr,
816 int n)
bellard31e31b82003-02-18 22:55:36 +0000817{
ths26edcf42007-12-09 02:25:24 +0000818 int i, nw, j, k;
819 abi_ulong b, *target_fds;
820
821 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
822 if (!(target_fds = lock_user(VERIFY_READ,
823 target_fds_addr,
824 sizeof(abi_ulong) * nw,
825 1)))
826 return -TARGET_EFAULT;
827
828 FD_ZERO(fds);
829 k = 0;
830 for (i = 0; i < nw; i++) {
831 /* grab the abi_ulong */
832 __get_user(b, &target_fds[i]);
833 for (j = 0; j < TARGET_ABI_BITS; j++) {
834 /* check the bit inside the abi_ulong */
835 if ((b >> j) & 1)
836 FD_SET(k, fds);
837 k++;
bellard31e31b82003-02-18 22:55:36 +0000838 }
bellard31e31b82003-02-18 22:55:36 +0000839 }
ths26edcf42007-12-09 02:25:24 +0000840
841 unlock_user(target_fds, target_fds_addr, 0);
842
843 return 0;
bellard31e31b82003-02-18 22:55:36 +0000844}
845
Mike Frysinger055e0902011-06-03 17:01:49 -0400846static inline abi_ulong copy_from_user_fdset_ptr(fd_set *fds, fd_set **fds_ptr,
847 abi_ulong target_fds_addr,
848 int n)
849{
850 if (target_fds_addr) {
851 if (copy_from_user_fdset(fds, target_fds_addr, n))
852 return -TARGET_EFAULT;
853 *fds_ptr = fds;
854 } else {
855 *fds_ptr = NULL;
856 }
857 return 0;
858}
859
ths26edcf42007-12-09 02:25:24 +0000860static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
861 const fd_set *fds,
862 int n)
bellard31e31b82003-02-18 22:55:36 +0000863{
bellard31e31b82003-02-18 22:55:36 +0000864 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000865 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000866 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000867
ths26edcf42007-12-09 02:25:24 +0000868 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
869 if (!(target_fds = lock_user(VERIFY_WRITE,
870 target_fds_addr,
871 sizeof(abi_ulong) * nw,
872 0)))
873 return -TARGET_EFAULT;
874
875 k = 0;
876 for (i = 0; i < nw; i++) {
877 v = 0;
878 for (j = 0; j < TARGET_ABI_BITS; j++) {
879 v |= ((FD_ISSET(k, fds) != 0) << j);
880 k++;
bellard31e31b82003-02-18 22:55:36 +0000881 }
ths26edcf42007-12-09 02:25:24 +0000882 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000883 }
ths26edcf42007-12-09 02:25:24 +0000884
885 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
886
887 return 0;
bellard31e31b82003-02-18 22:55:36 +0000888}
889
bellardc596ed12003-07-13 17:32:31 +0000890#if defined(__alpha__)
891#define HOST_HZ 1024
892#else
893#define HOST_HZ 100
894#endif
895
blueswir1992f48a2007-10-14 16:27:31 +0000896static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000897{
898#if HOST_HZ == TARGET_HZ
899 return ticks;
900#else
901 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
902#endif
903}
904
bellard579a97f2007-11-11 14:26:47 +0000905static inline abi_long host_to_target_rusage(abi_ulong target_addr,
906 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000907{
pbrook53a59602006-03-25 19:31:22 +0000908 struct target_rusage *target_rusage;
909
bellard579a97f2007-11-11 14:26:47 +0000910 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
911 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000912 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
913 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
914 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
915 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
916 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
917 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
918 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
919 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
920 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
921 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
922 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
923 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
924 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
925 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
926 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
927 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
928 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
929 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000930 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000931
932 return 0;
bellardb4091862003-05-16 15:39:34 +0000933}
934
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +0900935static inline rlim_t target_to_host_rlim(target_ulong target_rlim)
936{
937 if (target_rlim == TARGET_RLIM_INFINITY)
938 return RLIM_INFINITY;
939 else
940 return tswapl(target_rlim);
941}
942
943static inline target_ulong host_to_target_rlim(rlim_t rlim)
944{
945 if (rlim == RLIM_INFINITY || rlim != (target_long)rlim)
946 return TARGET_RLIM_INFINITY;
947 else
948 return tswapl(rlim);
949}
950
ths788f5ec2007-12-09 02:37:05 +0000951static inline abi_long copy_from_user_timeval(struct timeval *tv,
952 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000953{
pbrook53a59602006-03-25 19:31:22 +0000954 struct target_timeval *target_tv;
955
ths788f5ec2007-12-09 02:37:05 +0000956 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000957 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000958
959 __get_user(tv->tv_sec, &target_tv->tv_sec);
960 __get_user(tv->tv_usec, &target_tv->tv_usec);
961
962 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000963
964 return 0;
bellard31e31b82003-02-18 22:55:36 +0000965}
966
ths788f5ec2007-12-09 02:37:05 +0000967static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
968 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000969{
pbrook53a59602006-03-25 19:31:22 +0000970 struct target_timeval *target_tv;
971
ths788f5ec2007-12-09 02:37:05 +0000972 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000973 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000974
975 __put_user(tv->tv_sec, &target_tv->tv_sec);
976 __put_user(tv->tv_usec, &target_tv->tv_usec);
977
978 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000979
980 return 0;
bellard31e31b82003-02-18 22:55:36 +0000981}
982
Nathan Froyd8ec9cf82009-07-22 09:14:36 -0700983#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
984#include <mqueue.h>
985
aurel3224e10032009-04-15 16:11:43 +0000986static inline abi_long copy_from_user_mq_attr(struct mq_attr *attr,
987 abi_ulong target_mq_attr_addr)
988{
989 struct target_mq_attr *target_mq_attr;
990
991 if (!lock_user_struct(VERIFY_READ, target_mq_attr,
992 target_mq_attr_addr, 1))
993 return -TARGET_EFAULT;
994
995 __get_user(attr->mq_flags, &target_mq_attr->mq_flags);
996 __get_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
997 __get_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
998 __get_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
999
1000 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 0);
1001
1002 return 0;
1003}
1004
1005static inline abi_long copy_to_user_mq_attr(abi_ulong target_mq_attr_addr,
1006 const struct mq_attr *attr)
1007{
1008 struct target_mq_attr *target_mq_attr;
1009
1010 if (!lock_user_struct(VERIFY_WRITE, target_mq_attr,
1011 target_mq_attr_addr, 0))
1012 return -TARGET_EFAULT;
1013
1014 __put_user(attr->mq_flags, &target_mq_attr->mq_flags);
1015 __put_user(attr->mq_maxmsg, &target_mq_attr->mq_maxmsg);
1016 __put_user(attr->mq_msgsize, &target_mq_attr->mq_msgsize);
1017 __put_user(attr->mq_curmsgs, &target_mq_attr->mq_curmsgs);
1018
1019 unlock_user_struct(target_mq_attr, target_mq_attr_addr, 1);
1020
1021 return 0;
1022}
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07001023#endif
bellard31e31b82003-02-18 22:55:36 +00001024
Mike Frysinger055e0902011-06-03 17:01:49 -04001025#if defined(TARGET_NR_select) || defined(TARGET_NR__newselect)
ths0da46a62007-10-20 20:23:07 +00001026/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001027static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +00001028 abi_ulong rfd_addr, abi_ulong wfd_addr,
1029 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +00001030{
1031 fd_set rfds, wfds, efds;
1032 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
1033 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00001034 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00001035
Mike Frysinger055e0902011-06-03 17:01:49 -04001036 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
1037 if (ret) {
1038 return ret;
pbrook53a59602006-03-25 19:31:22 +00001039 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001040 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
1041 if (ret) {
1042 return ret;
pbrook53a59602006-03-25 19:31:22 +00001043 }
Mike Frysinger055e0902011-06-03 17:01:49 -04001044 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
1045 if (ret) {
1046 return ret;
pbrook53a59602006-03-25 19:31:22 +00001047 }
ths3b46e622007-09-17 08:09:54 +00001048
ths26edcf42007-12-09 02:25:24 +00001049 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +00001050 if (copy_from_user_timeval(&tv, target_tv_addr))
1051 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001052 tv_ptr = &tv;
1053 } else {
1054 tv_ptr = NULL;
1055 }
ths26edcf42007-12-09 02:25:24 +00001056
bellard31e31b82003-02-18 22:55:36 +00001057 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +00001058
ths26edcf42007-12-09 02:25:24 +00001059 if (!is_error(ret)) {
1060 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
1061 return -TARGET_EFAULT;
1062 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
1063 return -TARGET_EFAULT;
1064 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
1065 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001066
ths788f5ec2007-12-09 02:37:05 +00001067 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
1068 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +00001069 }
bellard579a97f2007-11-11 14:26:47 +00001070
bellard31e31b82003-02-18 22:55:36 +00001071 return ret;
1072}
Mike Frysinger055e0902011-06-03 17:01:49 -04001073#endif
bellard31e31b82003-02-18 22:55:36 +00001074
Riku Voipio099d6b02009-05-05 12:10:04 +03001075static abi_long do_pipe2(int host_pipe[], int flags)
1076{
1077#ifdef CONFIG_PIPE2
1078 return pipe2(host_pipe, flags);
1079#else
1080 return -ENOSYS;
1081#endif
1082}
1083
Richard Hendersonfb41a662010-05-03 10:07:52 -07001084static abi_long do_pipe(void *cpu_env, abi_ulong pipedes,
1085 int flags, int is_pipe2)
Riku Voipio099d6b02009-05-05 12:10:04 +03001086{
1087 int host_pipe[2];
1088 abi_long ret;
1089 ret = flags ? do_pipe2(host_pipe, flags) : pipe(host_pipe);
1090
1091 if (is_error(ret))
1092 return get_errno(ret);
Richard Hendersonfb41a662010-05-03 10:07:52 -07001093
1094 /* Several targets have special calling conventions for the original
1095 pipe syscall, but didn't replicate this into the pipe2 syscall. */
1096 if (!is_pipe2) {
1097#if defined(TARGET_ALPHA)
1098 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = host_pipe[1];
1099 return host_pipe[0];
1100#elif defined(TARGET_MIPS)
1101 ((CPUMIPSState*)cpu_env)->active_tc.gpr[3] = host_pipe[1];
1102 return host_pipe[0];
1103#elif defined(TARGET_SH4)
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001104 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
Richard Hendersonfb41a662010-05-03 10:07:52 -07001105 return host_pipe[0];
takasi-y@ops.dti.ne.jp597c0212010-02-18 00:35:03 +09001106#endif
Richard Hendersonfb41a662010-05-03 10:07:52 -07001107 }
1108
Riku Voipio099d6b02009-05-05 12:10:04 +03001109 if (put_user_s32(host_pipe[0], pipedes)
1110 || put_user_s32(host_pipe[1], pipedes + sizeof(host_pipe[0])))
1111 return -TARGET_EFAULT;
Riku Voipio099d6b02009-05-05 12:10:04 +03001112 return get_errno(ret);
1113}
1114
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001115static inline abi_long target_to_host_ip_mreq(struct ip_mreqn *mreqn,
1116 abi_ulong target_addr,
1117 socklen_t len)
1118{
1119 struct target_ip_mreqn *target_smreqn;
1120
1121 target_smreqn = lock_user(VERIFY_READ, target_addr, len, 1);
1122 if (!target_smreqn)
1123 return -TARGET_EFAULT;
1124 mreqn->imr_multiaddr.s_addr = target_smreqn->imr_multiaddr.s_addr;
1125 mreqn->imr_address.s_addr = target_smreqn->imr_address.s_addr;
1126 if (len == sizeof(struct target_ip_mreqn))
1127 mreqn->imr_ifindex = tswapl(target_smreqn->imr_ifindex);
1128 unlock_user(target_smreqn, target_addr, 0);
1129
1130 return 0;
1131}
1132
bellard579a97f2007-11-11 14:26:47 +00001133static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
1134 abi_ulong target_addr,
1135 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001136{
aurel32607175e2009-04-15 16:11:59 +00001137 const socklen_t unix_maxlen = sizeof (struct sockaddr_un);
1138 sa_family_t sa_family;
pbrook53a59602006-03-25 19:31:22 +00001139 struct target_sockaddr *target_saddr;
1140
bellard579a97f2007-11-11 14:26:47 +00001141 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
1142 if (!target_saddr)
1143 return -TARGET_EFAULT;
aurel32607175e2009-04-15 16:11:59 +00001144
1145 sa_family = tswap16(target_saddr->sa_family);
1146
1147 /* Oops. The caller might send a incomplete sun_path; sun_path
1148 * must be terminated by \0 (see the manual page), but
1149 * unfortunately it is quite common to specify sockaddr_un
1150 * length as "strlen(x->sun_path)" while it should be
1151 * "strlen(...) + 1". We'll fix that here if needed.
1152 * Linux kernel has a similar feature.
1153 */
1154
1155 if (sa_family == AF_UNIX) {
1156 if (len < unix_maxlen && len > 0) {
1157 char *cp = (char*)target_saddr;
1158
1159 if ( cp[len-1] && !cp[len] )
1160 len++;
1161 }
1162 if (len > unix_maxlen)
1163 len = unix_maxlen;
1164 }
1165
pbrook53a59602006-03-25 19:31:22 +00001166 memcpy(addr, target_saddr, len);
aurel32607175e2009-04-15 16:11:59 +00001167 addr->sa_family = sa_family;
pbrook53a59602006-03-25 19:31:22 +00001168 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001169
1170 return 0;
bellard7854b052003-03-29 17:22:23 +00001171}
1172
bellard579a97f2007-11-11 14:26:47 +00001173static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
1174 struct sockaddr *addr,
1175 socklen_t len)
bellard7854b052003-03-29 17:22:23 +00001176{
pbrook53a59602006-03-25 19:31:22 +00001177 struct target_sockaddr *target_saddr;
1178
bellard579a97f2007-11-11 14:26:47 +00001179 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
1180 if (!target_saddr)
1181 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001182 memcpy(target_saddr, addr, len);
1183 target_saddr->sa_family = tswap16(addr->sa_family);
1184 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +00001185
1186 return 0;
bellard7854b052003-03-29 17:22:23 +00001187}
1188
pbrook53a59602006-03-25 19:31:22 +00001189/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001190static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
1191 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +00001192{
1193 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001194 abi_long msg_controllen;
1195 abi_ulong target_cmsg_addr;
1196 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001197 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +00001198
1199 msg_controllen = tswapl(target_msgh->msg_controllen);
1200 if (msg_controllen < sizeof (struct target_cmsghdr))
1201 goto the_end;
1202 target_cmsg_addr = tswapl(target_msgh->msg_control);
1203 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
1204 if (!target_cmsg)
1205 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001206
1207 while (cmsg && target_cmsg) {
1208 void *data = CMSG_DATA(cmsg);
1209 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1210
ths5fafdf22007-09-16 21:08:06 +00001211 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +00001212 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
1213
1214 space += CMSG_SPACE(len);
1215 if (space > msgh->msg_controllen) {
1216 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001217 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001218 break;
1219 }
1220
1221 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
1222 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
1223 cmsg->cmsg_len = CMSG_LEN(len);
1224
bellard3532fa72006-06-24 15:06:03 +00001225 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001226 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1227 memcpy(data, target_data, len);
1228 } else {
1229 int *fd = (int *)data;
1230 int *target_fd = (int *)target_data;
1231 int i, numfds = len / sizeof(int);
1232
1233 for (i = 0; i < numfds; i++)
1234 fd[i] = tswap32(target_fd[i]);
1235 }
1236
1237 cmsg = CMSG_NXTHDR(msgh, cmsg);
1238 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1239 }
bellard5a4a8982007-11-11 17:39:18 +00001240 unlock_user(target_cmsg, target_cmsg_addr, 0);
1241 the_end:
bellard7854b052003-03-29 17:22:23 +00001242 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +00001243 return 0;
bellard7854b052003-03-29 17:22:23 +00001244}
1245
pbrook53a59602006-03-25 19:31:22 +00001246/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +00001247static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
1248 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +00001249{
1250 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +00001251 abi_long msg_controllen;
1252 abi_ulong target_cmsg_addr;
1253 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +00001254 socklen_t space = 0;
1255
bellard5a4a8982007-11-11 17:39:18 +00001256 msg_controllen = tswapl(target_msgh->msg_controllen);
1257 if (msg_controllen < sizeof (struct target_cmsghdr))
1258 goto the_end;
1259 target_cmsg_addr = tswapl(target_msgh->msg_control);
1260 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
1261 if (!target_cmsg)
1262 return -TARGET_EFAULT;
1263
bellard7854b052003-03-29 17:22:23 +00001264 while (cmsg && target_cmsg) {
1265 void *data = CMSG_DATA(cmsg);
1266 void *target_data = TARGET_CMSG_DATA(target_cmsg);
1267
1268 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
1269
1270 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +00001271 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +00001272 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +00001273 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +00001274 break;
1275 }
1276
1277 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
1278 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
1279 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
1280
bellard3532fa72006-06-24 15:06:03 +00001281 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +00001282 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
1283 memcpy(target_data, data, len);
1284 } else {
1285 int *fd = (int *)data;
1286 int *target_fd = (int *)target_data;
1287 int i, numfds = len / sizeof(int);
1288
1289 for (i = 0; i < numfds; i++)
1290 target_fd[i] = tswap32(fd[i]);
1291 }
1292
1293 cmsg = CMSG_NXTHDR(msgh, cmsg);
1294 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
1295 }
bellard5a4a8982007-11-11 17:39:18 +00001296 unlock_user(target_cmsg, target_cmsg_addr, space);
1297 the_end:
1298 target_msgh->msg_controllen = tswapl(space);
1299 return 0;
bellard7854b052003-03-29 17:22:23 +00001300}
1301
ths0da46a62007-10-20 20:23:07 +00001302/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001303static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001304 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +00001305{
blueswir1992f48a2007-10-14 16:27:31 +00001306 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +00001307 int val;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001308 struct ip_mreqn *ip_mreq;
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001309 struct ip_mreq_source *ip_mreq_source;
ths3b46e622007-09-17 08:09:54 +00001310
bellard8853f862004-02-22 14:57:26 +00001311 switch(level) {
1312 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +00001313 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +00001314 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +00001315 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +00001316
bellard2f619692007-11-16 10:46:05 +00001317 if (get_user_u32(val, optval_addr))
1318 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001319 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1320 break;
1321 case SOL_IP:
1322 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +00001323 case IP_TOS:
1324 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +00001325 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +00001326 case IP_ROUTER_ALERT:
1327 case IP_RECVOPTS:
1328 case IP_RETOPTS:
1329 case IP_PKTINFO:
1330 case IP_MTU_DISCOVER:
1331 case IP_RECVERR:
1332 case IP_RECVTOS:
1333#ifdef IP_FREEBIND
1334 case IP_FREEBIND:
1335#endif
1336 case IP_MULTICAST_TTL:
1337 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +00001338 val = 0;
1339 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +00001340 if (get_user_u32(val, optval_addr))
1341 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001342 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +00001343 if (get_user_u8(val, optval_addr))
1344 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001345 }
1346 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
1347 break;
Lionel Landwerlinb975b832009-04-25 23:30:19 +02001348 case IP_ADD_MEMBERSHIP:
1349 case IP_DROP_MEMBERSHIP:
1350 if (optlen < sizeof (struct target_ip_mreq) ||
1351 optlen > sizeof (struct target_ip_mreqn))
1352 return -TARGET_EINVAL;
1353
1354 ip_mreq = (struct ip_mreqn *) alloca(optlen);
1355 target_to_host_ip_mreq(ip_mreq, optval_addr, optlen);
1356 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq, optlen));
1357 break;
1358
Lionel Landwerlin6e3cb582009-04-25 23:31:18 +02001359 case IP_BLOCK_SOURCE:
1360 case IP_UNBLOCK_SOURCE:
1361 case IP_ADD_SOURCE_MEMBERSHIP:
1362 case IP_DROP_SOURCE_MEMBERSHIP:
1363 if (optlen != sizeof (struct target_ip_mreq_source))
1364 return -TARGET_EINVAL;
1365
1366 ip_mreq_source = lock_user(VERIFY_READ, optval_addr, optlen, 1);
1367 ret = get_errno(setsockopt(sockfd, level, optname, ip_mreq_source, optlen));
1368 unlock_user (ip_mreq_source, optval_addr, 0);
1369 break;
1370
bellard8853f862004-02-22 14:57:26 +00001371 default:
1372 goto unimplemented;
1373 }
1374 break;
bellard3532fa72006-06-24 15:06:03 +00001375 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +00001376 switch (optname) {
1377 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +00001378 case TARGET_SO_DEBUG:
1379 optname = SO_DEBUG;
1380 break;
1381 case TARGET_SO_REUSEADDR:
1382 optname = SO_REUSEADDR;
1383 break;
1384 case TARGET_SO_TYPE:
1385 optname = SO_TYPE;
1386 break;
1387 case TARGET_SO_ERROR:
1388 optname = SO_ERROR;
1389 break;
1390 case TARGET_SO_DONTROUTE:
1391 optname = SO_DONTROUTE;
1392 break;
1393 case TARGET_SO_BROADCAST:
1394 optname = SO_BROADCAST;
1395 break;
1396 case TARGET_SO_SNDBUF:
1397 optname = SO_SNDBUF;
1398 break;
1399 case TARGET_SO_RCVBUF:
1400 optname = SO_RCVBUF;
1401 break;
1402 case TARGET_SO_KEEPALIVE:
1403 optname = SO_KEEPALIVE;
1404 break;
1405 case TARGET_SO_OOBINLINE:
1406 optname = SO_OOBINLINE;
1407 break;
1408 case TARGET_SO_NO_CHECK:
1409 optname = SO_NO_CHECK;
1410 break;
1411 case TARGET_SO_PRIORITY:
1412 optname = SO_PRIORITY;
1413 break;
bellard5e83e8e2005-03-01 22:32:06 +00001414#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +00001415 case TARGET_SO_BSDCOMPAT:
1416 optname = SO_BSDCOMPAT;
1417 break;
bellard5e83e8e2005-03-01 22:32:06 +00001418#endif
bellard3532fa72006-06-24 15:06:03 +00001419 case TARGET_SO_PASSCRED:
1420 optname = SO_PASSCRED;
1421 break;
1422 case TARGET_SO_TIMESTAMP:
1423 optname = SO_TIMESTAMP;
1424 break;
1425 case TARGET_SO_RCVLOWAT:
1426 optname = SO_RCVLOWAT;
1427 break;
1428 case TARGET_SO_RCVTIMEO:
1429 optname = SO_RCVTIMEO;
1430 break;
1431 case TARGET_SO_SNDTIMEO:
1432 optname = SO_SNDTIMEO;
1433 break;
bellard8853f862004-02-22 14:57:26 +00001434 break;
1435 default:
1436 goto unimplemented;
1437 }
bellard3532fa72006-06-24 15:06:03 +00001438 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +00001439 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +00001440
bellard2f619692007-11-16 10:46:05 +00001441 if (get_user_u32(val, optval_addr))
1442 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001443 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +00001444 break;
bellard7854b052003-03-29 17:22:23 +00001445 default:
bellard8853f862004-02-22 14:57:26 +00001446 unimplemented:
1447 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +00001448 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +00001449 }
bellard8853f862004-02-22 14:57:26 +00001450 return ret;
bellard7854b052003-03-29 17:22:23 +00001451}
1452
ths0da46a62007-10-20 20:23:07 +00001453/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001454static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +00001455 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +00001456{
blueswir1992f48a2007-10-14 16:27:31 +00001457 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +00001458 int len, val;
1459 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +00001460
1461 switch(level) {
bellard3532fa72006-06-24 15:06:03 +00001462 case TARGET_SOL_SOCKET:
Jamie Lentinf3b974c2010-11-26 15:04:08 +02001463 level = SOL_SOCKET;
1464 switch (optname) {
1465 /* These don't just return a single integer */
1466 case TARGET_SO_LINGER:
1467 case TARGET_SO_RCVTIMEO:
1468 case TARGET_SO_SNDTIMEO:
1469 case TARGET_SO_PEERCRED:
1470 case TARGET_SO_PEERNAME:
1471 goto unimplemented;
1472 /* Options with 'int' argument. */
1473 case TARGET_SO_DEBUG:
1474 optname = SO_DEBUG;
1475 goto int_case;
1476 case TARGET_SO_REUSEADDR:
1477 optname = SO_REUSEADDR;
1478 goto int_case;
1479 case TARGET_SO_TYPE:
1480 optname = SO_TYPE;
1481 goto int_case;
1482 case TARGET_SO_ERROR:
1483 optname = SO_ERROR;
1484 goto int_case;
1485 case TARGET_SO_DONTROUTE:
1486 optname = SO_DONTROUTE;
1487 goto int_case;
1488 case TARGET_SO_BROADCAST:
1489 optname = SO_BROADCAST;
1490 goto int_case;
1491 case TARGET_SO_SNDBUF:
1492 optname = SO_SNDBUF;
1493 goto int_case;
1494 case TARGET_SO_RCVBUF:
1495 optname = SO_RCVBUF;
1496 goto int_case;
1497 case TARGET_SO_KEEPALIVE:
1498 optname = SO_KEEPALIVE;
1499 goto int_case;
1500 case TARGET_SO_OOBINLINE:
1501 optname = SO_OOBINLINE;
1502 goto int_case;
1503 case TARGET_SO_NO_CHECK:
1504 optname = SO_NO_CHECK;
1505 goto int_case;
1506 case TARGET_SO_PRIORITY:
1507 optname = SO_PRIORITY;
1508 goto int_case;
1509#ifdef SO_BSDCOMPAT
1510 case TARGET_SO_BSDCOMPAT:
1511 optname = SO_BSDCOMPAT;
1512 goto int_case;
1513#endif
1514 case TARGET_SO_PASSCRED:
1515 optname = SO_PASSCRED;
1516 goto int_case;
1517 case TARGET_SO_TIMESTAMP:
1518 optname = SO_TIMESTAMP;
1519 goto int_case;
1520 case TARGET_SO_RCVLOWAT:
1521 optname = SO_RCVLOWAT;
1522 goto int_case;
bellard8853f862004-02-22 14:57:26 +00001523 default:
bellard2efbe912005-07-23 15:10:20 +00001524 goto int_case;
1525 }
1526 break;
1527 case SOL_TCP:
1528 /* TCP options all take an 'int' value. */
1529 int_case:
bellard2f619692007-11-16 10:46:05 +00001530 if (get_user_u32(len, optlen))
1531 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001532 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001533 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05001534 lv = sizeof(lv);
bellard2efbe912005-07-23 15:10:20 +00001535 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1536 if (ret < 0)
1537 return ret;
bellard2efbe912005-07-23 15:10:20 +00001538 if (len > lv)
1539 len = lv;
bellard2f619692007-11-16 10:46:05 +00001540 if (len == 4) {
1541 if (put_user_u32(val, optval_addr))
1542 return -TARGET_EFAULT;
1543 } else {
1544 if (put_user_u8(val, optval_addr))
1545 return -TARGET_EFAULT;
Jamie Lentinf3b974c2010-11-26 15:04:08 +02001546 }
bellard2f619692007-11-16 10:46:05 +00001547 if (put_user_u32(len, optlen))
1548 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001549 break;
1550 case SOL_IP:
1551 switch(optname) {
1552 case IP_TOS:
1553 case IP_TTL:
1554 case IP_HDRINCL:
1555 case IP_ROUTER_ALERT:
1556 case IP_RECVOPTS:
1557 case IP_RETOPTS:
1558 case IP_PKTINFO:
1559 case IP_MTU_DISCOVER:
1560 case IP_RECVERR:
1561 case IP_RECVTOS:
1562#ifdef IP_FREEBIND
1563 case IP_FREEBIND:
1564#endif
1565 case IP_MULTICAST_TTL:
1566 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001567 if (get_user_u32(len, optlen))
1568 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001569 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001570 return -TARGET_EINVAL;
Mike Frysinger73160d92011-02-07 01:05:49 -05001571 lv = sizeof(lv);
bellard8853f862004-02-22 14:57:26 +00001572 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1573 if (ret < 0)
1574 return ret;
bellard2efbe912005-07-23 15:10:20 +00001575 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001576 len = 1;
bellard2f619692007-11-16 10:46:05 +00001577 if (put_user_u32(len, optlen)
1578 || put_user_u8(val, optval_addr))
1579 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001580 } else {
bellard2efbe912005-07-23 15:10:20 +00001581 if (len > sizeof(int))
1582 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001583 if (put_user_u32(len, optlen)
1584 || put_user_u32(val, optval_addr))
1585 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001586 }
bellard8853f862004-02-22 14:57:26 +00001587 break;
bellard2efbe912005-07-23 15:10:20 +00001588 default:
thsc02f4992007-12-18 02:39:59 +00001589 ret = -TARGET_ENOPROTOOPT;
1590 break;
bellard8853f862004-02-22 14:57:26 +00001591 }
1592 break;
1593 default:
1594 unimplemented:
1595 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1596 level, optname);
thsc02f4992007-12-18 02:39:59 +00001597 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001598 break;
1599 }
1600 return ret;
bellard7854b052003-03-29 17:22:23 +00001601}
1602
bellard579a97f2007-11-11 14:26:47 +00001603/* FIXME
1604 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1605 * other lock functions have a return code of 0 for failure.
1606 */
1607static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1608 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001609{
1610 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001611 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001612 int i;
pbrook53a59602006-03-25 19:31:22 +00001613
bellard579a97f2007-11-11 14:26:47 +00001614 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1615 if (!target_vec)
1616 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001617 for(i = 0;i < count; i++) {
1618 base = tswapl(target_vec[i].iov_base);
1619 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001620 if (vec[i].iov_len != 0) {
1621 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001622 /* Don't check lock_user return value. We must call writev even
1623 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001624 } else {
1625 /* zero length pointer is ignored */
1626 vec[i].iov_base = NULL;
1627 }
pbrook53a59602006-03-25 19:31:22 +00001628 }
1629 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001630 return 0;
pbrook53a59602006-03-25 19:31:22 +00001631}
1632
bellard579a97f2007-11-11 14:26:47 +00001633static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1634 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001635{
1636 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001637 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001638 int i;
1639
bellard579a97f2007-11-11 14:26:47 +00001640 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1641 if (!target_vec)
1642 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001643 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001644 if (target_vec[i].iov_base) {
1645 base = tswapl(target_vec[i].iov_base);
1646 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1647 }
pbrook53a59602006-03-25 19:31:22 +00001648 }
1649 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001650
1651 return 0;
pbrook53a59602006-03-25 19:31:22 +00001652}
1653
ths0da46a62007-10-20 20:23:07 +00001654/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001655static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001656{
1657#if defined(TARGET_MIPS)
1658 switch(type) {
1659 case TARGET_SOCK_DGRAM:
1660 type = SOCK_DGRAM;
1661 break;
1662 case TARGET_SOCK_STREAM:
1663 type = SOCK_STREAM;
1664 break;
1665 case TARGET_SOCK_RAW:
1666 type = SOCK_RAW;
1667 break;
1668 case TARGET_SOCK_RDM:
1669 type = SOCK_RDM;
1670 break;
1671 case TARGET_SOCK_SEQPACKET:
1672 type = SOCK_SEQPACKET;
1673 break;
1674 case TARGET_SOCK_PACKET:
1675 type = SOCK_PACKET;
1676 break;
1677 }
1678#endif
balrog12bc92a2007-10-30 21:06:14 +00001679 if (domain == PF_NETLINK)
1680 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001681 return get_errno(socket(domain, type, protocol));
1682}
1683
ths0da46a62007-10-20 20:23:07 +00001684/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001685static abi_long do_bind(int sockfd, abi_ulong target_addr,
1686 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001687{
aurel328f7aeaf2009-01-30 19:47:57 +00001688 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001689 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001690
Blue Swirl38724252010-09-18 05:53:14 +00001691 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001692 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001693 }
aurel328f7aeaf2009-01-30 19:47:57 +00001694
aurel32607175e2009-04-15 16:11:59 +00001695 addr = alloca(addrlen+1);
ths3b46e622007-09-17 08:09:54 +00001696
Arnaud Patard917507b2009-06-19 10:44:45 +03001697 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1698 if (ret)
1699 return ret;
1700
bellard3532fa72006-06-24 15:06:03 +00001701 return get_errno(bind(sockfd, addr, addrlen));
1702}
1703
ths0da46a62007-10-20 20:23:07 +00001704/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001705static abi_long do_connect(int sockfd, abi_ulong target_addr,
1706 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001707{
aurel328f7aeaf2009-01-30 19:47:57 +00001708 void *addr;
Arnaud Patard917507b2009-06-19 10:44:45 +03001709 abi_long ret;
aurel328f7aeaf2009-01-30 19:47:57 +00001710
Blue Swirl38724252010-09-18 05:53:14 +00001711 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001712 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001713 }
aurel328f7aeaf2009-01-30 19:47:57 +00001714
1715 addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001716
Arnaud Patard917507b2009-06-19 10:44:45 +03001717 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1718 if (ret)
1719 return ret;
1720
bellard3532fa72006-06-24 15:06:03 +00001721 return get_errno(connect(sockfd, addr, addrlen));
1722}
1723
ths0da46a62007-10-20 20:23:07 +00001724/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001725static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1726 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001727{
balrog6de645c2008-10-28 10:26:29 +00001728 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001729 struct target_msghdr *msgp;
1730 struct msghdr msg;
1731 int count;
1732 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001733 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001734
bellard579a97f2007-11-11 14:26:47 +00001735 /* FIXME */
1736 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1737 msgp,
1738 target_msg,
1739 send ? 1 : 0))
1740 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001741 if (msgp->msg_name) {
1742 msg.msg_namelen = tswap32(msgp->msg_namelen);
1743 msg.msg_name = alloca(msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001744 ret = target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
bellard3532fa72006-06-24 15:06:03 +00001745 msg.msg_namelen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001746 if (ret) {
1747 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
1748 return ret;
1749 }
bellard3532fa72006-06-24 15:06:03 +00001750 } else {
1751 msg.msg_name = NULL;
1752 msg.msg_namelen = 0;
1753 }
1754 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1755 msg.msg_control = alloca(msg.msg_controllen);
1756 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001757
bellard3532fa72006-06-24 15:06:03 +00001758 count = tswapl(msgp->msg_iovlen);
1759 vec = alloca(count * sizeof(struct iovec));
1760 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001761 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001762 msg.msg_iovlen = count;
1763 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001764
bellard3532fa72006-06-24 15:06:03 +00001765 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001766 ret = target_to_host_cmsg(&msg, msgp);
1767 if (ret == 0)
1768 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001769 } else {
1770 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001771 if (!is_error(ret)) {
1772 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001773 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001774 if (!is_error(ret))
1775 ret = len;
1776 }
bellard3532fa72006-06-24 15:06:03 +00001777 }
1778 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001779 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001780 return ret;
1781}
1782
ths0da46a62007-10-20 20:23:07 +00001783/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001784static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001785 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001786{
bellard2f619692007-11-16 10:46:05 +00001787 socklen_t addrlen;
1788 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001789 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001790
Arnaud Patard917507b2009-06-19 10:44:45 +03001791 if (target_addr == 0)
1792 return get_errno(accept(fd, NULL, NULL));
1793
1794 /* linux returns EINVAL if addrlen pointer is invalid */
bellard2f619692007-11-16 10:46:05 +00001795 if (get_user_u32(addrlen, target_addrlen_addr))
Arnaud Patard917507b2009-06-19 10:44:45 +03001796 return -TARGET_EINVAL;
bellard2f619692007-11-16 10:46:05 +00001797
Blue Swirl38724252010-09-18 05:53:14 +00001798 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001799 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001800 }
aurel328f7aeaf2009-01-30 19:47:57 +00001801
Arnaud Patard917507b2009-06-19 10:44:45 +03001802 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1803 return -TARGET_EINVAL;
1804
bellard2f619692007-11-16 10:46:05 +00001805 addr = alloca(addrlen);
1806
pbrook1be9e1d2006-11-19 15:26:04 +00001807 ret = get_errno(accept(fd, addr, &addrlen));
1808 if (!is_error(ret)) {
1809 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001810 if (put_user_u32(addrlen, target_addrlen_addr))
1811 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001812 }
1813 return ret;
1814}
1815
ths0da46a62007-10-20 20:23:07 +00001816/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001817static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001818 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001819{
bellard2f619692007-11-16 10:46:05 +00001820 socklen_t addrlen;
1821 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001822 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001823
bellard2f619692007-11-16 10:46:05 +00001824 if (get_user_u32(addrlen, target_addrlen_addr))
1825 return -TARGET_EFAULT;
1826
Blue Swirl38724252010-09-18 05:53:14 +00001827 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001828 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001829 }
aurel328f7aeaf2009-01-30 19:47:57 +00001830
Arnaud Patard917507b2009-06-19 10:44:45 +03001831 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1832 return -TARGET_EFAULT;
1833
bellard2f619692007-11-16 10:46:05 +00001834 addr = alloca(addrlen);
1835
pbrook1be9e1d2006-11-19 15:26:04 +00001836 ret = get_errno(getpeername(fd, addr, &addrlen));
1837 if (!is_error(ret)) {
1838 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001839 if (put_user_u32(addrlen, target_addrlen_addr))
1840 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001841 }
1842 return ret;
1843}
1844
ths0da46a62007-10-20 20:23:07 +00001845/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001846static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001847 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001848{
bellard2f619692007-11-16 10:46:05 +00001849 socklen_t addrlen;
1850 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001851 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001852
bellard2f619692007-11-16 10:46:05 +00001853 if (get_user_u32(addrlen, target_addrlen_addr))
1854 return -TARGET_EFAULT;
1855
Blue Swirl38724252010-09-18 05:53:14 +00001856 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001857 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001858 }
aurel328f7aeaf2009-01-30 19:47:57 +00001859
Arnaud Patard917507b2009-06-19 10:44:45 +03001860 if (!access_ok(VERIFY_WRITE, target_addr, addrlen))
1861 return -TARGET_EFAULT;
1862
bellard2f619692007-11-16 10:46:05 +00001863 addr = alloca(addrlen);
1864
pbrook1be9e1d2006-11-19 15:26:04 +00001865 ret = get_errno(getsockname(fd, addr, &addrlen));
1866 if (!is_error(ret)) {
1867 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001868 if (put_user_u32(addrlen, target_addrlen_addr))
1869 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001870 }
1871 return ret;
1872}
1873
ths0da46a62007-10-20 20:23:07 +00001874/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001875static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001876 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001877{
1878 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001879 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001880
1881 ret = get_errno(socketpair(domain, type, protocol, tab));
1882 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001883 if (put_user_s32(tab[0], target_tab_addr)
1884 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1885 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001886 }
1887 return ret;
1888}
1889
ths0da46a62007-10-20 20:23:07 +00001890/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001891static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1892 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001893{
1894 void *addr;
1895 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001896 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001897
Blue Swirl38724252010-09-18 05:53:14 +00001898 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001899 return -TARGET_EINVAL;
Blue Swirl38724252010-09-18 05:53:14 +00001900 }
aurel328f7aeaf2009-01-30 19:47:57 +00001901
bellard579a97f2007-11-11 14:26:47 +00001902 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1903 if (!host_msg)
1904 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001905 if (target_addr) {
1906 addr = alloca(addrlen);
Arnaud Patard917507b2009-06-19 10:44:45 +03001907 ret = target_to_host_sockaddr(addr, target_addr, addrlen);
1908 if (ret) {
1909 unlock_user(host_msg, msg, 0);
1910 return ret;
1911 }
pbrook1be9e1d2006-11-19 15:26:04 +00001912 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1913 } else {
1914 ret = get_errno(send(fd, host_msg, len, flags));
1915 }
1916 unlock_user(host_msg, msg, 0);
1917 return ret;
1918}
1919
ths0da46a62007-10-20 20:23:07 +00001920/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001921static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1922 abi_ulong target_addr,
1923 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001924{
1925 socklen_t addrlen;
1926 void *addr;
1927 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001928 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001929
bellard579a97f2007-11-11 14:26:47 +00001930 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1931 if (!host_msg)
1932 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001933 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001934 if (get_user_u32(addrlen, target_addrlen)) {
1935 ret = -TARGET_EFAULT;
1936 goto fail;
1937 }
Blue Swirl38724252010-09-18 05:53:14 +00001938 if ((int)addrlen < 0) {
aurel328f7aeaf2009-01-30 19:47:57 +00001939 ret = -TARGET_EINVAL;
1940 goto fail;
1941 }
pbrook1be9e1d2006-11-19 15:26:04 +00001942 addr = alloca(addrlen);
1943 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1944 } else {
1945 addr = NULL; /* To keep compiler quiet. */
1946 ret = get_errno(recv(fd, host_msg, len, flags));
1947 }
1948 if (!is_error(ret)) {
1949 if (target_addr) {
1950 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001951 if (put_user_u32(addrlen, target_addrlen)) {
1952 ret = -TARGET_EFAULT;
1953 goto fail;
1954 }
pbrook1be9e1d2006-11-19 15:26:04 +00001955 }
1956 unlock_user(host_msg, msg, len);
1957 } else {
bellard2f619692007-11-16 10:46:05 +00001958fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001959 unlock_user(host_msg, msg, 0);
1960 }
1961 return ret;
1962}
1963
j_mayer32407102007-09-26 23:01:49 +00001964#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001965/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001966static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001967{
blueswir1992f48a2007-10-14 16:27:31 +00001968 abi_long ret;
1969 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001970
1971 switch(num) {
1972 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001973 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001974 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00001975
Ulrich Hecht98818182009-07-03 17:09:28 +02001976 if (get_user_ual(domain, vptr)
1977 || get_user_ual(type, vptr + n)
1978 || get_user_ual(protocol, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001979 return -TARGET_EFAULT;
1980
bellard3532fa72006-06-24 15:06:03 +00001981 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001982 }
bellard31e31b82003-02-18 22:55:36 +00001983 break;
1984 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001985 {
Ulrich Hecht98818182009-07-03 17:09:28 +02001986 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00001987 abi_ulong target_addr;
1988 socklen_t addrlen;
1989
Ulrich Hecht98818182009-07-03 17:09:28 +02001990 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00001991 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02001992 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00001993 return -TARGET_EFAULT;
1994
bellard3532fa72006-06-24 15:06:03 +00001995 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001996 }
bellard31e31b82003-02-18 22:55:36 +00001997 break;
1998 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001999 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002000 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002001 abi_ulong target_addr;
2002 socklen_t addrlen;
2003
Ulrich Hecht98818182009-07-03 17:09:28 +02002004 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002005 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002006 || get_user_ual(addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002007 return -TARGET_EFAULT;
2008
bellard3532fa72006-06-24 15:06:03 +00002009 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00002010 }
bellard31e31b82003-02-18 22:55:36 +00002011 break;
2012 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00002013 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002014 abi_ulong sockfd, backlog;
bellard2f619692007-11-16 10:46:05 +00002015
Ulrich Hecht98818182009-07-03 17:09:28 +02002016 if (get_user_ual(sockfd, vptr)
2017 || get_user_ual(backlog, vptr + n))
bellard2f619692007-11-16 10:46:05 +00002018 return -TARGET_EFAULT;
2019
bellard7854b052003-03-29 17:22:23 +00002020 ret = get_errno(listen(sockfd, backlog));
2021 }
bellard31e31b82003-02-18 22:55:36 +00002022 break;
2023 case SOCKOP_accept:
2024 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002025 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002026 abi_ulong target_addr, target_addrlen;
2027
Ulrich Hecht98818182009-07-03 17:09:28 +02002028 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002029 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002030 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002031 return -TARGET_EFAULT;
2032
pbrook1be9e1d2006-11-19 15:26:04 +00002033 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00002034 }
2035 break;
2036 case SOCKOP_getsockname:
2037 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002038 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002039 abi_ulong target_addr, target_addrlen;
2040
Ulrich Hecht98818182009-07-03 17:09:28 +02002041 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002042 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002043 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002044 return -TARGET_EFAULT;
2045
pbrook1be9e1d2006-11-19 15:26:04 +00002046 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00002047 }
2048 break;
2049 case SOCKOP_getpeername:
2050 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002051 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002052 abi_ulong target_addr, target_addrlen;
2053
Ulrich Hecht98818182009-07-03 17:09:28 +02002054 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002055 || get_user_ual(target_addr, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002056 || get_user_ual(target_addrlen, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002057 return -TARGET_EFAULT;
2058
pbrook1be9e1d2006-11-19 15:26:04 +00002059 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00002060 }
2061 break;
2062 case SOCKOP_socketpair:
2063 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002064 abi_ulong domain, type, protocol;
bellard2f619692007-11-16 10:46:05 +00002065 abi_ulong tab;
2066
Ulrich Hecht98818182009-07-03 17:09:28 +02002067 if (get_user_ual(domain, vptr)
2068 || get_user_ual(type, vptr + n)
2069 || get_user_ual(protocol, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002070 || get_user_ual(tab, vptr + 3 * n))
2071 return -TARGET_EFAULT;
2072
pbrook1be9e1d2006-11-19 15:26:04 +00002073 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00002074 }
2075 break;
2076 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00002077 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002078 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002079 abi_ulong msg;
2080 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002081 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002082
Ulrich Hecht98818182009-07-03 17:09:28 +02002083 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002084 || get_user_ual(msg, vptr + n)
2085 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002086 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00002087 return -TARGET_EFAULT;
2088
pbrook1be9e1d2006-11-19 15:26:04 +00002089 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00002090 }
bellard31e31b82003-02-18 22:55:36 +00002091 break;
2092 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00002093 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002094 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002095 abi_ulong msg;
2096 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002097 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002098
Ulrich Hecht98818182009-07-03 17:09:28 +02002099 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002100 || get_user_ual(msg, vptr + n)
2101 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002102 || get_user_ual(flags, vptr + 3 * n))
bellard2f619692007-11-16 10:46:05 +00002103 return -TARGET_EFAULT;
2104
pbrook1be9e1d2006-11-19 15:26:04 +00002105 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00002106 }
bellard31e31b82003-02-18 22:55:36 +00002107 break;
2108 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00002109 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002110 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002111 abi_ulong msg;
2112 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002113 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002114 abi_ulong addr;
2115 socklen_t addrlen;
2116
Ulrich Hecht98818182009-07-03 17:09:28 +02002117 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002118 || get_user_ual(msg, vptr + n)
2119 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002120 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00002121 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002122 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00002123 return -TARGET_EFAULT;
2124
pbrook1be9e1d2006-11-19 15:26:04 +00002125 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00002126 }
bellard31e31b82003-02-18 22:55:36 +00002127 break;
2128 case SOCKOP_recvfrom:
2129 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002130 abi_ulong sockfd;
bellard2f619692007-11-16 10:46:05 +00002131 abi_ulong msg;
2132 size_t len;
Ulrich Hecht98818182009-07-03 17:09:28 +02002133 abi_ulong flags;
bellard2f619692007-11-16 10:46:05 +00002134 abi_ulong addr;
2135 socklen_t addrlen;
2136
Ulrich Hecht98818182009-07-03 17:09:28 +02002137 if (get_user_ual(sockfd, vptr)
bellard2f619692007-11-16 10:46:05 +00002138 || get_user_ual(msg, vptr + n)
2139 || get_user_ual(len, vptr + 2 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002140 || get_user_ual(flags, vptr + 3 * n)
bellard2f619692007-11-16 10:46:05 +00002141 || get_user_ual(addr, vptr + 4 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002142 || get_user_ual(addrlen, vptr + 5 * n))
bellard2f619692007-11-16 10:46:05 +00002143 return -TARGET_EFAULT;
2144
pbrook1be9e1d2006-11-19 15:26:04 +00002145 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00002146 }
2147 break;
2148 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00002149 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002150 abi_ulong sockfd, how;
bellard2f619692007-11-16 10:46:05 +00002151
Ulrich Hecht98818182009-07-03 17:09:28 +02002152 if (get_user_ual(sockfd, vptr)
2153 || get_user_ual(how, vptr + n))
bellard2f619692007-11-16 10:46:05 +00002154 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00002155
2156 ret = get_errno(shutdown(sockfd, how));
2157 }
bellard31e31b82003-02-18 22:55:36 +00002158 break;
2159 case SOCKOP_sendmsg:
2160 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00002161 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002162 abi_ulong fd;
blueswir1992f48a2007-10-14 16:27:31 +00002163 abi_ulong target_msg;
Ulrich Hecht98818182009-07-03 17:09:28 +02002164 abi_ulong flags;
bellard1a9353d2003-03-16 20:28:50 +00002165
Ulrich Hecht98818182009-07-03 17:09:28 +02002166 if (get_user_ual(fd, vptr)
bellard2f619692007-11-16 10:46:05 +00002167 || get_user_ual(target_msg, vptr + n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002168 || get_user_ual(flags, vptr + 2 * n))
bellard2f619692007-11-16 10:46:05 +00002169 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00002170
ths5fafdf22007-09-16 21:08:06 +00002171 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00002172 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00002173 }
2174 break;
bellard31e31b82003-02-18 22:55:36 +00002175 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00002176 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002177 abi_ulong sockfd;
2178 abi_ulong level;
2179 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00002180 abi_ulong optval;
2181 socklen_t optlen;
2182
Ulrich Hecht98818182009-07-03 17:09:28 +02002183 if (get_user_ual(sockfd, vptr)
2184 || get_user_ual(level, vptr + n)
2185 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002186 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002187 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00002188 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00002189
2190 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
2191 }
2192 break;
bellard31e31b82003-02-18 22:55:36 +00002193 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00002194 {
Ulrich Hecht98818182009-07-03 17:09:28 +02002195 abi_ulong sockfd;
2196 abi_ulong level;
2197 abi_ulong optname;
bellard2f619692007-11-16 10:46:05 +00002198 abi_ulong optval;
2199 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00002200
Ulrich Hecht98818182009-07-03 17:09:28 +02002201 if (get_user_ual(sockfd, vptr)
2202 || get_user_ual(level, vptr + n)
2203 || get_user_ual(optname, vptr + 2 * n)
bellard2f619692007-11-16 10:46:05 +00002204 || get_user_ual(optval, vptr + 3 * n)
Ulrich Hecht98818182009-07-03 17:09:28 +02002205 || get_user_ual(optlen, vptr + 4 * n))
bellard2f619692007-11-16 10:46:05 +00002206 return -TARGET_EFAULT;
2207
2208 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00002209 }
2210 break;
bellard31e31b82003-02-18 22:55:36 +00002211 default:
2212 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00002213 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002214 break;
2215 }
2216 return ret;
2217}
j_mayer32407102007-09-26 23:01:49 +00002218#endif
bellard31e31b82003-02-18 22:55:36 +00002219
bellard8853f862004-02-22 14:57:26 +00002220#define N_SHM_REGIONS 32
2221
2222static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00002223 abi_ulong start;
2224 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00002225} shm_regions[N_SHM_REGIONS];
2226
ths3eb6b042007-06-03 14:26:27 +00002227struct target_ipc_perm
2228{
blueswir1992f48a2007-10-14 16:27:31 +00002229 abi_long __key;
2230 abi_ulong uid;
2231 abi_ulong gid;
2232 abi_ulong cuid;
2233 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00002234 unsigned short int mode;
2235 unsigned short int __pad1;
2236 unsigned short int __seq;
2237 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00002238 abi_ulong __unused1;
2239 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00002240};
2241
2242struct target_semid_ds
2243{
2244 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00002245 abi_ulong sem_otime;
2246 abi_ulong __unused1;
2247 abi_ulong sem_ctime;
2248 abi_ulong __unused2;
2249 abi_ulong sem_nsems;
2250 abi_ulong __unused3;
2251 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00002252};
2253
bellard579a97f2007-11-11 14:26:47 +00002254static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
2255 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002256{
2257 struct target_ipc_perm *target_ip;
2258 struct target_semid_ds *target_sd;
2259
bellard579a97f2007-11-11 14:26:47 +00002260 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2261 return -TARGET_EFAULT;
Michael S. Tsirkine8bbe362009-09-30 18:56:44 +00002262 target_ip = &(target_sd->sem_perm);
ths3eb6b042007-06-03 14:26:27 +00002263 host_ip->__key = tswapl(target_ip->__key);
2264 host_ip->uid = tswapl(target_ip->uid);
2265 host_ip->gid = tswapl(target_ip->gid);
2266 host_ip->cuid = tswapl(target_ip->cuid);
2267 host_ip->cgid = tswapl(target_ip->cgid);
2268 host_ip->mode = tswapl(target_ip->mode);
2269 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002270 return 0;
ths3eb6b042007-06-03 14:26:27 +00002271}
2272
bellard579a97f2007-11-11 14:26:47 +00002273static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
2274 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00002275{
2276 struct target_ipc_perm *target_ip;
2277 struct target_semid_ds *target_sd;
2278
bellard579a97f2007-11-11 14:26:47 +00002279 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2280 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002281 target_ip = &(target_sd->sem_perm);
2282 target_ip->__key = tswapl(host_ip->__key);
2283 target_ip->uid = tswapl(host_ip->uid);
2284 target_ip->gid = tswapl(host_ip->gid);
2285 target_ip->cuid = tswapl(host_ip->cuid);
2286 target_ip->cgid = tswapl(host_ip->cgid);
2287 target_ip->mode = tswapl(host_ip->mode);
2288 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002289 return 0;
ths3eb6b042007-06-03 14:26:27 +00002290}
2291
bellard579a97f2007-11-11 14:26:47 +00002292static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
2293 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002294{
2295 struct target_semid_ds *target_sd;
2296
bellard579a97f2007-11-11 14:26:47 +00002297 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2298 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002299 if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr))
2300 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00002301 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
2302 host_sd->sem_otime = tswapl(target_sd->sem_otime);
2303 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
2304 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002305 return 0;
ths3eb6b042007-06-03 14:26:27 +00002306}
2307
bellard579a97f2007-11-11 14:26:47 +00002308static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
2309 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00002310{
2311 struct target_semid_ds *target_sd;
2312
bellard579a97f2007-11-11 14:26:47 +00002313 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2314 return -TARGET_EFAULT;
aurel32e5289082009-04-18 16:16:12 +00002315 if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)))
2316 return -TARGET_EFAULT;;
ths3eb6b042007-06-03 14:26:27 +00002317 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
2318 target_sd->sem_otime = tswapl(host_sd->sem_otime);
2319 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
2320 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002321 return 0;
ths3eb6b042007-06-03 14:26:27 +00002322}
2323
aurel32e5289082009-04-18 16:16:12 +00002324struct target_seminfo {
2325 int semmap;
2326 int semmni;
2327 int semmns;
2328 int semmnu;
2329 int semmsl;
2330 int semopm;
2331 int semume;
2332 int semusz;
2333 int semvmx;
2334 int semaem;
2335};
2336
2337static inline abi_long host_to_target_seminfo(abi_ulong target_addr,
2338 struct seminfo *host_seminfo)
2339{
2340 struct target_seminfo *target_seminfo;
2341 if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0))
2342 return -TARGET_EFAULT;
2343 __put_user(host_seminfo->semmap, &target_seminfo->semmap);
2344 __put_user(host_seminfo->semmni, &target_seminfo->semmni);
2345 __put_user(host_seminfo->semmns, &target_seminfo->semmns);
2346 __put_user(host_seminfo->semmnu, &target_seminfo->semmnu);
2347 __put_user(host_seminfo->semmsl, &target_seminfo->semmsl);
2348 __put_user(host_seminfo->semopm, &target_seminfo->semopm);
2349 __put_user(host_seminfo->semume, &target_seminfo->semume);
2350 __put_user(host_seminfo->semusz, &target_seminfo->semusz);
2351 __put_user(host_seminfo->semvmx, &target_seminfo->semvmx);
2352 __put_user(host_seminfo->semaem, &target_seminfo->semaem);
2353 unlock_user_struct(target_seminfo, target_addr, 1);
2354 return 0;
2355}
2356
thsfa294812007-02-02 22:05:00 +00002357union semun {
2358 int val;
ths3eb6b042007-06-03 14:26:27 +00002359 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00002360 unsigned short *array;
aurel32e5289082009-04-18 16:16:12 +00002361 struct seminfo *__buf;
thsfa294812007-02-02 22:05:00 +00002362};
2363
ths3eb6b042007-06-03 14:26:27 +00002364union target_semun {
2365 int val;
aurel32e5289082009-04-18 16:16:12 +00002366 abi_ulong buf;
2367 abi_ulong array;
2368 abi_ulong __buf;
ths3eb6b042007-06-03 14:26:27 +00002369};
2370
aurel32e5289082009-04-18 16:16:12 +00002371static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array,
2372 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00002373{
aurel32e5289082009-04-18 16:16:12 +00002374 int nsems;
2375 unsigned short *array;
2376 union semun semun;
2377 struct semid_ds semid_ds;
2378 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002379
aurel32e5289082009-04-18 16:16:12 +00002380 semun.buf = &semid_ds;
2381
2382 ret = semctl(semid, 0, IPC_STAT, semun);
2383 if (ret == -1)
2384 return get_errno(ret);
2385
2386 nsems = semid_ds.sem_nsems;
2387
2388 *host_array = malloc(nsems*sizeof(unsigned short));
2389 array = lock_user(VERIFY_READ, target_addr,
2390 nsems*sizeof(unsigned short), 1);
2391 if (!array)
2392 return -TARGET_EFAULT;
2393
2394 for(i=0; i<nsems; i++) {
2395 __get_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002396 }
aurel32e5289082009-04-18 16:16:12 +00002397 unlock_user(array, target_addr, 0);
2398
bellard579a97f2007-11-11 14:26:47 +00002399 return 0;
ths3eb6b042007-06-03 14:26:27 +00002400}
2401
aurel32e5289082009-04-18 16:16:12 +00002402static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr,
2403 unsigned short **host_array)
ths3eb6b042007-06-03 14:26:27 +00002404{
aurel32e5289082009-04-18 16:16:12 +00002405 int nsems;
2406 unsigned short *array;
2407 union semun semun;
2408 struct semid_ds semid_ds;
2409 int i, ret;
ths3eb6b042007-06-03 14:26:27 +00002410
aurel32e5289082009-04-18 16:16:12 +00002411 semun.buf = &semid_ds;
2412
2413 ret = semctl(semid, 0, IPC_STAT, semun);
2414 if (ret == -1)
2415 return get_errno(ret);
2416
2417 nsems = semid_ds.sem_nsems;
2418
2419 array = lock_user(VERIFY_WRITE, target_addr,
2420 nsems*sizeof(unsigned short), 0);
2421 if (!array)
2422 return -TARGET_EFAULT;
2423
2424 for(i=0; i<nsems; i++) {
2425 __put_user((*host_array)[i], &array[i]);
ths3eb6b042007-06-03 14:26:27 +00002426 }
aurel32e5289082009-04-18 16:16:12 +00002427 free(*host_array);
2428 unlock_user(array, target_addr, 1);
2429
bellard579a97f2007-11-11 14:26:47 +00002430 return 0;
ths3eb6b042007-06-03 14:26:27 +00002431}
2432
aurel32e5289082009-04-18 16:16:12 +00002433static inline abi_long do_semctl(int semid, int semnum, int cmd,
2434 union target_semun target_su)
ths3eb6b042007-06-03 14:26:27 +00002435{
2436 union semun arg;
2437 struct semid_ds dsarg;
vibi sreenivasan7b8118e2009-06-19 13:34:39 +05302438 unsigned short *array = NULL;
aurel32e5289082009-04-18 16:16:12 +00002439 struct seminfo seminfo;
2440 abi_long ret = -TARGET_EINVAL;
2441 abi_long err;
2442 cmd &= 0xff;
ths3eb6b042007-06-03 14:26:27 +00002443
2444 switch( cmd ) {
2445 case GETVAL:
ths3eb6b042007-06-03 14:26:27 +00002446 case SETVAL:
aurel32e5289082009-04-18 16:16:12 +00002447 arg.val = tswapl(target_su.val);
2448 ret = get_errno(semctl(semid, semnum, cmd, arg));
2449 target_su.val = tswapl(arg.val);
ths3eb6b042007-06-03 14:26:27 +00002450 break;
2451 case GETALL:
ths3eb6b042007-06-03 14:26:27 +00002452 case SETALL:
aurel32e5289082009-04-18 16:16:12 +00002453 err = target_to_host_semarray(semid, &array, target_su.array);
2454 if (err)
2455 return err;
2456 arg.array = array;
2457 ret = get_errno(semctl(semid, semnum, cmd, arg));
2458 err = host_to_target_semarray(semid, target_su.array, &array);
2459 if (err)
2460 return err;
ths3eb6b042007-06-03 14:26:27 +00002461 break;
2462 case IPC_STAT:
ths3eb6b042007-06-03 14:26:27 +00002463 case IPC_SET:
aurel32e5289082009-04-18 16:16:12 +00002464 case SEM_STAT:
2465 err = target_to_host_semid_ds(&dsarg, target_su.buf);
2466 if (err)
2467 return err;
2468 arg.buf = &dsarg;
2469 ret = get_errno(semctl(semid, semnum, cmd, arg));
2470 err = host_to_target_semid_ds(target_su.buf, &dsarg);
2471 if (err)
2472 return err;
ths3eb6b042007-06-03 14:26:27 +00002473 break;
aurel32e5289082009-04-18 16:16:12 +00002474 case IPC_INFO:
2475 case SEM_INFO:
2476 arg.__buf = &seminfo;
2477 ret = get_errno(semctl(semid, semnum, cmd, arg));
2478 err = host_to_target_seminfo(target_su.__buf, &seminfo);
2479 if (err)
2480 return err;
2481 break;
2482 case IPC_RMID:
2483 case GETPID:
2484 case GETNCNT:
2485 case GETZCNT:
2486 ret = get_errno(semctl(semid, semnum, cmd, NULL));
2487 break;
ths3eb6b042007-06-03 14:26:27 +00002488 }
2489
2490 return ret;
2491}
2492
aurel32e5289082009-04-18 16:16:12 +00002493struct target_sembuf {
2494 unsigned short sem_num;
2495 short sem_op;
2496 short sem_flg;
2497};
2498
2499static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf,
2500 abi_ulong target_addr,
2501 unsigned nsops)
2502{
2503 struct target_sembuf *target_sembuf;
2504 int i;
2505
2506 target_sembuf = lock_user(VERIFY_READ, target_addr,
2507 nsops*sizeof(struct target_sembuf), 1);
2508 if (!target_sembuf)
2509 return -TARGET_EFAULT;
2510
2511 for(i=0; i<nsops; i++) {
2512 __get_user(host_sembuf[i].sem_num, &target_sembuf[i].sem_num);
2513 __get_user(host_sembuf[i].sem_op, &target_sembuf[i].sem_op);
2514 __get_user(host_sembuf[i].sem_flg, &target_sembuf[i].sem_flg);
2515 }
2516
2517 unlock_user(target_sembuf, target_addr, 0);
2518
2519 return 0;
2520}
2521
2522static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops)
2523{
2524 struct sembuf sops[nsops];
2525
2526 if (target_to_host_sembuf(sops, ptr, nsops))
2527 return -TARGET_EFAULT;
2528
2529 return semop(semid, sops, nsops);
2530}
2531
ths1bc012f2007-06-03 14:27:49 +00002532struct target_msqid_ds
2533{
aurel321c54ff92008-10-13 21:08:44 +00002534 struct target_ipc_perm msg_perm;
2535 abi_ulong msg_stime;
2536#if TARGET_ABI_BITS == 32
2537 abi_ulong __unused1;
2538#endif
2539 abi_ulong msg_rtime;
2540#if TARGET_ABI_BITS == 32
2541 abi_ulong __unused2;
2542#endif
2543 abi_ulong msg_ctime;
2544#if TARGET_ABI_BITS == 32
2545 abi_ulong __unused3;
2546#endif
2547 abi_ulong __msg_cbytes;
2548 abi_ulong msg_qnum;
2549 abi_ulong msg_qbytes;
2550 abi_ulong msg_lspid;
2551 abi_ulong msg_lrpid;
2552 abi_ulong __unused4;
2553 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00002554};
2555
bellard579a97f2007-11-11 14:26:47 +00002556static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
2557 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00002558{
2559 struct target_msqid_ds *target_md;
2560
bellard579a97f2007-11-11 14:26:47 +00002561 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
2562 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002563 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
2564 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002565 host_md->msg_stime = tswapl(target_md->msg_stime);
2566 host_md->msg_rtime = tswapl(target_md->msg_rtime);
2567 host_md->msg_ctime = tswapl(target_md->msg_ctime);
2568 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
2569 host_md->msg_qnum = tswapl(target_md->msg_qnum);
2570 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
2571 host_md->msg_lspid = tswapl(target_md->msg_lspid);
2572 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
2573 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00002574 return 0;
ths1bc012f2007-06-03 14:27:49 +00002575}
2576
bellard579a97f2007-11-11 14:26:47 +00002577static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
2578 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00002579{
2580 struct target_msqid_ds *target_md;
2581
bellard579a97f2007-11-11 14:26:47 +00002582 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
2583 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002584 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
2585 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002586 target_md->msg_stime = tswapl(host_md->msg_stime);
2587 target_md->msg_rtime = tswapl(host_md->msg_rtime);
2588 target_md->msg_ctime = tswapl(host_md->msg_ctime);
2589 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
2590 target_md->msg_qnum = tswapl(host_md->msg_qnum);
2591 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
2592 target_md->msg_lspid = tswapl(host_md->msg_lspid);
2593 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
2594 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00002595 return 0;
ths1bc012f2007-06-03 14:27:49 +00002596}
2597
aurel321c54ff92008-10-13 21:08:44 +00002598struct target_msginfo {
2599 int msgpool;
2600 int msgmap;
2601 int msgmax;
2602 int msgmnb;
2603 int msgmni;
2604 int msgssz;
2605 int msgtql;
2606 unsigned short int msgseg;
2607};
2608
2609static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
2610 struct msginfo *host_msginfo)
2611{
2612 struct target_msginfo *target_msginfo;
2613 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
2614 return -TARGET_EFAULT;
2615 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
2616 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
2617 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
2618 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
2619 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
2620 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
2621 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
2622 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
2623 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00002624 return 0;
aurel321c54ff92008-10-13 21:08:44 +00002625}
2626
2627static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00002628{
2629 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00002630 struct msginfo msginfo;
2631 abi_long ret = -TARGET_EINVAL;
2632
2633 cmd &= 0xff;
2634
2635 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00002636 case IPC_STAT:
2637 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00002638 case MSG_STAT:
2639 if (target_to_host_msqid_ds(&dsarg,ptr))
2640 return -TARGET_EFAULT;
2641 ret = get_errno(msgctl(msgid, cmd, &dsarg));
2642 if (host_to_target_msqid_ds(ptr,&dsarg))
2643 return -TARGET_EFAULT;
2644 break;
2645 case IPC_RMID:
2646 ret = get_errno(msgctl(msgid, cmd, NULL));
2647 break;
2648 case IPC_INFO:
2649 case MSG_INFO:
2650 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
2651 if (host_to_target_msginfo(ptr, &msginfo))
2652 return -TARGET_EFAULT;
2653 break;
ths1bc012f2007-06-03 14:27:49 +00002654 }
aurel321c54ff92008-10-13 21:08:44 +00002655
ths1bc012f2007-06-03 14:27:49 +00002656 return ret;
2657}
2658
2659struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00002660 abi_long mtype;
2661 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00002662};
2663
blueswir1992f48a2007-10-14 16:27:31 +00002664static inline abi_long do_msgsnd(int msqid, abi_long msgp,
2665 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002666{
2667 struct target_msgbuf *target_mb;
2668 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002669 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002670
bellard579a97f2007-11-11 14:26:47 +00002671 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
2672 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00002673 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002674 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
2675 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00002676 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
2677 free(host_mb);
2678 unlock_user_struct(target_mb, msgp, 0);
2679
2680 return ret;
2681}
2682
blueswir1992f48a2007-10-14 16:27:31 +00002683static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002684 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002685 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002686{
2687 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002688 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002689 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002690 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002691
bellard579a97f2007-11-11 14:26:47 +00002692 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2693 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002694
ths1bc012f2007-06-03 14:27:49 +00002695 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002696 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2697
bellard579a97f2007-11-11 14:26:47 +00002698 if (ret > 0) {
2699 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2700 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2701 if (!target_mtext) {
2702 ret = -TARGET_EFAULT;
2703 goto end;
2704 }
aurel321c54ff92008-10-13 21:08:44 +00002705 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002706 unlock_user(target_mtext, target_mtext_addr, ret);
2707 }
aurel321c54ff92008-10-13 21:08:44 +00002708
ths1bc012f2007-06-03 14:27:49 +00002709 target_mb->mtype = tswapl(host_mb->mtype);
2710 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002711
bellard579a97f2007-11-11 14:26:47 +00002712end:
2713 if (target_mb)
2714 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002715 return ret;
2716}
2717
Riku Voipio88a8c982009-04-03 10:42:00 +03002718struct target_shmid_ds
2719{
2720 struct target_ipc_perm shm_perm;
2721 abi_ulong shm_segsz;
2722 abi_ulong shm_atime;
2723#if TARGET_ABI_BITS == 32
2724 abi_ulong __unused1;
2725#endif
2726 abi_ulong shm_dtime;
2727#if TARGET_ABI_BITS == 32
2728 abi_ulong __unused2;
2729#endif
2730 abi_ulong shm_ctime;
2731#if TARGET_ABI_BITS == 32
2732 abi_ulong __unused3;
2733#endif
2734 int shm_cpid;
2735 int shm_lpid;
2736 abi_ulong shm_nattch;
2737 unsigned long int __unused4;
2738 unsigned long int __unused5;
2739};
2740
2741static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd,
2742 abi_ulong target_addr)
2743{
2744 struct target_shmid_ds *target_sd;
2745
2746 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
2747 return -TARGET_EFAULT;
2748 if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr))
2749 return -TARGET_EFAULT;
2750 __get_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2751 __get_user(host_sd->shm_atime, &target_sd->shm_atime);
2752 __get_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2753 __get_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2754 __get_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2755 __get_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2756 __get_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2757 unlock_user_struct(target_sd, target_addr, 0);
2758 return 0;
2759}
2760
2761static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr,
2762 struct shmid_ds *host_sd)
2763{
2764 struct target_shmid_ds *target_sd;
2765
2766 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
2767 return -TARGET_EFAULT;
2768 if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm)))
2769 return -TARGET_EFAULT;
2770 __put_user(host_sd->shm_segsz, &target_sd->shm_segsz);
2771 __put_user(host_sd->shm_atime, &target_sd->shm_atime);
2772 __put_user(host_sd->shm_dtime, &target_sd->shm_dtime);
2773 __put_user(host_sd->shm_ctime, &target_sd->shm_ctime);
2774 __put_user(host_sd->shm_cpid, &target_sd->shm_cpid);
2775 __put_user(host_sd->shm_lpid, &target_sd->shm_lpid);
2776 __put_user(host_sd->shm_nattch, &target_sd->shm_nattch);
2777 unlock_user_struct(target_sd, target_addr, 1);
2778 return 0;
2779}
2780
2781struct target_shminfo {
2782 abi_ulong shmmax;
2783 abi_ulong shmmin;
2784 abi_ulong shmmni;
2785 abi_ulong shmseg;
2786 abi_ulong shmall;
2787};
2788
2789static inline abi_long host_to_target_shminfo(abi_ulong target_addr,
2790 struct shminfo *host_shminfo)
2791{
2792 struct target_shminfo *target_shminfo;
2793 if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0))
2794 return -TARGET_EFAULT;
2795 __put_user(host_shminfo->shmmax, &target_shminfo->shmmax);
2796 __put_user(host_shminfo->shmmin, &target_shminfo->shmmin);
2797 __put_user(host_shminfo->shmmni, &target_shminfo->shmmni);
2798 __put_user(host_shminfo->shmseg, &target_shminfo->shmseg);
2799 __put_user(host_shminfo->shmall, &target_shminfo->shmall);
2800 unlock_user_struct(target_shminfo, target_addr, 1);
2801 return 0;
2802}
2803
2804struct target_shm_info {
2805 int used_ids;
2806 abi_ulong shm_tot;
2807 abi_ulong shm_rss;
2808 abi_ulong shm_swp;
2809 abi_ulong swap_attempts;
2810 abi_ulong swap_successes;
2811};
2812
2813static inline abi_long host_to_target_shm_info(abi_ulong target_addr,
2814 struct shm_info *host_shm_info)
2815{
2816 struct target_shm_info *target_shm_info;
2817 if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0))
2818 return -TARGET_EFAULT;
2819 __put_user(host_shm_info->used_ids, &target_shm_info->used_ids);
2820 __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot);
2821 __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss);
2822 __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp);
2823 __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts);
2824 __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes);
2825 unlock_user_struct(target_shm_info, target_addr, 1);
2826 return 0;
2827}
2828
2829static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf)
2830{
2831 struct shmid_ds dsarg;
2832 struct shminfo shminfo;
2833 struct shm_info shm_info;
2834 abi_long ret = -TARGET_EINVAL;
2835
2836 cmd &= 0xff;
2837
2838 switch(cmd) {
2839 case IPC_STAT:
2840 case IPC_SET:
2841 case SHM_STAT:
2842 if (target_to_host_shmid_ds(&dsarg, buf))
2843 return -TARGET_EFAULT;
2844 ret = get_errno(shmctl(shmid, cmd, &dsarg));
2845 if (host_to_target_shmid_ds(buf, &dsarg))
2846 return -TARGET_EFAULT;
2847 break;
2848 case IPC_INFO:
2849 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo));
2850 if (host_to_target_shminfo(buf, &shminfo))
2851 return -TARGET_EFAULT;
2852 break;
2853 case SHM_INFO:
2854 ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info));
2855 if (host_to_target_shm_info(buf, &shm_info))
2856 return -TARGET_EFAULT;
2857 break;
2858 case IPC_RMID:
2859 case SHM_LOCK:
2860 case SHM_UNLOCK:
2861 ret = get_errno(shmctl(shmid, cmd, NULL));
2862 break;
2863 }
2864
2865 return ret;
2866}
2867
2868static inline abi_ulong do_shmat(int shmid, abi_ulong shmaddr, int shmflg)
2869{
2870 abi_long raddr;
2871 void *host_raddr;
2872 struct shmid_ds shm_info;
2873 int i,ret;
2874
2875 /* find out the length of the shared memory segment */
2876 ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info));
2877 if (is_error(ret)) {
2878 /* can't get length, bail out */
2879 return ret;
2880 }
2881
2882 mmap_lock();
2883
2884 if (shmaddr)
2885 host_raddr = shmat(shmid, (void *)g2h(shmaddr), shmflg);
2886 else {
2887 abi_ulong mmap_start;
2888
2889 mmap_start = mmap_find_vma(0, shm_info.shm_segsz);
2890
2891 if (mmap_start == -1) {
2892 errno = ENOMEM;
2893 host_raddr = (void *)-1;
2894 } else
2895 host_raddr = shmat(shmid, g2h(mmap_start), shmflg | SHM_REMAP);
2896 }
2897
2898 if (host_raddr == (void *)-1) {
2899 mmap_unlock();
2900 return get_errno((long)host_raddr);
2901 }
2902 raddr=h2g((unsigned long)host_raddr);
2903
2904 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2905 PAGE_VALID | PAGE_READ |
2906 ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE));
2907
2908 for (i = 0; i < N_SHM_REGIONS; i++) {
2909 if (shm_regions[i].start == 0) {
2910 shm_regions[i].start = raddr;
2911 shm_regions[i].size = shm_info.shm_segsz;
2912 break;
2913 }
2914 }
2915
2916 mmap_unlock();
2917 return raddr;
2918
2919}
2920
2921static inline abi_long do_shmdt(abi_ulong shmaddr)
2922{
2923 int i;
2924
2925 for (i = 0; i < N_SHM_REGIONS; ++i) {
2926 if (shm_regions[i].start == shmaddr) {
2927 shm_regions[i].start = 0;
takasi-y@ops.dti.ne.jpe00ac242010-04-11 02:09:57 +09002928 page_set_flags(shmaddr, shmaddr + shm_regions[i].size, 0);
Riku Voipio88a8c982009-04-03 10:42:00 +03002929 break;
2930 }
2931 }
2932
2933 return get_errno(shmdt(g2h(shmaddr)));
2934}
2935
aurel321c54ff92008-10-13 21:08:44 +00002936#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002937/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002938/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002939static abi_long do_ipc(unsigned int call, int first,
2940 int second, int third,
2941 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002942{
2943 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002944 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002945
2946 version = call >> 16;
2947 call &= 0xffff;
2948
2949 switch (call) {
thsfa294812007-02-02 22:05:00 +00002950 case IPCOP_semop:
aurel32e5289082009-04-18 16:16:12 +00002951 ret = do_semop(first, ptr, second);
thsfa294812007-02-02 22:05:00 +00002952 break;
2953
2954 case IPCOP_semget:
2955 ret = get_errno(semget(first, second, third));
2956 break;
2957
2958 case IPCOP_semctl:
aurel32e5289082009-04-18 16:16:12 +00002959 ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr);
thsfa294812007-02-02 22:05:00 +00002960 break;
thsd96372e2007-02-02 22:05:44 +00002961
aurel321c54ff92008-10-13 21:08:44 +00002962 case IPCOP_msgget:
2963 ret = get_errno(msgget(first, second));
2964 break;
thsd96372e2007-02-02 22:05:44 +00002965
aurel321c54ff92008-10-13 21:08:44 +00002966 case IPCOP_msgsnd:
2967 ret = do_msgsnd(first, ptr, second, third);
2968 break;
thsd96372e2007-02-02 22:05:44 +00002969
aurel321c54ff92008-10-13 21:08:44 +00002970 case IPCOP_msgctl:
2971 ret = do_msgctl(first, second, ptr);
2972 break;
thsd96372e2007-02-02 22:05:44 +00002973
aurel321c54ff92008-10-13 21:08:44 +00002974 case IPCOP_msgrcv:
2975 switch (version) {
2976 case 0:
2977 {
2978 struct target_ipc_kludge {
2979 abi_long msgp;
2980 abi_long msgtyp;
2981 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002982
aurel321c54ff92008-10-13 21:08:44 +00002983 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2984 ret = -TARGET_EFAULT;
2985 break;
ths1bc012f2007-06-03 14:27:49 +00002986 }
aurel321c54ff92008-10-13 21:08:44 +00002987
2988 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2989
2990 unlock_user_struct(tmp, ptr, 0);
2991 break;
2992 }
2993 default:
2994 ret = do_msgrcv(first, ptr, second, fifth, third);
2995 }
2996 break;
thsd96372e2007-02-02 22:05:44 +00002997
bellard8853f862004-02-22 14:57:26 +00002998 case IPCOP_shmat:
Riku Voipio88a8c982009-04-03 10:42:00 +03002999 switch (version) {
3000 default:
bellard5a4a8982007-11-11 17:39:18 +00003001 {
3002 abi_ulong raddr;
Riku Voipio88a8c982009-04-03 10:42:00 +03003003 raddr = do_shmat(first, ptr, second);
3004 if (is_error(raddr))
3005 return get_errno(raddr);
bellard2f619692007-11-16 10:46:05 +00003006 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00003007 return -TARGET_EFAULT;
Riku Voipio88a8c982009-04-03 10:42:00 +03003008 break;
3009 }
3010 case 1:
3011 ret = -TARGET_EINVAL;
3012 break;
bellard5a4a8982007-11-11 17:39:18 +00003013 }
bellard8853f862004-02-22 14:57:26 +00003014 break;
3015 case IPCOP_shmdt:
Riku Voipio88a8c982009-04-03 10:42:00 +03003016 ret = do_shmdt(ptr);
bellard8853f862004-02-22 14:57:26 +00003017 break;
3018
3019 case IPCOP_shmget:
3020 /* IPC_* flag values are the same on all linux platforms */
3021 ret = get_errno(shmget(first, second, third));
3022 break;
3023
3024 /* IPC_* and SHM_* command values are the same on all linux platforms */
3025 case IPCOP_shmctl:
Riku Voipio88a8c982009-04-03 10:42:00 +03003026 ret = do_shmctl(first, second, third);
bellard8853f862004-02-22 14:57:26 +00003027 break;
3028 default:
j_mayer32407102007-09-26 23:01:49 +00003029 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00003030 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00003031 break;
3032 }
3033 return ret;
3034}
j_mayer32407102007-09-26 23:01:49 +00003035#endif
bellard8853f862004-02-22 14:57:26 +00003036
bellard31e31b82003-02-18 22:55:36 +00003037/* kernel structure types definitions */
bellard31e31b82003-02-18 22:55:36 +00003038
Blue Swirl001faf32009-05-13 17:53:17 +00003039#define STRUCT(name, ...) STRUCT_ ## name,
bellard31e31b82003-02-18 22:55:36 +00003040#define STRUCT_SPECIAL(name) STRUCT_ ## name,
3041enum {
3042#include "syscall_types.h"
3043};
3044#undef STRUCT
3045#undef STRUCT_SPECIAL
3046
Blue Swirl001faf32009-05-13 17:53:17 +00003047#define STRUCT(name, ...) static const argtype struct_ ## name ## _def[] = { __VA_ARGS__, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00003048#define STRUCT_SPECIAL(name)
3049#include "syscall_types.h"
3050#undef STRUCT
3051#undef STRUCT_SPECIAL
3052
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003053typedef struct IOCTLEntry IOCTLEntry;
3054
3055typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
3056 int fd, abi_long cmd, abi_long arg);
3057
3058struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00003059 unsigned int target_cmd;
3060 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00003061 const char *name;
3062 int access;
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003063 do_ioctl_fn *do_ioctl;
bellard1a9353d2003-03-16 20:28:50 +00003064 const argtype arg_type[5];
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003065};
bellard31e31b82003-02-18 22:55:36 +00003066
3067#define IOC_R 0x0001
3068#define IOC_W 0x0002
3069#define IOC_RW (IOC_R | IOC_W)
3070
3071#define MAX_STRUCT_SIZE 4096
3072
Peter Maydelldace20d2011-01-10 13:11:24 +00003073#ifdef CONFIG_FIEMAP
Peter Maydell285da2b2011-01-06 15:04:18 +00003074/* So fiemap access checks don't overflow on 32 bit systems.
3075 * This is very slightly smaller than the limit imposed by
3076 * the underlying kernel.
3077 */
3078#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
3079 / sizeof(struct fiemap_extent))
3080
3081static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
3082 int fd, abi_long cmd, abi_long arg)
3083{
3084 /* The parameter for this ioctl is a struct fiemap followed
3085 * by an array of struct fiemap_extent whose size is set
3086 * in fiemap->fm_extent_count. The array is filled in by the
3087 * ioctl.
3088 */
3089 int target_size_in, target_size_out;
3090 struct fiemap *fm;
3091 const argtype *arg_type = ie->arg_type;
3092 const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
3093 void *argptr, *p;
3094 abi_long ret;
3095 int i, extent_size = thunk_type_size(extent_arg_type, 0);
3096 uint32_t outbufsz;
3097 int free_fm = 0;
3098
3099 assert(arg_type[0] == TYPE_PTR);
3100 assert(ie->access == IOC_RW);
3101 arg_type++;
3102 target_size_in = thunk_type_size(arg_type, 0);
3103 argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
3104 if (!argptr) {
3105 return -TARGET_EFAULT;
3106 }
3107 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3108 unlock_user(argptr, arg, 0);
3109 fm = (struct fiemap *)buf_temp;
3110 if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
3111 return -TARGET_EINVAL;
3112 }
3113
3114 outbufsz = sizeof (*fm) +
3115 (sizeof(struct fiemap_extent) * fm->fm_extent_count);
3116
3117 if (outbufsz > MAX_STRUCT_SIZE) {
3118 /* We can't fit all the extents into the fixed size buffer.
3119 * Allocate one that is large enough and use it instead.
3120 */
3121 fm = malloc(outbufsz);
3122 if (!fm) {
3123 return -TARGET_ENOMEM;
3124 }
3125 memcpy(fm, buf_temp, sizeof(struct fiemap));
3126 free_fm = 1;
3127 }
3128 ret = get_errno(ioctl(fd, ie->host_cmd, fm));
3129 if (!is_error(ret)) {
3130 target_size_out = target_size_in;
3131 /* An extent_count of 0 means we were only counting the extents
3132 * so there are no structs to copy
3133 */
3134 if (fm->fm_extent_count != 0) {
3135 target_size_out += fm->fm_mapped_extents * extent_size;
3136 }
3137 argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
3138 if (!argptr) {
3139 ret = -TARGET_EFAULT;
3140 } else {
3141 /* Convert the struct fiemap */
3142 thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
3143 if (fm->fm_extent_count != 0) {
3144 p = argptr + target_size_in;
3145 /* ...and then all the struct fiemap_extents */
3146 for (i = 0; i < fm->fm_mapped_extents; i++) {
3147 thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
3148 THUNK_TARGET);
3149 p += extent_size;
3150 }
3151 }
3152 unlock_user(argptr, arg, target_size_out);
3153 }
3154 }
3155 if (free_fm) {
3156 free(fm);
3157 }
3158 return ret;
3159}
Peter Maydelldace20d2011-01-10 13:11:24 +00003160#endif
Peter Maydell285da2b2011-01-06 15:04:18 +00003161
Laurent Vivier059c2f22011-03-30 00:12:12 +02003162static abi_long do_ioctl_ifconf(const IOCTLEntry *ie, uint8_t *buf_temp,
3163 int fd, abi_long cmd, abi_long arg)
3164{
3165 const argtype *arg_type = ie->arg_type;
3166 int target_size;
3167 void *argptr;
3168 int ret;
3169 struct ifconf *host_ifconf;
3170 uint32_t outbufsz;
3171 const argtype ifreq_arg_type[] = { MK_STRUCT(STRUCT_sockaddr_ifreq) };
3172 int target_ifreq_size;
3173 int nb_ifreq;
3174 int free_buf = 0;
3175 int i;
3176 int target_ifc_len;
3177 abi_long target_ifc_buf;
3178 int host_ifc_len;
3179 char *host_ifc_buf;
3180
3181 assert(arg_type[0] == TYPE_PTR);
3182 assert(ie->access == IOC_RW);
3183
3184 arg_type++;
3185 target_size = thunk_type_size(arg_type, 0);
3186
3187 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3188 if (!argptr)
3189 return -TARGET_EFAULT;
3190 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3191 unlock_user(argptr, arg, 0);
3192
3193 host_ifconf = (struct ifconf *)(unsigned long)buf_temp;
3194 target_ifc_len = host_ifconf->ifc_len;
3195 target_ifc_buf = (abi_long)(unsigned long)host_ifconf->ifc_buf;
3196
3197 target_ifreq_size = thunk_type_size(ifreq_arg_type, 0);
3198 nb_ifreq = target_ifc_len / target_ifreq_size;
3199 host_ifc_len = nb_ifreq * sizeof(struct ifreq);
3200
3201 outbufsz = sizeof(*host_ifconf) + host_ifc_len;
3202 if (outbufsz > MAX_STRUCT_SIZE) {
3203 /* We can't fit all the extents into the fixed size buffer.
3204 * Allocate one that is large enough and use it instead.
3205 */
3206 host_ifconf = malloc(outbufsz);
3207 if (!host_ifconf) {
3208 return -TARGET_ENOMEM;
3209 }
3210 memcpy(host_ifconf, buf_temp, sizeof(*host_ifconf));
3211 free_buf = 1;
3212 }
3213 host_ifc_buf = (char*)host_ifconf + sizeof(*host_ifconf);
3214
3215 host_ifconf->ifc_len = host_ifc_len;
3216 host_ifconf->ifc_buf = host_ifc_buf;
3217
3218 ret = get_errno(ioctl(fd, ie->host_cmd, host_ifconf));
3219 if (!is_error(ret)) {
3220 /* convert host ifc_len to target ifc_len */
3221
3222 nb_ifreq = host_ifconf->ifc_len / sizeof(struct ifreq);
3223 target_ifc_len = nb_ifreq * target_ifreq_size;
3224 host_ifconf->ifc_len = target_ifc_len;
3225
3226 /* restore target ifc_buf */
3227
3228 host_ifconf->ifc_buf = (char *)(unsigned long)target_ifc_buf;
3229
3230 /* copy struct ifconf to target user */
3231
3232 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3233 if (!argptr)
3234 return -TARGET_EFAULT;
3235 thunk_convert(argptr, host_ifconf, arg_type, THUNK_TARGET);
3236 unlock_user(argptr, arg, target_size);
3237
3238 /* copy ifreq[] to target user */
3239
3240 argptr = lock_user(VERIFY_WRITE, target_ifc_buf, target_ifc_len, 0);
3241 for (i = 0; i < nb_ifreq ; i++) {
3242 thunk_convert(argptr + i * target_ifreq_size,
3243 host_ifc_buf + i * sizeof(struct ifreq),
3244 ifreq_arg_type, THUNK_TARGET);
3245 }
3246 unlock_user(argptr, target_ifc_buf, target_ifc_len);
3247 }
3248
3249 if (free_buf) {
3250 free(host_ifconf);
3251 }
3252
3253 return ret;
3254}
3255
blueswir19f106a72008-10-05 10:52:52 +00003256static IOCTLEntry ioctl_entries[] = {
Blue Swirl001faf32009-05-13 17:53:17 +00003257#define IOCTL(cmd, access, ...) \
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003258 { TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
3259#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
3260 { TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
bellard31e31b82003-02-18 22:55:36 +00003261#include "ioctls.h"
3262 { 0, 0, },
3263};
3264
pbrook53a59602006-03-25 19:31:22 +00003265/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00003266/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00003267static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00003268{
3269 const IOCTLEntry *ie;
3270 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00003271 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003272 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00003273 int target_size;
3274 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00003275
3276 ie = ioctl_entries;
3277 for(;;) {
3278 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00003279 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00003280 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00003281 }
3282 if (ie->target_cmd == cmd)
3283 break;
3284 ie++;
3285 }
3286 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00003287#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00003288 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00003289#endif
Peter Maydelld2ef05b2011-01-06 15:04:17 +00003290 if (ie->do_ioctl) {
3291 return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
3292 }
3293
bellard31e31b82003-02-18 22:55:36 +00003294 switch(arg_type[0]) {
3295 case TYPE_NULL:
3296 /* no argument */
3297 ret = get_errno(ioctl(fd, ie->host_cmd));
3298 break;
3299 case TYPE_PTRVOID:
3300 case TYPE_INT:
3301 /* int argment */
3302 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
3303 break;
3304 case TYPE_PTR:
3305 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00003306 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00003307 switch(ie->access) {
3308 case IOC_R:
3309 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3310 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003311 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3312 if (!argptr)
3313 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003314 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3315 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00003316 }
3317 break;
3318 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00003319 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3320 if (!argptr)
3321 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003322 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3323 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00003324 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3325 break;
3326 default:
3327 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00003328 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
3329 if (!argptr)
3330 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003331 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
3332 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00003333 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
3334 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00003335 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
3336 if (!argptr)
3337 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003338 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
3339 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00003340 }
3341 break;
3342 }
3343 break;
3344 default:
j_mayer32407102007-09-26 23:01:49 +00003345 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
3346 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00003347 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00003348 break;
3349 }
3350 return ret;
3351}
3352
blueswir1b39bc502008-10-05 10:51:10 +00003353static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003354 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
3355 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
3356 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
3357 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
3358 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
3359 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
3360 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
3361 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
3362 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
3363 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
3364 { TARGET_IXON, TARGET_IXON, IXON, IXON },
3365 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
3366 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
3367 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
3368 { 0, 0, 0, 0 }
3369};
3370
blueswir1b39bc502008-10-05 10:51:10 +00003371static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003372 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
3373 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
3374 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
3375 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
3376 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
3377 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
3378 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
3379 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
3380 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
3381 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
3382 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
3383 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
3384 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
3385 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
3386 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
3387 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
3388 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
3389 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
3390 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
3391 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
3392 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
3393 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
3394 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
3395 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
3396 { 0, 0, 0, 0 }
3397};
3398
blueswir1b39bc502008-10-05 10:51:10 +00003399static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003400 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
3401 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
3402 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
3403 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
3404 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
3405 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
3406 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
3407 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
3408 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
3409 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
3410 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
3411 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
3412 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
3413 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
3414 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
3415 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
3416 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
3417 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
3418 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
3419 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
3420 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
3421 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
3422 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
3423 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
3424 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
3425 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
3426 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
3427 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
3428 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
3429 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
3430 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
3431 { 0, 0, 0, 0 }
3432};
3433
blueswir1b39bc502008-10-05 10:51:10 +00003434static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00003435 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
3436 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
3437 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
3438 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
3439 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
3440 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
3441 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
3442 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
3443 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
3444 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
3445 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
3446 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
3447 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
3448 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
3449 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
3450 { 0, 0, 0, 0 }
3451};
3452
3453static void target_to_host_termios (void *dst, const void *src)
3454{
3455 struct host_termios *host = dst;
3456 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00003457
ths5fafdf22007-09-16 21:08:06 +00003458 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003459 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003460 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003461 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003462 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003463 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00003464 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003465 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
3466 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00003467
Arnaud Patard44607122009-04-21 17:39:08 +03003468 memset(host->c_cc, 0, sizeof(host->c_cc));
ths5fafdf22007-09-16 21:08:06 +00003469 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
3470 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00003471 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00003472 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00003473 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00003474 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00003475 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00003476 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00003477 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00003478 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
3479 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00003480 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
3481 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
3482 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
3483 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
3484 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00003485 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00003486}
ths3b46e622007-09-17 08:09:54 +00003487
bellard31e31b82003-02-18 22:55:36 +00003488static void host_to_target_termios (void *dst, const void *src)
3489{
3490 struct target_termios *target = dst;
3491 const struct host_termios *host = src;
3492
ths5fafdf22007-09-16 21:08:06 +00003493 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00003494 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003495 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00003496 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003497 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00003498 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00003499 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00003500 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
3501 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00003502
Arnaud Patard44607122009-04-21 17:39:08 +03003503 memset(target->c_cc, 0, sizeof(target->c_cc));
bellard31e31b82003-02-18 22:55:36 +00003504 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
3505 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
3506 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
3507 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
3508 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
3509 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
3510 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
3511 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
3512 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
3513 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
3514 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
3515 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
3516 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
3517 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
3518 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
3519 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
3520 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
3521}
3522
blueswir18e853dc2008-10-05 10:49:32 +00003523static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00003524 .convert = { host_to_target_termios, target_to_host_termios },
3525 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
3526 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
3527};
3528
bellard5286db72003-06-05 00:57:30 +00003529static bitmask_transtbl mmap_flags_tbl[] = {
3530 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
3531 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
3532 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
3533 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
3534 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
3535 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
3536 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
3537 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
3538 { 0, 0, 0, 0 }
3539};
3540
bellard2ab83ea2003-06-15 19:56:46 +00003541#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00003542
3543/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00003544static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00003545
bellard03acab62007-11-11 14:57:14 +00003546static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003547{
3548 int size;
pbrook53a59602006-03-25 19:31:22 +00003549 void *p;
bellard6dbad632003-03-16 18:05:05 +00003550
3551 if (!ldt_table)
3552 return 0;
3553 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
3554 if (size > bytecount)
3555 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00003556 p = lock_user(VERIFY_WRITE, ptr, size, 0);
3557 if (!p)
bellard03acab62007-11-11 14:57:14 +00003558 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00003559 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00003560 memcpy(p, ldt_table, size);
3561 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00003562 return size;
3563}
3564
3565/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00003566static abi_long write_ldt(CPUX86State *env,
3567 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00003568{
3569 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00003570 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00003571 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00003572 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00003573 uint32_t *lp, entry_1, entry_2;
3574
3575 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00003576 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00003577 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00003578 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003579 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3580 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3581 ldt_info.limit = tswap32(target_ldt_info->limit);
3582 ldt_info.flags = tswap32(target_ldt_info->flags);
3583 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00003584
bellard6dbad632003-03-16 18:05:05 +00003585 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00003586 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003587 seg_32bit = ldt_info.flags & 1;
3588 contents = (ldt_info.flags >> 1) & 3;
3589 read_exec_only = (ldt_info.flags >> 3) & 1;
3590 limit_in_pages = (ldt_info.flags >> 4) & 1;
3591 seg_not_present = (ldt_info.flags >> 5) & 1;
3592 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00003593#ifdef TARGET_ABI32
3594 lm = 0;
3595#else
3596 lm = (ldt_info.flags >> 7) & 1;
3597#endif
bellard6dbad632003-03-16 18:05:05 +00003598 if (contents == 3) {
3599 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00003600 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003601 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00003602 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00003603 }
3604 /* allocate the LDT */
3605 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00003606 env->ldt.base = target_mmap(0,
3607 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
3608 PROT_READ|PROT_WRITE,
3609 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
3610 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00003611 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00003612 memset(g2h(env->ldt.base), 0,
3613 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00003614 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00003615 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00003616 }
3617
3618 /* NOTE: same code as Linux kernel */
3619 /* Allow LDTs to be cleared by the user. */
3620 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3621 if (oldmode ||
3622 (contents == 0 &&
3623 read_exec_only == 1 &&
3624 seg_32bit == 0 &&
3625 limit_in_pages == 0 &&
3626 seg_not_present == 1 &&
3627 useable == 0 )) {
3628 entry_1 = 0;
3629 entry_2 = 0;
3630 goto install;
3631 }
3632 }
ths3b46e622007-09-17 08:09:54 +00003633
bellard6dbad632003-03-16 18:05:05 +00003634 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3635 (ldt_info.limit & 0x0ffff);
3636 entry_2 = (ldt_info.base_addr & 0xff000000) |
3637 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3638 (ldt_info.limit & 0xf0000) |
3639 ((read_exec_only ^ 1) << 9) |
3640 (contents << 10) |
3641 ((seg_not_present ^ 1) << 15) |
3642 (seg_32bit << 22) |
3643 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00003644 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00003645 0x7000;
3646 if (!oldmode)
3647 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00003648
bellard6dbad632003-03-16 18:05:05 +00003649 /* Install the new entry ... */
3650install:
3651 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
3652 lp[0] = tswap32(entry_1);
3653 lp[1] = tswap32(entry_2);
3654 return 0;
3655}
3656
3657/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00003658static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
3659 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00003660{
bellard03acab62007-11-11 14:57:14 +00003661 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00003662
bellard6dbad632003-03-16 18:05:05 +00003663 switch (func) {
3664 case 0:
3665 ret = read_ldt(ptr, bytecount);
3666 break;
3667 case 1:
3668 ret = write_ldt(env, ptr, bytecount, 1);
3669 break;
3670 case 0x11:
3671 ret = write_ldt(env, ptr, bytecount, 0);
3672 break;
bellard03acab62007-11-11 14:57:14 +00003673 default:
3674 ret = -TARGET_ENOSYS;
3675 break;
bellard6dbad632003-03-16 18:05:05 +00003676 }
3677 return ret;
3678}
bellard1b6b0292003-03-22 17:31:38 +00003679
blueswir14583f582008-08-24 10:35:55 +00003680#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00003681static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003682{
3683 uint64_t *gdt_table = g2h(env->gdt.base);
3684 struct target_modify_ldt_ldt_s ldt_info;
3685 struct target_modify_ldt_ldt_s *target_ldt_info;
3686 int seg_32bit, contents, read_exec_only, limit_in_pages;
3687 int seg_not_present, useable, lm;
3688 uint32_t *lp, entry_1, entry_2;
3689 int i;
3690
3691 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3692 if (!target_ldt_info)
3693 return -TARGET_EFAULT;
3694 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
3695 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
3696 ldt_info.limit = tswap32(target_ldt_info->limit);
3697 ldt_info.flags = tswap32(target_ldt_info->flags);
3698 if (ldt_info.entry_number == -1) {
3699 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
3700 if (gdt_table[i] == 0) {
3701 ldt_info.entry_number = i;
3702 target_ldt_info->entry_number = tswap32(i);
3703 break;
3704 }
3705 }
3706 }
3707 unlock_user_struct(target_ldt_info, ptr, 1);
3708
3709 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
3710 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
3711 return -TARGET_EINVAL;
3712 seg_32bit = ldt_info.flags & 1;
3713 contents = (ldt_info.flags >> 1) & 3;
3714 read_exec_only = (ldt_info.flags >> 3) & 1;
3715 limit_in_pages = (ldt_info.flags >> 4) & 1;
3716 seg_not_present = (ldt_info.flags >> 5) & 1;
3717 useable = (ldt_info.flags >> 6) & 1;
3718#ifdef TARGET_ABI32
3719 lm = 0;
3720#else
3721 lm = (ldt_info.flags >> 7) & 1;
3722#endif
3723
3724 if (contents == 3) {
3725 if (seg_not_present == 0)
3726 return -TARGET_EINVAL;
3727 }
3728
3729 /* NOTE: same code as Linux kernel */
3730 /* Allow LDTs to be cleared by the user. */
3731 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
3732 if ((contents == 0 &&
3733 read_exec_only == 1 &&
3734 seg_32bit == 0 &&
3735 limit_in_pages == 0 &&
3736 seg_not_present == 1 &&
3737 useable == 0 )) {
3738 entry_1 = 0;
3739 entry_2 = 0;
3740 goto install;
3741 }
3742 }
3743
3744 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
3745 (ldt_info.limit & 0x0ffff);
3746 entry_2 = (ldt_info.base_addr & 0xff000000) |
3747 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
3748 (ldt_info.limit & 0xf0000) |
3749 ((read_exec_only ^ 1) << 9) |
3750 (contents << 10) |
3751 ((seg_not_present ^ 1) << 15) |
3752 (seg_32bit << 22) |
3753 (limit_in_pages << 23) |
3754 (useable << 20) |
3755 (lm << 21) |
3756 0x7000;
3757
3758 /* Install the new entry ... */
3759install:
3760 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
3761 lp[0] = tswap32(entry_1);
3762 lp[1] = tswap32(entry_2);
3763 return 0;
3764}
3765
blueswir18fcd3692008-08-17 20:26:25 +00003766static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00003767{
3768 struct target_modify_ldt_ldt_s *target_ldt_info;
3769 uint64_t *gdt_table = g2h(env->gdt.base);
3770 uint32_t base_addr, limit, flags;
3771 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
3772 int seg_not_present, useable, lm;
3773 uint32_t *lp, entry_1, entry_2;
3774
3775 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
3776 if (!target_ldt_info)
3777 return -TARGET_EFAULT;
3778 idx = tswap32(target_ldt_info->entry_number);
3779 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
3780 idx > TARGET_GDT_ENTRY_TLS_MAX) {
3781 unlock_user_struct(target_ldt_info, ptr, 1);
3782 return -TARGET_EINVAL;
3783 }
3784 lp = (uint32_t *)(gdt_table + idx);
3785 entry_1 = tswap32(lp[0]);
3786 entry_2 = tswap32(lp[1]);
3787
3788 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
3789 contents = (entry_2 >> 10) & 3;
3790 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
3791 seg_32bit = (entry_2 >> 22) & 1;
3792 limit_in_pages = (entry_2 >> 23) & 1;
3793 useable = (entry_2 >> 20) & 1;
3794#ifdef TARGET_ABI32
3795 lm = 0;
3796#else
3797 lm = (entry_2 >> 21) & 1;
3798#endif
3799 flags = (seg_32bit << 0) | (contents << 1) |
3800 (read_exec_only << 3) | (limit_in_pages << 4) |
3801 (seg_not_present << 5) | (useable << 6) | (lm << 7);
3802 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
3803 base_addr = (entry_1 >> 16) |
3804 (entry_2 & 0xff000000) |
3805 ((entry_2 & 0xff) << 16);
3806 target_ldt_info->base_addr = tswapl(base_addr);
3807 target_ldt_info->limit = tswap32(limit);
3808 target_ldt_info->flags = tswap32(flags);
3809 unlock_user_struct(target_ldt_info, ptr, 1);
3810 return 0;
3811}
blueswir14583f582008-08-24 10:35:55 +00003812#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00003813
bellardd2fd1af2007-11-14 18:08:56 +00003814#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00003815static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00003816{
Juan Quintela1add8692011-06-16 17:37:09 +01003817 abi_long ret = 0;
bellardd2fd1af2007-11-14 18:08:56 +00003818 abi_ulong val;
3819 int idx;
Juan Quintela1add8692011-06-16 17:37:09 +01003820
bellardd2fd1af2007-11-14 18:08:56 +00003821 switch(code) {
3822 case TARGET_ARCH_SET_GS:
3823 case TARGET_ARCH_SET_FS:
3824 if (code == TARGET_ARCH_SET_GS)
3825 idx = R_GS;
3826 else
3827 idx = R_FS;
3828 cpu_x86_load_seg(env, idx, 0);
3829 env->segs[idx].base = addr;
3830 break;
3831 case TARGET_ARCH_GET_GS:
3832 case TARGET_ARCH_GET_FS:
3833 if (code == TARGET_ARCH_GET_GS)
3834 idx = R_GS;
3835 else
3836 idx = R_FS;
3837 val = env->segs[idx].base;
3838 if (put_user(val, addr, abi_ulong))
Juan Quintela1add8692011-06-16 17:37:09 +01003839 ret = -TARGET_EFAULT;
bellardd2fd1af2007-11-14 18:08:56 +00003840 break;
3841 default:
3842 ret = -TARGET_EINVAL;
3843 break;
3844 }
Juan Quintela1add8692011-06-16 17:37:09 +01003845 return ret;
bellardd2fd1af2007-11-14 18:08:56 +00003846}
3847#endif
3848
bellard2ab83ea2003-06-15 19:56:46 +00003849#endif /* defined(TARGET_I386) */
3850
Riku Voipio05098a92011-03-04 15:27:29 +02003851#define NEW_STACK_SIZE 0x40000
pbrookd865bab2008-06-07 22:12:17 +00003852
Riku Voipio05098a92011-03-04 15:27:29 +02003853#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003854
3855static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
3856typedef struct {
3857 CPUState *env;
3858 pthread_mutex_t mutex;
3859 pthread_cond_t cond;
3860 pthread_t thread;
3861 uint32_t tid;
3862 abi_ulong child_tidptr;
3863 abi_ulong parent_tidptr;
3864 sigset_t sigmask;
3865} new_thread_info;
3866
3867static void *clone_func(void *arg)
3868{
3869 new_thread_info *info = arg;
3870 CPUState *env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003871 TaskState *ts;
pbrookd865bab2008-06-07 22:12:17 +00003872
3873 env = info->env;
3874 thread_env = env;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003875 ts = (TaskState *)thread_env->opaque;
pbrookd865bab2008-06-07 22:12:17 +00003876 info->tid = gettid();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07003877 env->host_tid = info->tid;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003878 task_settid(ts);
pbrookd865bab2008-06-07 22:12:17 +00003879 if (info->child_tidptr)
3880 put_user_u32(info->tid, info->child_tidptr);
3881 if (info->parent_tidptr)
3882 put_user_u32(info->tid, info->parent_tidptr);
3883 /* Enable signals. */
3884 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
3885 /* Signal to the parent that we're ready. */
3886 pthread_mutex_lock(&info->mutex);
3887 pthread_cond_broadcast(&info->cond);
3888 pthread_mutex_unlock(&info->mutex);
3889 /* Wait until the parent has finshed initializing the tls state. */
3890 pthread_mutex_lock(&clone_lock);
3891 pthread_mutex_unlock(&clone_lock);
3892 cpu_loop(env);
3893 /* never exits */
3894 return NULL;
3895}
3896#else
bellard1b6b0292003-03-22 17:31:38 +00003897
3898static int clone_func(void *arg)
3899{
bellard2ab83ea2003-06-15 19:56:46 +00003900 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00003901 cpu_loop(env);
3902 /* never exits */
3903 return 0;
3904}
pbrookd865bab2008-06-07 22:12:17 +00003905#endif
bellard1b6b0292003-03-22 17:31:38 +00003906
ths0da46a62007-10-20 20:23:07 +00003907/* do_fork() Must return host values and target errnos (unlike most
3908 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00003909static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
3910 abi_ulong parent_tidptr, target_ulong newtls,
3911 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00003912{
3913 int ret;
bellard5cd43932003-03-29 16:54:36 +00003914 TaskState *ts;
bellard2ab83ea2003-06-15 19:56:46 +00003915 CPUState *new_env;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003916#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003917 unsigned int nptl_flags;
3918 sigset_t sigmask;
Riku Voipio91907492010-11-26 16:21:34 +02003919#else
3920 uint8_t *new_stack;
pbrookd865bab2008-06-07 22:12:17 +00003921#endif
ths3b46e622007-09-17 08:09:54 +00003922
balrog436d1242008-09-21 02:39:45 +00003923 /* Emulate vfork() with fork() */
3924 if (flags & CLONE_VFORK)
3925 flags &= ~(CLONE_VFORK | CLONE_VM);
3926
bellard1b6b0292003-03-22 17:31:38 +00003927 if (flags & CLONE_VM) {
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003928 TaskState *parent_ts = (TaskState *)env->opaque;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003929#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003930 new_thread_info info;
3931 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00003932#endif
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003933 ts = qemu_mallocz(sizeof(TaskState));
pbrook624f7972008-05-31 16:11:38 +00003934 init_task_state(ts);
bellard1b6b0292003-03-22 17:31:38 +00003935 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00003936 new_env = cpu_copy(env);
Blue Swirlb4558d72009-11-07 16:34:12 +00003937#if defined(TARGET_I386) || defined(TARGET_SPARC) || defined(TARGET_PPC)
3938 cpu_reset(new_env);
3939#endif
pbrook6e68e072008-05-30 17:22:15 +00003940 /* Init regs that differ from the parent. */
3941 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00003942 new_env->opaque = ts;
Mika Westerbergedf8e2a2009-04-07 09:57:11 +03003943 ts->bprm = parent_ts->bprm;
3944 ts->info = parent_ts->info;
Juan Quintela2f7bb872009-07-27 16:13:24 +02003945#if defined(CONFIG_USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00003946 nptl_flags = flags;
3947 flags &= ~CLONE_NPTL_FLAGS2;
3948
pbrookc2764712009-03-07 15:24:59 +00003949 if (nptl_flags & CLONE_CHILD_CLEARTID) {
3950 ts->child_tidptr = child_tidptr;
3951 }
3952
pbrookd865bab2008-06-07 22:12:17 +00003953 if (nptl_flags & CLONE_SETTLS)
3954 cpu_set_tls (new_env, newtls);
3955
3956 /* Grab a mutex so that thread setup appears atomic. */
3957 pthread_mutex_lock(&clone_lock);
3958
3959 memset(&info, 0, sizeof(info));
3960 pthread_mutex_init(&info.mutex, NULL);
3961 pthread_mutex_lock(&info.mutex);
3962 pthread_cond_init(&info.cond, NULL);
3963 info.env = new_env;
3964 if (nptl_flags & CLONE_CHILD_SETTID)
3965 info.child_tidptr = child_tidptr;
3966 if (nptl_flags & CLONE_PARENT_SETTID)
3967 info.parent_tidptr = parent_tidptr;
3968
3969 ret = pthread_attr_init(&attr);
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003970 ret = pthread_attr_setstacksize(&attr, NEW_STACK_SIZE);
3971 ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pbrookd865bab2008-06-07 22:12:17 +00003972 /* It is not safe to deliver signals until the child has finished
3973 initializing, so temporarily block all signals. */
3974 sigfillset(&sigmask);
3975 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
3976
3977 ret = pthread_create(&info.thread, &attr, clone_func, &info);
pbrookc2764712009-03-07 15:24:59 +00003978 /* TODO: Free new CPU state if thread creation failed. */
pbrookd865bab2008-06-07 22:12:17 +00003979
3980 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
3981 pthread_attr_destroy(&attr);
3982 if (ret == 0) {
3983 /* Wait for the child to initialize. */
3984 pthread_cond_wait(&info.cond, &info.mutex);
3985 ret = info.tid;
3986 if (flags & CLONE_PARENT_SETTID)
3987 put_user_u32(ret, parent_tidptr);
3988 } else {
3989 ret = -1;
3990 }
3991 pthread_mutex_unlock(&info.mutex);
3992 pthread_cond_destroy(&info.cond);
3993 pthread_mutex_destroy(&info.mutex);
3994 pthread_mutex_unlock(&clone_lock);
3995#else
3996 if (flags & CLONE_NPTL_FLAGS2)
3997 return -EINVAL;
3998 /* This is probably going to die very quickly, but do it anyway. */
Nathan Froyd48e15fc2010-10-29 07:48:57 -07003999 new_stack = qemu_mallocz (NEW_STACK_SIZE);
bellard27725c12003-04-29 21:08:18 +00004000#ifdef __ia64__
Aurelien Jarno60e99242010-03-29 02:12:51 +02004001 ret = __clone2(clone_func, new_stack, NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00004002#else
4003 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
4004#endif
pbrookd865bab2008-06-07 22:12:17 +00004005#endif
bellard1b6b0292003-03-22 17:31:38 +00004006 } else {
4007 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00004008 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00004009 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00004010 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00004011 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00004012 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00004013 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00004014 cpu_clone_regs(env, newsp);
4015 fork_end(1);
Juan Quintela2f7bb872009-07-27 16:13:24 +02004016#if defined(CONFIG_USE_NPTL)
aurel322b1319c2008-12-18 22:44:04 +00004017 /* There is a race condition here. The parent process could
4018 theoretically read the TID in the child process before the child
4019 tid is set. This would require using either ptrace
4020 (not implemented) or having *_tidptr to point at a shared memory
4021 mapping. We can't repeat the spinlock hack used above because
4022 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00004023 if (flags & CLONE_CHILD_SETTID)
4024 put_user_u32(gettid(), child_tidptr);
4025 if (flags & CLONE_PARENT_SETTID)
4026 put_user_u32(gettid(), parent_tidptr);
4027 ts = (TaskState *)env->opaque;
4028 if (flags & CLONE_SETTLS)
4029 cpu_set_tls (env, newtls);
pbrookc2764712009-03-07 15:24:59 +00004030 if (flags & CLONE_CHILD_CLEARTID)
4031 ts->child_tidptr = child_tidptr;
aurel322b1319c2008-12-18 22:44:04 +00004032#endif
pbrookd865bab2008-06-07 22:12:17 +00004033 } else {
4034 fork_end(0);
4035 }
bellard1b6b0292003-03-22 17:31:38 +00004036 }
4037 return ret;
4038}
4039
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004040/* warning : doesn't handle linux specific flags... */
4041static int target_to_host_fcntl_cmd(int cmd)
4042{
4043 switch(cmd) {
4044 case TARGET_F_DUPFD:
4045 case TARGET_F_GETFD:
4046 case TARGET_F_SETFD:
4047 case TARGET_F_GETFL:
4048 case TARGET_F_SETFL:
4049 return cmd;
4050 case TARGET_F_GETLK:
4051 return F_GETLK;
4052 case TARGET_F_SETLK:
4053 return F_SETLK;
4054 case TARGET_F_SETLKW:
4055 return F_SETLKW;
4056 case TARGET_F_GETOWN:
4057 return F_GETOWN;
4058 case TARGET_F_SETOWN:
4059 return F_SETOWN;
4060 case TARGET_F_GETSIG:
4061 return F_GETSIG;
4062 case TARGET_F_SETSIG:
4063 return F_SETSIG;
4064#if TARGET_ABI_BITS == 32
4065 case TARGET_F_GETLK64:
4066 return F_GETLK64;
4067 case TARGET_F_SETLK64:
4068 return F_SETLK64;
4069 case TARGET_F_SETLKW64:
4070 return F_SETLKW64;
4071#endif
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004072 case TARGET_F_SETLEASE:
4073 return F_SETLEASE;
4074 case TARGET_F_GETLEASE:
4075 return F_GETLEASE;
malcfbd5de92009-09-06 06:31:59 +04004076#ifdef F_DUPFD_CLOEXEC
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004077 case TARGET_F_DUPFD_CLOEXEC:
4078 return F_DUPFD_CLOEXEC;
malcfbd5de92009-09-06 06:31:59 +04004079#endif
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004080 case TARGET_F_NOTIFY:
4081 return F_NOTIFY;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004082 default:
4083 return -TARGET_EINVAL;
4084 }
4085 return -TARGET_EINVAL;
4086}
4087
blueswir1992f48a2007-10-14 16:27:31 +00004088static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00004089{
4090 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00004091 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00004092 struct flock64 fl64;
4093 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00004094 abi_long ret;
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004095 int host_cmd = target_to_host_fcntl_cmd(cmd);
4096
4097 if (host_cmd == -TARGET_EINVAL)
4098 return host_cmd;
pbrook53a59602006-03-25 19:31:22 +00004099
bellard7775e9e2003-05-14 22:46:48 +00004100 switch(cmd) {
4101 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00004102 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4103 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00004104 fl.l_type = tswap16(target_fl->l_type);
4105 fl.l_whence = tswap16(target_fl->l_whence);
4106 fl.l_start = tswapl(target_fl->l_start);
4107 fl.l_len = tswapl(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004108 fl.l_pid = tswap32(target_fl->l_pid);
ths58134272007-03-31 18:59:32 +00004109 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004110 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00004111 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00004112 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
4113 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00004114 target_fl->l_type = tswap16(fl.l_type);
4115 target_fl->l_whence = tswap16(fl.l_whence);
4116 target_fl->l_start = tswapl(fl.l_start);
4117 target_fl->l_len = tswapl(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004118 target_fl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00004119 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00004120 }
4121 break;
ths3b46e622007-09-17 08:09:54 +00004122
bellard7775e9e2003-05-14 22:46:48 +00004123 case TARGET_F_SETLK:
4124 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00004125 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
4126 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00004127 fl.l_type = tswap16(target_fl->l_type);
4128 fl.l_whence = tswap16(target_fl->l_whence);
4129 fl.l_start = tswapl(target_fl->l_start);
4130 fl.l_len = tswapl(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004131 fl.l_pid = tswap32(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00004132 unlock_user_struct(target_fl, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004133 ret = get_errno(fcntl(fd, host_cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00004134 break;
ths3b46e622007-09-17 08:09:54 +00004135
bellard7775e9e2003-05-14 22:46:48 +00004136 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00004137 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4138 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00004139 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
4140 fl64.l_whence = tswap16(target_fl64->l_whence);
4141 fl64.l_start = tswapl(target_fl64->l_start);
4142 fl64.l_len = tswapl(target_fl64->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004143 fl64.l_pid = tswap32(target_fl64->l_pid);
ths58134272007-03-31 18:59:32 +00004144 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004145 ret = get_errno(fcntl(fd, host_cmd, &fl64));
ths43f238d2007-01-05 20:55:49 +00004146 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00004147 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
4148 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00004149 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
4150 target_fl64->l_whence = tswap16(fl64.l_whence);
4151 target_fl64->l_start = tswapl(fl64.l_start);
4152 target_fl64->l_len = tswapl(fl64.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004153 target_fl64->l_pid = tswap32(fl64.l_pid);
ths43f238d2007-01-05 20:55:49 +00004154 unlock_user_struct(target_fl64, arg, 1);
4155 }
bellard9ee1fa22007-11-11 15:11:19 +00004156 break;
bellard7775e9e2003-05-14 22:46:48 +00004157 case TARGET_F_SETLK64:
4158 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00004159 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
4160 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00004161 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
4162 fl64.l_whence = tswap16(target_fl64->l_whence);
4163 fl64.l_start = tswapl(target_fl64->l_start);
4164 fl64.l_len = tswapl(target_fl64->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004165 fl64.l_pid = tswap32(target_fl64->l_pid);
ths43f238d2007-01-05 20:55:49 +00004166 unlock_user_struct(target_fl64, arg, 0);
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004167 ret = get_errno(fcntl(fd, host_cmd, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00004168 break;
4169
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004170 case TARGET_F_GETFL:
4171 ret = get_errno(fcntl(fd, host_cmd, arg));
bellard9ee1fa22007-11-11 15:11:19 +00004172 if (ret >= 0) {
4173 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
4174 }
bellardffa65c32004-01-04 23:57:22 +00004175 break;
4176
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004177 case TARGET_F_SETFL:
4178 ret = get_errno(fcntl(fd, host_cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
4179 break;
4180
4181 case TARGET_F_SETOWN:
4182 case TARGET_F_GETOWN:
4183 case TARGET_F_SETSIG:
4184 case TARGET_F_GETSIG:
Ulrich Hecht7e22e542009-07-24 19:10:27 +02004185 case TARGET_F_SETLEASE:
4186 case TARGET_F_GETLEASE:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02004187 ret = get_errno(fcntl(fd, host_cmd, arg));
bellardffa65c32004-01-04 23:57:22 +00004188 break;
4189
bellard7775e9e2003-05-14 22:46:48 +00004190 default:
bellard9ee1fa22007-11-11 15:11:19 +00004191 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00004192 break;
4193 }
4194 return ret;
4195}
4196
bellard67867302003-11-23 17:05:30 +00004197#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00004198
bellard67867302003-11-23 17:05:30 +00004199static inline int high2lowuid(int uid)
4200{
4201 if (uid > 65535)
4202 return 65534;
4203 else
4204 return uid;
4205}
4206
4207static inline int high2lowgid(int gid)
4208{
4209 if (gid > 65535)
4210 return 65534;
4211 else
4212 return gid;
4213}
4214
4215static inline int low2highuid(int uid)
4216{
4217 if ((int16_t)uid == -1)
4218 return -1;
4219 else
4220 return uid;
4221}
4222
4223static inline int low2highgid(int gid)
4224{
4225 if ((int16_t)gid == -1)
4226 return -1;
4227 else
4228 return gid;
4229}
Riku Voipio0c866a72011-04-18 15:23:06 +03004230static inline int tswapid(int id)
4231{
4232 return tswap16(id);
4233}
4234#else /* !USE_UID16 */
4235static inline int high2lowuid(int uid)
4236{
4237 return uid;
4238}
4239static inline int high2lowgid(int gid)
4240{
4241 return gid;
4242}
4243static inline int low2highuid(int uid)
4244{
4245 return uid;
4246}
4247static inline int low2highgid(int gid)
4248{
4249 return gid;
4250}
4251static inline int tswapid(int id)
4252{
4253 return tswap32(id);
4254}
bellard67867302003-11-23 17:05:30 +00004255#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00004256
bellard31e31b82003-02-18 22:55:36 +00004257void syscall_init(void)
4258{
bellard2ab83ea2003-06-15 19:56:46 +00004259 IOCTLEntry *ie;
4260 const argtype *arg_type;
4261 int size;
thsb92c47c2007-11-01 00:07:38 +00004262 int i;
bellard2ab83ea2003-06-15 19:56:46 +00004263
Blue Swirl001faf32009-05-13 17:53:17 +00004264#define STRUCT(name, ...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
ths5fafdf22007-09-16 21:08:06 +00004265#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00004266#include "syscall_types.h"
4267#undef STRUCT
4268#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00004269
4270 /* we patch the ioctl size if necessary. We rely on the fact that
4271 no ioctl has all the bits at '1' in the size field */
4272 ie = ioctl_entries;
4273 while (ie->target_cmd != 0) {
4274 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
4275 TARGET_IOC_SIZEMASK) {
4276 arg_type = ie->arg_type;
4277 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00004278 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00004279 ie->target_cmd);
4280 exit(1);
4281 }
4282 arg_type++;
4283 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00004284 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00004285 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
4286 (size << TARGET_IOC_SIZESHIFT);
4287 }
thsb92c47c2007-11-01 00:07:38 +00004288
4289 /* Build target_to_host_errno_table[] table from
4290 * host_to_target_errno_table[]. */
4291 for (i=0; i < ERRNO_TABLE_SIZE; i++)
4292 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
4293
bellard2ab83ea2003-06-15 19:56:46 +00004294 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00004295#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
4296 (defined(__x86_64__) && defined(TARGET_X86_64))
4297 if (unlikely(ie->target_cmd != ie->host_cmd)) {
4298 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
4299 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00004300 }
4301#endif
4302 ie++;
4303 }
bellard31e31b82003-02-18 22:55:36 +00004304}
bellardc573ff62004-01-04 15:51:36 +00004305
blueswir1992f48a2007-10-14 16:27:31 +00004306#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00004307static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
4308{
thsaf325d32008-06-10 15:29:15 +00004309#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00004310 return ((uint64_t)word0 << 32) | word1;
4311#else
4312 return ((uint64_t)word1 << 32) | word0;
4313#endif
4314}
blueswir1992f48a2007-10-14 16:27:31 +00004315#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00004316static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
4317{
4318 return word0;
4319}
blueswir1992f48a2007-10-14 16:27:31 +00004320#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00004321
4322#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00004323static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
4324 abi_long arg2,
4325 abi_long arg3,
4326 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00004327{
4328#ifdef TARGET_ARM
4329 if (((CPUARMState *)cpu_env)->eabi)
4330 {
4331 arg2 = arg3;
4332 arg3 = arg4;
4333 }
4334#endif
4335 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
4336}
4337#endif
4338
4339#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00004340static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
4341 abi_long arg2,
4342 abi_long arg3,
4343 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00004344{
4345#ifdef TARGET_ARM
4346 if (((CPUARMState *)cpu_env)->eabi)
4347 {
4348 arg2 = arg3;
4349 arg3 = arg4;
4350 }
4351#endif
4352 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
4353}
4354#endif
4355
bellard579a97f2007-11-11 14:26:47 +00004356static inline abi_long target_to_host_timespec(struct timespec *host_ts,
4357 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00004358{
4359 struct target_timespec *target_ts;
4360
bellard579a97f2007-11-11 14:26:47 +00004361 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
4362 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004363 host_ts->tv_sec = tswapl(target_ts->tv_sec);
4364 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
4365 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00004366 return 0;
pbrook53a59602006-03-25 19:31:22 +00004367}
4368
bellard579a97f2007-11-11 14:26:47 +00004369static inline abi_long host_to_target_timespec(abi_ulong target_addr,
4370 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00004371{
4372 struct target_timespec *target_ts;
4373
bellard579a97f2007-11-11 14:26:47 +00004374 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
4375 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00004376 target_ts->tv_sec = tswapl(host_ts->tv_sec);
4377 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
4378 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00004379 return 0;
pbrook53a59602006-03-25 19:31:22 +00004380}
4381
aurel329d33b762009-04-08 23:07:05 +00004382#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat)
balrog6a24a772008-09-20 02:23:36 +00004383static inline abi_long host_to_target_stat64(void *cpu_env,
4384 abi_ulong target_addr,
4385 struct stat *host_st)
4386{
4387#ifdef TARGET_ARM
4388 if (((CPUARMState *)cpu_env)->eabi) {
4389 struct target_eabi_stat64 *target_st;
4390
4391 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4392 return -TARGET_EFAULT;
4393 memset(target_st, 0, sizeof(struct target_eabi_stat64));
4394 __put_user(host_st->st_dev, &target_st->st_dev);
4395 __put_user(host_st->st_ino, &target_st->st_ino);
4396#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4397 __put_user(host_st->st_ino, &target_st->__st_ino);
4398#endif
4399 __put_user(host_st->st_mode, &target_st->st_mode);
4400 __put_user(host_st->st_nlink, &target_st->st_nlink);
4401 __put_user(host_st->st_uid, &target_st->st_uid);
4402 __put_user(host_st->st_gid, &target_st->st_gid);
4403 __put_user(host_st->st_rdev, &target_st->st_rdev);
4404 __put_user(host_st->st_size, &target_st->st_size);
4405 __put_user(host_st->st_blksize, &target_st->st_blksize);
4406 __put_user(host_st->st_blocks, &target_st->st_blocks);
4407 __put_user(host_st->st_atime, &target_st->target_st_atime);
4408 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4409 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4410 unlock_user_struct(target_st, target_addr, 1);
4411 } else
4412#endif
4413 {
Richard Hendersoned18c5c2010-04-26 10:27:22 -07004414#if TARGET_ABI_BITS == 64 && !defined(TARGET_ALPHA)
aurel329d33b762009-04-08 23:07:05 +00004415 struct target_stat *target_st;
4416#else
balrog6a24a772008-09-20 02:23:36 +00004417 struct target_stat64 *target_st;
aurel329d33b762009-04-08 23:07:05 +00004418#endif
balrog6a24a772008-09-20 02:23:36 +00004419
4420 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
4421 return -TARGET_EFAULT;
aurel329d33b762009-04-08 23:07:05 +00004422 memset(target_st, 0, sizeof(*target_st));
balrog6a24a772008-09-20 02:23:36 +00004423 __put_user(host_st->st_dev, &target_st->st_dev);
4424 __put_user(host_st->st_ino, &target_st->st_ino);
4425#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
4426 __put_user(host_st->st_ino, &target_st->__st_ino);
4427#endif
4428 __put_user(host_st->st_mode, &target_st->st_mode);
4429 __put_user(host_st->st_nlink, &target_st->st_nlink);
4430 __put_user(host_st->st_uid, &target_st->st_uid);
4431 __put_user(host_st->st_gid, &target_st->st_gid);
4432 __put_user(host_st->st_rdev, &target_st->st_rdev);
4433 /* XXX: better use of kernel struct */
4434 __put_user(host_st->st_size, &target_st->st_size);
4435 __put_user(host_st->st_blksize, &target_st->st_blksize);
4436 __put_user(host_st->st_blocks, &target_st->st_blocks);
4437 __put_user(host_st->st_atime, &target_st->target_st_atime);
4438 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
4439 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
4440 unlock_user_struct(target_st, target_addr, 1);
4441 }
4442
4443 return 0;
4444}
4445#endif
4446
Juan Quintela2f7bb872009-07-27 16:13:24 +02004447#if defined(CONFIG_USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +00004448/* ??? Using host futex calls even when target atomic operations
4449 are not really atomic probably breaks things. However implementing
4450 futexes locally would make futexes shared between multiple processes
4451 tricky. However they're probably useless because guest atomic
4452 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00004453static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
4454 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00004455{
4456 struct timespec ts, *pts;
Nathan Froyda16aae02009-08-03 08:43:29 -07004457 int base_op;
pbrookbd0c5662008-05-29 14:34:11 +00004458
4459 /* ??? We assume FUTEX_* constants are the same on both host
4460 and target. */
Martin Mohringa29ccd62009-05-04 21:34:56 +03004461#ifdef FUTEX_CMD_MASK
Nathan Froyda16aae02009-08-03 08:43:29 -07004462 base_op = op & FUTEX_CMD_MASK;
Martin Mohringa29ccd62009-05-04 21:34:56 +03004463#else
Nathan Froyda16aae02009-08-03 08:43:29 -07004464 base_op = op;
Martin Mohringa29ccd62009-05-04 21:34:56 +03004465#endif
Nathan Froyda16aae02009-08-03 08:43:29 -07004466 switch (base_op) {
pbrookbd0c5662008-05-29 14:34:11 +00004467 case FUTEX_WAIT:
4468 if (timeout) {
4469 pts = &ts;
4470 target_to_host_timespec(pts, timeout);
4471 } else {
4472 pts = NULL;
4473 }
Martin Mohringa29ccd62009-05-04 21:34:56 +03004474 return get_errno(sys_futex(g2h(uaddr), op, tswap32(val),
pbrookbd0c5662008-05-29 14:34:11 +00004475 pts, NULL, 0));
4476 case FUTEX_WAKE:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004477 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00004478 case FUTEX_FD:
Martin Mohringa29ccd62009-05-04 21:34:56 +03004479 return get_errno(sys_futex(g2h(uaddr), op, val, NULL, NULL, 0));
pbrookbd0c5662008-05-29 14:34:11 +00004480 case FUTEX_REQUEUE:
pbrookbd0c5662008-05-29 14:34:11 +00004481 case FUTEX_CMP_REQUEUE:
Nathan Froyda16aae02009-08-03 08:43:29 -07004482 case FUTEX_WAKE_OP:
4483 /* For FUTEX_REQUEUE, FUTEX_CMP_REQUEUE, and FUTEX_WAKE_OP, the
4484 TIMEOUT parameter is interpreted as a uint32_t by the kernel.
4485 But the prototype takes a `struct timespec *'; insert casts
4486 to satisfy the compiler. We do not need to tswap TIMEOUT
4487 since it's not compared to guest memory. */
4488 pts = (struct timespec *)(uintptr_t) timeout;
4489 return get_errno(sys_futex(g2h(uaddr), op, val, pts,
4490 g2h(uaddr2),
4491 (base_op == FUTEX_CMP_REQUEUE
4492 ? tswap32(val3)
4493 : val3)));
pbrookbd0c5662008-05-29 14:34:11 +00004494 default:
4495 return -TARGET_ENOSYS;
4496 }
4497}
4498#endif
4499
pbrook1d9d8b52009-04-16 15:17:02 +00004500/* Map host to target signal numbers for the wait family of syscalls.
4501 Assume all other status bits are the same. */
4502static int host_to_target_waitstatus(int status)
4503{
4504 if (WIFSIGNALED(status)) {
4505 return host_to_target_signal(WTERMSIG(status)) | (status & ~0x7f);
4506 }
4507 if (WIFSTOPPED(status)) {
4508 return (host_to_target_signal(WSTOPSIG(status)) << 8)
4509 | (status & 0xff);
4510 }
4511 return status;
4512}
4513
pbrooka745ec62008-05-06 15:36:17 +00004514int get_osversion(void)
4515{
4516 static int osversion;
4517 struct new_utsname buf;
4518 const char *s;
4519 int i, n, tmp;
4520 if (osversion)
4521 return osversion;
4522 if (qemu_uname_release && *qemu_uname_release) {
4523 s = qemu_uname_release;
4524 } else {
4525 if (sys_uname(&buf))
4526 return 0;
4527 s = buf.release;
4528 }
4529 tmp = 0;
4530 for (i = 0; i < 3; i++) {
4531 n = 0;
4532 while (*s >= '0' && *s <= '9') {
4533 n *= 10;
4534 n += *s - '0';
4535 s++;
4536 }
4537 tmp = (tmp << 8) + n;
4538 if (*s == '.')
4539 s++;
4540 }
4541 osversion = tmp;
4542 return osversion;
4543}
4544
ths0da46a62007-10-20 20:23:07 +00004545/* do_syscall() should always have a single exit point at the end so
4546 that actions, such as logging of syscall results, can be performed.
4547 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00004548abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
4549 abi_long arg2, abi_long arg3, abi_long arg4,
Peter Maydell5945cfc2011-06-16 17:37:13 +01004550 abi_long arg5, abi_long arg6, abi_long arg7,
4551 abi_long arg8)
bellard31e31b82003-02-18 22:55:36 +00004552{
blueswir1992f48a2007-10-14 16:27:31 +00004553 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00004554 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00004555 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00004556 void *p;
ths3b46e622007-09-17 08:09:54 +00004557
bellard72f03902003-02-18 23:33:18 +00004558#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00004559 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00004560#endif
thsb92c47c2007-11-01 00:07:38 +00004561 if(do_strace)
4562 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
4563
bellard31e31b82003-02-18 22:55:36 +00004564 switch(num) {
4565 case TARGET_NR_exit:
Juan Quintela2f7bb872009-07-27 16:13:24 +02004566#ifdef CONFIG_USE_NPTL
pbrookc2764712009-03-07 15:24:59 +00004567 /* In old applications this may be used to implement _exit(2).
4568 However in threaded applictions it is used for thread termination,
4569 and _exit_group is used for application termination.
4570 Do thread termination if we have more then one thread. */
4571 /* FIXME: This probably breaks if a signal arrives. We should probably
4572 be disabling signals. */
4573 if (first_cpu->next_cpu) {
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004574 TaskState *ts;
pbrookc2764712009-03-07 15:24:59 +00004575 CPUState **lastp;
4576 CPUState *p;
4577
4578 cpu_list_lock();
4579 lastp = &first_cpu;
4580 p = first_cpu;
4581 while (p && p != (CPUState *)cpu_env) {
4582 lastp = &p->next_cpu;
4583 p = p->next_cpu;
4584 }
4585 /* If we didn't find the CPU for this thread then something is
4586 horribly wrong. */
4587 if (!p)
4588 abort();
4589 /* Remove the CPU from the list. */
4590 *lastp = p->next_cpu;
4591 cpu_list_unlock();
Nathan Froyd1e9fa732009-06-03 11:33:08 -07004592 ts = ((CPUState *)cpu_env)->opaque;
pbrookc2764712009-03-07 15:24:59 +00004593 if (ts->child_tidptr) {
4594 put_user_u32(0, ts->child_tidptr);
4595 sys_futex(g2h(ts->child_tidptr), FUTEX_WAKE, INT_MAX,
4596 NULL, NULL, 0);
4597 }
Nathan Froyd48e15fc2010-10-29 07:48:57 -07004598 thread_env = NULL;
4599 qemu_free(cpu_env);
4600 qemu_free(ts);
pbrookc2764712009-03-07 15:24:59 +00004601 pthread_exit(NULL);
4602 }
4603#endif
Juan Quintela9788c9c2009-07-27 16:13:02 +02004604#ifdef TARGET_GPROF
bellard7d132992003-03-06 23:23:54 +00004605 _mcleanup();
4606#endif
bellarde9009672005-04-26 20:42:36 +00004607 gdb_exit(cpu_env, arg1);
pbrookc2764712009-03-07 15:24:59 +00004608 _exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00004609 ret = 0; /* avoid warning */
4610 break;
4611 case TARGET_NR_read:
aurel3238d840e2009-01-30 19:48:17 +00004612 if (arg3 == 0)
4613 ret = 0;
4614 else {
4615 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
4616 goto efault;
4617 ret = get_errno(read(arg1, p, arg3));
4618 unlock_user(p, arg2, ret);
4619 }
bellard31e31b82003-02-18 22:55:36 +00004620 break;
4621 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00004622 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
4623 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004624 ret = get_errno(write(arg1, p, arg3));
4625 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00004626 break;
4627 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00004628 if (!(p = lock_user_string(arg1)))
4629 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004630 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00004631 target_to_host_bitmask(arg2, fcntl_flags_tbl),
4632 arg3));
pbrook53a59602006-03-25 19:31:22 +00004633 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004634 break;
ths82424832007-09-24 09:21:55 +00004635#if defined(TARGET_NR_openat) && defined(__NR_openat)
4636 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00004637 if (!(p = lock_user_string(arg2)))
4638 goto efault;
4639 ret = get_errno(sys_openat(arg1,
4640 path(p),
4641 target_to_host_bitmask(arg3, fcntl_flags_tbl),
4642 arg4));
4643 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00004644 break;
4645#endif
bellard31e31b82003-02-18 22:55:36 +00004646 case TARGET_NR_close:
4647 ret = get_errno(close(arg1));
4648 break;
4649 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00004650 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00004651 break;
4652 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00004653 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00004654 break;
thse5febef2007-04-01 18:31:35 +00004655#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00004656 case TARGET_NR_waitpid:
4657 {
pbrook53a59602006-03-25 19:31:22 +00004658 int status;
4659 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00004660 if (!is_error(ret) && arg2
pbrook1d9d8b52009-04-16 15:17:02 +00004661 && put_user_s32(host_to_target_waitstatus(status), arg2))
bellard2f619692007-11-16 10:46:05 +00004662 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004663 }
4664 break;
thse5febef2007-04-01 18:31:35 +00004665#endif
pbrookf0cbb612008-05-30 18:20:05 +00004666#ifdef TARGET_NR_waitid
4667 case TARGET_NR_waitid:
4668 {
4669 siginfo_t info;
4670 info.si_pid = 0;
4671 ret = get_errno(waitid(arg1, arg2, &info, arg4));
4672 if (!is_error(ret) && arg3 && info.si_pid != 0) {
Anthony Liguoric227f092009-10-01 16:12:16 -05004673 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
pbrookf0cbb612008-05-30 18:20:05 +00004674 goto efault;
4675 host_to_target_siginfo(p, &info);
Anthony Liguoric227f092009-10-01 16:12:16 -05004676 unlock_user(p, arg3, sizeof(target_siginfo_t));
pbrookf0cbb612008-05-30 18:20:05 +00004677 }
4678 }
4679 break;
4680#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004681#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004682 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00004683 if (!(p = lock_user_string(arg1)))
4684 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004685 ret = get_errno(creat(p, arg2));
4686 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004687 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004688#endif
bellard31e31b82003-02-18 22:55:36 +00004689 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00004690 {
4691 void * p2;
4692 p = lock_user_string(arg1);
4693 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004694 if (!p || !p2)
4695 ret = -TARGET_EFAULT;
4696 else
4697 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004698 unlock_user(p2, arg2, 0);
4699 unlock_user(p, arg1, 0);
4700 }
bellard31e31b82003-02-18 22:55:36 +00004701 break;
ths64f0ce42007-09-24 09:25:06 +00004702#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
4703 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00004704 {
4705 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00004706 if (!arg2 || !arg4)
4707 goto efault;
ths64f0ce42007-09-24 09:25:06 +00004708 p = lock_user_string(arg2);
4709 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00004710 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004711 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00004712 else
4713 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00004714 unlock_user(p, arg2, 0);
4715 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00004716 }
4717 break;
4718#endif
bellard31e31b82003-02-18 22:55:36 +00004719 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00004720 if (!(p = lock_user_string(arg1)))
4721 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004722 ret = get_errno(unlink(p));
4723 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004724 break;
ths8170f562007-09-24 09:24:11 +00004725#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
4726 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00004727 if (!(p = lock_user_string(arg2)))
4728 goto efault;
4729 ret = get_errno(sys_unlinkat(arg1, p, arg3));
4730 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00004731 break;
balrogb7d35e62007-12-12 00:40:24 +00004732#endif
bellard31e31b82003-02-18 22:55:36 +00004733 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00004734 {
4735 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00004736 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00004737 abi_ulong gp;
4738 abi_ulong guest_argp;
4739 abi_ulong guest_envp;
4740 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00004741 char **q;
4742
bellardf7341ff2003-03-30 21:00:25 +00004743 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00004744 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00004745 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004746 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004747 goto efault;
ths03aa1972007-12-02 06:28:08 +00004748 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004749 break;
bellard7854b052003-03-29 17:22:23 +00004750 argc++;
bellard2f619692007-11-16 10:46:05 +00004751 }
bellardf7341ff2003-03-30 21:00:25 +00004752 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00004753 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00004754 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00004755 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00004756 goto efault;
ths03aa1972007-12-02 06:28:08 +00004757 if (!addr)
bellard2f619692007-11-16 10:46:05 +00004758 break;
bellard7854b052003-03-29 17:22:23 +00004759 envc++;
bellard2f619692007-11-16 10:46:05 +00004760 }
bellard7854b052003-03-29 17:22:23 +00004761
bellardf7341ff2003-03-30 21:00:25 +00004762 argp = alloca((argc + 1) * sizeof(void *));
4763 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00004764
pbrookda94d262008-05-30 18:24:00 +00004765 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004766 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004767 if (get_user_ual(addr, gp))
4768 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004769 if (!addr)
4770 break;
bellard2f619692007-11-16 10:46:05 +00004771 if (!(*q = lock_user_string(addr)))
4772 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004773 }
bellardf7341ff2003-03-30 21:00:25 +00004774 *q = NULL;
4775
pbrookda94d262008-05-30 18:24:00 +00004776 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00004777 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004778 if (get_user_ual(addr, gp))
4779 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004780 if (!addr)
4781 break;
bellard2f619692007-11-16 10:46:05 +00004782 if (!(*q = lock_user_string(addr)))
4783 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004784 }
bellardf7341ff2003-03-30 21:00:25 +00004785 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00004786
bellard2f619692007-11-16 10:46:05 +00004787 if (!(p = lock_user_string(arg1)))
4788 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00004789 ret = get_errno(execve(p, argp, envp));
4790 unlock_user(p, arg1, 0);
4791
bellard2f619692007-11-16 10:46:05 +00004792 goto execve_end;
4793
4794 execve_efault:
4795 ret = -TARGET_EFAULT;
4796
4797 execve_end:
pbrook53a59602006-03-25 19:31:22 +00004798 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004799 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004800 if (get_user_ual(addr, gp)
4801 || !addr)
4802 break;
pbrook53a59602006-03-25 19:31:22 +00004803 unlock_user(*q, addr, 0);
4804 }
4805 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00004806 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00004807 if (get_user_ual(addr, gp)
4808 || !addr)
4809 break;
pbrook53a59602006-03-25 19:31:22 +00004810 unlock_user(*q, addr, 0);
4811 }
bellard7854b052003-03-29 17:22:23 +00004812 }
bellard31e31b82003-02-18 22:55:36 +00004813 break;
4814 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00004815 if (!(p = lock_user_string(arg1)))
4816 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004817 ret = get_errno(chdir(p));
4818 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004819 break;
bellarda315a142005-01-30 22:59:18 +00004820#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00004821 case TARGET_NR_time:
4822 {
pbrook53a59602006-03-25 19:31:22 +00004823 time_t host_time;
4824 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00004825 if (!is_error(ret)
4826 && arg1
4827 && put_user_sal(host_time, arg1))
4828 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004829 }
4830 break;
bellarda315a142005-01-30 22:59:18 +00004831#endif
bellard31e31b82003-02-18 22:55:36 +00004832 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00004833 if (!(p = lock_user_string(arg1)))
4834 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004835 ret = get_errno(mknod(p, arg2, arg3));
4836 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004837 break;
ths75ac37a2007-09-24 09:23:05 +00004838#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
4839 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00004840 if (!(p = lock_user_string(arg2)))
4841 goto efault;
4842 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
4843 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00004844 break;
4845#endif
bellard31e31b82003-02-18 22:55:36 +00004846 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00004847 if (!(p = lock_user_string(arg1)))
4848 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004849 ret = get_errno(chmod(p, arg2));
4850 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004851 break;
bellardebc05482003-09-30 21:08:41 +00004852#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00004853 case TARGET_NR_break:
4854 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004855#endif
4856#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00004857 case TARGET_NR_oldstat:
4858 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004859#endif
bellard31e31b82003-02-18 22:55:36 +00004860 case TARGET_NR_lseek:
4861 ret = get_errno(lseek(arg1, arg2, arg3));
4862 break;
Richard Henderson92317332010-05-03 10:07:53 -07004863#if defined(TARGET_NR_getxpid) && defined(TARGET_ALPHA)
4864 /* Alpha specific */
j_mayer7a3148a2007-04-05 07:13:51 +00004865 case TARGET_NR_getxpid:
Richard Henderson92317332010-05-03 10:07:53 -07004866 ((CPUAlphaState *)cpu_env)->ir[IR_A4] = getppid();
bellard31e31b82003-02-18 22:55:36 +00004867 ret = get_errno(getpid());
4868 break;
Richard Henderson92317332010-05-03 10:07:53 -07004869#endif
4870#ifdef TARGET_NR_getpid
4871 case TARGET_NR_getpid:
4872 ret = get_errno(getpid());
4873 break;
4874#endif
bellard31e31b82003-02-18 22:55:36 +00004875 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00004876 {
4877 /* need to look at the data field */
4878 void *p2, *p3;
4879 p = lock_user_string(arg1);
4880 p2 = lock_user_string(arg2);
4881 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004882 if (!p || !p2 || !p3)
4883 ret = -TARGET_EFAULT;
Jan-Simon Möllerdab46402009-10-17 21:52:43 +03004884 else {
bellard579a97f2007-11-11 14:26:47 +00004885 /* FIXME - arg5 should be locked, but it isn't clear how to
4886 * do that since it's not guaranteed to be a NULL-terminated
4887 * string.
4888 */
Jan-Simon Möllerdab46402009-10-17 21:52:43 +03004889 if ( ! arg5 )
4890 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, NULL));
4891 else
4892 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
4893 }
bellard579a97f2007-11-11 14:26:47 +00004894 unlock_user(p, arg1, 0);
4895 unlock_user(p2, arg2, 0);
4896 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00004897 break;
4898 }
thse5febef2007-04-01 18:31:35 +00004899#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00004900 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00004901 if (!(p = lock_user_string(arg1)))
4902 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004903 ret = get_errno(umount(p));
4904 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004905 break;
thse5febef2007-04-01 18:31:35 +00004906#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004907#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004908 case TARGET_NR_stime:
4909 {
pbrook53a59602006-03-25 19:31:22 +00004910 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00004911 if (get_user_sal(host_time, arg1))
4912 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004913 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00004914 }
4915 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004916#endif
bellard31e31b82003-02-18 22:55:36 +00004917 case TARGET_NR_ptrace:
4918 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00004919#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004920 case TARGET_NR_alarm:
4921 ret = alarm(arg1);
4922 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004923#endif
bellardebc05482003-09-30 21:08:41 +00004924#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00004925 case TARGET_NR_oldfstat:
4926 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004927#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004928#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004929 case TARGET_NR_pause:
4930 ret = get_errno(pause());
4931 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004932#endif
thse5febef2007-04-01 18:31:35 +00004933#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00004934 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00004935 {
pbrook53a59602006-03-25 19:31:22 +00004936 struct utimbuf tbuf, *host_tbuf;
4937 struct target_utimbuf *target_tbuf;
4938 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004939 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
4940 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004941 tbuf.actime = tswapl(target_tbuf->actime);
4942 tbuf.modtime = tswapl(target_tbuf->modtime);
4943 unlock_user_struct(target_tbuf, arg2, 0);
4944 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00004945 } else {
pbrook53a59602006-03-25 19:31:22 +00004946 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00004947 }
bellard579a97f2007-11-11 14:26:47 +00004948 if (!(p = lock_user_string(arg1)))
4949 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004950 ret = get_errno(utime(p, host_tbuf));
4951 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00004952 }
4953 break;
thse5febef2007-04-01 18:31:35 +00004954#endif
bellard978a66f2004-12-06 22:58:05 +00004955 case TARGET_NR_utimes:
4956 {
bellard978a66f2004-12-06 22:58:05 +00004957 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00004958 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00004959 if (copy_from_user_timeval(&tv[0], arg2)
4960 || copy_from_user_timeval(&tv[1],
4961 arg2 + sizeof(struct target_timeval)))
4962 goto efault;
bellard978a66f2004-12-06 22:58:05 +00004963 tvp = tv;
4964 } else {
4965 tvp = NULL;
4966 }
bellard579a97f2007-11-11 14:26:47 +00004967 if (!(p = lock_user_string(arg1)))
4968 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004969 ret = get_errno(utimes(p, tvp));
4970 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00004971 }
4972 break;
balrogac8a6552008-09-20 02:25:39 +00004973#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
4974 case TARGET_NR_futimesat:
4975 {
4976 struct timeval *tvp, tv[2];
4977 if (arg3) {
4978 if (copy_from_user_timeval(&tv[0], arg3)
4979 || copy_from_user_timeval(&tv[1],
4980 arg3 + sizeof(struct target_timeval)))
4981 goto efault;
4982 tvp = tv;
4983 } else {
4984 tvp = NULL;
4985 }
4986 if (!(p = lock_user_string(arg2)))
4987 goto efault;
4988 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
4989 unlock_user(p, arg2, 0);
4990 }
4991 break;
4992#endif
bellardebc05482003-09-30 21:08:41 +00004993#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00004994 case TARGET_NR_stty:
4995 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004996#endif
4997#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00004998 case TARGET_NR_gtty:
4999 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005000#endif
bellard31e31b82003-02-18 22:55:36 +00005001 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00005002 if (!(p = lock_user_string(arg1)))
5003 goto efault;
Ulrich Hecht719f9082009-07-03 17:09:29 +02005004 ret = get_errno(access(path(p), arg2));
pbrook53a59602006-03-25 19:31:22 +00005005 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005006 break;
ths92a34c12007-09-24 09:27:49 +00005007#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
5008 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00005009 if (!(p = lock_user_string(arg2)))
5010 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005011 ret = get_errno(sys_faccessat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005012 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00005013 break;
5014#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005015#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005016 case TARGET_NR_nice:
5017 ret = get_errno(nice(arg1));
5018 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005019#endif
bellardebc05482003-09-30 21:08:41 +00005020#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00005021 case TARGET_NR_ftime:
5022 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005023#endif
bellard31e31b82003-02-18 22:55:36 +00005024 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00005025 sync();
5026 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00005027 break;
5028 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00005029 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00005030 break;
5031 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00005032 {
5033 void *p2;
5034 p = lock_user_string(arg1);
5035 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005036 if (!p || !p2)
5037 ret = -TARGET_EFAULT;
5038 else
5039 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005040 unlock_user(p2, arg2, 0);
5041 unlock_user(p, arg1, 0);
5042 }
bellard31e31b82003-02-18 22:55:36 +00005043 break;
ths722183f2007-09-24 09:24:37 +00005044#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
5045 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00005046 {
bellard579a97f2007-11-11 14:26:47 +00005047 void *p2;
ths722183f2007-09-24 09:24:37 +00005048 p = lock_user_string(arg2);
5049 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00005050 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005051 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00005052 else
5053 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00005054 unlock_user(p2, arg4, 0);
5055 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00005056 }
5057 break;
5058#endif
bellard31e31b82003-02-18 22:55:36 +00005059 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00005060 if (!(p = lock_user_string(arg1)))
5061 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005062 ret = get_errno(mkdir(p, arg2));
5063 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005064 break;
ths4472ad02007-09-24 09:22:32 +00005065#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
5066 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00005067 if (!(p = lock_user_string(arg2)))
5068 goto efault;
5069 ret = get_errno(sys_mkdirat(arg1, p, arg3));
5070 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00005071 break;
5072#endif
bellard31e31b82003-02-18 22:55:36 +00005073 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00005074 if (!(p = lock_user_string(arg1)))
5075 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005076 ret = get_errno(rmdir(p));
5077 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005078 break;
5079 case TARGET_NR_dup:
5080 ret = get_errno(dup(arg1));
5081 break;
5082 case TARGET_NR_pipe:
Richard Hendersonfb41a662010-05-03 10:07:52 -07005083 ret = do_pipe(cpu_env, arg1, 0, 0);
bellard31e31b82003-02-18 22:55:36 +00005084 break;
Riku Voipio099d6b02009-05-05 12:10:04 +03005085#ifdef TARGET_NR_pipe2
5086 case TARGET_NR_pipe2:
Richard Hendersonfb41a662010-05-03 10:07:52 -07005087 ret = do_pipe(cpu_env, arg1, arg2, 1);
Riku Voipio099d6b02009-05-05 12:10:04 +03005088 break;
5089#endif
bellard31e31b82003-02-18 22:55:36 +00005090 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00005091 {
pbrook53a59602006-03-25 19:31:22 +00005092 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00005093 struct tms tms;
5094 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00005095 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00005096 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
5097 if (!tmsp)
5098 goto efault;
bellardc596ed12003-07-13 17:32:31 +00005099 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
5100 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
5101 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
5102 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00005103 }
bellardc596ed12003-07-13 17:32:31 +00005104 if (!is_error(ret))
5105 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00005106 }
5107 break;
bellardebc05482003-09-30 21:08:41 +00005108#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00005109 case TARGET_NR_prof:
5110 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005111#endif
thse5febef2007-04-01 18:31:35 +00005112#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00005113 case TARGET_NR_signal:
5114 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005115#endif
bellard31e31b82003-02-18 22:55:36 +00005116 case TARGET_NR_acct:
aurel3238d840e2009-01-30 19:48:17 +00005117 if (arg1 == 0) {
5118 ret = get_errno(acct(NULL));
5119 } else {
5120 if (!(p = lock_user_string(arg1)))
5121 goto efault;
5122 ret = get_errno(acct(path(p)));
5123 unlock_user(p, arg1, 0);
5124 }
pbrook24836682006-04-16 14:14:53 +00005125 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005126#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005127 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00005128 if (!(p = lock_user_string(arg1)))
5129 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005130 ret = get_errno(umount2(p, arg2));
5131 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005132 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005133#endif
bellardebc05482003-09-30 21:08:41 +00005134#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00005135 case TARGET_NR_lock:
5136 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005137#endif
bellard31e31b82003-02-18 22:55:36 +00005138 case TARGET_NR_ioctl:
5139 ret = do_ioctl(arg1, arg2, arg3);
5140 break;
5141 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00005142 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00005143 break;
bellardebc05482003-09-30 21:08:41 +00005144#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00005145 case TARGET_NR_mpx:
5146 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005147#endif
bellard31e31b82003-02-18 22:55:36 +00005148 case TARGET_NR_setpgid:
5149 ret = get_errno(setpgid(arg1, arg2));
5150 break;
bellardebc05482003-09-30 21:08:41 +00005151#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00005152 case TARGET_NR_ulimit:
5153 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005154#endif
5155#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00005156 case TARGET_NR_oldolduname:
5157 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005158#endif
bellard31e31b82003-02-18 22:55:36 +00005159 case TARGET_NR_umask:
5160 ret = get_errno(umask(arg1));
5161 break;
5162 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00005163 if (!(p = lock_user_string(arg1)))
5164 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005165 ret = get_errno(chroot(p));
5166 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005167 break;
5168 case TARGET_NR_ustat:
5169 goto unimplemented;
5170 case TARGET_NR_dup2:
5171 ret = get_errno(dup2(arg1, arg2));
5172 break;
Ulrich Hechtd0927932009-09-17 20:22:14 +03005173#if defined(CONFIG_DUP3) && defined(TARGET_NR_dup3)
5174 case TARGET_NR_dup3:
5175 ret = get_errno(dup3(arg1, arg2, arg3));
5176 break;
5177#endif
j_mayer7a3148a2007-04-05 07:13:51 +00005178#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005179 case TARGET_NR_getppid:
5180 ret = get_errno(getppid());
5181 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005182#endif
bellard31e31b82003-02-18 22:55:36 +00005183 case TARGET_NR_getpgrp:
5184 ret = get_errno(getpgrp());
5185 break;
5186 case TARGET_NR_setsid:
5187 ret = get_errno(setsid());
5188 break;
thse5febef2007-04-01 18:31:35 +00005189#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00005190 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00005191 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005192#if defined(TARGET_ALPHA)
5193 struct target_sigaction act, oact, *pact = 0;
pbrook53a59602006-03-25 19:31:22 +00005194 struct target_old_sigaction *old_act;
pbrook53a59602006-03-25 19:31:22 +00005195 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00005196 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5197 goto efault;
bellard66fb9762003-03-23 01:06:05 +00005198 act._sa_handler = old_act->_sa_handler;
5199 target_siginitset(&act.sa_mask, old_act->sa_mask);
5200 act.sa_flags = old_act->sa_flags;
Richard Henderson6049f4f2009-12-27 18:30:03 -08005201 act.sa_restorer = 0;
pbrook53a59602006-03-25 19:31:22 +00005202 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005203 pact = &act;
bellard66fb9762003-03-23 01:06:05 +00005204 }
5205 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00005206 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00005207 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5208 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005209 old_act->_sa_handler = oact._sa_handler;
5210 old_act->sa_mask = oact.sa_mask.sig[0];
5211 old_act->sa_flags = oact.sa_flags;
pbrook53a59602006-03-25 19:31:22 +00005212 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00005213 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08005214#elif defined(TARGET_MIPS)
bellard106ec872006-06-27 21:08:10 +00005215 struct target_sigaction act, oact, *pact, *old_act;
5216
5217 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00005218 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5219 goto efault;
bellard106ec872006-06-27 21:08:10 +00005220 act._sa_handler = old_act->_sa_handler;
5221 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
5222 act.sa_flags = old_act->sa_flags;
5223 unlock_user_struct(old_act, arg2, 0);
5224 pact = &act;
5225 } else {
5226 pact = NULL;
5227 }
5228
5229 ret = get_errno(do_sigaction(arg1, pact, &oact));
5230
5231 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00005232 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5233 goto efault;
bellard106ec872006-06-27 21:08:10 +00005234 old_act->_sa_handler = oact._sa_handler;
5235 old_act->sa_flags = oact.sa_flags;
5236 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
5237 old_act->sa_mask.sig[1] = 0;
5238 old_act->sa_mask.sig[2] = 0;
5239 old_act->sa_mask.sig[3] = 0;
5240 unlock_user_struct(old_act, arg3, 1);
5241 }
Richard Henderson6049f4f2009-12-27 18:30:03 -08005242#else
5243 struct target_old_sigaction *old_act;
5244 struct target_sigaction act, oact, *pact;
5245 if (arg2) {
5246 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
5247 goto efault;
5248 act._sa_handler = old_act->_sa_handler;
5249 target_siginitset(&act.sa_mask, old_act->sa_mask);
5250 act.sa_flags = old_act->sa_flags;
5251 act.sa_restorer = old_act->sa_restorer;
5252 unlock_user_struct(old_act, arg2, 0);
5253 pact = &act;
5254 } else {
5255 pact = NULL;
5256 }
5257 ret = get_errno(do_sigaction(arg1, pact, &oact));
5258 if (!is_error(ret) && arg3) {
5259 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
5260 goto efault;
5261 old_act->_sa_handler = oact._sa_handler;
5262 old_act->sa_mask = oact.sa_mask.sig[0];
5263 old_act->sa_flags = oact.sa_flags;
5264 old_act->sa_restorer = oact.sa_restorer;
5265 unlock_user_struct(old_act, arg3, 1);
5266 }
ths388bb212007-05-13 13:58:00 +00005267#endif
bellard31e31b82003-02-18 22:55:36 +00005268 }
5269 break;
thse5febef2007-04-01 18:31:35 +00005270#endif
bellard66fb9762003-03-23 01:06:05 +00005271 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00005272 {
Richard Henderson6049f4f2009-12-27 18:30:03 -08005273#if defined(TARGET_ALPHA)
5274 struct target_sigaction act, oact, *pact = 0;
5275 struct target_rt_sigaction *rt_act;
5276 /* ??? arg4 == sizeof(sigset_t). */
5277 if (arg2) {
5278 if (!lock_user_struct(VERIFY_READ, rt_act, arg2, 1))
5279 goto efault;
5280 act._sa_handler = rt_act->_sa_handler;
5281 act.sa_mask = rt_act->sa_mask;
5282 act.sa_flags = rt_act->sa_flags;
5283 act.sa_restorer = arg5;
5284 unlock_user_struct(rt_act, arg2, 0);
5285 pact = &act;
5286 }
5287 ret = get_errno(do_sigaction(arg1, pact, &oact));
5288 if (!is_error(ret) && arg3) {
5289 if (!lock_user_struct(VERIFY_WRITE, rt_act, arg3, 0))
5290 goto efault;
5291 rt_act->_sa_handler = oact._sa_handler;
5292 rt_act->sa_mask = oact.sa_mask;
5293 rt_act->sa_flags = oact.sa_flags;
5294 unlock_user_struct(rt_act, arg3, 1);
5295 }
5296#else
pbrook53a59602006-03-25 19:31:22 +00005297 struct target_sigaction *act;
5298 struct target_sigaction *oact;
5299
bellard579a97f2007-11-11 14:26:47 +00005300 if (arg2) {
5301 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
5302 goto efault;
5303 } else
pbrook53a59602006-03-25 19:31:22 +00005304 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00005305 if (arg3) {
5306 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
5307 ret = -TARGET_EFAULT;
5308 goto rt_sigaction_fail;
5309 }
5310 } else
pbrook53a59602006-03-25 19:31:22 +00005311 oact = NULL;
5312 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00005313 rt_sigaction_fail:
5314 if (act)
pbrook53a59602006-03-25 19:31:22 +00005315 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00005316 if (oact)
pbrook53a59602006-03-25 19:31:22 +00005317 unlock_user_struct(oact, arg3, 1);
Richard Henderson6049f4f2009-12-27 18:30:03 -08005318#endif
pbrook53a59602006-03-25 19:31:22 +00005319 }
bellard66fb9762003-03-23 01:06:05 +00005320 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005321#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005322 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00005323 {
5324 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00005325 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00005326 sigprocmask(0, NULL, &cur_set);
5327 host_to_target_old_sigset(&target_set, &cur_set);
5328 ret = target_set;
5329 }
5330 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005331#endif
5332#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00005333 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00005334 {
5335 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00005336 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00005337 sigprocmask(0, NULL, &cur_set);
5338 target_to_host_old_sigset(&set, &target_set);
5339 sigorset(&set, &set, &cur_set);
5340 sigprocmask(SIG_SETMASK, &set, &oset);
5341 host_to_target_old_sigset(&target_set, &oset);
5342 ret = target_set;
5343 }
5344 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005345#endif
thse5febef2007-04-01 18:31:35 +00005346#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00005347 case TARGET_NR_sigprocmask:
5348 {
Richard Hendersona5b3b132010-05-03 10:07:55 -07005349#if defined(TARGET_ALPHA)
5350 sigset_t set, oldset;
5351 abi_ulong mask;
5352 int how;
5353
5354 switch (arg1) {
5355 case TARGET_SIG_BLOCK:
5356 how = SIG_BLOCK;
5357 break;
5358 case TARGET_SIG_UNBLOCK:
5359 how = SIG_UNBLOCK;
5360 break;
5361 case TARGET_SIG_SETMASK:
5362 how = SIG_SETMASK;
5363 break;
5364 default:
5365 ret = -TARGET_EINVAL;
5366 goto fail;
5367 }
5368 mask = arg2;
5369 target_to_host_old_sigset(&set, &mask);
5370
5371 ret = get_errno(sigprocmask(how, &set, &oldset));
5372
5373 if (!is_error(ret)) {
5374 host_to_target_old_sigset(&mask, &oldset);
5375 ret = mask;
5376 ((CPUAlphaState *)cpu_env)->[IR_V0] = 0; /* force no error */
5377 }
5378#else
bellard66fb9762003-03-23 01:06:05 +00005379 sigset_t set, oldset, *set_ptr;
Richard Hendersona5b3b132010-05-03 10:07:55 -07005380 int how;
ths3b46e622007-09-17 08:09:54 +00005381
pbrook53a59602006-03-25 19:31:22 +00005382 if (arg2) {
Richard Hendersona5b3b132010-05-03 10:07:55 -07005383 switch (arg1) {
bellard66fb9762003-03-23 01:06:05 +00005384 case TARGET_SIG_BLOCK:
5385 how = SIG_BLOCK;
5386 break;
5387 case TARGET_SIG_UNBLOCK:
5388 how = SIG_UNBLOCK;
5389 break;
5390 case TARGET_SIG_SETMASK:
5391 how = SIG_SETMASK;
5392 break;
5393 default:
ths0da46a62007-10-20 20:23:07 +00005394 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00005395 goto fail;
5396 }
Anthony Liguoric227f092009-10-01 16:12:16 -05005397 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005398 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005399 target_to_host_old_sigset(&set, p);
5400 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005401 set_ptr = &set;
5402 } else {
5403 how = 0;
5404 set_ptr = NULL;
5405 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07005406 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00005407 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005408 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005409 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005410 host_to_target_old_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05005411 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005412 }
Richard Hendersona5b3b132010-05-03 10:07:55 -07005413#endif
bellard66fb9762003-03-23 01:06:05 +00005414 }
5415 break;
thse5febef2007-04-01 18:31:35 +00005416#endif
bellard66fb9762003-03-23 01:06:05 +00005417 case TARGET_NR_rt_sigprocmask:
5418 {
5419 int how = arg1;
5420 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00005421
pbrook53a59602006-03-25 19:31:22 +00005422 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00005423 switch(how) {
5424 case TARGET_SIG_BLOCK:
5425 how = SIG_BLOCK;
5426 break;
5427 case TARGET_SIG_UNBLOCK:
5428 how = SIG_UNBLOCK;
5429 break;
5430 case TARGET_SIG_SETMASK:
5431 how = SIG_SETMASK;
5432 break;
5433 default:
ths0da46a62007-10-20 20:23:07 +00005434 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00005435 goto fail;
5436 }
Anthony Liguoric227f092009-10-01 16:12:16 -05005437 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005438 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005439 target_to_host_sigset(&set, p);
5440 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00005441 set_ptr = &set;
5442 } else {
5443 how = 0;
5444 set_ptr = NULL;
5445 }
5446 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00005447 if (!is_error(ret) && arg3) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005448 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005449 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005450 host_to_target_sigset(p, &oldset);
Anthony Liguoric227f092009-10-01 16:12:16 -05005451 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005452 }
5453 }
5454 break;
thse5febef2007-04-01 18:31:35 +00005455#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00005456 case TARGET_NR_sigpending:
5457 {
5458 sigset_t set;
5459 ret = get_errno(sigpending(&set));
5460 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005461 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005462 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005463 host_to_target_old_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05005464 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005465 }
5466 }
5467 break;
thse5febef2007-04-01 18:31:35 +00005468#endif
bellard66fb9762003-03-23 01:06:05 +00005469 case TARGET_NR_rt_sigpending:
5470 {
5471 sigset_t set;
5472 ret = get_errno(sigpending(&set));
5473 if (!is_error(ret)) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005474 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005475 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005476 host_to_target_sigset(p, &set);
Anthony Liguoric227f092009-10-01 16:12:16 -05005477 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00005478 }
5479 }
5480 break;
thse5febef2007-04-01 18:31:35 +00005481#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00005482 case TARGET_NR_sigsuspend:
5483 {
5484 sigset_t set;
Richard Hendersonf43ce122010-05-03 10:07:54 -07005485#if defined(TARGET_ALPHA)
5486 abi_ulong mask = arg1;
5487 target_to_host_old_sigset(&set, &mask);
5488#else
Anthony Liguoric227f092009-10-01 16:12:16 -05005489 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005490 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005491 target_to_host_old_sigset(&set, p);
5492 unlock_user(p, arg1, 0);
Richard Hendersonf43ce122010-05-03 10:07:54 -07005493#endif
bellard66fb9762003-03-23 01:06:05 +00005494 ret = get_errno(sigsuspend(&set));
5495 }
5496 break;
thse5febef2007-04-01 18:31:35 +00005497#endif
bellard66fb9762003-03-23 01:06:05 +00005498 case TARGET_NR_rt_sigsuspend:
5499 {
5500 sigset_t set;
Anthony Liguoric227f092009-10-01 16:12:16 -05005501 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005502 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005503 target_to_host_sigset(&set, p);
5504 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00005505 ret = get_errno(sigsuspend(&set));
5506 }
5507 break;
5508 case TARGET_NR_rt_sigtimedwait:
5509 {
bellard66fb9762003-03-23 01:06:05 +00005510 sigset_t set;
5511 struct timespec uts, *puts;
5512 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00005513
Anthony Liguoric227f092009-10-01 16:12:16 -05005514 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005515 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005516 target_to_host_sigset(&set, p);
5517 unlock_user(p, arg1, 0);
5518 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00005519 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00005520 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00005521 } else {
5522 puts = NULL;
5523 }
5524 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00005525 if (!is_error(ret) && arg2) {
Anthony Liguoric227f092009-10-01 16:12:16 -05005526 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00005527 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005528 host_to_target_siginfo(p, &uinfo);
Anthony Liguoric227f092009-10-01 16:12:16 -05005529 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00005530 }
5531 }
5532 break;
5533 case TARGET_NR_rt_sigqueueinfo:
5534 {
5535 siginfo_t uinfo;
Anthony Liguoric227f092009-10-01 16:12:16 -05005536 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
bellard579a97f2007-11-11 14:26:47 +00005537 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005538 target_to_host_siginfo(&uinfo, p);
5539 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00005540 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
5541 }
5542 break;
thse5febef2007-04-01 18:31:35 +00005543#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00005544 case TARGET_NR_sigreturn:
5545 /* NOTE: ret is eax, so not transcoding must be done */
5546 ret = do_sigreturn(cpu_env);
5547 break;
thse5febef2007-04-01 18:31:35 +00005548#endif
bellard66fb9762003-03-23 01:06:05 +00005549 case TARGET_NR_rt_sigreturn:
5550 /* NOTE: ret is eax, so not transcoding must be done */
5551 ret = do_rt_sigreturn(cpu_env);
5552 break;
bellard31e31b82003-02-18 22:55:36 +00005553 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00005554 if (!(p = lock_user_string(arg1)))
5555 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005556 ret = get_errno(sethostname(p, arg2));
5557 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005558 break;
5559 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00005560 {
bellard9de5e442003-03-23 16:49:39 +00005561 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005562 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005563 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00005564 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
5565 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09005566 rlim.rlim_cur = target_to_host_rlim(target_rlim->rlim_cur);
5567 rlim.rlim_max = target_to_host_rlim(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005568 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00005569 ret = get_errno(setrlimit(resource, &rlim));
5570 }
5571 break;
bellard31e31b82003-02-18 22:55:36 +00005572 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00005573 {
bellard9de5e442003-03-23 16:49:39 +00005574 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00005575 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00005576 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00005577
bellard9de5e442003-03-23 16:49:39 +00005578 ret = get_errno(getrlimit(resource, &rlim));
5579 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005580 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5581 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09005582 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
5583 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005584 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00005585 }
5586 }
5587 break;
bellard31e31b82003-02-18 22:55:36 +00005588 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00005589 {
5590 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00005591 ret = get_errno(getrusage(arg1, &rusage));
5592 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005593 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00005594 }
5595 }
5596 break;
bellard31e31b82003-02-18 22:55:36 +00005597 case TARGET_NR_gettimeofday:
5598 {
bellard31e31b82003-02-18 22:55:36 +00005599 struct timeval tv;
5600 ret = get_errno(gettimeofday(&tv, NULL));
5601 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00005602 if (copy_to_user_timeval(arg1, &tv))
5603 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005604 }
5605 }
5606 break;
5607 case TARGET_NR_settimeofday:
5608 {
bellard31e31b82003-02-18 22:55:36 +00005609 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00005610 if (copy_from_user_timeval(&tv, arg1))
5611 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005612 ret = get_errno(settimeofday(&tv, NULL));
5613 }
5614 break;
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005615#if defined(TARGET_NR_select) && !defined(TARGET_S390X) && !defined(TARGET_S390)
bellard31e31b82003-02-18 22:55:36 +00005616 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00005617 {
pbrook53a59602006-03-25 19:31:22 +00005618 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00005619 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00005620 long nsel;
5621
bellard579a97f2007-11-11 14:26:47 +00005622 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
5623 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005624 nsel = tswapl(sel->n);
5625 inp = tswapl(sel->inp);
5626 outp = tswapl(sel->outp);
5627 exp = tswapl(sel->exp);
5628 tvp = tswapl(sel->tvp);
5629 unlock_user_struct(sel, arg1, 0);
5630 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00005631 }
5632 break;
bellard048f6b42005-11-26 18:47:20 +00005633#endif
Riku Voipio9e423822010-05-07 12:28:05 +00005634#ifdef TARGET_NR_pselect6
5635 case TARGET_NR_pselect6:
Mike Frysinger055e0902011-06-03 17:01:49 -04005636 {
5637 abi_long rfd_addr, wfd_addr, efd_addr, n, ts_addr;
5638 fd_set rfds, wfds, efds;
5639 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
5640 struct timespec ts, *ts_ptr;
5641
5642 /*
5643 * The 6th arg is actually two args smashed together,
5644 * so we cannot use the C library.
5645 */
5646 sigset_t set;
5647 struct {
5648 sigset_t *set;
5649 size_t size;
5650 } sig, *sig_ptr;
5651
5652 abi_ulong arg_sigset, arg_sigsize, *arg7;
5653 target_sigset_t *target_sigset;
5654
5655 n = arg1;
5656 rfd_addr = arg2;
5657 wfd_addr = arg3;
5658 efd_addr = arg4;
5659 ts_addr = arg5;
5660
5661 ret = copy_from_user_fdset_ptr(&rfds, &rfds_ptr, rfd_addr, n);
5662 if (ret) {
5663 goto fail;
5664 }
5665 ret = copy_from_user_fdset_ptr(&wfds, &wfds_ptr, wfd_addr, n);
5666 if (ret) {
5667 goto fail;
5668 }
5669 ret = copy_from_user_fdset_ptr(&efds, &efds_ptr, efd_addr, n);
5670 if (ret) {
5671 goto fail;
5672 }
5673
5674 /*
5675 * This takes a timespec, and not a timeval, so we cannot
5676 * use the do_select() helper ...
5677 */
5678 if (ts_addr) {
5679 if (target_to_host_timespec(&ts, ts_addr)) {
5680 goto efault;
5681 }
5682 ts_ptr = &ts;
5683 } else {
5684 ts_ptr = NULL;
5685 }
5686
5687 /* Extract the two packed args for the sigset */
5688 if (arg6) {
5689 sig_ptr = &sig;
5690 sig.size = _NSIG / 8;
5691
5692 arg7 = lock_user(VERIFY_READ, arg6, sizeof(*arg7) * 2, 1);
5693 if (!arg7) {
5694 goto efault;
5695 }
5696 arg_sigset = tswapl(arg7[0]);
5697 arg_sigsize = tswapl(arg7[1]);
5698 unlock_user(arg7, arg6, 0);
5699
5700 if (arg_sigset) {
5701 sig.set = &set;
Peter Maydell8f04eeb2011-06-28 12:21:57 +01005702 if (arg_sigsize != sizeof(*target_sigset)) {
5703 /* Like the kernel, we enforce correct size sigsets */
5704 ret = -TARGET_EINVAL;
5705 goto fail;
5706 }
Mike Frysinger055e0902011-06-03 17:01:49 -04005707 target_sigset = lock_user(VERIFY_READ, arg_sigset,
5708 sizeof(*target_sigset), 1);
5709 if (!target_sigset) {
5710 goto efault;
5711 }
5712 target_to_host_sigset(&set, target_sigset);
5713 unlock_user(target_sigset, arg_sigset, 0);
5714 } else {
5715 sig.set = NULL;
5716 }
5717 } else {
5718 sig_ptr = NULL;
5719 }
5720
5721 ret = get_errno(sys_pselect6(n, rfds_ptr, wfds_ptr, efds_ptr,
5722 ts_ptr, sig_ptr));
5723
5724 if (!is_error(ret)) {
5725 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
5726 goto efault;
5727 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
5728 goto efault;
5729 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
5730 goto efault;
5731
5732 if (ts_addr && host_to_target_timespec(ts_addr, &ts))
5733 goto efault;
5734 }
5735 }
5736 break;
Riku Voipio9e423822010-05-07 12:28:05 +00005737#endif
bellard31e31b82003-02-18 22:55:36 +00005738 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00005739 {
5740 void *p2;
5741 p = lock_user_string(arg1);
5742 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005743 if (!p || !p2)
5744 ret = -TARGET_EFAULT;
5745 else
5746 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00005747 unlock_user(p2, arg2, 0);
5748 unlock_user(p, arg1, 0);
5749 }
bellard31e31b82003-02-18 22:55:36 +00005750 break;
thsf0b62432007-09-24 09:25:40 +00005751#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
5752 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00005753 {
bellard579a97f2007-11-11 14:26:47 +00005754 void *p2;
thsf0b62432007-09-24 09:25:40 +00005755 p = lock_user_string(arg1);
5756 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00005757 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005758 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00005759 else
5760 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00005761 unlock_user(p2, arg3, 0);
5762 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00005763 }
5764 break;
5765#endif
bellardebc05482003-09-30 21:08:41 +00005766#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00005767 case TARGET_NR_oldlstat:
5768 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005769#endif
bellard31e31b82003-02-18 22:55:36 +00005770 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00005771 {
aurel32d088d662009-01-30 20:09:01 +00005772 void *p2, *temp;
pbrook53a59602006-03-25 19:31:22 +00005773 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00005774 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
5775 if (!p || !p2)
5776 ret = -TARGET_EFAULT;
aurel32d088d662009-01-30 20:09:01 +00005777 else {
5778 if (strncmp((const char *)p, "/proc/self/exe", 14) == 0) {
5779 char real[PATH_MAX];
5780 temp = realpath(exec_path,real);
5781 ret = (temp==NULL) ? get_errno(-1) : strlen(real) ;
5782 snprintf((char *)p2, arg3, "%s", real);
5783 }
5784 else
5785 ret = get_errno(readlink(path(p), p2, arg3));
aurel32d088d662009-01-30 20:09:01 +00005786 }
pbrook53a59602006-03-25 19:31:22 +00005787 unlock_user(p2, arg2, ret);
5788 unlock_user(p, arg1, 0);
5789 }
bellard31e31b82003-02-18 22:55:36 +00005790 break;
ths5e0ccb12007-09-24 09:26:10 +00005791#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
5792 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00005793 {
bellard579a97f2007-11-11 14:26:47 +00005794 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00005795 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00005796 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
5797 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00005798 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00005799 else
5800 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00005801 unlock_user(p2, arg3, ret);
5802 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00005803 }
5804 break;
5805#endif
thse5febef2007-04-01 18:31:35 +00005806#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00005807 case TARGET_NR_uselib:
5808 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005809#endif
5810#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00005811 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00005812 if (!(p = lock_user_string(arg1)))
5813 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005814 ret = get_errno(swapon(p, arg2));
5815 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005816 break;
thse5febef2007-04-01 18:31:35 +00005817#endif
bellard31e31b82003-02-18 22:55:36 +00005818 case TARGET_NR_reboot:
5819 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005820#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00005821 case TARGET_NR_readdir:
5822 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005823#endif
5824#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00005825 case TARGET_NR_mmap:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02005826#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || \
5827 defined(TARGET_M68K) || defined(TARGET_CRIS) || defined(TARGET_MICROBLAZE) \
5828 || defined(TARGET_S390X)
bellard31e31b82003-02-18 22:55:36 +00005829 {
blueswir1992f48a2007-10-14 16:27:31 +00005830 abi_ulong *v;
5831 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00005832 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
5833 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005834 v1 = tswapl(v[0]);
5835 v2 = tswapl(v[1]);
5836 v3 = tswapl(v[2]);
5837 v4 = tswapl(v[3]);
5838 v5 = tswapl(v[4]);
5839 v6 = tswapl(v[5]);
5840 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00005841 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00005842 target_to_host_bitmask(v4, mmap_flags_tbl),
5843 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00005844 }
bellard31e31b82003-02-18 22:55:36 +00005845#else
ths5fafdf22007-09-16 21:08:06 +00005846 ret = get_errno(target_mmap(arg1, arg2, arg3,
5847 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00005848 arg5,
5849 arg6));
bellard31e31b82003-02-18 22:55:36 +00005850#endif
bellard6fb883e2003-07-09 17:12:39 +00005851 break;
thse5febef2007-04-01 18:31:35 +00005852#endif
bellarda315a142005-01-30 22:59:18 +00005853#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00005854 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00005855#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00005856#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00005857#endif
ths5fafdf22007-09-16 21:08:06 +00005858 ret = get_errno(target_mmap(arg1, arg2, arg3,
5859 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00005860 arg5,
bellardc573ff62004-01-04 15:51:36 +00005861 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00005862 break;
bellarda315a142005-01-30 22:59:18 +00005863#endif
bellard31e31b82003-02-18 22:55:36 +00005864 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00005865 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005866 break;
bellard9de5e442003-03-23 16:49:39 +00005867 case TARGET_NR_mprotect:
Paul Brook97374d32010-06-16 13:03:51 +01005868 {
5869 TaskState *ts = ((CPUState *)cpu_env)->opaque;
5870 /* Special hack to detect libc making the stack executable. */
5871 if ((arg3 & PROT_GROWSDOWN)
5872 && arg1 >= ts->info->stack_limit
5873 && arg1 <= ts->info->start_stack) {
5874 arg3 &= ~PROT_GROWSDOWN;
5875 arg2 = arg2 + arg1 - ts->info->stack_limit;
5876 arg1 = ts->info->stack_limit;
5877 }
5878 }
bellard54936002003-05-13 00:25:15 +00005879 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005880 break;
thse5febef2007-04-01 18:31:35 +00005881#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00005882 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00005883 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00005884 break;
thse5febef2007-04-01 18:31:35 +00005885#endif
pbrook53a59602006-03-25 19:31:22 +00005886 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00005887#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00005888 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00005889 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00005890 break;
thse5febef2007-04-01 18:31:35 +00005891#endif
5892#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00005893 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00005894 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005895 break;
thse5febef2007-04-01 18:31:35 +00005896#endif
5897#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00005898 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00005899 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00005900 break;
thse5febef2007-04-01 18:31:35 +00005901#endif
5902#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00005903 case TARGET_NR_mlockall:
5904 ret = get_errno(mlockall(arg1));
5905 break;
thse5febef2007-04-01 18:31:35 +00005906#endif
5907#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00005908 case TARGET_NR_munlockall:
5909 ret = get_errno(munlockall());
5910 break;
thse5febef2007-04-01 18:31:35 +00005911#endif
bellard31e31b82003-02-18 22:55:36 +00005912 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00005913 if (!(p = lock_user_string(arg1)))
5914 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005915 ret = get_errno(truncate(p, arg2));
5916 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005917 break;
5918 case TARGET_NR_ftruncate:
5919 ret = get_errno(ftruncate(arg1, arg2));
5920 break;
5921 case TARGET_NR_fchmod:
5922 ret = get_errno(fchmod(arg1, arg2));
5923 break;
ths814d7972007-09-24 09:26:51 +00005924#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
5925 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00005926 if (!(p = lock_user_string(arg2)))
5927 goto efault;
aurel32465c9f02009-04-19 08:52:17 +00005928 ret = get_errno(sys_fchmodat(arg1, p, arg3));
bellard579a97f2007-11-11 14:26:47 +00005929 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00005930 break;
5931#endif
bellard31e31b82003-02-18 22:55:36 +00005932 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00005933 /* libc does special remapping of the return value of
5934 * sys_getpriority() so it's just easiest to call
5935 * sys_getpriority() directly rather than through libc. */
Ulrich Hecht69137202009-09-17 21:08:37 +03005936 ret = get_errno(sys_getpriority(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005937 break;
5938 case TARGET_NR_setpriority:
5939 ret = get_errno(setpriority(arg1, arg2, arg3));
5940 break;
bellardebc05482003-09-30 21:08:41 +00005941#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00005942 case TARGET_NR_profil:
5943 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005944#endif
bellard31e31b82003-02-18 22:55:36 +00005945 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00005946 if (!(p = lock_user_string(arg1)))
5947 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005948 ret = get_errno(statfs(path(p), &stfs));
5949 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00005950 convert_statfs:
5951 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005952 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005953
bellard579a97f2007-11-11 14:26:47 +00005954 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
5955 goto efault;
5956 __put_user(stfs.f_type, &target_stfs->f_type);
5957 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5958 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5959 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5960 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5961 __put_user(stfs.f_files, &target_stfs->f_files);
5962 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5963 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5964 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5965 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00005966 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00005967 }
5968 break;
5969 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00005970 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00005971 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00005972#ifdef TARGET_NR_statfs64
5973 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00005974 if (!(p = lock_user_string(arg1)))
5975 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005976 ret = get_errno(statfs(path(p), &stfs));
5977 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00005978 convert_statfs64:
5979 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005980 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00005981
bellard579a97f2007-11-11 14:26:47 +00005982 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
5983 goto efault;
5984 __put_user(stfs.f_type, &target_stfs->f_type);
5985 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
5986 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
5987 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
5988 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
5989 __put_user(stfs.f_files, &target_stfs->f_files);
5990 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
5991 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
5992 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
5993 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
5994 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00005995 }
5996 break;
5997 case TARGET_NR_fstatfs64:
5998 ret = get_errno(fstatfs(arg1, &stfs));
5999 goto convert_statfs64;
6000#endif
bellardebc05482003-09-30 21:08:41 +00006001#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00006002 case TARGET_NR_ioperm:
6003 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006004#endif
thse5febef2007-04-01 18:31:35 +00006005#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00006006 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00006007 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00006008 break;
thse5febef2007-04-01 18:31:35 +00006009#endif
bellard3532fa72006-06-24 15:06:03 +00006010#ifdef TARGET_NR_accept
6011 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00006012 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00006013 break;
6014#endif
6015#ifdef TARGET_NR_bind
6016 case TARGET_NR_bind:
6017 ret = do_bind(arg1, arg2, arg3);
6018 break;
6019#endif
6020#ifdef TARGET_NR_connect
6021 case TARGET_NR_connect:
6022 ret = do_connect(arg1, arg2, arg3);
6023 break;
6024#endif
6025#ifdef TARGET_NR_getpeername
6026 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00006027 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00006028 break;
6029#endif
6030#ifdef TARGET_NR_getsockname
6031 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00006032 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00006033 break;
6034#endif
6035#ifdef TARGET_NR_getsockopt
6036 case TARGET_NR_getsockopt:
6037 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
6038 break;
6039#endif
6040#ifdef TARGET_NR_listen
6041 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00006042 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00006043 break;
6044#endif
6045#ifdef TARGET_NR_recv
6046 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00006047 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00006048 break;
6049#endif
6050#ifdef TARGET_NR_recvfrom
6051 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00006052 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00006053 break;
6054#endif
6055#ifdef TARGET_NR_recvmsg
6056 case TARGET_NR_recvmsg:
6057 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
6058 break;
6059#endif
6060#ifdef TARGET_NR_send
6061 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00006062 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00006063 break;
6064#endif
6065#ifdef TARGET_NR_sendmsg
6066 case TARGET_NR_sendmsg:
6067 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
6068 break;
6069#endif
6070#ifdef TARGET_NR_sendto
6071 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00006072 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00006073 break;
6074#endif
6075#ifdef TARGET_NR_shutdown
6076 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00006077 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00006078 break;
6079#endif
6080#ifdef TARGET_NR_socket
6081 case TARGET_NR_socket:
6082 ret = do_socket(arg1, arg2, arg3);
6083 break;
6084#endif
6085#ifdef TARGET_NR_socketpair
6086 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00006087 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00006088 break;
6089#endif
6090#ifdef TARGET_NR_setsockopt
6091 case TARGET_NR_setsockopt:
6092 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
6093 break;
6094#endif
ths7494b0f2007-02-11 18:26:53 +00006095
bellard31e31b82003-02-18 22:55:36 +00006096 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00006097 if (!(p = lock_user_string(arg2)))
6098 goto efault;
thse5574482007-02-11 20:03:13 +00006099 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
6100 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00006101 break;
6102
bellard31e31b82003-02-18 22:55:36 +00006103 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00006104 {
bellard66fb9762003-03-23 01:06:05 +00006105 struct itimerval value, ovalue, *pvalue;
6106
pbrook53a59602006-03-25 19:31:22 +00006107 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00006108 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00006109 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
6110 || copy_from_user_timeval(&pvalue->it_value,
6111 arg2 + sizeof(struct target_timeval)))
6112 goto efault;
bellard66fb9762003-03-23 01:06:05 +00006113 } else {
6114 pvalue = NULL;
6115 }
6116 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00006117 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00006118 if (copy_to_user_timeval(arg3,
6119 &ovalue.it_interval)
6120 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
6121 &ovalue.it_value))
6122 goto efault;
bellard66fb9762003-03-23 01:06:05 +00006123 }
6124 }
6125 break;
bellard31e31b82003-02-18 22:55:36 +00006126 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00006127 {
bellard66fb9762003-03-23 01:06:05 +00006128 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00006129
bellard66fb9762003-03-23 01:06:05 +00006130 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00006131 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00006132 if (copy_to_user_timeval(arg2,
6133 &value.it_interval)
6134 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
6135 &value.it_value))
6136 goto efault;
bellard66fb9762003-03-23 01:06:05 +00006137 }
6138 }
6139 break;
bellard31e31b82003-02-18 22:55:36 +00006140 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00006141 if (!(p = lock_user_string(arg1)))
6142 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006143 ret = get_errno(stat(path(p), &st));
6144 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00006145 goto do_stat;
6146 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00006147 if (!(p = lock_user_string(arg1)))
6148 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006149 ret = get_errno(lstat(path(p), &st));
6150 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00006151 goto do_stat;
6152 case TARGET_NR_fstat:
6153 {
6154 ret = get_errno(fstat(arg1, &st));
6155 do_stat:
6156 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006157 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00006158
bellard579a97f2007-11-11 14:26:47 +00006159 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
6160 goto efault;
Ulrich Hecht12727912009-07-24 19:10:32 +02006161 memset(target_st, 0, sizeof(*target_st));
bellardd2fd1af2007-11-14 18:08:56 +00006162 __put_user(st.st_dev, &target_st->st_dev);
6163 __put_user(st.st_ino, &target_st->st_ino);
6164 __put_user(st.st_mode, &target_st->st_mode);
6165 __put_user(st.st_uid, &target_st->st_uid);
6166 __put_user(st.st_gid, &target_st->st_gid);
6167 __put_user(st.st_nlink, &target_st->st_nlink);
6168 __put_user(st.st_rdev, &target_st->st_rdev);
6169 __put_user(st.st_size, &target_st->st_size);
6170 __put_user(st.st_blksize, &target_st->st_blksize);
6171 __put_user(st.st_blocks, &target_st->st_blocks);
6172 __put_user(st.st_atime, &target_st->target_st_atime);
6173 __put_user(st.st_mtime, &target_st->target_st_mtime);
6174 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00006175 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00006176 }
6177 }
6178 break;
bellardebc05482003-09-30 21:08:41 +00006179#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00006180 case TARGET_NR_olduname:
6181 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006182#endif
6183#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00006184 case TARGET_NR_iopl:
6185 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006186#endif
bellard31e31b82003-02-18 22:55:36 +00006187 case TARGET_NR_vhangup:
6188 ret = get_errno(vhangup());
6189 break;
bellardebc05482003-09-30 21:08:41 +00006190#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00006191 case TARGET_NR_idle:
6192 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006193#endif
bellard42ad6ae2005-01-03 22:48:11 +00006194#ifdef TARGET_NR_syscall
6195 case TARGET_NR_syscall:
Peter Maydell5945cfc2011-06-16 17:37:13 +01006196 ret = do_syscall(cpu_env, arg1 & 0xffff, arg2, arg3, arg4, arg5,
6197 arg6, arg7, arg8, 0);
6198 break;
bellard42ad6ae2005-01-03 22:48:11 +00006199#endif
bellard31e31b82003-02-18 22:55:36 +00006200 case TARGET_NR_wait4:
6201 {
6202 int status;
blueswir1992f48a2007-10-14 16:27:31 +00006203 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00006204 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00006205 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00006206 if (target_rusage)
6207 rusage_ptr = &rusage;
6208 else
6209 rusage_ptr = NULL;
6210 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
6211 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00006212 if (status_ptr) {
pbrook1d9d8b52009-04-16 15:17:02 +00006213 status = host_to_target_waitstatus(status);
bellard2f619692007-11-16 10:46:05 +00006214 if (put_user_s32(status, status_ptr))
6215 goto efault;
bellard31e31b82003-02-18 22:55:36 +00006216 }
bellard2f619692007-11-16 10:46:05 +00006217 if (target_rusage)
6218 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00006219 }
6220 }
6221 break;
thse5febef2007-04-01 18:31:35 +00006222#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00006223 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00006224 if (!(p = lock_user_string(arg1)))
6225 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006226 ret = get_errno(swapoff(p));
6227 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00006228 break;
thse5febef2007-04-01 18:31:35 +00006229#endif
bellard31e31b82003-02-18 22:55:36 +00006230 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00006231 {
pbrook53a59602006-03-25 19:31:22 +00006232 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00006233 struct sysinfo value;
6234 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00006235 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00006236 {
bellard579a97f2007-11-11 14:26:47 +00006237 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
6238 goto efault;
bellarda5448a72004-06-19 16:59:03 +00006239 __put_user(value.uptime, &target_value->uptime);
6240 __put_user(value.loads[0], &target_value->loads[0]);
6241 __put_user(value.loads[1], &target_value->loads[1]);
6242 __put_user(value.loads[2], &target_value->loads[2]);
6243 __put_user(value.totalram, &target_value->totalram);
6244 __put_user(value.freeram, &target_value->freeram);
6245 __put_user(value.sharedram, &target_value->sharedram);
6246 __put_user(value.bufferram, &target_value->bufferram);
6247 __put_user(value.totalswap, &target_value->totalswap);
6248 __put_user(value.freeswap, &target_value->freeswap);
6249 __put_user(value.procs, &target_value->procs);
6250 __put_user(value.totalhigh, &target_value->totalhigh);
6251 __put_user(value.freehigh, &target_value->freehigh);
6252 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00006253 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00006254 }
6255 }
6256 break;
thse5febef2007-04-01 18:31:35 +00006257#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00006258 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00006259 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
6260 break;
thse5febef2007-04-01 18:31:35 +00006261#endif
aurel32e5289082009-04-18 16:16:12 +00006262#ifdef TARGET_NR_semget
6263 case TARGET_NR_semget:
6264 ret = get_errno(semget(arg1, arg2, arg3));
6265 break;
6266#endif
6267#ifdef TARGET_NR_semop
6268 case TARGET_NR_semop:
6269 ret = get_errno(do_semop(arg1, arg2, arg3));
6270 break;
6271#endif
6272#ifdef TARGET_NR_semctl
6273 case TARGET_NR_semctl:
6274 ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4);
6275 break;
6276#endif
aurel32eeb438c2008-10-13 21:08:55 +00006277#ifdef TARGET_NR_msgctl
6278 case TARGET_NR_msgctl:
6279 ret = do_msgctl(arg1, arg2, arg3);
6280 break;
6281#endif
6282#ifdef TARGET_NR_msgget
6283 case TARGET_NR_msgget:
6284 ret = get_errno(msgget(arg1, arg2));
6285 break;
6286#endif
6287#ifdef TARGET_NR_msgrcv
6288 case TARGET_NR_msgrcv:
6289 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
6290 break;
6291#endif
6292#ifdef TARGET_NR_msgsnd
6293 case TARGET_NR_msgsnd:
6294 ret = do_msgsnd(arg1, arg2, arg3, arg4);
6295 break;
6296#endif
Riku Voipio88a8c982009-04-03 10:42:00 +03006297#ifdef TARGET_NR_shmget
6298 case TARGET_NR_shmget:
6299 ret = get_errno(shmget(arg1, arg2, arg3));
6300 break;
6301#endif
6302#ifdef TARGET_NR_shmctl
6303 case TARGET_NR_shmctl:
6304 ret = do_shmctl(arg1, arg2, arg3);
6305 break;
6306#endif
6307#ifdef TARGET_NR_shmat
6308 case TARGET_NR_shmat:
6309 ret = do_shmat(arg1, arg2, arg3);
6310 break;
6311#endif
6312#ifdef TARGET_NR_shmdt
6313 case TARGET_NR_shmdt:
6314 ret = do_shmdt(arg1);
6315 break;
6316#endif
bellard31e31b82003-02-18 22:55:36 +00006317 case TARGET_NR_fsync:
6318 ret = get_errno(fsync(arg1));
6319 break;
bellard31e31b82003-02-18 22:55:36 +00006320 case TARGET_NR_clone:
Richard Hendersona4b388f2010-04-12 16:17:22 -07006321#if defined(TARGET_SH4) || defined(TARGET_ALPHA)
aurel320b6d3ae2008-09-15 07:43:43 +00006322 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00006323#elif defined(TARGET_CRIS)
6324 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
Ulrich Hechta4c075f2009-07-24 16:57:31 +02006325#elif defined(TARGET_S390X)
6326 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg5, arg4));
aurel320b6d3ae2008-09-15 07:43:43 +00006327#else
pbrookd865bab2008-06-07 22:12:17 +00006328 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00006329#endif
bellard1b6b0292003-03-22 17:31:38 +00006330 break;
bellardec86b0f2003-04-11 00:15:04 +00006331#ifdef __NR_exit_group
6332 /* new thread calls */
6333 case TARGET_NR_exit_group:
Juan Quintela9788c9c2009-07-27 16:13:02 +02006334#ifdef TARGET_GPROF
aurel326d946cd2008-11-06 16:15:18 +00006335 _mcleanup();
6336#endif
bellarde9009672005-04-26 20:42:36 +00006337 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00006338 ret = get_errno(exit_group(arg1));
6339 break;
6340#endif
bellard31e31b82003-02-18 22:55:36 +00006341 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00006342 if (!(p = lock_user_string(arg1)))
6343 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006344 ret = get_errno(setdomainname(p, arg2));
6345 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00006346 break;
6347 case TARGET_NR_uname:
6348 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00006349 {
6350 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00006351
bellard579a97f2007-11-11 14:26:47 +00006352 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
6353 goto efault;
bellard29e619b2004-09-13 21:41:04 +00006354 ret = get_errno(sys_uname(buf));
6355 if (!is_error(ret)) {
6356 /* Overrite the native machine name with whatever is being
6357 emulated. */
Loïc Minierda790302009-12-29 22:06:13 +01006358 strcpy (buf->machine, cpu_to_uname_machine(cpu_env));
pbrookc5937222006-05-14 11:30:38 +00006359 /* Allow the user to override the reported release. */
6360 if (qemu_uname_release && *qemu_uname_release)
6361 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00006362 }
pbrook53a59602006-03-25 19:31:22 +00006363 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00006364 }
bellard31e31b82003-02-18 22:55:36 +00006365 break;
bellard6dbad632003-03-16 18:05:05 +00006366#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00006367 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00006368 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00006369 break;
j_mayer84409dd2007-04-06 08:56:50 +00006370#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00006371 case TARGET_NR_vm86old:
6372 goto unimplemented;
6373 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00006374 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00006375 break;
6376#endif
j_mayer84409dd2007-04-06 08:56:50 +00006377#endif
bellard31e31b82003-02-18 22:55:36 +00006378 case TARGET_NR_adjtimex:
6379 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006380#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00006381 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00006382#endif
bellard31e31b82003-02-18 22:55:36 +00006383 case TARGET_NR_init_module:
6384 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00006385#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00006386 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00006387#endif
bellard31e31b82003-02-18 22:55:36 +00006388 goto unimplemented;
6389 case TARGET_NR_quotactl:
6390 goto unimplemented;
6391 case TARGET_NR_getpgid:
6392 ret = get_errno(getpgid(arg1));
6393 break;
6394 case TARGET_NR_fchdir:
6395 ret = get_errno(fchdir(arg1));
6396 break;
j_mayer84409dd2007-04-06 08:56:50 +00006397#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00006398 case TARGET_NR_bdflush:
6399 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00006400#endif
thse5febef2007-04-01 18:31:35 +00006401#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00006402 case TARGET_NR_sysfs:
6403 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006404#endif
bellard31e31b82003-02-18 22:55:36 +00006405 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00006406 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00006407 break;
thse5febef2007-04-01 18:31:35 +00006408#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00006409 case TARGET_NR_afs_syscall:
6410 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006411#endif
j_mayer7a3148a2007-04-05 07:13:51 +00006412#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00006413 case TARGET_NR__llseek:
6414 {
6415 int64_t res;
Peter Maydell0c1592d2011-02-22 13:02:26 +00006416#if !defined(__NR_llseek)
6417 res = lseek(arg1, ((uint64_t)arg2 << 32) | arg3, arg5);
6418 if (res == -1) {
6419 ret = get_errno(res);
6420 } else {
6421 ret = 0;
6422 }
6423#else
bellard31e31b82003-02-18 22:55:36 +00006424 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard4f2ac232004-04-26 19:44:02 +00006425#endif
Peter Maydell0c1592d2011-02-22 13:02:26 +00006426 if ((ret == 0) && put_user_s64(res, arg4)) {
6427 goto efault;
6428 }
bellard31e31b82003-02-18 22:55:36 +00006429 }
6430 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006431#endif
bellard31e31b82003-02-18 22:55:36 +00006432 case TARGET_NR_getdents:
Ulrich Hechtd83c8732009-07-24 19:10:28 +02006433#if TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00006434 {
pbrook53a59602006-03-25 19:31:22 +00006435 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00006436 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006437 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00006438
6439 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00006440 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00006441 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00006442 goto fail;
6443 }
ths3b46e622007-09-17 08:09:54 +00006444
bellard4add45b2003-06-05 01:52:59 +00006445 ret = get_errno(sys_getdents(arg1, dirp, count));
6446 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006447 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00006448 struct target_dirent *tde;
6449 int len = ret;
6450 int reclen, treclen;
6451 int count1, tnamelen;
6452
6453 count1 = 0;
6454 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00006455 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6456 goto efault;
bellard4add45b2003-06-05 01:52:59 +00006457 tde = target_dirp;
6458 while (len > 0) {
6459 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00006460 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00006461 tde->d_reclen = tswap16(treclen);
6462 tde->d_ino = tswapl(de->d_ino);
6463 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00006464 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00006465 if (tnamelen > 256)
6466 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00006467 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00006468 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00006469 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00006470 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00006471 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00006472 count1 += treclen;
6473 }
6474 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00006475 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00006476 }
6477 free(dirp);
6478 }
6479#else
bellard31e31b82003-02-18 22:55:36 +00006480 {
aurel326556a832008-10-13 21:08:17 +00006481 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006482 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00006483
bellard579a97f2007-11-11 14:26:47 +00006484 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6485 goto efault;
bellard72f03902003-02-18 23:33:18 +00006486 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00006487 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006488 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00006489 int len = ret;
6490 int reclen;
6491 de = dirp;
6492 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00006493 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00006494 if (reclen > len)
6495 break;
bellard8083a3e2003-03-24 23:12:16 +00006496 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00006497 tswapls(&de->d_ino);
6498 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00006499 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00006500 len -= reclen;
6501 }
6502 }
pbrook53a59602006-03-25 19:31:22 +00006503 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00006504 }
bellard4add45b2003-06-05 01:52:59 +00006505#endif
bellard31e31b82003-02-18 22:55:36 +00006506 break;
ths3ae43202007-09-16 21:39:48 +00006507#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00006508 case TARGET_NR_getdents64:
6509 {
aurel326556a832008-10-13 21:08:17 +00006510 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00006511 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00006512 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
6513 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00006514 ret = get_errno(sys_getdents64(arg1, dirp, count));
6515 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00006516 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00006517 int len = ret;
6518 int reclen;
6519 de = dirp;
6520 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00006521 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00006522 if (reclen > len)
6523 break;
bellard8083a3e2003-03-24 23:12:16 +00006524 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00006525 tswap64s((uint64_t *)&de->d_ino);
6526 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00006527 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00006528 len -= reclen;
6529 }
6530 }
pbrook53a59602006-03-25 19:31:22 +00006531 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00006532 }
6533 break;
bellarda541f292004-04-12 20:39:29 +00006534#endif /* TARGET_NR_getdents64 */
Ulrich Hechta4c075f2009-07-24 16:57:31 +02006535#if defined(TARGET_NR__newselect) || defined(TARGET_S390X)
6536#ifdef TARGET_S390X
6537 case TARGET_NR_select:
6538#else
bellard31e31b82003-02-18 22:55:36 +00006539 case TARGET_NR__newselect:
Ulrich Hechta4c075f2009-07-24 16:57:31 +02006540#endif
pbrook53a59602006-03-25 19:31:22 +00006541 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00006542 break;
thse5febef2007-04-01 18:31:35 +00006543#endif
Mike Frysingerd8035d42011-02-07 01:05:51 -05006544#if defined(TARGET_NR_poll) || defined(TARGET_NR_ppoll)
6545# ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00006546 case TARGET_NR_poll:
Mike Frysingerd8035d42011-02-07 01:05:51 -05006547# endif
6548# ifdef TARGET_NR_ppoll
6549 case TARGET_NR_ppoll:
6550# endif
bellard9de5e442003-03-23 16:49:39 +00006551 {
pbrook53a59602006-03-25 19:31:22 +00006552 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00006553 unsigned int nfds = arg2;
6554 int timeout = arg3;
6555 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00006556 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00006557
bellard579a97f2007-11-11 14:26:47 +00006558 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
6559 if (!target_pfd)
6560 goto efault;
Mike Frysingerd8035d42011-02-07 01:05:51 -05006561
bellard9de5e442003-03-23 16:49:39 +00006562 pfd = alloca(sizeof(struct pollfd) * nfds);
6563 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00006564 pfd[i].fd = tswap32(target_pfd[i].fd);
6565 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00006566 }
Mike Frysingerd8035d42011-02-07 01:05:51 -05006567
6568# ifdef TARGET_NR_ppoll
6569 if (num == TARGET_NR_ppoll) {
6570 struct timespec _timeout_ts, *timeout_ts = &_timeout_ts;
6571 target_sigset_t *target_set;
6572 sigset_t _set, *set = &_set;
6573
6574 if (arg3) {
6575 if (target_to_host_timespec(timeout_ts, arg3)) {
6576 unlock_user(target_pfd, arg1, 0);
6577 goto efault;
6578 }
6579 } else {
6580 timeout_ts = NULL;
6581 }
6582
6583 if (arg4) {
6584 target_set = lock_user(VERIFY_READ, arg4, sizeof(target_sigset_t), 1);
6585 if (!target_set) {
6586 unlock_user(target_pfd, arg1, 0);
6587 goto efault;
6588 }
6589 target_to_host_sigset(set, target_set);
6590 } else {
6591 set = NULL;
6592 }
6593
6594 ret = get_errno(sys_ppoll(pfd, nfds, timeout_ts, set, _NSIG/8));
6595
6596 if (!is_error(ret) && arg3) {
6597 host_to_target_timespec(arg3, timeout_ts);
6598 }
6599 if (arg4) {
6600 unlock_user(target_set, arg4, 0);
6601 }
6602 } else
6603# endif
6604 ret = get_errno(poll(pfd, nfds, timeout));
6605
bellard9de5e442003-03-23 16:49:39 +00006606 if (!is_error(ret)) {
6607 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00006608 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00006609 }
6610 }
Peter Maydell30cb4cd2011-02-25 10:27:40 +00006611 unlock_user(target_pfd, arg1, sizeof(struct target_pollfd) * nfds);
bellard9de5e442003-03-23 16:49:39 +00006612 }
6613 break;
thse5febef2007-04-01 18:31:35 +00006614#endif
bellard31e31b82003-02-18 22:55:36 +00006615 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00006616 /* NOTE: the flock constant seems to be the same for every
6617 Linux platform */
6618 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00006619 break;
6620 case TARGET_NR_readv:
6621 {
6622 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00006623 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00006624
6625 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00006626 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
6627 goto efault;
bellard31e31b82003-02-18 22:55:36 +00006628 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00006629 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00006630 }
6631 break;
6632 case TARGET_NR_writev:
6633 {
6634 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00006635 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00006636
6637 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00006638 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
6639 goto efault;
bellard31e31b82003-02-18 22:55:36 +00006640 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00006641 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00006642 }
6643 break;
6644 case TARGET_NR_getsid:
6645 ret = get_errno(getsid(arg1));
6646 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006647#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00006648 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00006649 ret = get_errno(fdatasync(arg1));
6650 break;
j_mayer7a3148a2007-04-05 07:13:51 +00006651#endif
bellard31e31b82003-02-18 22:55:36 +00006652 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00006653 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00006654 return value. */
ths0da46a62007-10-20 20:23:07 +00006655 ret = -TARGET_ENOTDIR;
6656 break;
Mike Frysinger737de1d2011-02-07 01:05:55 -05006657 case TARGET_NR_sched_getaffinity:
6658 {
6659 unsigned int mask_size;
6660 unsigned long *mask;
6661
6662 /*
6663 * sched_getaffinity needs multiples of ulong, so need to take
6664 * care of mismatches between target ulong and host ulong sizes.
6665 */
6666 if (arg2 & (sizeof(abi_ulong) - 1)) {
6667 ret = -TARGET_EINVAL;
6668 break;
6669 }
6670 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6671
6672 mask = alloca(mask_size);
6673 ret = get_errno(sys_sched_getaffinity(arg1, mask_size, mask));
6674
6675 if (!is_error(ret)) {
Mike McCormackcd18f052011-04-18 14:43:36 +09006676 if (copy_to_user(arg3, mask, ret)) {
Mike Frysinger737de1d2011-02-07 01:05:55 -05006677 goto efault;
6678 }
Mike Frysinger737de1d2011-02-07 01:05:55 -05006679 }
6680 }
6681 break;
6682 case TARGET_NR_sched_setaffinity:
6683 {
6684 unsigned int mask_size;
6685 unsigned long *mask;
6686
6687 /*
6688 * sched_setaffinity needs multiples of ulong, so need to take
6689 * care of mismatches between target ulong and host ulong sizes.
6690 */
6691 if (arg2 & (sizeof(abi_ulong) - 1)) {
6692 ret = -TARGET_EINVAL;
6693 break;
6694 }
6695 mask_size = (arg2 + (sizeof(*mask) - 1)) & ~(sizeof(*mask) - 1);
6696
6697 mask = alloca(mask_size);
6698 if (!lock_user_struct(VERIFY_READ, p, arg3, 1)) {
6699 goto efault;
6700 }
6701 memcpy(mask, p, arg2);
6702 unlock_user_struct(p, arg2, 0);
6703
6704 ret = get_errno(sys_sched_setaffinity(arg1, mask_size, mask));
6705 }
6706 break;
bellard31e31b82003-02-18 22:55:36 +00006707 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00006708 {
pbrook53a59602006-03-25 19:31:22 +00006709 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006710 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00006711
bellard579a97f2007-11-11 14:26:47 +00006712 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
6713 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006714 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006715 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00006716 ret = get_errno(sched_setparam(arg1, &schp));
6717 }
6718 break;
bellard31e31b82003-02-18 22:55:36 +00006719 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00006720 {
pbrook53a59602006-03-25 19:31:22 +00006721 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006722 struct sched_param schp;
6723 ret = get_errno(sched_getparam(arg1, &schp));
6724 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006725 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
6726 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006727 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006728 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00006729 }
6730 }
6731 break;
bellard31e31b82003-02-18 22:55:36 +00006732 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00006733 {
pbrook53a59602006-03-25 19:31:22 +00006734 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00006735 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00006736 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
6737 goto efault;
bellard5cd43932003-03-29 16:54:36 +00006738 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00006739 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00006740 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
6741 }
6742 break;
bellard31e31b82003-02-18 22:55:36 +00006743 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00006744 ret = get_errno(sched_getscheduler(arg1));
6745 break;
bellard31e31b82003-02-18 22:55:36 +00006746 case TARGET_NR_sched_yield:
6747 ret = get_errno(sched_yield());
6748 break;
6749 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00006750 ret = get_errno(sched_get_priority_max(arg1));
6751 break;
bellard31e31b82003-02-18 22:55:36 +00006752 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00006753 ret = get_errno(sched_get_priority_min(arg1));
6754 break;
bellard31e31b82003-02-18 22:55:36 +00006755 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00006756 {
bellard5cd43932003-03-29 16:54:36 +00006757 struct timespec ts;
6758 ret = get_errno(sched_rr_get_interval(arg1, &ts));
6759 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006760 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00006761 }
6762 }
6763 break;
bellard31e31b82003-02-18 22:55:36 +00006764 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00006765 {
bellard1b6b0292003-03-22 17:31:38 +00006766 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00006767 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00006768 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00006769 if (is_error(ret) && arg2) {
6770 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00006771 }
6772 }
6773 break;
thse5febef2007-04-01 18:31:35 +00006774#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00006775 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00006776 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006777#endif
6778#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00006779 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00006780 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00006781#endif
bellard31e31b82003-02-18 22:55:36 +00006782 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00006783 switch (arg1)
6784 {
6785 case PR_GET_PDEATHSIG:
6786 {
6787 int deathsig;
6788 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00006789 if (!is_error(ret) && arg2
6790 && put_user_ual(deathsig, arg2))
6791 goto efault;
thse5574482007-02-11 20:03:13 +00006792 }
6793 break;
6794 default:
6795 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
6796 break;
6797 }
ths39b9aae2007-02-11 18:36:44 +00006798 break;
bellardd2fd1af2007-11-14 18:08:56 +00006799#ifdef TARGET_NR_arch_prctl
6800 case TARGET_NR_arch_prctl:
6801#if defined(TARGET_I386) && !defined(TARGET_ABI32)
6802 ret = do_arch_prctl(cpu_env, arg1, arg2);
6803 break;
6804#else
6805 goto unimplemented;
6806#endif
6807#endif
bellard67867302003-11-23 17:05:30 +00006808#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00006809 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00006810#ifdef TARGET_ARM
6811 if (((CPUARMState *)cpu_env)->eabi)
6812 arg4 = arg5;
6813#endif
bellard579a97f2007-11-11 14:26:47 +00006814 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6815 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006816 ret = get_errno(pread(arg1, p, arg3, arg4));
6817 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00006818 break;
bellard31e31b82003-02-18 22:55:36 +00006819 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00006820#ifdef TARGET_ARM
6821 if (((CPUARMState *)cpu_env)->eabi)
6822 arg4 = arg5;
6823#endif
bellard579a97f2007-11-11 14:26:47 +00006824 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6825 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006826 ret = get_errno(pwrite(arg1, p, arg3, arg4));
6827 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00006828 break;
bellard67867302003-11-23 17:05:30 +00006829#endif
aurel32f2c7ba12008-03-28 22:32:06 +00006830#ifdef TARGET_NR_pread64
6831 case TARGET_NR_pread64:
6832 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
6833 goto efault;
6834 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
6835 unlock_user(p, arg2, ret);
6836 break;
6837 case TARGET_NR_pwrite64:
6838 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
6839 goto efault;
6840 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
6841 unlock_user(p, arg2, 0);
6842 break;
6843#endif
bellard31e31b82003-02-18 22:55:36 +00006844 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00006845 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
6846 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006847 ret = get_errno(sys_getcwd1(p, arg2));
6848 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00006849 break;
6850 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00006851 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006852 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00006853 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00006854 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00006855#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
Laurent Vivierc761c152009-08-03 16:12:19 +02006856 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
Ulrich Hechta4c075f2009-07-24 16:57:31 +02006857 defined(TARGET_M68K) || defined(TARGET_S390X)
bellard579a97f2007-11-11 14:26:47 +00006858 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00006859 break;
6860#else
bellard5cd43932003-03-29 16:54:36 +00006861 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00006862#endif
bellard31e31b82003-02-18 22:55:36 +00006863 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00006864 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006865#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00006866 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00006867 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006868#endif
6869#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00006870 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00006871 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00006872#endif
bellard048f6b42005-11-26 18:47:20 +00006873#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00006874 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00006875 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
6876 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00006877 break;
bellard048f6b42005-11-26 18:47:20 +00006878#endif
bellardebc05482003-09-30 21:08:41 +00006879#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00006880 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00006881 {
6882 struct rlimit rlim;
6883 ret = get_errno(getrlimit(arg1, &rlim));
6884 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00006885 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00006886 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
6887 goto efault;
takasi-y@ops.dti.ne.jp81bbe902010-04-12 04:07:35 +09006888 target_rlim->rlim_cur = host_to_target_rlim(rlim.rlim_cur);
6889 target_rlim->rlim_max = host_to_target_rlim(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00006890 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00006891 }
6892 break;
6893 }
bellardebc05482003-09-30 21:08:41 +00006894#endif
bellarda315a142005-01-30 22:59:18 +00006895#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00006896 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00006897 if (!(p = lock_user_string(arg1)))
6898 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006899 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
6900 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00006901 break;
bellarda315a142005-01-30 22:59:18 +00006902#endif
6903#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00006904 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00006905 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00006906 break;
bellarda315a142005-01-30 22:59:18 +00006907#endif
6908#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00006909 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00006910 if (!(p = lock_user_string(arg1)))
6911 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006912 ret = get_errno(stat(path(p), &st));
6913 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006914 if (!is_error(ret))
6915 ret = host_to_target_stat64(cpu_env, arg2, &st);
6916 break;
bellarda315a142005-01-30 22:59:18 +00006917#endif
6918#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00006919 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00006920 if (!(p = lock_user_string(arg1)))
6921 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006922 ret = get_errno(lstat(path(p), &st));
6923 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00006924 if (!is_error(ret))
6925 ret = host_to_target_stat64(cpu_env, arg2, &st);
6926 break;
bellarda315a142005-01-30 22:59:18 +00006927#endif
6928#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00006929 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00006930 ret = get_errno(fstat(arg1, &st));
6931 if (!is_error(ret))
6932 ret = host_to_target_stat64(cpu_env, arg2, &st);
6933 break;
bellardec86b0f2003-04-11 00:15:04 +00006934#endif
aurel329d33b762009-04-08 23:07:05 +00006935#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \
6936 (defined(__NR_fstatat64) || defined(__NR_newfstatat))
6937#ifdef TARGET_NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006938 case TARGET_NR_fstatat64:
aurel329d33b762009-04-08 23:07:05 +00006939#endif
6940#ifdef TARGET_NR_newfstatat
6941 case TARGET_NR_newfstatat:
6942#endif
balrog6a24a772008-09-20 02:23:36 +00006943 if (!(p = lock_user_string(arg2)))
6944 goto efault;
aurel329d33b762009-04-08 23:07:05 +00006945#ifdef __NR_fstatat64
balrog6a24a772008-09-20 02:23:36 +00006946 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
aurel329d33b762009-04-08 23:07:05 +00006947#else
6948 ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4));
6949#endif
balrog6a24a772008-09-20 02:23:36 +00006950 if (!is_error(ret))
6951 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00006952 break;
bellarda315a142005-01-30 22:59:18 +00006953#endif
bellard67867302003-11-23 17:05:30 +00006954 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00006955 if (!(p = lock_user_string(arg1)))
6956 goto efault;
pbrook53a59602006-03-25 19:31:22 +00006957 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
6958 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00006959 break;
Riku Voipio0c866a72011-04-18 15:23:06 +03006960#ifdef TARGET_NR_getuid
bellard67867302003-11-23 17:05:30 +00006961 case TARGET_NR_getuid:
6962 ret = get_errno(high2lowuid(getuid()));
6963 break;
Riku Voipio0c866a72011-04-18 15:23:06 +03006964#endif
6965#ifdef TARGET_NR_getgid
bellard67867302003-11-23 17:05:30 +00006966 case TARGET_NR_getgid:
6967 ret = get_errno(high2lowgid(getgid()));
6968 break;
Riku Voipio0c866a72011-04-18 15:23:06 +03006969#endif
6970#ifdef TARGET_NR_geteuid
bellard67867302003-11-23 17:05:30 +00006971 case TARGET_NR_geteuid:
6972 ret = get_errno(high2lowuid(geteuid()));
6973 break;
Riku Voipio0c866a72011-04-18 15:23:06 +03006974#endif
6975#ifdef TARGET_NR_getegid
bellard67867302003-11-23 17:05:30 +00006976 case TARGET_NR_getegid:
6977 ret = get_errno(high2lowgid(getegid()));
6978 break;
Riku Voipio0c866a72011-04-18 15:23:06 +03006979#endif
bellard67867302003-11-23 17:05:30 +00006980 case TARGET_NR_setreuid:
6981 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
6982 break;
6983 case TARGET_NR_setregid:
6984 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
6985 break;
6986 case TARGET_NR_getgroups:
6987 {
6988 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +03006989 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +00006990 gid_t *grouplist;
6991 int i;
6992
6993 grouplist = alloca(gidsetsize * sizeof(gid_t));
6994 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00006995 if (gidsetsize == 0)
6996 break;
bellard67867302003-11-23 17:05:30 +00006997 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00006998 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
6999 if (!target_grouplist)
7000 goto efault;
balroga2155fc2008-09-20 02:12:08 +00007001 for(i = 0;i < ret; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +03007002 target_grouplist[i] = tswapid(high2lowgid(grouplist[i]));
pbrook53a59602006-03-25 19:31:22 +00007003 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00007004 }
7005 }
7006 break;
7007 case TARGET_NR_setgroups:
7008 {
7009 int gidsetsize = arg1;
Riku Voipio0c866a72011-04-18 15:23:06 +03007010 target_id *target_grouplist;
bellard67867302003-11-23 17:05:30 +00007011 gid_t *grouplist;
7012 int i;
7013
7014 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00007015 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
7016 if (!target_grouplist) {
7017 ret = -TARGET_EFAULT;
7018 goto fail;
7019 }
bellard67867302003-11-23 17:05:30 +00007020 for(i = 0;i < gidsetsize; i++)
Riku Voipio0c866a72011-04-18 15:23:06 +03007021 grouplist[i] = low2highgid(tswapid(target_grouplist[i]));
pbrook53a59602006-03-25 19:31:22 +00007022 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00007023 ret = get_errno(setgroups(gidsetsize, grouplist));
7024 }
7025 break;
7026 case TARGET_NR_fchown:
7027 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
7028 break;
thsccfa72b2007-09-24 09:23:34 +00007029#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
7030 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00007031 if (!(p = lock_user_string(arg2)))
7032 goto efault;
7033 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
7034 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00007035 break;
7036#endif
bellard67867302003-11-23 17:05:30 +00007037#ifdef TARGET_NR_setresuid
7038 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00007039 ret = get_errno(setresuid(low2highuid(arg1),
7040 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00007041 low2highuid(arg3)));
7042 break;
7043#endif
7044#ifdef TARGET_NR_getresuid
7045 case TARGET_NR_getresuid:
7046 {
pbrook53a59602006-03-25 19:31:22 +00007047 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00007048 ret = get_errno(getresuid(&ruid, &euid, &suid));
7049 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007050 if (put_user_u16(high2lowuid(ruid), arg1)
7051 || put_user_u16(high2lowuid(euid), arg2)
7052 || put_user_u16(high2lowuid(suid), arg3))
7053 goto efault;
bellard67867302003-11-23 17:05:30 +00007054 }
7055 }
7056 break;
7057#endif
7058#ifdef TARGET_NR_getresgid
7059 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00007060 ret = get_errno(setresgid(low2highgid(arg1),
7061 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00007062 low2highgid(arg3)));
7063 break;
7064#endif
7065#ifdef TARGET_NR_getresgid
7066 case TARGET_NR_getresgid:
7067 {
pbrook53a59602006-03-25 19:31:22 +00007068 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00007069 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7070 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007071 if (put_user_u16(high2lowgid(rgid), arg1)
7072 || put_user_u16(high2lowgid(egid), arg2)
7073 || put_user_u16(high2lowgid(sgid), arg3))
7074 goto efault;
bellard67867302003-11-23 17:05:30 +00007075 }
7076 }
7077 break;
7078#endif
7079 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00007080 if (!(p = lock_user_string(arg1)))
7081 goto efault;
pbrook53a59602006-03-25 19:31:22 +00007082 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
7083 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00007084 break;
7085 case TARGET_NR_setuid:
7086 ret = get_errno(setuid(low2highuid(arg1)));
7087 break;
7088 case TARGET_NR_setgid:
7089 ret = get_errno(setgid(low2highgid(arg1)));
7090 break;
7091 case TARGET_NR_setfsuid:
7092 ret = get_errno(setfsuid(arg1));
7093 break;
7094 case TARGET_NR_setfsgid:
7095 ret = get_errno(setfsgid(arg1));
7096 break;
bellard67867302003-11-23 17:05:30 +00007097
bellarda315a142005-01-30 22:59:18 +00007098#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00007099 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00007100 if (!(p = lock_user_string(arg1)))
7101 goto efault;
pbrook53a59602006-03-25 19:31:22 +00007102 ret = get_errno(lchown(p, arg2, arg3));
7103 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00007104 break;
bellarda315a142005-01-30 22:59:18 +00007105#endif
7106#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00007107 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00007108 ret = get_errno(getuid());
7109 break;
bellarda315a142005-01-30 22:59:18 +00007110#endif
aurel3264b4d282008-11-14 17:20:15 +00007111
7112#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
7113 /* Alpha specific */
7114 case TARGET_NR_getxuid:
Richard Hendersonba0e2762009-12-09 15:56:29 -08007115 {
7116 uid_t euid;
7117 euid=geteuid();
7118 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
7119 }
aurel3264b4d282008-11-14 17:20:15 +00007120 ret = get_errno(getuid());
7121 break;
7122#endif
7123#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
7124 /* Alpha specific */
7125 case TARGET_NR_getxgid:
Richard Hendersonba0e2762009-12-09 15:56:29 -08007126 {
7127 uid_t egid;
7128 egid=getegid();
7129 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
7130 }
aurel3264b4d282008-11-14 17:20:15 +00007131 ret = get_errno(getgid());
7132 break;
7133#endif
Richard Hendersonba0e2762009-12-09 15:56:29 -08007134#if defined(TARGET_NR_osf_getsysinfo) && defined(TARGET_ALPHA)
7135 /* Alpha specific */
7136 case TARGET_NR_osf_getsysinfo:
7137 ret = -TARGET_EOPNOTSUPP;
7138 switch (arg1) {
7139 case TARGET_GSI_IEEE_FP_CONTROL:
7140 {
7141 uint64_t swcr, fpcr = cpu_alpha_load_fpcr (cpu_env);
7142
7143 /* Copied from linux ieee_fpcr_to_swcr. */
7144 swcr = (fpcr >> 35) & SWCR_STATUS_MASK;
7145 swcr |= (fpcr >> 36) & SWCR_MAP_DMZ;
7146 swcr |= (~fpcr >> 48) & (SWCR_TRAP_ENABLE_INV
7147 | SWCR_TRAP_ENABLE_DZE
7148 | SWCR_TRAP_ENABLE_OVF);
7149 swcr |= (~fpcr >> 57) & (SWCR_TRAP_ENABLE_UNF
7150 | SWCR_TRAP_ENABLE_INE);
7151 swcr |= (fpcr >> 47) & SWCR_MAP_UMZ;
7152 swcr |= (~fpcr >> 41) & SWCR_TRAP_ENABLE_DNO;
7153
7154 if (put_user_u64 (swcr, arg2))
7155 goto efault;
7156 ret = 0;
7157 }
7158 break;
7159
7160 /* case GSI_IEEE_STATE_AT_SIGNAL:
7161 -- Not implemented in linux kernel.
7162 case GSI_UACPROC:
7163 -- Retrieves current unaligned access state; not much used.
7164 case GSI_PROC_TYPE:
7165 -- Retrieves implver information; surely not used.
7166 case GSI_GET_HWRPB:
7167 -- Grabs a copy of the HWRPB; surely not used.
7168 */
7169 }
7170 break;
7171#endif
7172#if defined(TARGET_NR_osf_setsysinfo) && defined(TARGET_ALPHA)
7173 /* Alpha specific */
7174 case TARGET_NR_osf_setsysinfo:
7175 ret = -TARGET_EOPNOTSUPP;
7176 switch (arg1) {
7177 case TARGET_SSI_IEEE_FP_CONTROL:
7178 case TARGET_SSI_IEEE_RAISE_EXCEPTION:
7179 {
7180 uint64_t swcr, fpcr, orig_fpcr;
7181
7182 if (get_user_u64 (swcr, arg2))
7183 goto efault;
7184 orig_fpcr = cpu_alpha_load_fpcr (cpu_env);
7185 fpcr = orig_fpcr & FPCR_DYN_MASK;
7186
7187 /* Copied from linux ieee_swcr_to_fpcr. */
7188 fpcr |= (swcr & SWCR_STATUS_MASK) << 35;
7189 fpcr |= (swcr & SWCR_MAP_DMZ) << 36;
7190 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_INV
7191 | SWCR_TRAP_ENABLE_DZE
7192 | SWCR_TRAP_ENABLE_OVF)) << 48;
7193 fpcr |= (~swcr & (SWCR_TRAP_ENABLE_UNF
7194 | SWCR_TRAP_ENABLE_INE)) << 57;
7195 fpcr |= (swcr & SWCR_MAP_UMZ ? FPCR_UNDZ | FPCR_UNFD : 0);
7196 fpcr |= (~swcr & SWCR_TRAP_ENABLE_DNO) << 41;
7197
7198 cpu_alpha_store_fpcr (cpu_env, fpcr);
7199 ret = 0;
7200
7201 if (arg1 == TARGET_SSI_IEEE_RAISE_EXCEPTION) {
7202 /* Old exceptions are not signaled. */
7203 fpcr &= ~(orig_fpcr & FPCR_STATUS_MASK);
7204
7205 /* If any exceptions set by this call, and are unmasked,
7206 send a signal. */
7207 /* ??? FIXME */
7208 }
7209 }
7210 break;
7211
7212 /* case SSI_NVPAIRS:
7213 -- Used with SSIN_UACPROC to enable unaligned accesses.
7214 case SSI_IEEE_STATE_AT_SIGNAL:
7215 case SSI_IEEE_IGNORE_STATE_AT_SIGNAL:
7216 -- Not implemented in linux kernel
7217 */
7218 }
7219 break;
7220#endif
7221#ifdef TARGET_NR_osf_sigprocmask
7222 /* Alpha specific. */
7223 case TARGET_NR_osf_sigprocmask:
7224 {
7225 abi_ulong mask;
Juan Quintelabc088ba2011-06-16 17:37:10 +01007226 int how;
Richard Hendersonba0e2762009-12-09 15:56:29 -08007227 sigset_t set, oldset;
7228
7229 switch(arg1) {
7230 case TARGET_SIG_BLOCK:
7231 how = SIG_BLOCK;
7232 break;
7233 case TARGET_SIG_UNBLOCK:
7234 how = SIG_UNBLOCK;
7235 break;
7236 case TARGET_SIG_SETMASK:
7237 how = SIG_SETMASK;
7238 break;
7239 default:
7240 ret = -TARGET_EINVAL;
7241 goto fail;
7242 }
7243 mask = arg2;
7244 target_to_host_old_sigset(&set, &mask);
Juan Quintelabc088ba2011-06-16 17:37:10 +01007245 sigprocmask(how, &set, &oldset);
Richard Hendersonba0e2762009-12-09 15:56:29 -08007246 host_to_target_old_sigset(&mask, &oldset);
7247 ret = mask;
7248 }
7249 break;
7250#endif
aurel3264b4d282008-11-14 17:20:15 +00007251
bellarda315a142005-01-30 22:59:18 +00007252#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00007253 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00007254 ret = get_errno(getgid());
7255 break;
bellarda315a142005-01-30 22:59:18 +00007256#endif
7257#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00007258 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00007259 ret = get_errno(geteuid());
7260 break;
bellarda315a142005-01-30 22:59:18 +00007261#endif
7262#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00007263 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00007264 ret = get_errno(getegid());
7265 break;
bellarda315a142005-01-30 22:59:18 +00007266#endif
7267#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00007268 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00007269 ret = get_errno(setreuid(arg1, arg2));
7270 break;
bellarda315a142005-01-30 22:59:18 +00007271#endif
7272#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00007273 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00007274 ret = get_errno(setregid(arg1, arg2));
7275 break;
bellarda315a142005-01-30 22:59:18 +00007276#endif
7277#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00007278 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00007279 {
7280 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00007281 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00007282 gid_t *grouplist;
7283 int i;
7284
7285 grouplist = alloca(gidsetsize * sizeof(gid_t));
7286 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00007287 if (gidsetsize == 0)
7288 break;
bellard99c475a2005-01-31 20:45:13 +00007289 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00007290 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
7291 if (!target_grouplist) {
7292 ret = -TARGET_EFAULT;
7293 goto fail;
7294 }
balroga2155fc2008-09-20 02:12:08 +00007295 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00007296 target_grouplist[i] = tswap32(grouplist[i]);
7297 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00007298 }
7299 }
7300 break;
bellarda315a142005-01-30 22:59:18 +00007301#endif
7302#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00007303 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00007304 {
7305 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00007306 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00007307 gid_t *grouplist;
7308 int i;
ths3b46e622007-09-17 08:09:54 +00007309
bellard99c475a2005-01-31 20:45:13 +00007310 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00007311 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
7312 if (!target_grouplist) {
7313 ret = -TARGET_EFAULT;
7314 goto fail;
7315 }
bellard99c475a2005-01-31 20:45:13 +00007316 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00007317 grouplist[i] = tswap32(target_grouplist[i]);
7318 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00007319 ret = get_errno(setgroups(gidsetsize, grouplist));
7320 }
7321 break;
bellarda315a142005-01-30 22:59:18 +00007322#endif
7323#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00007324 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00007325 ret = get_errno(fchown(arg1, arg2, arg3));
7326 break;
bellarda315a142005-01-30 22:59:18 +00007327#endif
7328#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00007329 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00007330 ret = get_errno(setresuid(arg1, arg2, arg3));
7331 break;
bellarda315a142005-01-30 22:59:18 +00007332#endif
7333#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00007334 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00007335 {
pbrook53a59602006-03-25 19:31:22 +00007336 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00007337 ret = get_errno(getresuid(&ruid, &euid, &suid));
7338 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007339 if (put_user_u32(ruid, arg1)
7340 || put_user_u32(euid, arg2)
7341 || put_user_u32(suid, arg3))
7342 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00007343 }
7344 }
7345 break;
bellarda315a142005-01-30 22:59:18 +00007346#endif
7347#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00007348 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00007349 ret = get_errno(setresgid(arg1, arg2, arg3));
7350 break;
bellarda315a142005-01-30 22:59:18 +00007351#endif
7352#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00007353 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00007354 {
pbrook53a59602006-03-25 19:31:22 +00007355 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00007356 ret = get_errno(getresgid(&rgid, &egid, &sgid));
7357 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00007358 if (put_user_u32(rgid, arg1)
7359 || put_user_u32(egid, arg2)
7360 || put_user_u32(sgid, arg3))
7361 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00007362 }
7363 }
7364 break;
bellarda315a142005-01-30 22:59:18 +00007365#endif
7366#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00007367 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00007368 if (!(p = lock_user_string(arg1)))
7369 goto efault;
pbrook53a59602006-03-25 19:31:22 +00007370 ret = get_errno(chown(p, arg2, arg3));
7371 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00007372 break;
bellarda315a142005-01-30 22:59:18 +00007373#endif
7374#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00007375 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00007376 ret = get_errno(setuid(arg1));
7377 break;
bellarda315a142005-01-30 22:59:18 +00007378#endif
7379#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00007380 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00007381 ret = get_errno(setgid(arg1));
7382 break;
bellarda315a142005-01-30 22:59:18 +00007383#endif
7384#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00007385 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00007386 ret = get_errno(setfsuid(arg1));
7387 break;
bellarda315a142005-01-30 22:59:18 +00007388#endif
7389#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00007390 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00007391 ret = get_errno(setfsgid(arg1));
7392 break;
bellarda315a142005-01-30 22:59:18 +00007393#endif
bellard67867302003-11-23 17:05:30 +00007394
bellard31e31b82003-02-18 22:55:36 +00007395 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00007396 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00007397#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00007398 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00007399 {
7400 void *a;
7401 ret = -TARGET_EFAULT;
7402 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
7403 goto efault;
7404 if (!(p = lock_user_string(arg3)))
7405 goto mincore_fail;
7406 ret = get_errno(mincore(a, arg2, p));
7407 unlock_user(p, arg3, ret);
7408 mincore_fail:
7409 unlock_user(a, arg1, 0);
7410 }
7411 break;
bellardffa65c32004-01-04 23:57:22 +00007412#endif
aurel32408321b2008-10-01 21:46:32 +00007413#ifdef TARGET_NR_arm_fadvise64_64
7414 case TARGET_NR_arm_fadvise64_64:
7415 {
7416 /*
7417 * arm_fadvise64_64 looks like fadvise64_64 but
7418 * with different argument order
7419 */
7420 abi_long temp;
7421 temp = arg3;
7422 arg3 = arg4;
7423 arg4 = temp;
7424 }
7425#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +02007426#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64) || defined(TARGET_NR_fadvise64)
aurel32408321b2008-10-01 21:46:32 +00007427#ifdef TARGET_NR_fadvise64_64
7428 case TARGET_NR_fadvise64_64:
7429#endif
Ulrich Hechte72d2cc2009-07-24 19:10:31 +02007430#ifdef TARGET_NR_fadvise64
7431 case TARGET_NR_fadvise64:
7432#endif
7433#ifdef TARGET_S390X
7434 switch (arg4) {
7435 case 4: arg4 = POSIX_FADV_NOREUSE + 1; break; /* make sure it's an invalid value */
7436 case 5: arg4 = POSIX_FADV_NOREUSE + 2; break; /* ditto */
7437 case 6: arg4 = POSIX_FADV_DONTNEED; break;
7438 case 7: arg4 = POSIX_FADV_NOREUSE; break;
7439 default: break;
7440 }
7441#endif
7442 ret = -posix_fadvise(arg1, arg2, arg3, arg4);
aurel32408321b2008-10-01 21:46:32 +00007443 break;
7444#endif
bellardffa65c32004-01-04 23:57:22 +00007445#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00007446 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00007447 /* A straight passthrough may not be safe because qemu sometimes
7448 turns private flie-backed mappings into anonymous mappings.
7449 This will break MADV_DONTNEED.
7450 This is a hint, so ignoring and returning success is ok. */
7451 ret = get_errno(0);
7452 break;
bellardffa65c32004-01-04 23:57:22 +00007453#endif
blueswir1992f48a2007-10-14 16:27:31 +00007454#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00007455 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00007456 {
thsb1e341e2007-03-20 21:50:52 +00007457 int cmd;
bellard77e46722003-04-29 20:39:06 +00007458 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00007459 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00007460#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00007461 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00007462#endif
bellard77e46722003-04-29 20:39:06 +00007463
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007464 cmd = target_to_host_fcntl_cmd(arg2);
7465 if (cmd == -TARGET_EINVAL)
7466 return cmd;
thsb1e341e2007-03-20 21:50:52 +00007467
bellard60cd49d2003-03-16 22:53:56 +00007468 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00007469 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00007470#ifdef TARGET_ARM
7471 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007472 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7473 goto efault;
ths58134272007-03-31 18:59:32 +00007474 fl.l_type = tswap16(target_efl->l_type);
7475 fl.l_whence = tswap16(target_efl->l_whence);
7476 fl.l_start = tswap64(target_efl->l_start);
7477 fl.l_len = tswap64(target_efl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007478 fl.l_pid = tswap32(target_efl->l_pid);
ths58134272007-03-31 18:59:32 +00007479 unlock_user_struct(target_efl, arg3, 0);
7480 } else
7481#endif
7482 {
bellard9ee1fa22007-11-11 15:11:19 +00007483 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7484 goto efault;
ths58134272007-03-31 18:59:32 +00007485 fl.l_type = tswap16(target_fl->l_type);
7486 fl.l_whence = tswap16(target_fl->l_whence);
7487 fl.l_start = tswap64(target_fl->l_start);
7488 fl.l_len = tswap64(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007489 fl.l_pid = tswap32(target_fl->l_pid);
ths58134272007-03-31 18:59:32 +00007490 unlock_user_struct(target_fl, arg3, 0);
7491 }
thsb1e341e2007-03-20 21:50:52 +00007492 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00007493 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00007494#ifdef TARGET_ARM
7495 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007496 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
7497 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007498 target_efl->l_type = tswap16(fl.l_type);
7499 target_efl->l_whence = tswap16(fl.l_whence);
7500 target_efl->l_start = tswap64(fl.l_start);
7501 target_efl->l_len = tswap64(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007502 target_efl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00007503 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00007504 } else
7505#endif
7506 {
bellard9ee1fa22007-11-11 15:11:19 +00007507 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
7508 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007509 target_fl->l_type = tswap16(fl.l_type);
7510 target_fl->l_whence = tswap16(fl.l_whence);
7511 target_fl->l_start = tswap64(fl.l_start);
7512 target_fl->l_len = tswap64(fl.l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007513 target_fl->l_pid = tswap32(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00007514 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00007515 }
bellard77e46722003-04-29 20:39:06 +00007516 }
7517 break;
7518
thsb1e341e2007-03-20 21:50:52 +00007519 case TARGET_F_SETLK64:
7520 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00007521#ifdef TARGET_ARM
7522 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00007523 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
7524 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007525 fl.l_type = tswap16(target_efl->l_type);
7526 fl.l_whence = tswap16(target_efl->l_whence);
7527 fl.l_start = tswap64(target_efl->l_start);
7528 fl.l_len = tswap64(target_efl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007529 fl.l_pid = tswap32(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00007530 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00007531 } else
7532#endif
7533 {
bellard9ee1fa22007-11-11 15:11:19 +00007534 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
7535 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00007536 fl.l_type = tswap16(target_fl->l_type);
7537 fl.l_whence = tswap16(target_fl->l_whence);
7538 fl.l_start = tswap64(target_fl->l_start);
7539 fl.l_len = tswap64(target_fl->l_len);
Ulrich Hecht7e22e542009-07-24 19:10:27 +02007540 fl.l_pid = tswap32(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00007541 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00007542 }
thsb1e341e2007-03-20 21:50:52 +00007543 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00007544 break;
bellard60cd49d2003-03-16 22:53:56 +00007545 default:
Arnaud Patard (Rtp)5f106812009-06-03 14:35:04 +02007546 ret = do_fcntl(arg1, arg2, arg3);
bellard60cd49d2003-03-16 22:53:56 +00007547 break;
7548 }
bellard77e46722003-04-29 20:39:06 +00007549 break;
7550 }
bellard60cd49d2003-03-16 22:53:56 +00007551#endif
ths7d600c82006-12-08 01:32:58 +00007552#ifdef TARGET_NR_cacheflush
7553 case TARGET_NR_cacheflush:
7554 /* self-modifying code is handled automatically, so nothing needed */
7555 ret = 0;
7556 break;
7557#endif
bellardebc05482003-09-30 21:08:41 +00007558#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00007559 case TARGET_NR_security:
7560 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00007561#endif
bellardc573ff62004-01-04 15:51:36 +00007562#ifdef TARGET_NR_getpagesize
7563 case TARGET_NR_getpagesize:
7564 ret = TARGET_PAGE_SIZE;
7565 break;
7566#endif
bellard31e31b82003-02-18 22:55:36 +00007567 case TARGET_NR_gettid:
7568 ret = get_errno(gettid());
7569 break;
thse5febef2007-04-01 18:31:35 +00007570#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00007571 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00007572#if TARGET_ABI_BITS == 32
7573#ifdef TARGET_ARM
7574 if (((CPUARMState *)cpu_env)->eabi)
7575 {
7576 arg2 = arg3;
7577 arg3 = arg4;
7578 arg4 = arg5;
7579 }
7580#endif
7581 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
7582#else
7583 ret = get_errno(readahead(arg1, arg2, arg3));
7584#endif
7585 break;
thse5febef2007-04-01 18:31:35 +00007586#endif
bellardebc05482003-09-30 21:08:41 +00007587#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00007588 case TARGET_NR_setxattr:
7589 case TARGET_NR_lsetxattr:
7590 case TARGET_NR_fsetxattr:
7591 case TARGET_NR_getxattr:
7592 case TARGET_NR_lgetxattr:
7593 case TARGET_NR_fgetxattr:
7594 case TARGET_NR_listxattr:
7595 case TARGET_NR_llistxattr:
7596 case TARGET_NR_flistxattr:
7597 case TARGET_NR_removexattr:
7598 case TARGET_NR_lremovexattr:
7599 case TARGET_NR_fremovexattr:
Arnaud Patard6f932f92009-04-21 21:04:18 +03007600 ret = -TARGET_EOPNOTSUPP;
7601 break;
bellardebc05482003-09-30 21:08:41 +00007602#endif
7603#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00007604 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00007605#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00007606 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
7607 ret = 0;
7608 break;
edgar_iglef967792009-01-07 14:19:38 +00007609#elif defined(TARGET_CRIS)
7610 if (arg1 & 0xff)
7611 ret = -TARGET_EINVAL;
7612 else {
7613 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
7614 ret = 0;
7615 }
7616 break;
bellard8d18e892007-11-14 15:18:40 +00007617#elif defined(TARGET_I386) && defined(TARGET_ABI32)
7618 ret = do_set_thread_area(cpu_env, arg1);
7619 break;
ths6f5b89a2007-03-02 20:48:00 +00007620#else
7621 goto unimplemented_nowarn;
7622#endif
7623#endif
7624#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00007625 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00007626#if defined(TARGET_I386) && defined(TARGET_ABI32)
7627 ret = do_get_thread_area(cpu_env, arg1);
7628#else
bellard5cd43932003-03-29 16:54:36 +00007629 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00007630#endif
bellard8d18e892007-11-14 15:18:40 +00007631#endif
bellard48dc41e2006-06-21 18:15:50 +00007632#ifdef TARGET_NR_getdomainname
7633 case TARGET_NR_getdomainname:
7634 goto unimplemented_nowarn;
7635#endif
ths6f5b89a2007-03-02 20:48:00 +00007636
thsb5906f92007-03-19 13:32:45 +00007637#ifdef TARGET_NR_clock_gettime
7638 case TARGET_NR_clock_gettime:
7639 {
7640 struct timespec ts;
7641 ret = get_errno(clock_gettime(arg1, &ts));
7642 if (!is_error(ret)) {
7643 host_to_target_timespec(arg2, &ts);
7644 }
7645 break;
7646 }
7647#endif
7648#ifdef TARGET_NR_clock_getres
7649 case TARGET_NR_clock_getres:
7650 {
7651 struct timespec ts;
7652 ret = get_errno(clock_getres(arg1, &ts));
7653 if (!is_error(ret)) {
7654 host_to_target_timespec(arg2, &ts);
7655 }
7656 break;
7657 }
7658#endif
pbrook63d76512008-05-29 13:43:29 +00007659#ifdef TARGET_NR_clock_nanosleep
7660 case TARGET_NR_clock_nanosleep:
7661 {
7662 struct timespec ts;
7663 target_to_host_timespec(&ts, arg3);
7664 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
7665 if (arg4)
7666 host_to_target_timespec(arg4, &ts);
7667 break;
7668 }
7669#endif
thsb5906f92007-03-19 13:32:45 +00007670
ths6f5b89a2007-03-02 20:48:00 +00007671#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
7672 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00007673 ret = get_errno(set_tid_address((int *)g2h(arg1)));
7674 break;
ths6f5b89a2007-03-02 20:48:00 +00007675#endif
7676
ths3ae43202007-09-16 21:39:48 +00007677#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00007678 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00007679 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00007680 break;
7681#endif
7682
ths3ae43202007-09-16 21:39:48 +00007683#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00007684 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00007685 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
7686 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00007687 break;
7688#endif
7689
ths4f2b1fe2007-06-21 21:57:12 +00007690#ifdef TARGET_NR_set_robust_list
7691 case TARGET_NR_set_robust_list:
7692 goto unimplemented_nowarn;
7693#endif
7694
ths9007f0e2007-09-25 17:50:37 +00007695#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
7696 case TARGET_NR_utimensat:
7697 {
Riku Voipioebc996f2009-04-21 15:01:51 +03007698 struct timespec *tsp, ts[2];
7699 if (!arg3) {
7700 tsp = NULL;
7701 } else {
7702 target_to_host_timespec(ts, arg3);
7703 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
7704 tsp = ts;
7705 }
ths9007f0e2007-09-25 17:50:37 +00007706 if (!arg2)
Riku Voipioebc996f2009-04-21 15:01:51 +03007707 ret = get_errno(sys_utimensat(arg1, NULL, tsp, arg4));
ths9007f0e2007-09-25 17:50:37 +00007708 else {
bellard579a97f2007-11-11 14:26:47 +00007709 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00007710 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00007711 goto fail;
7712 }
Riku Voipioebc996f2009-04-21 15:01:51 +03007713 ret = get_errno(sys_utimensat(arg1, path(p), tsp, arg4));
bellard579a97f2007-11-11 14:26:47 +00007714 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00007715 }
7716 }
7717 break;
7718#endif
Juan Quintela2f7bb872009-07-27 16:13:24 +02007719#if defined(CONFIG_USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +00007720 case TARGET_NR_futex:
7721 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
7722 break;
7723#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007724#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
aurel3239b59762008-10-01 21:46:50 +00007725 case TARGET_NR_inotify_init:
7726 ret = get_errno(sys_inotify_init());
7727 break;
7728#endif
Stefan Weila1606b02010-03-28 11:44:41 +02007729#ifdef CONFIG_INOTIFY1
Riku Voipioc05c7a72010-03-26 15:25:11 +00007730#if defined(TARGET_NR_inotify_init1) && defined(__NR_inotify_init1)
7731 case TARGET_NR_inotify_init1:
7732 ret = get_errno(sys_inotify_init1(arg1));
7733 break;
7734#endif
Stefan Weila1606b02010-03-28 11:44:41 +02007735#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007736#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
aurel3239b59762008-10-01 21:46:50 +00007737 case TARGET_NR_inotify_add_watch:
7738 p = lock_user_string(arg2);
7739 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
7740 unlock_user(p, arg2, 0);
7741 break;
7742#endif
aurel32dbfe4c32009-04-08 21:29:30 +00007743#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
aurel3239b59762008-10-01 21:46:50 +00007744 case TARGET_NR_inotify_rm_watch:
7745 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
7746 break;
7747#endif
ths9007f0e2007-09-25 17:50:37 +00007748
Nathan Froyd8ec9cf82009-07-22 09:14:36 -07007749#if defined(TARGET_NR_mq_open) && defined(__NR_mq_open)
aurel3224e10032009-04-15 16:11:43 +00007750 case TARGET_NR_mq_open:
7751 {
7752 struct mq_attr posix_mq_attr;
7753
7754 p = lock_user_string(arg1 - 1);
7755 if (arg4 != 0)
7756 copy_from_user_mq_attr (&posix_mq_attr, arg4);
7757 ret = get_errno(mq_open(p, arg2, arg3, &posix_mq_attr));
7758 unlock_user (p, arg1, 0);
7759 }
7760 break;
7761
7762 case TARGET_NR_mq_unlink:
7763 p = lock_user_string(arg1 - 1);
7764 ret = get_errno(mq_unlink(p));
7765 unlock_user (p, arg1, 0);
7766 break;
7767
7768 case TARGET_NR_mq_timedsend:
7769 {
7770 struct timespec ts;
7771
7772 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7773 if (arg5 != 0) {
7774 target_to_host_timespec(&ts, arg5);
7775 ret = get_errno(mq_timedsend(arg1, p, arg3, arg4, &ts));
7776 host_to_target_timespec(arg5, &ts);
7777 }
7778 else
7779 ret = get_errno(mq_send(arg1, p, arg3, arg4));
7780 unlock_user (p, arg2, arg3);
7781 }
7782 break;
7783
7784 case TARGET_NR_mq_timedreceive:
7785 {
7786 struct timespec ts;
7787 unsigned int prio;
7788
7789 p = lock_user (VERIFY_READ, arg2, arg3, 1);
7790 if (arg5 != 0) {
7791 target_to_host_timespec(&ts, arg5);
7792 ret = get_errno(mq_timedreceive(arg1, p, arg3, &prio, &ts));
7793 host_to_target_timespec(arg5, &ts);
7794 }
7795 else
7796 ret = get_errno(mq_receive(arg1, p, arg3, &prio));
7797 unlock_user (p, arg2, arg3);
7798 if (arg4 != 0)
7799 put_user_u32(prio, arg4);
7800 }
7801 break;
7802
7803 /* Not implemented for now... */
7804/* case TARGET_NR_mq_notify: */
7805/* break; */
7806
7807 case TARGET_NR_mq_getsetattr:
7808 {
7809 struct mq_attr posix_mq_attr_in, posix_mq_attr_out;
7810 ret = 0;
7811 if (arg3 != 0) {
7812 ret = mq_getattr(arg1, &posix_mq_attr_out);
7813 copy_to_user_mq_attr(arg3, &posix_mq_attr_out);
7814 }
7815 if (arg2 != 0) {
7816 copy_from_user_mq_attr(&posix_mq_attr_in, arg2);
7817 ret |= mq_setattr(arg1, &posix_mq_attr_in, &posix_mq_attr_out);
7818 }
7819
7820 }
7821 break;
7822#endif
7823
vibisreenivasan3ce34df2009-05-16 18:32:41 +05307824#ifdef CONFIG_SPLICE
7825#ifdef TARGET_NR_tee
7826 case TARGET_NR_tee:
7827 {
7828 ret = get_errno(tee(arg1,arg2,arg3,arg4));
7829 }
7830 break;
7831#endif
7832#ifdef TARGET_NR_splice
7833 case TARGET_NR_splice:
7834 {
7835 loff_t loff_in, loff_out;
7836 loff_t *ploff_in = NULL, *ploff_out = NULL;
7837 if(arg2) {
7838 get_user_u64(loff_in, arg2);
7839 ploff_in = &loff_in;
7840 }
7841 if(arg4) {
7842 get_user_u64(loff_out, arg2);
7843 ploff_out = &loff_out;
7844 }
7845 ret = get_errno(splice(arg1, ploff_in, arg3, ploff_out, arg5, arg6));
7846 }
7847 break;
7848#endif
7849#ifdef TARGET_NR_vmsplice
7850 case TARGET_NR_vmsplice:
7851 {
7852 int count = arg3;
7853 struct iovec *vec;
7854
7855 vec = alloca(count * sizeof(struct iovec));
7856 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
7857 goto efault;
7858 ret = get_errno(vmsplice(arg1, vec, count, arg4));
7859 unlock_iovec(vec, arg2, count, 0);
7860 }
7861 break;
7862#endif
7863#endif /* CONFIG_SPLICE */
Riku Voipioc2882b92009-08-12 15:08:24 +03007864#ifdef CONFIG_EVENTFD
7865#if defined(TARGET_NR_eventfd)
7866 case TARGET_NR_eventfd:
7867 ret = get_errno(eventfd(arg1, 0));
7868 break;
7869#endif
7870#if defined(TARGET_NR_eventfd2)
7871 case TARGET_NR_eventfd2:
7872 ret = get_errno(eventfd(arg1, arg2));
7873 break;
7874#endif
7875#endif /* CONFIG_EVENTFD */
Ulrich Hechtd0927932009-09-17 20:22:14 +03007876#if defined(CONFIG_FALLOCATE) && defined(TARGET_NR_fallocate)
7877 case TARGET_NR_fallocate:
7878 ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
7879 break;
7880#endif
Peter Maydellc727f472011-01-06 11:05:10 +00007881#if defined(CONFIG_SYNC_FILE_RANGE)
7882#if defined(TARGET_NR_sync_file_range)
7883 case TARGET_NR_sync_file_range:
7884#if TARGET_ABI_BITS == 32
Riku Voipiobfcedc52011-06-20 16:24:39 +03007885#if defined(TARGET_MIPS)
7886 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
7887 target_offset64(arg5, arg6), arg7));
7888#else
Peter Maydellc727f472011-01-06 11:05:10 +00007889 ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
7890 target_offset64(arg4, arg5), arg6));
Riku Voipiobfcedc52011-06-20 16:24:39 +03007891#endif /* !TARGET_MIPS */
Peter Maydellc727f472011-01-06 11:05:10 +00007892#else
7893 ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
7894#endif
7895 break;
7896#endif
7897#if defined(TARGET_NR_sync_file_range2)
7898 case TARGET_NR_sync_file_range2:
7899 /* This is like sync_file_range but the arguments are reordered */
7900#if TARGET_ABI_BITS == 32
7901 ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
7902 target_offset64(arg5, arg6), arg2));
7903#else
7904 ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
7905#endif
7906 break;
7907#endif
7908#endif
Peter Maydell3b6edd12011-02-15 18:35:05 +00007909#if defined(CONFIG_EPOLL)
7910#if defined(TARGET_NR_epoll_create)
7911 case TARGET_NR_epoll_create:
7912 ret = get_errno(epoll_create(arg1));
7913 break;
7914#endif
7915#if defined(TARGET_NR_epoll_create1) && defined(CONFIG_EPOLL_CREATE1)
7916 case TARGET_NR_epoll_create1:
7917 ret = get_errno(epoll_create1(arg1));
7918 break;
7919#endif
7920#if defined(TARGET_NR_epoll_ctl)
7921 case TARGET_NR_epoll_ctl:
7922 {
7923 struct epoll_event ep;
7924 struct epoll_event *epp = 0;
7925 if (arg4) {
7926 struct target_epoll_event *target_ep;
7927 if (!lock_user_struct(VERIFY_READ, target_ep, arg4, 1)) {
7928 goto efault;
7929 }
7930 ep.events = tswap32(target_ep->events);
7931 /* The epoll_data_t union is just opaque data to the kernel,
7932 * so we transfer all 64 bits across and need not worry what
7933 * actual data type it is.
7934 */
7935 ep.data.u64 = tswap64(target_ep->data.u64);
7936 unlock_user_struct(target_ep, arg4, 0);
7937 epp = &ep;
7938 }
7939 ret = get_errno(epoll_ctl(arg1, arg2, arg3, epp));
7940 break;
7941 }
7942#endif
7943
7944#if defined(TARGET_NR_epoll_pwait) && defined(CONFIG_EPOLL_PWAIT)
7945#define IMPLEMENT_EPOLL_PWAIT
7946#endif
7947#if defined(TARGET_NR_epoll_wait) || defined(IMPLEMENT_EPOLL_PWAIT)
7948#if defined(TARGET_NR_epoll_wait)
7949 case TARGET_NR_epoll_wait:
7950#endif
7951#if defined(IMPLEMENT_EPOLL_PWAIT)
7952 case TARGET_NR_epoll_pwait:
7953#endif
7954 {
7955 struct target_epoll_event *target_ep;
7956 struct epoll_event *ep;
7957 int epfd = arg1;
7958 int maxevents = arg3;
7959 int timeout = arg4;
7960
7961 target_ep = lock_user(VERIFY_WRITE, arg2,
7962 maxevents * sizeof(struct target_epoll_event), 1);
7963 if (!target_ep) {
7964 goto efault;
7965 }
7966
7967 ep = alloca(maxevents * sizeof(struct epoll_event));
7968
7969 switch (num) {
7970#if defined(IMPLEMENT_EPOLL_PWAIT)
7971 case TARGET_NR_epoll_pwait:
7972 {
7973 target_sigset_t *target_set;
7974 sigset_t _set, *set = &_set;
7975
7976 if (arg5) {
7977 target_set = lock_user(VERIFY_READ, arg5,
7978 sizeof(target_sigset_t), 1);
7979 if (!target_set) {
7980 unlock_user(target_ep, arg2, 0);
7981 goto efault;
7982 }
7983 target_to_host_sigset(set, target_set);
7984 unlock_user(target_set, arg5, 0);
7985 } else {
7986 set = NULL;
7987 }
7988
7989 ret = get_errno(epoll_pwait(epfd, ep, maxevents, timeout, set));
7990 break;
7991 }
7992#endif
7993#if defined(TARGET_NR_epoll_wait)
7994 case TARGET_NR_epoll_wait:
7995 ret = get_errno(epoll_wait(epfd, ep, maxevents, timeout));
7996 break;
7997#endif
7998 default:
7999 ret = -TARGET_ENOSYS;
8000 }
8001 if (!is_error(ret)) {
8002 int i;
8003 for (i = 0; i < ret; i++) {
8004 target_ep[i].events = tswap32(ep[i].events);
8005 target_ep[i].data.u64 = tswap64(ep[i].data.u64);
8006 }
8007 }
8008 unlock_user(target_ep, arg2, ret * sizeof(struct target_epoll_event));
8009 break;
8010 }
8011#endif
8012#endif
Peter Maydell163a05a2011-06-27 17:44:52 +01008013#ifdef TARGET_NR_prlimit64
8014 case TARGET_NR_prlimit64:
8015 {
8016 /* args: pid, resource number, ptr to new rlimit, ptr to old rlimit */
8017 struct target_rlimit64 *target_rnew, *target_rold;
8018 struct host_rlimit64 rnew, rold, *rnewp = 0;
8019 if (arg3) {
8020 if (!lock_user_struct(VERIFY_READ, target_rnew, arg3, 1)) {
8021 goto efault;
8022 }
8023 rnew.rlim_cur = tswap64(target_rnew->rlim_cur);
8024 rnew.rlim_max = tswap64(target_rnew->rlim_max);
8025 unlock_user_struct(target_rnew, arg3, 0);
8026 rnewp = &rnew;
8027 }
8028
8029 ret = get_errno(sys_prlimit64(arg1, arg2, rnewp, arg4 ? &rold : 0));
8030 if (!is_error(ret) && arg4) {
8031 if (!lock_user_struct(VERIFY_WRITE, target_rold, arg4, 1)) {
8032 goto efault;
8033 }
8034 target_rold->rlim_cur = tswap64(rold.rlim_cur);
8035 target_rold->rlim_max = tswap64(rold.rlim_max);
8036 unlock_user_struct(target_rold, arg4, 1);
8037 }
8038 break;
8039 }
8040#endif
bellard31e31b82003-02-18 22:55:36 +00008041 default:
8042 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00008043 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00008044#if defined(TARGET_NR_setxattr) || defined(TARGET_NR_get_thread_area) || defined(TARGET_NR_getdomainname) || defined(TARGET_NR_set_robust_list)
bellard5cd43932003-03-29 16:54:36 +00008045 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00008046#endif
ths0da46a62007-10-20 20:23:07 +00008047 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00008048 break;
8049 }
bellard579a97f2007-11-11 14:26:47 +00008050fail:
bellardc573ff62004-01-04 15:51:36 +00008051#ifdef DEBUG
Blue Swirl0bf9e312009-07-20 17:19:25 +00008052 gemu_log(" = " TARGET_ABI_FMT_ld "\n", ret);
bellardc573ff62004-01-04 15:51:36 +00008053#endif
thsb92c47c2007-11-01 00:07:38 +00008054 if(do_strace)
8055 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00008056 return ret;
bellard579a97f2007-11-11 14:26:47 +00008057efault:
8058 ret = -TARGET_EFAULT;
8059 goto fail;
bellard31e31b82003-02-18 22:55:36 +00008060}