blob: 5d787bb7530ef4c2b8c0d8ea4dd29ebad102c481 [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
17 * along with this program; if not, write to the Free Software
blueswir1530e7612009-01-05 18:11:53 +000018 * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 * MA 02110-1301, USA.
bellard31e31b82003-02-18 22:55:36 +000020 */
21#include <stdlib.h>
22#include <stdio.h>
23#include <stdarg.h>
bellard04369ff2003-03-20 22:33:23 +000024#include <string.h>
bellard31e31b82003-02-18 22:55:36 +000025#include <elf.h>
26#include <endian.h>
27#include <errno.h>
28#include <unistd.h>
29#include <fcntl.h>
bellard7854b052003-03-29 17:22:23 +000030#include <time.h>
pbrook82e671d2008-06-09 12:10:22 +000031#include <limits.h>
bellard31e31b82003-02-18 22:55:36 +000032#include <sys/types.h>
thsd08d3bb2007-03-19 13:09:22 +000033#include <sys/ipc.h>
34#include <sys/msg.h>
bellard31e31b82003-02-18 22:55:36 +000035#include <sys/wait.h>
36#include <sys/time.h>
37#include <sys/stat.h>
38#include <sys/mount.h>
ths39b9aae2007-02-11 18:36:44 +000039#include <sys/prctl.h>
bellard31e31b82003-02-18 22:55:36 +000040#include <sys/resource.h>
41#include <sys/mman.h>
42#include <sys/swap.h>
43#include <signal.h>
44#include <sched.h>
45#include <sys/socket.h>
46#include <sys/uio.h>
bellard9de5e442003-03-23 16:49:39 +000047#include <sys/poll.h>
bellard32f36bc2003-03-30 21:29:48 +000048#include <sys/times.h>
bellard8853f862004-02-22 14:57:26 +000049#include <sys/shm.h>
thsfa294812007-02-02 22:05:00 +000050#include <sys/sem.h>
bellard56c8f682005-11-28 22:28:41 +000051#include <sys/statfs.h>
bellardebc05482003-09-30 21:08:41 +000052#include <utime.h>
bellarda5448a72004-06-19 16:59:03 +000053#include <sys/sysinfo.h>
bellard72f03902003-02-18 23:33:18 +000054//#include <sys/user.h>
bellard8853f862004-02-22 14:57:26 +000055#include <netinet/ip.h>
bellard7854b052003-03-29 17:22:23 +000056#include <netinet/tcp.h>
aurel320b6d3ae2008-09-15 07:43:43 +000057#include <qemu-common.h>
aurel326d946cd2008-11-06 16:15:18 +000058#ifdef HAVE_GPROF
59#include <sys/gmon.h>
60#endif
bellard31e31b82003-02-18 22:55:36 +000061
62#define termios host_termios
63#define winsize host_winsize
64#define termio host_termio
bellard04369ff2003-03-20 22:33:23 +000065#define sgttyb host_sgttyb /* same as target */
66#define tchars host_tchars /* same as target */
67#define ltchars host_ltchars /* same as target */
bellard31e31b82003-02-18 22:55:36 +000068
69#include <linux/termios.h>
70#include <linux/unistd.h>
71#include <linux/utsname.h>
72#include <linux/cdrom.h>
73#include <linux/hdreg.h>
74#include <linux/soundcard.h>
bellard19b84f32003-05-08 15:41:49 +000075#include <linux/kd.h>
balrog8fbd6b52008-09-20 03:03:09 +000076#include <linux/mtio.h>
pbrookd7e40362008-05-23 16:06:43 +000077#include "linux_loop.h"
bellard31e31b82003-02-18 22:55:36 +000078
bellard3ef693a2003-03-23 20:17:16 +000079#include "qemu.h"
balrog526ccb72008-07-16 12:13:52 +000080#include "qemu-common.h"
bellard31e31b82003-02-18 22:55:36 +000081
pbrook30813ce2008-06-02 15:45:44 +000082#if defined(USE_NPTL)
83#include <linux/futex.h>
pbrookd865bab2008-06-07 22:12:17 +000084#define CLONE_NPTL_FLAGS2 (CLONE_SETTLS | \
85 CLONE_PARENT_SETTID | CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)
86#else
87/* XXX: Hardcode the above values. */
88#define CLONE_NPTL_FLAGS2 0
pbrook30813ce2008-06-02 15:45:44 +000089#endif
90
bellard72f03902003-02-18 23:33:18 +000091//#define DEBUG
bellard31e31b82003-02-18 22:55:36 +000092
pbrooke6e59062006-10-22 00:18:54 +000093#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_SPARC) \
ths48733d12007-10-08 13:36:46 +000094 || defined(TARGET_M68K) || defined(TARGET_SH4) || defined(TARGET_CRIS)
bellard67867302003-11-23 17:05:30 +000095/* 16 bit uid wrappers emulation */
96#define USE_UID16
97#endif
98
bellard1a9353d2003-03-16 20:28:50 +000099//#include <linux/msdos_fs.h>
aurel326556a832008-10-13 21:08:17 +0000100#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2])
101#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2])
bellard1a9353d2003-03-16 20:28:50 +0000102
bellard70a194b2003-08-11 22:20:16 +0000103
bellard70a194b2003-08-11 22:20:16 +0000104#undef _syscall0
105#undef _syscall1
106#undef _syscall2
107#undef _syscall3
108#undef _syscall4
109#undef _syscall5
bellard83fcb512006-06-14 13:37:16 +0000110#undef _syscall6
bellard70a194b2003-08-11 22:20:16 +0000111
bellard83fcb512006-06-14 13:37:16 +0000112#define _syscall0(type,name) \
blueswir18fcd3692008-08-17 20:26:25 +0000113static type name (void) \
bellard83fcb512006-06-14 13:37:16 +0000114{ \
115 return syscall(__NR_##name); \
bellard70a194b2003-08-11 22:20:16 +0000116}
117
bellard83fcb512006-06-14 13:37:16 +0000118#define _syscall1(type,name,type1,arg1) \
blueswir18fcd3692008-08-17 20:26:25 +0000119static type name (type1 arg1) \
bellard83fcb512006-06-14 13:37:16 +0000120{ \
121 return syscall(__NR_##name, arg1); \
bellard70a194b2003-08-11 22:20:16 +0000122}
123
bellard83fcb512006-06-14 13:37:16 +0000124#define _syscall2(type,name,type1,arg1,type2,arg2) \
blueswir18fcd3692008-08-17 20:26:25 +0000125static type name (type1 arg1,type2 arg2) \
bellard83fcb512006-06-14 13:37:16 +0000126{ \
127 return syscall(__NR_##name, arg1, arg2); \
bellard70a194b2003-08-11 22:20:16 +0000128}
129
bellard83fcb512006-06-14 13:37:16 +0000130#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
blueswir18fcd3692008-08-17 20:26:25 +0000131static type name (type1 arg1,type2 arg2,type3 arg3) \
bellard83fcb512006-06-14 13:37:16 +0000132{ \
133 return syscall(__NR_##name, arg1, arg2, arg3); \
bellard70a194b2003-08-11 22:20:16 +0000134}
135
bellard83fcb512006-06-14 13:37:16 +0000136#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
blueswir18fcd3692008-08-17 20:26:25 +0000137static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4) \
bellard83fcb512006-06-14 13:37:16 +0000138{ \
139 return syscall(__NR_##name, arg1, arg2, arg3, arg4); \
bellard70a194b2003-08-11 22:20:16 +0000140}
141
bellard83fcb512006-06-14 13:37:16 +0000142#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
143 type5,arg5) \
blueswir18fcd3692008-08-17 20:26:25 +0000144static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \
bellard83fcb512006-06-14 13:37:16 +0000145{ \
146 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5); \
bellard70a194b2003-08-11 22:20:16 +0000147}
bellard83fcb512006-06-14 13:37:16 +0000148
149
150#define _syscall6(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4, \
151 type5,arg5,type6,arg6) \
blueswir18fcd3692008-08-17 20:26:25 +0000152static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \
153 type6 arg6) \
bellard83fcb512006-06-14 13:37:16 +0000154{ \
155 return syscall(__NR_##name, arg1, arg2, arg3, arg4, arg5, arg6); \
156}
157
bellard70a194b2003-08-11 22:20:16 +0000158
balroga2f86d82008-10-28 10:18:28 +0000159#define __NR_sys_exit __NR_exit
bellard31e31b82003-02-18 22:55:36 +0000160#define __NR_sys_uname __NR_uname
ths92a34c12007-09-24 09:27:49 +0000161#define __NR_sys_faccessat __NR_faccessat
ths814d7972007-09-24 09:26:51 +0000162#define __NR_sys_fchmodat __NR_fchmodat
thsccfa72b2007-09-24 09:23:34 +0000163#define __NR_sys_fchownat __NR_fchownat
balrog6a24a772008-09-20 02:23:36 +0000164#define __NR_sys_fstatat64 __NR_fstatat64
balrogac8a6552008-09-20 02:25:39 +0000165#define __NR_sys_futimesat __NR_futimesat
bellard72f03902003-02-18 23:33:18 +0000166#define __NR_sys_getcwd1 __NR_getcwd
bellard72f03902003-02-18 23:33:18 +0000167#define __NR_sys_getdents __NR_getdents
bellarddab2ed92003-03-22 15:23:14 +0000168#define __NR_sys_getdents64 __NR_getdents64
thsc6cda172007-10-09 03:42:34 +0000169#define __NR_sys_getpriority __NR_getpriority
ths64f0ce42007-09-24 09:25:06 +0000170#define __NR_sys_linkat __NR_linkat
ths4472ad02007-09-24 09:22:32 +0000171#define __NR_sys_mkdirat __NR_mkdirat
ths75ac37a2007-09-24 09:23:05 +0000172#define __NR_sys_mknodat __NR_mknodat
ths82424832007-09-24 09:21:55 +0000173#define __NR_sys_openat __NR_openat
ths5e0ccb12007-09-24 09:26:10 +0000174#define __NR_sys_readlinkat __NR_readlinkat
ths722183f2007-09-24 09:24:37 +0000175#define __NR_sys_renameat __NR_renameat
bellard66fb9762003-03-23 01:06:05 +0000176#define __NR_sys_rt_sigqueueinfo __NR_rt_sigqueueinfo
thsf0b62432007-09-24 09:25:40 +0000177#define __NR_sys_symlinkat __NR_symlinkat
ths7494b0f2007-02-11 18:26:53 +0000178#define __NR_sys_syslog __NR_syslog
ths71455572007-06-21 21:45:30 +0000179#define __NR_sys_tgkill __NR_tgkill
ths4cae1d12007-07-12 11:06:53 +0000180#define __NR_sys_tkill __NR_tkill
ths8170f562007-09-24 09:24:11 +0000181#define __NR_sys_unlinkat __NR_unlinkat
ths9007f0e2007-09-25 17:50:37 +0000182#define __NR_sys_utimensat __NR_utimensat
pbrookbd0c5662008-05-29 14:34:11 +0000183#define __NR_sys_futex __NR_futex
aurel3239b59762008-10-01 21:46:50 +0000184#define __NR_sys_inotify_init __NR_inotify_init
185#define __NR_sys_inotify_add_watch __NR_inotify_add_watch
186#define __NR_sys_inotify_rm_watch __NR_inotify_rm_watch
bellard31e31b82003-02-18 22:55:36 +0000187
bellardbc51c5c2004-03-17 23:46:04 +0000188#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
bellard9af9eaa2003-04-07 21:34:41 +0000189#define __NR__llseek __NR_lseek
190#endif
191
bellard72f03902003-02-18 23:33:18 +0000192#ifdef __NR_gettid
bellard31e31b82003-02-18 22:55:36 +0000193_syscall0(int, gettid)
bellard72f03902003-02-18 23:33:18 +0000194#else
ths0da46a62007-10-20 20:23:07 +0000195/* This is a replacement for the host gettid() and must return a host
196 errno. */
bellard72f03902003-02-18 23:33:18 +0000197static int gettid(void) {
198 return -ENOSYS;
199}
200#endif
balroga2f86d82008-10-28 10:18:28 +0000201_syscall1(int,sys_exit,int,status)
bellard31e31b82003-02-18 22:55:36 +0000202_syscall1(int,sys_uname,struct new_utsname *,buf)
ths92a34c12007-09-24 09:27:49 +0000203#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
204_syscall4(int,sys_faccessat,int,dirfd,const char *,pathname,int,mode,int,flags)
205#endif
ths814d7972007-09-24 09:26:51 +0000206#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
207_syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname,
208 mode_t,mode,int,flags)
209#endif
blueswir14583f582008-08-24 10:35:55 +0000210#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat) && defined(USE_UID16)
thsccfa72b2007-09-24 09:23:34 +0000211_syscall5(int,sys_fchownat,int,dirfd,const char *,pathname,
212 uid_t,owner,gid_t,group,int,flags)
213#endif
balrog6a24a772008-09-20 02:23:36 +0000214#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
215_syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname,
216 struct stat *,buf,int,flags)
217#endif
balrogac8a6552008-09-20 02:25:39 +0000218#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
219_syscall3(int,sys_futimesat,int,dirfd,const char *,pathname,
220 const struct timeval *,times)
221#endif
bellard72f03902003-02-18 23:33:18 +0000222_syscall2(int,sys_getcwd1,char *,buf,size_t,size)
blueswir14583f582008-08-24 10:35:55 +0000223#if TARGET_ABI_BITS == 32
aurel326556a832008-10-13 21:08:17 +0000224_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count);
blueswir14583f582008-08-24 10:35:55 +0000225#endif
ths3ae43202007-09-16 21:39:48 +0000226#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
aurel326556a832008-10-13 21:08:17 +0000227_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count);
ths3ae43202007-09-16 21:39:48 +0000228#endif
thsc6cda172007-10-09 03:42:34 +0000229_syscall2(int, sys_getpriority, int, which, int, who);
blueswir18fcd3692008-08-17 20:26:25 +0000230#if !defined (__x86_64__)
bellard31e31b82003-02-18 22:55:36 +0000231_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo,
232 loff_t *, res, uint, wh);
blueswir18fcd3692008-08-17 20:26:25 +0000233#endif
ths64f0ce42007-09-24 09:25:06 +0000234#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
235_syscall5(int,sys_linkat,int,olddirfd,const char *,oldpath,
236 int,newdirfd,const char *,newpath,int,flags)
237#endif
ths4472ad02007-09-24 09:22:32 +0000238#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
239_syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode)
240#endif
ths75ac37a2007-09-24 09:23:05 +0000241#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
242_syscall4(int,sys_mknodat,int,dirfd,const char *,pathname,
243 mode_t,mode,dev_t,dev)
244#endif
ths82424832007-09-24 09:21:55 +0000245#if defined(TARGET_NR_openat) && defined(__NR_openat)
246_syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode)
247#endif
ths5e0ccb12007-09-24 09:26:10 +0000248#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
249_syscall4(int,sys_readlinkat,int,dirfd,const char *,pathname,
250 char *,buf,size_t,bufsize)
251#endif
ths722183f2007-09-24 09:24:37 +0000252#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
253_syscall4(int,sys_renameat,int,olddirfd,const char *,oldpath,
254 int,newdirfd,const char *,newpath)
255#endif
bellard66fb9762003-03-23 01:06:05 +0000256_syscall3(int,sys_rt_sigqueueinfo,int,pid,int,sig,siginfo_t *,uinfo)
thsb51eaa82007-09-25 16:09:22 +0000257#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
thsf0b62432007-09-24 09:25:40 +0000258_syscall3(int,sys_symlinkat,const char *,oldpath,
259 int,newdirfd,const char *,newpath)
260#endif
ths7494b0f2007-02-11 18:26:53 +0000261_syscall3(int,sys_syslog,int,type,char*,bufp,int,len)
ths3ae43202007-09-16 21:39:48 +0000262#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +0000263_syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig)
ths4cae1d12007-07-12 11:06:53 +0000264#endif
ths3ae43202007-09-16 21:39:48 +0000265#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +0000266_syscall2(int,sys_tkill,int,tid,int,sig)
267#endif
bellardec86b0f2003-04-11 00:15:04 +0000268#ifdef __NR_exit_group
269_syscall1(int,exit_group,int,error_code)
270#endif
ths6f5b89a2007-03-02 20:48:00 +0000271#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
272_syscall1(int,set_tid_address,int *,tidptr)
273#endif
ths8170f562007-09-24 09:24:11 +0000274#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
275_syscall3(int,sys_unlinkat,int,dirfd,const char *,pathname,int,flags)
276#endif
ths9007f0e2007-09-25 17:50:37 +0000277#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
278_syscall4(int,sys_utimensat,int,dirfd,const char *,pathname,
279 const struct timespec *,tsp,int,flags)
280#endif
aurel3239b59762008-10-01 21:46:50 +0000281#if defined(TARGET_NR_inotify_init) && defined(__NR_inotify_init)
282_syscall0(int,sys_inotify_init)
283#endif
284#if defined(TARGET_NR_inotify_add_watch) && defined(__NR_inotify_add_watch)
285_syscall3(int,sys_inotify_add_watch,int,fd,const char *,pathname,uint32_t,mask)
286#endif
287#if defined(TARGET_NR_inotify_rm_watch) && defined(__NR_inotify_rm_watch)
288_syscall2(int,sys_inotify_rm_watch,int,fd,uint32_t,wd)
289#endif
blueswir18fcd3692008-08-17 20:26:25 +0000290#if defined(USE_NPTL)
pbrookbd0c5662008-05-29 14:34:11 +0000291#if defined(TARGET_NR_futex) && defined(__NR_futex)
292_syscall6(int,sys_futex,int *,uaddr,int,op,int,val,
293 const struct timespec *,timeout,int *,uaddr2,int,val3)
blueswir18fcd3692008-08-17 20:26:25 +0000294#endif
pbrookbd0c5662008-05-29 14:34:11 +0000295#endif
bellard66fb9762003-03-23 01:06:05 +0000296
297extern int personality(int);
bellard9de5e442003-03-23 16:49:39 +0000298extern int flock(int, int);
299extern int setfsuid(int);
300extern int setfsgid(int);
bellard19b84f32003-05-08 15:41:49 +0000301extern int setgroups(int, gid_t *);
bellard31e31b82003-02-18 22:55:36 +0000302
thsb92c47c2007-11-01 00:07:38 +0000303#define ERRNO_TABLE_SIZE 1200
304
305/* target_to_host_errno_table[] is initialized from
306 * host_to_target_errno_table[] in syscall_init(). */
307static uint16_t target_to_host_errno_table[ERRNO_TABLE_SIZE] = {
308};
309
ths637947f2007-06-01 12:09:19 +0000310/*
thsfe8f0962007-07-12 10:59:21 +0000311 * This list is the union of errno values overridden in asm-<arch>/errno.h
ths637947f2007-06-01 12:09:19 +0000312 * minus the errnos that are not actually generic to all archs.
313 */
thsb92c47c2007-11-01 00:07:38 +0000314static uint16_t host_to_target_errno_table[ERRNO_TABLE_SIZE] = {
ths637947f2007-06-01 12:09:19 +0000315 [EIDRM] = TARGET_EIDRM,
316 [ECHRNG] = TARGET_ECHRNG,
317 [EL2NSYNC] = TARGET_EL2NSYNC,
318 [EL3HLT] = TARGET_EL3HLT,
319 [EL3RST] = TARGET_EL3RST,
320 [ELNRNG] = TARGET_ELNRNG,
321 [EUNATCH] = TARGET_EUNATCH,
322 [ENOCSI] = TARGET_ENOCSI,
323 [EL2HLT] = TARGET_EL2HLT,
324 [EDEADLK] = TARGET_EDEADLK,
325 [ENOLCK] = TARGET_ENOLCK,
326 [EBADE] = TARGET_EBADE,
327 [EBADR] = TARGET_EBADR,
328 [EXFULL] = TARGET_EXFULL,
329 [ENOANO] = TARGET_ENOANO,
330 [EBADRQC] = TARGET_EBADRQC,
331 [EBADSLT] = TARGET_EBADSLT,
332 [EBFONT] = TARGET_EBFONT,
333 [ENOSTR] = TARGET_ENOSTR,
334 [ENODATA] = TARGET_ENODATA,
335 [ETIME] = TARGET_ETIME,
336 [ENOSR] = TARGET_ENOSR,
337 [ENONET] = TARGET_ENONET,
338 [ENOPKG] = TARGET_ENOPKG,
339 [EREMOTE] = TARGET_EREMOTE,
340 [ENOLINK] = TARGET_ENOLINK,
341 [EADV] = TARGET_EADV,
342 [ESRMNT] = TARGET_ESRMNT,
343 [ECOMM] = TARGET_ECOMM,
344 [EPROTO] = TARGET_EPROTO,
345 [EDOTDOT] = TARGET_EDOTDOT,
346 [EMULTIHOP] = TARGET_EMULTIHOP,
347 [EBADMSG] = TARGET_EBADMSG,
348 [ENAMETOOLONG] = TARGET_ENAMETOOLONG,
349 [EOVERFLOW] = TARGET_EOVERFLOW,
350 [ENOTUNIQ] = TARGET_ENOTUNIQ,
351 [EBADFD] = TARGET_EBADFD,
352 [EREMCHG] = TARGET_EREMCHG,
353 [ELIBACC] = TARGET_ELIBACC,
354 [ELIBBAD] = TARGET_ELIBBAD,
355 [ELIBSCN] = TARGET_ELIBSCN,
356 [ELIBMAX] = TARGET_ELIBMAX,
357 [ELIBEXEC] = TARGET_ELIBEXEC,
358 [EILSEQ] = TARGET_EILSEQ,
359 [ENOSYS] = TARGET_ENOSYS,
360 [ELOOP] = TARGET_ELOOP,
361 [ERESTART] = TARGET_ERESTART,
362 [ESTRPIPE] = TARGET_ESTRPIPE,
363 [ENOTEMPTY] = TARGET_ENOTEMPTY,
364 [EUSERS] = TARGET_EUSERS,
365 [ENOTSOCK] = TARGET_ENOTSOCK,
366 [EDESTADDRREQ] = TARGET_EDESTADDRREQ,
367 [EMSGSIZE] = TARGET_EMSGSIZE,
368 [EPROTOTYPE] = TARGET_EPROTOTYPE,
369 [ENOPROTOOPT] = TARGET_ENOPROTOOPT,
370 [EPROTONOSUPPORT] = TARGET_EPROTONOSUPPORT,
371 [ESOCKTNOSUPPORT] = TARGET_ESOCKTNOSUPPORT,
372 [EOPNOTSUPP] = TARGET_EOPNOTSUPP,
373 [EPFNOSUPPORT] = TARGET_EPFNOSUPPORT,
374 [EAFNOSUPPORT] = TARGET_EAFNOSUPPORT,
375 [EADDRINUSE] = TARGET_EADDRINUSE,
376 [EADDRNOTAVAIL] = TARGET_EADDRNOTAVAIL,
377 [ENETDOWN] = TARGET_ENETDOWN,
378 [ENETUNREACH] = TARGET_ENETUNREACH,
379 [ENETRESET] = TARGET_ENETRESET,
380 [ECONNABORTED] = TARGET_ECONNABORTED,
381 [ECONNRESET] = TARGET_ECONNRESET,
382 [ENOBUFS] = TARGET_ENOBUFS,
383 [EISCONN] = TARGET_EISCONN,
384 [ENOTCONN] = TARGET_ENOTCONN,
385 [EUCLEAN] = TARGET_EUCLEAN,
386 [ENOTNAM] = TARGET_ENOTNAM,
387 [ENAVAIL] = TARGET_ENAVAIL,
388 [EISNAM] = TARGET_EISNAM,
389 [EREMOTEIO] = TARGET_EREMOTEIO,
390 [ESHUTDOWN] = TARGET_ESHUTDOWN,
391 [ETOOMANYREFS] = TARGET_ETOOMANYREFS,
392 [ETIMEDOUT] = TARGET_ETIMEDOUT,
393 [ECONNREFUSED] = TARGET_ECONNREFUSED,
394 [EHOSTDOWN] = TARGET_EHOSTDOWN,
395 [EHOSTUNREACH] = TARGET_EHOSTUNREACH,
396 [EALREADY] = TARGET_EALREADY,
397 [EINPROGRESS] = TARGET_EINPROGRESS,
398 [ESTALE] = TARGET_ESTALE,
399 [ECANCELED] = TARGET_ECANCELED,
400 [ENOMEDIUM] = TARGET_ENOMEDIUM,
401 [EMEDIUMTYPE] = TARGET_EMEDIUMTYPE,
thsb7fe5db2007-07-23 15:37:46 +0000402#ifdef ENOKEY
ths637947f2007-06-01 12:09:19 +0000403 [ENOKEY] = TARGET_ENOKEY,
thsb7fe5db2007-07-23 15:37:46 +0000404#endif
405#ifdef EKEYEXPIRED
ths637947f2007-06-01 12:09:19 +0000406 [EKEYEXPIRED] = TARGET_EKEYEXPIRED,
thsb7fe5db2007-07-23 15:37:46 +0000407#endif
408#ifdef EKEYREVOKED
ths637947f2007-06-01 12:09:19 +0000409 [EKEYREVOKED] = TARGET_EKEYREVOKED,
thsb7fe5db2007-07-23 15:37:46 +0000410#endif
411#ifdef EKEYREJECTED
ths637947f2007-06-01 12:09:19 +0000412 [EKEYREJECTED] = TARGET_EKEYREJECTED,
thsb7fe5db2007-07-23 15:37:46 +0000413#endif
414#ifdef EOWNERDEAD
ths637947f2007-06-01 12:09:19 +0000415 [EOWNERDEAD] = TARGET_EOWNERDEAD,
thsb7fe5db2007-07-23 15:37:46 +0000416#endif
417#ifdef ENOTRECOVERABLE
ths637947f2007-06-01 12:09:19 +0000418 [ENOTRECOVERABLE] = TARGET_ENOTRECOVERABLE,
thsb7fe5db2007-07-23 15:37:46 +0000419#endif
thsb92c47c2007-11-01 00:07:38 +0000420};
ths637947f2007-06-01 12:09:19 +0000421
422static inline int host_to_target_errno(int err)
423{
424 if(host_to_target_errno_table[err])
425 return host_to_target_errno_table[err];
426 return err;
427}
428
thsb92c47c2007-11-01 00:07:38 +0000429static inline int target_to_host_errno(int err)
430{
431 if (target_to_host_errno_table[err])
432 return target_to_host_errno_table[err];
433 return err;
434}
435
blueswir1992f48a2007-10-14 16:27:31 +0000436static inline abi_long get_errno(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000437{
438 if (ret == -1)
ths637947f2007-06-01 12:09:19 +0000439 return -host_to_target_errno(errno);
bellard31e31b82003-02-18 22:55:36 +0000440 else
441 return ret;
442}
443
blueswir1992f48a2007-10-14 16:27:31 +0000444static inline int is_error(abi_long ret)
bellard31e31b82003-02-18 22:55:36 +0000445{
blueswir1992f48a2007-10-14 16:27:31 +0000446 return (abi_ulong)ret >= (abi_ulong)(-4096);
bellard31e31b82003-02-18 22:55:36 +0000447}
448
thsb92c47c2007-11-01 00:07:38 +0000449char *target_strerror(int err)
450{
451 return strerror(target_to_host_errno(err));
452}
453
blueswir1992f48a2007-10-14 16:27:31 +0000454static abi_ulong target_brk;
455static abi_ulong target_original_brk;
bellard31e31b82003-02-18 22:55:36 +0000456
blueswir1992f48a2007-10-14 16:27:31 +0000457void target_set_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000458{
blueswir14c1de732007-07-07 20:45:44 +0000459 target_original_brk = target_brk = HOST_PAGE_ALIGN(new_brk);
bellard31e31b82003-02-18 22:55:36 +0000460}
461
ths0da46a62007-10-20 20:23:07 +0000462/* do_brk() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000463abi_long do_brk(abi_ulong new_brk)
bellard31e31b82003-02-18 22:55:36 +0000464{
blueswir1992f48a2007-10-14 16:27:31 +0000465 abi_ulong brk_page;
466 abi_long mapped_addr;
bellard31e31b82003-02-18 22:55:36 +0000467 int new_alloc_size;
468
469 if (!new_brk)
pbrook53a59602006-03-25 19:31:22 +0000470 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000471 if (new_brk < target_original_brk)
balrog7ab240a2008-04-26 12:17:34 +0000472 return target_brk;
ths3b46e622007-09-17 08:09:54 +0000473
pbrook53a59602006-03-25 19:31:22 +0000474 brk_page = HOST_PAGE_ALIGN(target_brk);
bellard31e31b82003-02-18 22:55:36 +0000475
476 /* If the new brk is less than this, set it and we're done... */
477 if (new_brk < brk_page) {
478 target_brk = new_brk;
pbrook53a59602006-03-25 19:31:22 +0000479 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000480 }
481
482 /* We need to allocate more memory after the brk... */
bellard54936002003-05-13 00:25:15 +0000483 new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1);
ths5fafdf22007-09-16 21:08:06 +0000484 mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size,
bellard54936002003-05-13 00:25:15 +0000485 PROT_READ|PROT_WRITE,
486 MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0));
balrog7ab240a2008-04-26 12:17:34 +0000487
488 if (!is_error(mapped_addr))
bellard31e31b82003-02-18 22:55:36 +0000489 target_brk = new_brk;
balrog7ab240a2008-04-26 12:17:34 +0000490
491 return target_brk;
bellard31e31b82003-02-18 22:55:36 +0000492}
493
ths26edcf42007-12-09 02:25:24 +0000494static inline abi_long copy_from_user_fdset(fd_set *fds,
495 abi_ulong target_fds_addr,
496 int n)
bellard31e31b82003-02-18 22:55:36 +0000497{
ths26edcf42007-12-09 02:25:24 +0000498 int i, nw, j, k;
499 abi_ulong b, *target_fds;
500
501 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
502 if (!(target_fds = lock_user(VERIFY_READ,
503 target_fds_addr,
504 sizeof(abi_ulong) * nw,
505 1)))
506 return -TARGET_EFAULT;
507
508 FD_ZERO(fds);
509 k = 0;
510 for (i = 0; i < nw; i++) {
511 /* grab the abi_ulong */
512 __get_user(b, &target_fds[i]);
513 for (j = 0; j < TARGET_ABI_BITS; j++) {
514 /* check the bit inside the abi_ulong */
515 if ((b >> j) & 1)
516 FD_SET(k, fds);
517 k++;
bellard31e31b82003-02-18 22:55:36 +0000518 }
bellard31e31b82003-02-18 22:55:36 +0000519 }
ths26edcf42007-12-09 02:25:24 +0000520
521 unlock_user(target_fds, target_fds_addr, 0);
522
523 return 0;
bellard31e31b82003-02-18 22:55:36 +0000524}
525
ths26edcf42007-12-09 02:25:24 +0000526static inline abi_long copy_to_user_fdset(abi_ulong target_fds_addr,
527 const fd_set *fds,
528 int n)
bellard31e31b82003-02-18 22:55:36 +0000529{
bellard31e31b82003-02-18 22:55:36 +0000530 int i, nw, j, k;
blueswir1992f48a2007-10-14 16:27:31 +0000531 abi_long v;
ths26edcf42007-12-09 02:25:24 +0000532 abi_ulong *target_fds;
bellard31e31b82003-02-18 22:55:36 +0000533
ths26edcf42007-12-09 02:25:24 +0000534 nw = (n + TARGET_ABI_BITS - 1) / TARGET_ABI_BITS;
535 if (!(target_fds = lock_user(VERIFY_WRITE,
536 target_fds_addr,
537 sizeof(abi_ulong) * nw,
538 0)))
539 return -TARGET_EFAULT;
540
541 k = 0;
542 for (i = 0; i < nw; i++) {
543 v = 0;
544 for (j = 0; j < TARGET_ABI_BITS; j++) {
545 v |= ((FD_ISSET(k, fds) != 0) << j);
546 k++;
bellard31e31b82003-02-18 22:55:36 +0000547 }
ths26edcf42007-12-09 02:25:24 +0000548 __put_user(v, &target_fds[i]);
bellard31e31b82003-02-18 22:55:36 +0000549 }
ths26edcf42007-12-09 02:25:24 +0000550
551 unlock_user(target_fds, target_fds_addr, sizeof(abi_ulong) * nw);
552
553 return 0;
bellard31e31b82003-02-18 22:55:36 +0000554}
555
bellardc596ed12003-07-13 17:32:31 +0000556#if defined(__alpha__)
557#define HOST_HZ 1024
558#else
559#define HOST_HZ 100
560#endif
561
blueswir1992f48a2007-10-14 16:27:31 +0000562static inline abi_long host_to_target_clock_t(long ticks)
bellardc596ed12003-07-13 17:32:31 +0000563{
564#if HOST_HZ == TARGET_HZ
565 return ticks;
566#else
567 return ((int64_t)ticks * TARGET_HZ) / HOST_HZ;
568#endif
569}
570
bellard579a97f2007-11-11 14:26:47 +0000571static inline abi_long host_to_target_rusage(abi_ulong target_addr,
572 const struct rusage *rusage)
bellardb4091862003-05-16 15:39:34 +0000573{
pbrook53a59602006-03-25 19:31:22 +0000574 struct target_rusage *target_rusage;
575
bellard579a97f2007-11-11 14:26:47 +0000576 if (!lock_user_struct(VERIFY_WRITE, target_rusage, target_addr, 0))
577 return -TARGET_EFAULT;
bellardb4091862003-05-16 15:39:34 +0000578 target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec);
579 target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec);
580 target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec);
581 target_rusage->ru_stime.tv_usec = tswapl(rusage->ru_stime.tv_usec);
582 target_rusage->ru_maxrss = tswapl(rusage->ru_maxrss);
583 target_rusage->ru_ixrss = tswapl(rusage->ru_ixrss);
584 target_rusage->ru_idrss = tswapl(rusage->ru_idrss);
585 target_rusage->ru_isrss = tswapl(rusage->ru_isrss);
586 target_rusage->ru_minflt = tswapl(rusage->ru_minflt);
587 target_rusage->ru_majflt = tswapl(rusage->ru_majflt);
588 target_rusage->ru_nswap = tswapl(rusage->ru_nswap);
589 target_rusage->ru_inblock = tswapl(rusage->ru_inblock);
590 target_rusage->ru_oublock = tswapl(rusage->ru_oublock);
591 target_rusage->ru_msgsnd = tswapl(rusage->ru_msgsnd);
592 target_rusage->ru_msgrcv = tswapl(rusage->ru_msgrcv);
593 target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals);
594 target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw);
595 target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw);
pbrook53a59602006-03-25 19:31:22 +0000596 unlock_user_struct(target_rusage, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000597
598 return 0;
bellardb4091862003-05-16 15:39:34 +0000599}
600
ths788f5ec2007-12-09 02:37:05 +0000601static inline abi_long copy_from_user_timeval(struct timeval *tv,
602 abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000603{
pbrook53a59602006-03-25 19:31:22 +0000604 struct target_timeval *target_tv;
605
ths788f5ec2007-12-09 02:37:05 +0000606 if (!lock_user_struct(VERIFY_READ, target_tv, target_tv_addr, 1))
bellard579a97f2007-11-11 14:26:47 +0000607 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000608
609 __get_user(tv->tv_sec, &target_tv->tv_sec);
610 __get_user(tv->tv_usec, &target_tv->tv_usec);
611
612 unlock_user_struct(target_tv, target_tv_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000613
614 return 0;
bellard31e31b82003-02-18 22:55:36 +0000615}
616
ths788f5ec2007-12-09 02:37:05 +0000617static inline abi_long copy_to_user_timeval(abi_ulong target_tv_addr,
618 const struct timeval *tv)
bellard31e31b82003-02-18 22:55:36 +0000619{
pbrook53a59602006-03-25 19:31:22 +0000620 struct target_timeval *target_tv;
621
ths788f5ec2007-12-09 02:37:05 +0000622 if (!lock_user_struct(VERIFY_WRITE, target_tv, target_tv_addr, 0))
bellard579a97f2007-11-11 14:26:47 +0000623 return -TARGET_EFAULT;
ths788f5ec2007-12-09 02:37:05 +0000624
625 __put_user(tv->tv_sec, &target_tv->tv_sec);
626 __put_user(tv->tv_usec, &target_tv->tv_usec);
627
628 unlock_user_struct(target_tv, target_tv_addr, 1);
bellard579a97f2007-11-11 14:26:47 +0000629
630 return 0;
bellard31e31b82003-02-18 22:55:36 +0000631}
632
633
ths0da46a62007-10-20 20:23:07 +0000634/* do_select() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000635static abi_long do_select(int n,
ths26edcf42007-12-09 02:25:24 +0000636 abi_ulong rfd_addr, abi_ulong wfd_addr,
637 abi_ulong efd_addr, abi_ulong target_tv_addr)
bellard31e31b82003-02-18 22:55:36 +0000638{
639 fd_set rfds, wfds, efds;
640 fd_set *rfds_ptr, *wfds_ptr, *efds_ptr;
641 struct timeval tv, *tv_ptr;
blueswir1992f48a2007-10-14 16:27:31 +0000642 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +0000643
ths26edcf42007-12-09 02:25:24 +0000644 if (rfd_addr) {
645 if (copy_from_user_fdset(&rfds, rfd_addr, n))
646 return -TARGET_EFAULT;
647 rfds_ptr = &rfds;
pbrook53a59602006-03-25 19:31:22 +0000648 } else {
pbrook53a59602006-03-25 19:31:22 +0000649 rfds_ptr = NULL;
650 }
ths26edcf42007-12-09 02:25:24 +0000651 if (wfd_addr) {
652 if (copy_from_user_fdset(&wfds, wfd_addr, n))
653 return -TARGET_EFAULT;
654 wfds_ptr = &wfds;
pbrook53a59602006-03-25 19:31:22 +0000655 } else {
pbrook53a59602006-03-25 19:31:22 +0000656 wfds_ptr = NULL;
657 }
ths26edcf42007-12-09 02:25:24 +0000658 if (efd_addr) {
659 if (copy_from_user_fdset(&efds, efd_addr, n))
660 return -TARGET_EFAULT;
661 efds_ptr = &efds;
pbrook53a59602006-03-25 19:31:22 +0000662 } else {
pbrook53a59602006-03-25 19:31:22 +0000663 efds_ptr = NULL;
664 }
ths3b46e622007-09-17 08:09:54 +0000665
ths26edcf42007-12-09 02:25:24 +0000666 if (target_tv_addr) {
ths788f5ec2007-12-09 02:37:05 +0000667 if (copy_from_user_timeval(&tv, target_tv_addr))
668 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000669 tv_ptr = &tv;
670 } else {
671 tv_ptr = NULL;
672 }
ths26edcf42007-12-09 02:25:24 +0000673
bellard31e31b82003-02-18 22:55:36 +0000674 ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr));
pbrook53a59602006-03-25 19:31:22 +0000675
ths26edcf42007-12-09 02:25:24 +0000676 if (!is_error(ret)) {
677 if (rfd_addr && copy_to_user_fdset(rfd_addr, &rfds, n))
678 return -TARGET_EFAULT;
679 if (wfd_addr && copy_to_user_fdset(wfd_addr, &wfds, n))
680 return -TARGET_EFAULT;
681 if (efd_addr && copy_to_user_fdset(efd_addr, &efds, n))
682 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000683
ths788f5ec2007-12-09 02:37:05 +0000684 if (target_tv_addr && copy_to_user_timeval(target_tv_addr, &tv))
685 return -TARGET_EFAULT;
bellard31e31b82003-02-18 22:55:36 +0000686 }
bellard579a97f2007-11-11 14:26:47 +0000687
bellard31e31b82003-02-18 22:55:36 +0000688 return ret;
689}
690
bellard579a97f2007-11-11 14:26:47 +0000691static inline abi_long target_to_host_sockaddr(struct sockaddr *addr,
692 abi_ulong target_addr,
693 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000694{
pbrook53a59602006-03-25 19:31:22 +0000695 struct target_sockaddr *target_saddr;
696
bellard579a97f2007-11-11 14:26:47 +0000697 target_saddr = lock_user(VERIFY_READ, target_addr, len, 1);
698 if (!target_saddr)
699 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000700 memcpy(addr, target_saddr, len);
701 addr->sa_family = tswap16(target_saddr->sa_family);
702 unlock_user(target_saddr, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +0000703
704 return 0;
bellard7854b052003-03-29 17:22:23 +0000705}
706
bellard579a97f2007-11-11 14:26:47 +0000707static inline abi_long host_to_target_sockaddr(abi_ulong target_addr,
708 struct sockaddr *addr,
709 socklen_t len)
bellard7854b052003-03-29 17:22:23 +0000710{
pbrook53a59602006-03-25 19:31:22 +0000711 struct target_sockaddr *target_saddr;
712
bellard579a97f2007-11-11 14:26:47 +0000713 target_saddr = lock_user(VERIFY_WRITE, target_addr, len, 0);
714 if (!target_saddr)
715 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +0000716 memcpy(target_saddr, addr, len);
717 target_saddr->sa_family = tswap16(addr->sa_family);
718 unlock_user(target_saddr, target_addr, len);
bellard579a97f2007-11-11 14:26:47 +0000719
720 return 0;
bellard7854b052003-03-29 17:22:23 +0000721}
722
pbrook53a59602006-03-25 19:31:22 +0000723/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000724static inline abi_long target_to_host_cmsg(struct msghdr *msgh,
725 struct target_msghdr *target_msgh)
bellard7854b052003-03-29 17:22:23 +0000726{
727 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000728 abi_long msg_controllen;
729 abi_ulong target_cmsg_addr;
730 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000731 socklen_t space = 0;
bellard5a4a8982007-11-11 17:39:18 +0000732
733 msg_controllen = tswapl(target_msgh->msg_controllen);
734 if (msg_controllen < sizeof (struct target_cmsghdr))
735 goto the_end;
736 target_cmsg_addr = tswapl(target_msgh->msg_control);
737 target_cmsg = lock_user(VERIFY_READ, target_cmsg_addr, msg_controllen, 1);
738 if (!target_cmsg)
739 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +0000740
741 while (cmsg && target_cmsg) {
742 void *data = CMSG_DATA(cmsg);
743 void *target_data = TARGET_CMSG_DATA(target_cmsg);
744
ths5fafdf22007-09-16 21:08:06 +0000745 int len = tswapl(target_cmsg->cmsg_len)
bellard7854b052003-03-29 17:22:23 +0000746 - TARGET_CMSG_ALIGN(sizeof (struct target_cmsghdr));
747
748 space += CMSG_SPACE(len);
749 if (space > msgh->msg_controllen) {
750 space -= CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000751 gemu_log("Host cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000752 break;
753 }
754
755 cmsg->cmsg_level = tswap32(target_cmsg->cmsg_level);
756 cmsg->cmsg_type = tswap32(target_cmsg->cmsg_type);
757 cmsg->cmsg_len = CMSG_LEN(len);
758
bellard3532fa72006-06-24 15:06:03 +0000759 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000760 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
761 memcpy(data, target_data, len);
762 } else {
763 int *fd = (int *)data;
764 int *target_fd = (int *)target_data;
765 int i, numfds = len / sizeof(int);
766
767 for (i = 0; i < numfds; i++)
768 fd[i] = tswap32(target_fd[i]);
769 }
770
771 cmsg = CMSG_NXTHDR(msgh, cmsg);
772 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
773 }
bellard5a4a8982007-11-11 17:39:18 +0000774 unlock_user(target_cmsg, target_cmsg_addr, 0);
775 the_end:
bellard7854b052003-03-29 17:22:23 +0000776 msgh->msg_controllen = space;
bellard5a4a8982007-11-11 17:39:18 +0000777 return 0;
bellard7854b052003-03-29 17:22:23 +0000778}
779
pbrook53a59602006-03-25 19:31:22 +0000780/* ??? Should this also swap msgh->name? */
bellard5a4a8982007-11-11 17:39:18 +0000781static inline abi_long host_to_target_cmsg(struct target_msghdr *target_msgh,
782 struct msghdr *msgh)
bellard7854b052003-03-29 17:22:23 +0000783{
784 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msgh);
bellard5a4a8982007-11-11 17:39:18 +0000785 abi_long msg_controllen;
786 abi_ulong target_cmsg_addr;
787 struct target_cmsghdr *target_cmsg;
bellard7854b052003-03-29 17:22:23 +0000788 socklen_t space = 0;
789
bellard5a4a8982007-11-11 17:39:18 +0000790 msg_controllen = tswapl(target_msgh->msg_controllen);
791 if (msg_controllen < sizeof (struct target_cmsghdr))
792 goto the_end;
793 target_cmsg_addr = tswapl(target_msgh->msg_control);
794 target_cmsg = lock_user(VERIFY_WRITE, target_cmsg_addr, msg_controllen, 0);
795 if (!target_cmsg)
796 return -TARGET_EFAULT;
797
bellard7854b052003-03-29 17:22:23 +0000798 while (cmsg && target_cmsg) {
799 void *data = CMSG_DATA(cmsg);
800 void *target_data = TARGET_CMSG_DATA(target_cmsg);
801
802 int len = cmsg->cmsg_len - CMSG_ALIGN(sizeof (struct cmsghdr));
803
804 space += TARGET_CMSG_SPACE(len);
bellard5a4a8982007-11-11 17:39:18 +0000805 if (space > msg_controllen) {
bellard7854b052003-03-29 17:22:23 +0000806 space -= TARGET_CMSG_SPACE(len);
bellard31febb72005-12-18 20:03:27 +0000807 gemu_log("Target cmsg overflow\n");
bellard7854b052003-03-29 17:22:23 +0000808 break;
809 }
810
811 target_cmsg->cmsg_level = tswap32(cmsg->cmsg_level);
812 target_cmsg->cmsg_type = tswap32(cmsg->cmsg_type);
813 target_cmsg->cmsg_len = tswapl(TARGET_CMSG_LEN(len));
814
bellard3532fa72006-06-24 15:06:03 +0000815 if (cmsg->cmsg_level != TARGET_SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
bellard7854b052003-03-29 17:22:23 +0000816 gemu_log("Unsupported ancillary data: %d/%d\n", cmsg->cmsg_level, cmsg->cmsg_type);
817 memcpy(target_data, data, len);
818 } else {
819 int *fd = (int *)data;
820 int *target_fd = (int *)target_data;
821 int i, numfds = len / sizeof(int);
822
823 for (i = 0; i < numfds; i++)
824 target_fd[i] = tswap32(fd[i]);
825 }
826
827 cmsg = CMSG_NXTHDR(msgh, cmsg);
828 target_cmsg = TARGET_CMSG_NXTHDR(target_msgh, target_cmsg);
829 }
bellard5a4a8982007-11-11 17:39:18 +0000830 unlock_user(target_cmsg, target_cmsg_addr, space);
831 the_end:
832 target_msgh->msg_controllen = tswapl(space);
833 return 0;
bellard7854b052003-03-29 17:22:23 +0000834}
835
ths0da46a62007-10-20 20:23:07 +0000836/* do_setsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000837static abi_long do_setsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000838 abi_ulong optval_addr, socklen_t optlen)
bellard7854b052003-03-29 17:22:23 +0000839{
blueswir1992f48a2007-10-14 16:27:31 +0000840 abi_long ret;
j_mayer32407102007-09-26 23:01:49 +0000841 int val;
ths3b46e622007-09-17 08:09:54 +0000842
bellard8853f862004-02-22 14:57:26 +0000843 switch(level) {
844 case SOL_TCP:
bellard7854b052003-03-29 17:22:23 +0000845 /* TCP options all take an 'int' value. */
bellard7854b052003-03-29 17:22:23 +0000846 if (optlen < sizeof(uint32_t))
ths0da46a62007-10-20 20:23:07 +0000847 return -TARGET_EINVAL;
ths3b46e622007-09-17 08:09:54 +0000848
bellard2f619692007-11-16 10:46:05 +0000849 if (get_user_u32(val, optval_addr))
850 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000851 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
852 break;
853 case SOL_IP:
854 switch(optname) {
bellard2efbe912005-07-23 15:10:20 +0000855 case IP_TOS:
856 case IP_TTL:
bellard8853f862004-02-22 14:57:26 +0000857 case IP_HDRINCL:
bellard2efbe912005-07-23 15:10:20 +0000858 case IP_ROUTER_ALERT:
859 case IP_RECVOPTS:
860 case IP_RETOPTS:
861 case IP_PKTINFO:
862 case IP_MTU_DISCOVER:
863 case IP_RECVERR:
864 case IP_RECVTOS:
865#ifdef IP_FREEBIND
866 case IP_FREEBIND:
867#endif
868 case IP_MULTICAST_TTL:
869 case IP_MULTICAST_LOOP:
bellard8853f862004-02-22 14:57:26 +0000870 val = 0;
871 if (optlen >= sizeof(uint32_t)) {
bellard2f619692007-11-16 10:46:05 +0000872 if (get_user_u32(val, optval_addr))
873 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000874 } else if (optlen >= 1) {
bellard2f619692007-11-16 10:46:05 +0000875 if (get_user_u8(val, optval_addr))
876 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +0000877 }
878 ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
879 break;
880 default:
881 goto unimplemented;
882 }
883 break;
bellard3532fa72006-06-24 15:06:03 +0000884 case TARGET_SOL_SOCKET:
bellard8853f862004-02-22 14:57:26 +0000885 switch (optname) {
886 /* Options with 'int' argument. */
bellard3532fa72006-06-24 15:06:03 +0000887 case TARGET_SO_DEBUG:
888 optname = SO_DEBUG;
889 break;
890 case TARGET_SO_REUSEADDR:
891 optname = SO_REUSEADDR;
892 break;
893 case TARGET_SO_TYPE:
894 optname = SO_TYPE;
895 break;
896 case TARGET_SO_ERROR:
897 optname = SO_ERROR;
898 break;
899 case TARGET_SO_DONTROUTE:
900 optname = SO_DONTROUTE;
901 break;
902 case TARGET_SO_BROADCAST:
903 optname = SO_BROADCAST;
904 break;
905 case TARGET_SO_SNDBUF:
906 optname = SO_SNDBUF;
907 break;
908 case TARGET_SO_RCVBUF:
909 optname = SO_RCVBUF;
910 break;
911 case TARGET_SO_KEEPALIVE:
912 optname = SO_KEEPALIVE;
913 break;
914 case TARGET_SO_OOBINLINE:
915 optname = SO_OOBINLINE;
916 break;
917 case TARGET_SO_NO_CHECK:
918 optname = SO_NO_CHECK;
919 break;
920 case TARGET_SO_PRIORITY:
921 optname = SO_PRIORITY;
922 break;
bellard5e83e8e2005-03-01 22:32:06 +0000923#ifdef SO_BSDCOMPAT
bellard3532fa72006-06-24 15:06:03 +0000924 case TARGET_SO_BSDCOMPAT:
925 optname = SO_BSDCOMPAT;
926 break;
bellard5e83e8e2005-03-01 22:32:06 +0000927#endif
bellard3532fa72006-06-24 15:06:03 +0000928 case TARGET_SO_PASSCRED:
929 optname = SO_PASSCRED;
930 break;
931 case TARGET_SO_TIMESTAMP:
932 optname = SO_TIMESTAMP;
933 break;
934 case TARGET_SO_RCVLOWAT:
935 optname = SO_RCVLOWAT;
936 break;
937 case TARGET_SO_RCVTIMEO:
938 optname = SO_RCVTIMEO;
939 break;
940 case TARGET_SO_SNDTIMEO:
941 optname = SO_SNDTIMEO;
942 break;
bellard8853f862004-02-22 14:57:26 +0000943 break;
944 default:
945 goto unimplemented;
946 }
bellard3532fa72006-06-24 15:06:03 +0000947 if (optlen < sizeof(uint32_t))
bellard2f619692007-11-16 10:46:05 +0000948 return -TARGET_EINVAL;
bellard3532fa72006-06-24 15:06:03 +0000949
bellard2f619692007-11-16 10:46:05 +0000950 if (get_user_u32(val, optval_addr))
951 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +0000952 ret = get_errno(setsockopt(sockfd, SOL_SOCKET, optname, &val, sizeof(val)));
bellard8853f862004-02-22 14:57:26 +0000953 break;
bellard7854b052003-03-29 17:22:23 +0000954 default:
bellard8853f862004-02-22 14:57:26 +0000955 unimplemented:
956 gemu_log("Unsupported setsockopt level=%d optname=%d \n", level, optname);
ths6fa13c12007-12-18 02:41:04 +0000957 ret = -TARGET_ENOPROTOOPT;
bellard7854b052003-03-29 17:22:23 +0000958 }
bellard8853f862004-02-22 14:57:26 +0000959 return ret;
bellard7854b052003-03-29 17:22:23 +0000960}
961
ths0da46a62007-10-20 20:23:07 +0000962/* do_getsockopt() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +0000963static abi_long do_getsockopt(int sockfd, int level, int optname,
bellard2f619692007-11-16 10:46:05 +0000964 abi_ulong optval_addr, abi_ulong optlen)
bellard7854b052003-03-29 17:22:23 +0000965{
blueswir1992f48a2007-10-14 16:27:31 +0000966 abi_long ret;
blueswir1b55266b2008-09-20 08:07:15 +0000967 int len, val;
968 socklen_t lv;
bellard8853f862004-02-22 14:57:26 +0000969
970 switch(level) {
bellard3532fa72006-06-24 15:06:03 +0000971 case TARGET_SOL_SOCKET:
972 level = SOL_SOCKET;
bellard8853f862004-02-22 14:57:26 +0000973 switch (optname) {
bellard3532fa72006-06-24 15:06:03 +0000974 case TARGET_SO_LINGER:
975 case TARGET_SO_RCVTIMEO:
976 case TARGET_SO_SNDTIMEO:
977 case TARGET_SO_PEERCRED:
978 case TARGET_SO_PEERNAME:
bellard8853f862004-02-22 14:57:26 +0000979 /* These don't just return a single integer */
980 goto unimplemented;
981 default:
bellard2efbe912005-07-23 15:10:20 +0000982 goto int_case;
983 }
984 break;
985 case SOL_TCP:
986 /* TCP options all take an 'int' value. */
987 int_case:
bellard2f619692007-11-16 10:46:05 +0000988 if (get_user_u32(len, optlen))
989 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +0000990 if (len < 0)
ths0da46a62007-10-20 20:23:07 +0000991 return -TARGET_EINVAL;
bellard2efbe912005-07-23 15:10:20 +0000992 lv = sizeof(int);
993 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
994 if (ret < 0)
995 return ret;
996 val = tswap32(val);
997 if (len > lv)
998 len = lv;
bellard2f619692007-11-16 10:46:05 +0000999 if (len == 4) {
1000 if (put_user_u32(val, optval_addr))
1001 return -TARGET_EFAULT;
1002 } else {
1003 if (put_user_u8(val, optval_addr))
1004 return -TARGET_EFAULT;
1005 }
1006 if (put_user_u32(len, optlen))
1007 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001008 break;
1009 case SOL_IP:
1010 switch(optname) {
1011 case IP_TOS:
1012 case IP_TTL:
1013 case IP_HDRINCL:
1014 case IP_ROUTER_ALERT:
1015 case IP_RECVOPTS:
1016 case IP_RETOPTS:
1017 case IP_PKTINFO:
1018 case IP_MTU_DISCOVER:
1019 case IP_RECVERR:
1020 case IP_RECVTOS:
1021#ifdef IP_FREEBIND
1022 case IP_FREEBIND:
1023#endif
1024 case IP_MULTICAST_TTL:
1025 case IP_MULTICAST_LOOP:
bellard2f619692007-11-16 10:46:05 +00001026 if (get_user_u32(len, optlen))
1027 return -TARGET_EFAULT;
bellard8853f862004-02-22 14:57:26 +00001028 if (len < 0)
ths0da46a62007-10-20 20:23:07 +00001029 return -TARGET_EINVAL;
bellard8853f862004-02-22 14:57:26 +00001030 lv = sizeof(int);
1031 ret = get_errno(getsockopt(sockfd, level, optname, &val, &lv));
1032 if (ret < 0)
1033 return ret;
bellard2efbe912005-07-23 15:10:20 +00001034 if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) {
bellard2efbe912005-07-23 15:10:20 +00001035 len = 1;
bellard2f619692007-11-16 10:46:05 +00001036 if (put_user_u32(len, optlen)
1037 || put_user_u8(val, optval_addr))
1038 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001039 } else {
bellard2efbe912005-07-23 15:10:20 +00001040 if (len > sizeof(int))
1041 len = sizeof(int);
bellard2f619692007-11-16 10:46:05 +00001042 if (put_user_u32(len, optlen)
1043 || put_user_u32(val, optval_addr))
1044 return -TARGET_EFAULT;
bellard2efbe912005-07-23 15:10:20 +00001045 }
bellard8853f862004-02-22 14:57:26 +00001046 break;
bellard2efbe912005-07-23 15:10:20 +00001047 default:
thsc02f4992007-12-18 02:39:59 +00001048 ret = -TARGET_ENOPROTOOPT;
1049 break;
bellard8853f862004-02-22 14:57:26 +00001050 }
1051 break;
1052 default:
1053 unimplemented:
1054 gemu_log("getsockopt level=%d optname=%d not yet supported\n",
1055 level, optname);
thsc02f4992007-12-18 02:39:59 +00001056 ret = -TARGET_EOPNOTSUPP;
bellard8853f862004-02-22 14:57:26 +00001057 break;
1058 }
1059 return ret;
bellard7854b052003-03-29 17:22:23 +00001060}
1061
bellard579a97f2007-11-11 14:26:47 +00001062/* FIXME
1063 * lock_iovec()/unlock_iovec() have a return code of 0 for success where
1064 * other lock functions have a return code of 0 for failure.
1065 */
1066static abi_long lock_iovec(int type, struct iovec *vec, abi_ulong target_addr,
1067 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001068{
1069 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001070 abi_ulong base;
balrogd732dcb2008-10-28 10:21:03 +00001071 int i;
pbrook53a59602006-03-25 19:31:22 +00001072
bellard579a97f2007-11-11 14:26:47 +00001073 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1074 if (!target_vec)
1075 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001076 for(i = 0;i < count; i++) {
1077 base = tswapl(target_vec[i].iov_base);
1078 vec[i].iov_len = tswapl(target_vec[i].iov_len);
bellard41df8412008-02-04 22:26:57 +00001079 if (vec[i].iov_len != 0) {
1080 vec[i].iov_base = lock_user(type, base, vec[i].iov_len, copy);
balrogd732dcb2008-10-28 10:21:03 +00001081 /* Don't check lock_user return value. We must call writev even
1082 if a element has invalid base address. */
bellard41df8412008-02-04 22:26:57 +00001083 } else {
1084 /* zero length pointer is ignored */
1085 vec[i].iov_base = NULL;
1086 }
pbrook53a59602006-03-25 19:31:22 +00001087 }
1088 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001089 return 0;
pbrook53a59602006-03-25 19:31:22 +00001090}
1091
bellard579a97f2007-11-11 14:26:47 +00001092static abi_long unlock_iovec(struct iovec *vec, abi_ulong target_addr,
1093 int count, int copy)
pbrook53a59602006-03-25 19:31:22 +00001094{
1095 struct target_iovec *target_vec;
blueswir1992f48a2007-10-14 16:27:31 +00001096 abi_ulong base;
pbrook53a59602006-03-25 19:31:22 +00001097 int i;
1098
bellard579a97f2007-11-11 14:26:47 +00001099 target_vec = lock_user(VERIFY_READ, target_addr, count * sizeof(struct target_iovec), 1);
1100 if (!target_vec)
1101 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00001102 for(i = 0;i < count; i++) {
balrogd732dcb2008-10-28 10:21:03 +00001103 if (target_vec[i].iov_base) {
1104 base = tswapl(target_vec[i].iov_base);
1105 unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0);
1106 }
pbrook53a59602006-03-25 19:31:22 +00001107 }
1108 unlock_user (target_vec, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001109
1110 return 0;
pbrook53a59602006-03-25 19:31:22 +00001111}
1112
ths0da46a62007-10-20 20:23:07 +00001113/* do_socket() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001114static abi_long do_socket(int domain, int type, int protocol)
bellard3532fa72006-06-24 15:06:03 +00001115{
1116#if defined(TARGET_MIPS)
1117 switch(type) {
1118 case TARGET_SOCK_DGRAM:
1119 type = SOCK_DGRAM;
1120 break;
1121 case TARGET_SOCK_STREAM:
1122 type = SOCK_STREAM;
1123 break;
1124 case TARGET_SOCK_RAW:
1125 type = SOCK_RAW;
1126 break;
1127 case TARGET_SOCK_RDM:
1128 type = SOCK_RDM;
1129 break;
1130 case TARGET_SOCK_SEQPACKET:
1131 type = SOCK_SEQPACKET;
1132 break;
1133 case TARGET_SOCK_PACKET:
1134 type = SOCK_PACKET;
1135 break;
1136 }
1137#endif
balrog12bc92a2007-10-30 21:06:14 +00001138 if (domain == PF_NETLINK)
1139 return -EAFNOSUPPORT; /* do not NETLINK socket connections possible */
bellard3532fa72006-06-24 15:06:03 +00001140 return get_errno(socket(domain, type, protocol));
1141}
1142
ths0da46a62007-10-20 20:23:07 +00001143/* do_bind() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001144static abi_long do_bind(int sockfd, abi_ulong target_addr,
1145 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001146{
1147 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001148
bellard3532fa72006-06-24 15:06:03 +00001149 target_to_host_sockaddr(addr, target_addr, addrlen);
1150 return get_errno(bind(sockfd, addr, addrlen));
1151}
1152
ths0da46a62007-10-20 20:23:07 +00001153/* do_connect() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001154static abi_long do_connect(int sockfd, abi_ulong target_addr,
1155 socklen_t addrlen)
bellard3532fa72006-06-24 15:06:03 +00001156{
1157 void *addr = alloca(addrlen);
ths3b46e622007-09-17 08:09:54 +00001158
bellard3532fa72006-06-24 15:06:03 +00001159 target_to_host_sockaddr(addr, target_addr, addrlen);
1160 return get_errno(connect(sockfd, addr, addrlen));
1161}
1162
ths0da46a62007-10-20 20:23:07 +00001163/* do_sendrecvmsg() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001164static abi_long do_sendrecvmsg(int fd, abi_ulong target_msg,
1165 int flags, int send)
bellard3532fa72006-06-24 15:06:03 +00001166{
balrog6de645c2008-10-28 10:26:29 +00001167 abi_long ret, len;
bellard3532fa72006-06-24 15:06:03 +00001168 struct target_msghdr *msgp;
1169 struct msghdr msg;
1170 int count;
1171 struct iovec *vec;
blueswir1992f48a2007-10-14 16:27:31 +00001172 abi_ulong target_vec;
bellard3532fa72006-06-24 15:06:03 +00001173
bellard579a97f2007-11-11 14:26:47 +00001174 /* FIXME */
1175 if (!lock_user_struct(send ? VERIFY_READ : VERIFY_WRITE,
1176 msgp,
1177 target_msg,
1178 send ? 1 : 0))
1179 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001180 if (msgp->msg_name) {
1181 msg.msg_namelen = tswap32(msgp->msg_namelen);
1182 msg.msg_name = alloca(msg.msg_namelen);
1183 target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name),
1184 msg.msg_namelen);
1185 } else {
1186 msg.msg_name = NULL;
1187 msg.msg_namelen = 0;
1188 }
1189 msg.msg_controllen = 2 * tswapl(msgp->msg_controllen);
1190 msg.msg_control = alloca(msg.msg_controllen);
1191 msg.msg_flags = tswap32(msgp->msg_flags);
ths3b46e622007-09-17 08:09:54 +00001192
bellard3532fa72006-06-24 15:06:03 +00001193 count = tswapl(msgp->msg_iovlen);
1194 vec = alloca(count * sizeof(struct iovec));
1195 target_vec = tswapl(msgp->msg_iov);
bellard579a97f2007-11-11 14:26:47 +00001196 lock_iovec(send ? VERIFY_READ : VERIFY_WRITE, vec, target_vec, count, send);
bellard3532fa72006-06-24 15:06:03 +00001197 msg.msg_iovlen = count;
1198 msg.msg_iov = vec;
ths3b46e622007-09-17 08:09:54 +00001199
bellard3532fa72006-06-24 15:06:03 +00001200 if (send) {
bellard5a4a8982007-11-11 17:39:18 +00001201 ret = target_to_host_cmsg(&msg, msgp);
1202 if (ret == 0)
1203 ret = get_errno(sendmsg(fd, &msg, flags));
bellard3532fa72006-06-24 15:06:03 +00001204 } else {
1205 ret = get_errno(recvmsg(fd, &msg, flags));
balrog6de645c2008-10-28 10:26:29 +00001206 if (!is_error(ret)) {
1207 len = ret;
bellard5a4a8982007-11-11 17:39:18 +00001208 ret = host_to_target_cmsg(msgp, &msg);
balrog6de645c2008-10-28 10:26:29 +00001209 if (!is_error(ret))
1210 ret = len;
1211 }
bellard3532fa72006-06-24 15:06:03 +00001212 }
1213 unlock_iovec(vec, target_vec, count, !send);
bellard579a97f2007-11-11 14:26:47 +00001214 unlock_user_struct(msgp, target_msg, send ? 0 : 1);
bellard3532fa72006-06-24 15:06:03 +00001215 return ret;
1216}
1217
ths0da46a62007-10-20 20:23:07 +00001218/* do_accept() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001219static abi_long do_accept(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001220 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001221{
bellard2f619692007-11-16 10:46:05 +00001222 socklen_t addrlen;
1223 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001224 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001225
bellard2f619692007-11-16 10:46:05 +00001226 if (get_user_u32(addrlen, target_addrlen_addr))
1227 return -TARGET_EFAULT;
1228
1229 addr = alloca(addrlen);
1230
pbrook1be9e1d2006-11-19 15:26:04 +00001231 ret = get_errno(accept(fd, addr, &addrlen));
1232 if (!is_error(ret)) {
1233 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001234 if (put_user_u32(addrlen, target_addrlen_addr))
1235 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001236 }
1237 return ret;
1238}
1239
ths0da46a62007-10-20 20:23:07 +00001240/* do_getpeername() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001241static abi_long do_getpeername(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001242 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001243{
bellard2f619692007-11-16 10:46:05 +00001244 socklen_t addrlen;
1245 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001246 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001247
bellard2f619692007-11-16 10:46:05 +00001248 if (get_user_u32(addrlen, target_addrlen_addr))
1249 return -TARGET_EFAULT;
1250
1251 addr = alloca(addrlen);
1252
pbrook1be9e1d2006-11-19 15:26:04 +00001253 ret = get_errno(getpeername(fd, addr, &addrlen));
1254 if (!is_error(ret)) {
1255 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001256 if (put_user_u32(addrlen, target_addrlen_addr))
1257 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001258 }
1259 return ret;
1260}
1261
ths0da46a62007-10-20 20:23:07 +00001262/* do_getsockname() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001263static abi_long do_getsockname(int fd, abi_ulong target_addr,
bellard2f619692007-11-16 10:46:05 +00001264 abi_ulong target_addrlen_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001265{
bellard2f619692007-11-16 10:46:05 +00001266 socklen_t addrlen;
1267 void *addr;
blueswir1992f48a2007-10-14 16:27:31 +00001268 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001269
bellard2f619692007-11-16 10:46:05 +00001270 if (get_user_u32(addrlen, target_addrlen_addr))
1271 return -TARGET_EFAULT;
1272
1273 addr = alloca(addrlen);
1274
pbrook1be9e1d2006-11-19 15:26:04 +00001275 ret = get_errno(getsockname(fd, addr, &addrlen));
1276 if (!is_error(ret)) {
1277 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001278 if (put_user_u32(addrlen, target_addrlen_addr))
1279 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001280 }
1281 return ret;
1282}
1283
ths0da46a62007-10-20 20:23:07 +00001284/* do_socketpair() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001285static abi_long do_socketpair(int domain, int type, int protocol,
bellard2f619692007-11-16 10:46:05 +00001286 abi_ulong target_tab_addr)
pbrook1be9e1d2006-11-19 15:26:04 +00001287{
1288 int tab[2];
blueswir1992f48a2007-10-14 16:27:31 +00001289 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001290
1291 ret = get_errno(socketpair(domain, type, protocol, tab));
1292 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00001293 if (put_user_s32(tab[0], target_tab_addr)
1294 || put_user_s32(tab[1], target_tab_addr + sizeof(tab[0])))
1295 ret = -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001296 }
1297 return ret;
1298}
1299
ths0da46a62007-10-20 20:23:07 +00001300/* do_sendto() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001301static abi_long do_sendto(int fd, abi_ulong msg, size_t len, int flags,
1302 abi_ulong target_addr, socklen_t addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001303{
1304 void *addr;
1305 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001306 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001307
bellard579a97f2007-11-11 14:26:47 +00001308 host_msg = lock_user(VERIFY_READ, msg, len, 1);
1309 if (!host_msg)
1310 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001311 if (target_addr) {
1312 addr = alloca(addrlen);
1313 target_to_host_sockaddr(addr, target_addr, addrlen);
1314 ret = get_errno(sendto(fd, host_msg, len, flags, addr, addrlen));
1315 } else {
1316 ret = get_errno(send(fd, host_msg, len, flags));
1317 }
1318 unlock_user(host_msg, msg, 0);
1319 return ret;
1320}
1321
ths0da46a62007-10-20 20:23:07 +00001322/* do_recvfrom() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001323static abi_long do_recvfrom(int fd, abi_ulong msg, size_t len, int flags,
1324 abi_ulong target_addr,
1325 abi_ulong target_addrlen)
pbrook1be9e1d2006-11-19 15:26:04 +00001326{
1327 socklen_t addrlen;
1328 void *addr;
1329 void *host_msg;
blueswir1992f48a2007-10-14 16:27:31 +00001330 abi_long ret;
pbrook1be9e1d2006-11-19 15:26:04 +00001331
bellard579a97f2007-11-11 14:26:47 +00001332 host_msg = lock_user(VERIFY_WRITE, msg, len, 0);
1333 if (!host_msg)
1334 return -TARGET_EFAULT;
pbrook1be9e1d2006-11-19 15:26:04 +00001335 if (target_addr) {
bellard2f619692007-11-16 10:46:05 +00001336 if (get_user_u32(addrlen, target_addrlen)) {
1337 ret = -TARGET_EFAULT;
1338 goto fail;
1339 }
pbrook1be9e1d2006-11-19 15:26:04 +00001340 addr = alloca(addrlen);
1341 ret = get_errno(recvfrom(fd, host_msg, len, flags, addr, &addrlen));
1342 } else {
1343 addr = NULL; /* To keep compiler quiet. */
1344 ret = get_errno(recv(fd, host_msg, len, flags));
1345 }
1346 if (!is_error(ret)) {
1347 if (target_addr) {
1348 host_to_target_sockaddr(target_addr, addr, addrlen);
bellard2f619692007-11-16 10:46:05 +00001349 if (put_user_u32(addrlen, target_addrlen)) {
1350 ret = -TARGET_EFAULT;
1351 goto fail;
1352 }
pbrook1be9e1d2006-11-19 15:26:04 +00001353 }
1354 unlock_user(host_msg, msg, len);
1355 } else {
bellard2f619692007-11-16 10:46:05 +00001356fail:
pbrook1be9e1d2006-11-19 15:26:04 +00001357 unlock_user(host_msg, msg, 0);
1358 }
1359 return ret;
1360}
1361
j_mayer32407102007-09-26 23:01:49 +00001362#ifdef TARGET_NR_socketcall
ths0da46a62007-10-20 20:23:07 +00001363/* do_socketcall() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00001364static abi_long do_socketcall(int num, abi_ulong vptr)
bellard31e31b82003-02-18 22:55:36 +00001365{
blueswir1992f48a2007-10-14 16:27:31 +00001366 abi_long ret;
1367 const int n = sizeof(abi_ulong);
bellard31e31b82003-02-18 22:55:36 +00001368
1369 switch(num) {
1370 case SOCKOP_socket:
bellard7854b052003-03-29 17:22:23 +00001371 {
bellard2f619692007-11-16 10:46:05 +00001372 int domain, type, protocol;
1373
1374 if (get_user_s32(domain, vptr)
1375 || get_user_s32(type, vptr + n)
1376 || get_user_s32(protocol, vptr + 2 * n))
1377 return -TARGET_EFAULT;
1378
bellard3532fa72006-06-24 15:06:03 +00001379 ret = do_socket(domain, type, protocol);
bellard7854b052003-03-29 17:22:23 +00001380 }
bellard31e31b82003-02-18 22:55:36 +00001381 break;
1382 case SOCKOP_bind:
bellard7854b052003-03-29 17:22:23 +00001383 {
bellard2f619692007-11-16 10:46:05 +00001384 int sockfd;
1385 abi_ulong target_addr;
1386 socklen_t addrlen;
1387
1388 if (get_user_s32(sockfd, vptr)
1389 || get_user_ual(target_addr, vptr + n)
1390 || get_user_u32(addrlen, vptr + 2 * n))
1391 return -TARGET_EFAULT;
1392
bellard3532fa72006-06-24 15:06:03 +00001393 ret = do_bind(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001394 }
bellard31e31b82003-02-18 22:55:36 +00001395 break;
1396 case SOCKOP_connect:
bellard7854b052003-03-29 17:22:23 +00001397 {
bellard2f619692007-11-16 10:46:05 +00001398 int sockfd;
1399 abi_ulong target_addr;
1400 socklen_t addrlen;
1401
1402 if (get_user_s32(sockfd, vptr)
1403 || get_user_ual(target_addr, vptr + n)
1404 || get_user_u32(addrlen, vptr + 2 * n))
1405 return -TARGET_EFAULT;
1406
bellard3532fa72006-06-24 15:06:03 +00001407 ret = do_connect(sockfd, target_addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001408 }
bellard31e31b82003-02-18 22:55:36 +00001409 break;
1410 case SOCKOP_listen:
bellard7854b052003-03-29 17:22:23 +00001411 {
bellard2f619692007-11-16 10:46:05 +00001412 int sockfd, backlog;
1413
1414 if (get_user_s32(sockfd, vptr)
1415 || get_user_s32(backlog, vptr + n))
1416 return -TARGET_EFAULT;
1417
bellard7854b052003-03-29 17:22:23 +00001418 ret = get_errno(listen(sockfd, backlog));
1419 }
bellard31e31b82003-02-18 22:55:36 +00001420 break;
1421 case SOCKOP_accept:
1422 {
bellard2f619692007-11-16 10:46:05 +00001423 int sockfd;
1424 abi_ulong target_addr, target_addrlen;
1425
1426 if (get_user_s32(sockfd, vptr)
1427 || get_user_ual(target_addr, vptr + n)
1428 || get_user_u32(target_addrlen, vptr + 2 * n))
1429 return -TARGET_EFAULT;
1430
pbrook1be9e1d2006-11-19 15:26:04 +00001431 ret = do_accept(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001432 }
1433 break;
1434 case SOCKOP_getsockname:
1435 {
bellard2f619692007-11-16 10:46:05 +00001436 int sockfd;
1437 abi_ulong target_addr, target_addrlen;
1438
1439 if (get_user_s32(sockfd, vptr)
1440 || get_user_ual(target_addr, vptr + n)
1441 || get_user_u32(target_addrlen, vptr + 2 * n))
1442 return -TARGET_EFAULT;
1443
pbrook1be9e1d2006-11-19 15:26:04 +00001444 ret = do_getsockname(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001445 }
1446 break;
1447 case SOCKOP_getpeername:
1448 {
bellard2f619692007-11-16 10:46:05 +00001449 int sockfd;
1450 abi_ulong target_addr, target_addrlen;
1451
1452 if (get_user_s32(sockfd, vptr)
1453 || get_user_ual(target_addr, vptr + n)
1454 || get_user_u32(target_addrlen, vptr + 2 * n))
1455 return -TARGET_EFAULT;
1456
pbrook1be9e1d2006-11-19 15:26:04 +00001457 ret = do_getpeername(sockfd, target_addr, target_addrlen);
bellard31e31b82003-02-18 22:55:36 +00001458 }
1459 break;
1460 case SOCKOP_socketpair:
1461 {
bellard2f619692007-11-16 10:46:05 +00001462 int domain, type, protocol;
1463 abi_ulong tab;
1464
1465 if (get_user_s32(domain, vptr)
1466 || get_user_s32(type, vptr + n)
1467 || get_user_s32(protocol, vptr + 2 * n)
1468 || get_user_ual(tab, vptr + 3 * n))
1469 return -TARGET_EFAULT;
1470
pbrook1be9e1d2006-11-19 15:26:04 +00001471 ret = do_socketpair(domain, type, protocol, tab);
bellard31e31b82003-02-18 22:55:36 +00001472 }
1473 break;
1474 case SOCKOP_send:
bellard7854b052003-03-29 17:22:23 +00001475 {
bellard2f619692007-11-16 10:46:05 +00001476 int sockfd;
1477 abi_ulong msg;
1478 size_t len;
1479 int flags;
1480
1481 if (get_user_s32(sockfd, vptr)
1482 || get_user_ual(msg, vptr + n)
1483 || get_user_ual(len, vptr + 2 * n)
1484 || get_user_s32(flags, vptr + 3 * n))
1485 return -TARGET_EFAULT;
1486
pbrook1be9e1d2006-11-19 15:26:04 +00001487 ret = do_sendto(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001488 }
bellard31e31b82003-02-18 22:55:36 +00001489 break;
1490 case SOCKOP_recv:
bellard7854b052003-03-29 17:22:23 +00001491 {
bellard2f619692007-11-16 10:46:05 +00001492 int sockfd;
1493 abi_ulong msg;
1494 size_t len;
1495 int flags;
1496
1497 if (get_user_s32(sockfd, vptr)
1498 || get_user_ual(msg, vptr + n)
1499 || get_user_ual(len, vptr + 2 * n)
1500 || get_user_s32(flags, vptr + 3 * n))
1501 return -TARGET_EFAULT;
1502
pbrook1be9e1d2006-11-19 15:26:04 +00001503 ret = do_recvfrom(sockfd, msg, len, flags, 0, 0);
bellard7854b052003-03-29 17:22:23 +00001504 }
bellard31e31b82003-02-18 22:55:36 +00001505 break;
1506 case SOCKOP_sendto:
bellard7854b052003-03-29 17:22:23 +00001507 {
bellard2f619692007-11-16 10:46:05 +00001508 int sockfd;
1509 abi_ulong msg;
1510 size_t len;
1511 int flags;
1512 abi_ulong addr;
1513 socklen_t addrlen;
1514
1515 if (get_user_s32(sockfd, vptr)
1516 || get_user_ual(msg, vptr + n)
1517 || get_user_ual(len, vptr + 2 * n)
1518 || get_user_s32(flags, vptr + 3 * n)
1519 || get_user_ual(addr, vptr + 4 * n)
1520 || get_user_u32(addrlen, vptr + 5 * n))
1521 return -TARGET_EFAULT;
1522
pbrook1be9e1d2006-11-19 15:26:04 +00001523 ret = do_sendto(sockfd, msg, len, flags, addr, addrlen);
bellard7854b052003-03-29 17:22:23 +00001524 }
bellard31e31b82003-02-18 22:55:36 +00001525 break;
1526 case SOCKOP_recvfrom:
1527 {
bellard2f619692007-11-16 10:46:05 +00001528 int sockfd;
1529 abi_ulong msg;
1530 size_t len;
1531 int flags;
1532 abi_ulong addr;
1533 socklen_t addrlen;
1534
1535 if (get_user_s32(sockfd, vptr)
1536 || get_user_ual(msg, vptr + n)
1537 || get_user_ual(len, vptr + 2 * n)
1538 || get_user_s32(flags, vptr + 3 * n)
1539 || get_user_ual(addr, vptr + 4 * n)
1540 || get_user_u32(addrlen, vptr + 5 * n))
1541 return -TARGET_EFAULT;
1542
pbrook1be9e1d2006-11-19 15:26:04 +00001543 ret = do_recvfrom(sockfd, msg, len, flags, addr, addrlen);
bellard31e31b82003-02-18 22:55:36 +00001544 }
1545 break;
1546 case SOCKOP_shutdown:
bellard7854b052003-03-29 17:22:23 +00001547 {
bellard2f619692007-11-16 10:46:05 +00001548 int sockfd, how;
1549
1550 if (get_user_s32(sockfd, vptr)
1551 || get_user_s32(how, vptr + n))
1552 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001553
1554 ret = get_errno(shutdown(sockfd, how));
1555 }
bellard31e31b82003-02-18 22:55:36 +00001556 break;
1557 case SOCKOP_sendmsg:
1558 case SOCKOP_recvmsg:
bellard1a9353d2003-03-16 20:28:50 +00001559 {
1560 int fd;
blueswir1992f48a2007-10-14 16:27:31 +00001561 abi_ulong target_msg;
bellard3532fa72006-06-24 15:06:03 +00001562 int flags;
bellard1a9353d2003-03-16 20:28:50 +00001563
bellard2f619692007-11-16 10:46:05 +00001564 if (get_user_s32(fd, vptr)
1565 || get_user_ual(target_msg, vptr + n)
1566 || get_user_s32(flags, vptr + 2 * n))
1567 return -TARGET_EFAULT;
bellard3532fa72006-06-24 15:06:03 +00001568
ths5fafdf22007-09-16 21:08:06 +00001569 ret = do_sendrecvmsg(fd, target_msg, flags,
bellard3532fa72006-06-24 15:06:03 +00001570 (num == SOCKOP_sendmsg));
bellard1a9353d2003-03-16 20:28:50 +00001571 }
1572 break;
bellard31e31b82003-02-18 22:55:36 +00001573 case SOCKOP_setsockopt:
bellard7854b052003-03-29 17:22:23 +00001574 {
bellard2f619692007-11-16 10:46:05 +00001575 int sockfd;
1576 int level;
1577 int optname;
1578 abi_ulong optval;
1579 socklen_t optlen;
1580
1581 if (get_user_s32(sockfd, vptr)
1582 || get_user_s32(level, vptr + n)
1583 || get_user_s32(optname, vptr + 2 * n)
1584 || get_user_ual(optval, vptr + 3 * n)
1585 || get_user_u32(optlen, vptr + 4 * n))
1586 return -TARGET_EFAULT;
bellard7854b052003-03-29 17:22:23 +00001587
1588 ret = do_setsockopt(sockfd, level, optname, optval, optlen);
1589 }
1590 break;
bellard31e31b82003-02-18 22:55:36 +00001591 case SOCKOP_getsockopt:
bellard7854b052003-03-29 17:22:23 +00001592 {
bellard2f619692007-11-16 10:46:05 +00001593 int sockfd;
1594 int level;
1595 int optname;
1596 abi_ulong optval;
1597 socklen_t optlen;
bellard7854b052003-03-29 17:22:23 +00001598
bellard2f619692007-11-16 10:46:05 +00001599 if (get_user_s32(sockfd, vptr)
1600 || get_user_s32(level, vptr + n)
1601 || get_user_s32(optname, vptr + 2 * n)
1602 || get_user_ual(optval, vptr + 3 * n)
1603 || get_user_u32(optlen, vptr + 4 * n))
1604 return -TARGET_EFAULT;
1605
1606 ret = do_getsockopt(sockfd, level, optname, optval, optlen);
bellard7854b052003-03-29 17:22:23 +00001607 }
1608 break;
bellard31e31b82003-02-18 22:55:36 +00001609 default:
1610 gemu_log("Unsupported socketcall: %d\n", num);
ths0da46a62007-10-20 20:23:07 +00001611 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00001612 break;
1613 }
1614 return ret;
1615}
j_mayer32407102007-09-26 23:01:49 +00001616#endif
bellard31e31b82003-02-18 22:55:36 +00001617
blueswir13f911a52008-12-13 11:37:02 +00001618#ifdef TARGET_NR_ipc
bellard8853f862004-02-22 14:57:26 +00001619#define N_SHM_REGIONS 32
1620
1621static struct shm_region {
bellard5a4a8982007-11-11 17:39:18 +00001622 abi_ulong start;
1623 abi_ulong size;
bellard8853f862004-02-22 14:57:26 +00001624} shm_regions[N_SHM_REGIONS];
blueswir13f911a52008-12-13 11:37:02 +00001625#endif
bellard8853f862004-02-22 14:57:26 +00001626
ths3eb6b042007-06-03 14:26:27 +00001627struct target_ipc_perm
1628{
blueswir1992f48a2007-10-14 16:27:31 +00001629 abi_long __key;
1630 abi_ulong uid;
1631 abi_ulong gid;
1632 abi_ulong cuid;
1633 abi_ulong cgid;
ths3eb6b042007-06-03 14:26:27 +00001634 unsigned short int mode;
1635 unsigned short int __pad1;
1636 unsigned short int __seq;
1637 unsigned short int __pad2;
blueswir1992f48a2007-10-14 16:27:31 +00001638 abi_ulong __unused1;
1639 abi_ulong __unused2;
ths3eb6b042007-06-03 14:26:27 +00001640};
1641
1642struct target_semid_ds
1643{
1644 struct target_ipc_perm sem_perm;
blueswir1992f48a2007-10-14 16:27:31 +00001645 abi_ulong sem_otime;
1646 abi_ulong __unused1;
1647 abi_ulong sem_ctime;
1648 abi_ulong __unused2;
1649 abi_ulong sem_nsems;
1650 abi_ulong __unused3;
1651 abi_ulong __unused4;
ths3eb6b042007-06-03 14:26:27 +00001652};
1653
bellard579a97f2007-11-11 14:26:47 +00001654static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
1655 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001656{
1657 struct target_ipc_perm *target_ip;
1658 struct target_semid_ds *target_sd;
1659
bellard579a97f2007-11-11 14:26:47 +00001660 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1661 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001662 target_ip=&(target_sd->sem_perm);
1663 host_ip->__key = tswapl(target_ip->__key);
1664 host_ip->uid = tswapl(target_ip->uid);
1665 host_ip->gid = tswapl(target_ip->gid);
1666 host_ip->cuid = tswapl(target_ip->cuid);
1667 host_ip->cgid = tswapl(target_ip->cgid);
1668 host_ip->mode = tswapl(target_ip->mode);
1669 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001670 return 0;
ths3eb6b042007-06-03 14:26:27 +00001671}
1672
bellard579a97f2007-11-11 14:26:47 +00001673static inline abi_long host_to_target_ipc_perm(abi_ulong target_addr,
1674 struct ipc_perm *host_ip)
ths3eb6b042007-06-03 14:26:27 +00001675{
1676 struct target_ipc_perm *target_ip;
1677 struct target_semid_ds *target_sd;
1678
bellard579a97f2007-11-11 14:26:47 +00001679 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1680 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001681 target_ip = &(target_sd->sem_perm);
1682 target_ip->__key = tswapl(host_ip->__key);
1683 target_ip->uid = tswapl(host_ip->uid);
1684 target_ip->gid = tswapl(host_ip->gid);
1685 target_ip->cuid = tswapl(host_ip->cuid);
1686 target_ip->cgid = tswapl(host_ip->cgid);
1687 target_ip->mode = tswapl(host_ip->mode);
1688 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001689 return 0;
ths3eb6b042007-06-03 14:26:27 +00001690}
1691
bellard579a97f2007-11-11 14:26:47 +00001692static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
1693 abi_ulong target_addr)
ths3eb6b042007-06-03 14:26:27 +00001694{
1695 struct target_semid_ds *target_sd;
1696
bellard579a97f2007-11-11 14:26:47 +00001697 if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1))
1698 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001699 target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr);
1700 host_sd->sem_nsems = tswapl(target_sd->sem_nsems);
1701 host_sd->sem_otime = tswapl(target_sd->sem_otime);
1702 host_sd->sem_ctime = tswapl(target_sd->sem_ctime);
1703 unlock_user_struct(target_sd, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001704 return 0;
ths3eb6b042007-06-03 14:26:27 +00001705}
1706
bellard579a97f2007-11-11 14:26:47 +00001707static inline abi_long host_to_target_semid_ds(abi_ulong target_addr,
1708 struct semid_ds *host_sd)
ths3eb6b042007-06-03 14:26:27 +00001709{
1710 struct target_semid_ds *target_sd;
1711
bellard579a97f2007-11-11 14:26:47 +00001712 if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0))
1713 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001714 host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm));
1715 target_sd->sem_nsems = tswapl(host_sd->sem_nsems);
1716 target_sd->sem_otime = tswapl(host_sd->sem_otime);
1717 target_sd->sem_ctime = tswapl(host_sd->sem_ctime);
1718 unlock_user_struct(target_sd, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001719 return 0;
ths3eb6b042007-06-03 14:26:27 +00001720}
1721
thsfa294812007-02-02 22:05:00 +00001722union semun {
1723 int val;
ths3eb6b042007-06-03 14:26:27 +00001724 struct semid_ds *buf;
thsfa294812007-02-02 22:05:00 +00001725 unsigned short *array;
1726};
1727
ths3eb6b042007-06-03 14:26:27 +00001728union target_semun {
1729 int val;
blueswir1992f48a2007-10-14 16:27:31 +00001730 abi_long buf;
ths3eb6b042007-06-03 14:26:27 +00001731 unsigned short int *array;
1732};
1733
bellard579a97f2007-11-11 14:26:47 +00001734static inline abi_long target_to_host_semun(int cmd,
1735 union semun *host_su,
1736 abi_ulong target_addr,
1737 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001738{
1739 union target_semun *target_su;
1740
1741 switch( cmd ) {
1742 case IPC_STAT:
1743 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001744 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1745 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001746 target_to_host_semid_ds(ds,target_su->buf);
1747 host_su->buf = ds;
1748 unlock_user_struct(target_su, target_addr, 0);
1749 break;
1750 case GETVAL:
1751 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001752 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1753 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001754 host_su->val = tswapl(target_su->val);
1755 unlock_user_struct(target_su, target_addr, 0);
1756 break;
1757 case GETALL:
1758 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001759 if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
1760 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001761 *host_su->array = tswap16(*target_su->array);
1762 unlock_user_struct(target_su, target_addr, 0);
1763 break;
1764 default:
1765 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1766 }
bellard579a97f2007-11-11 14:26:47 +00001767 return 0;
ths3eb6b042007-06-03 14:26:27 +00001768}
1769
bellard579a97f2007-11-11 14:26:47 +00001770static inline abi_long host_to_target_semun(int cmd,
1771 abi_ulong target_addr,
1772 union semun *host_su,
1773 struct semid_ds *ds)
ths3eb6b042007-06-03 14:26:27 +00001774{
1775 union target_semun *target_su;
1776
1777 switch( cmd ) {
1778 case IPC_STAT:
1779 case IPC_SET:
bellard579a97f2007-11-11 14:26:47 +00001780 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1781 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001782 host_to_target_semid_ds(target_su->buf,ds);
1783 unlock_user_struct(target_su, target_addr, 1);
1784 break;
1785 case GETVAL:
1786 case SETVAL:
bellard579a97f2007-11-11 14:26:47 +00001787 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1788 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001789 target_su->val = tswapl(host_su->val);
1790 unlock_user_struct(target_su, target_addr, 1);
1791 break;
1792 case GETALL:
1793 case SETALL:
bellard579a97f2007-11-11 14:26:47 +00001794 if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
1795 return -TARGET_EFAULT;
ths3eb6b042007-06-03 14:26:27 +00001796 *target_su->array = tswap16(*host_su->array);
1797 unlock_user_struct(target_su, target_addr, 1);
1798 break;
1799 default:
1800 gemu_log("semun operation not fully supported: %d\n", (int)cmd);
1801 }
bellard579a97f2007-11-11 14:26:47 +00001802 return 0;
ths3eb6b042007-06-03 14:26:27 +00001803}
1804
blueswir1992f48a2007-10-14 16:27:31 +00001805static inline abi_long do_semctl(int first, int second, int third,
1806 abi_long ptr)
ths3eb6b042007-06-03 14:26:27 +00001807{
1808 union semun arg;
1809 struct semid_ds dsarg;
1810 int cmd = third&0xff;
blueswir1992f48a2007-10-14 16:27:31 +00001811 abi_long ret = 0;
ths3eb6b042007-06-03 14:26:27 +00001812
1813 switch( cmd ) {
1814 case GETVAL:
1815 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1816 ret = get_errno(semctl(first, second, cmd, arg));
1817 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1818 break;
1819 case SETVAL:
1820 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1821 ret = get_errno(semctl(first, second, cmd, arg));
1822 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1823 break;
1824 case GETALL:
1825 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1826 ret = get_errno(semctl(first, second, cmd, arg));
1827 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1828 break;
1829 case SETALL:
1830 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1831 ret = get_errno(semctl(first, second, cmd, arg));
1832 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1833 break;
1834 case IPC_STAT:
1835 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1836 ret = get_errno(semctl(first, second, cmd, arg));
1837 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1838 break;
1839 case IPC_SET:
1840 target_to_host_semun(cmd,&arg,ptr,&dsarg);
1841 ret = get_errno(semctl(first, second, cmd, arg));
1842 host_to_target_semun(cmd,ptr,&arg,&dsarg);
1843 break;
1844 default:
1845 ret = get_errno(semctl(first, second, cmd, arg));
1846 }
1847
1848 return ret;
1849}
1850
ths1bc012f2007-06-03 14:27:49 +00001851struct target_msqid_ds
1852{
aurel321c54ff92008-10-13 21:08:44 +00001853 struct target_ipc_perm msg_perm;
1854 abi_ulong msg_stime;
1855#if TARGET_ABI_BITS == 32
1856 abi_ulong __unused1;
1857#endif
1858 abi_ulong msg_rtime;
1859#if TARGET_ABI_BITS == 32
1860 abi_ulong __unused2;
1861#endif
1862 abi_ulong msg_ctime;
1863#if TARGET_ABI_BITS == 32
1864 abi_ulong __unused3;
1865#endif
1866 abi_ulong __msg_cbytes;
1867 abi_ulong msg_qnum;
1868 abi_ulong msg_qbytes;
1869 abi_ulong msg_lspid;
1870 abi_ulong msg_lrpid;
1871 abi_ulong __unused4;
1872 abi_ulong __unused5;
ths1bc012f2007-06-03 14:27:49 +00001873};
1874
bellard579a97f2007-11-11 14:26:47 +00001875static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
1876 abi_ulong target_addr)
ths1bc012f2007-06-03 14:27:49 +00001877{
1878 struct target_msqid_ds *target_md;
1879
bellard579a97f2007-11-11 14:26:47 +00001880 if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1))
1881 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00001882 if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr))
1883 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001884 host_md->msg_stime = tswapl(target_md->msg_stime);
1885 host_md->msg_rtime = tswapl(target_md->msg_rtime);
1886 host_md->msg_ctime = tswapl(target_md->msg_ctime);
1887 host_md->__msg_cbytes = tswapl(target_md->__msg_cbytes);
1888 host_md->msg_qnum = tswapl(target_md->msg_qnum);
1889 host_md->msg_qbytes = tswapl(target_md->msg_qbytes);
1890 host_md->msg_lspid = tswapl(target_md->msg_lspid);
1891 host_md->msg_lrpid = tswapl(target_md->msg_lrpid);
1892 unlock_user_struct(target_md, target_addr, 0);
bellard579a97f2007-11-11 14:26:47 +00001893 return 0;
ths1bc012f2007-06-03 14:27:49 +00001894}
1895
bellard579a97f2007-11-11 14:26:47 +00001896static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr,
1897 struct msqid_ds *host_md)
ths1bc012f2007-06-03 14:27:49 +00001898{
1899 struct target_msqid_ds *target_md;
1900
bellard579a97f2007-11-11 14:26:47 +00001901 if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0))
1902 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00001903 if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)))
1904 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001905 target_md->msg_stime = tswapl(host_md->msg_stime);
1906 target_md->msg_rtime = tswapl(host_md->msg_rtime);
1907 target_md->msg_ctime = tswapl(host_md->msg_ctime);
1908 target_md->__msg_cbytes = tswapl(host_md->__msg_cbytes);
1909 target_md->msg_qnum = tswapl(host_md->msg_qnum);
1910 target_md->msg_qbytes = tswapl(host_md->msg_qbytes);
1911 target_md->msg_lspid = tswapl(host_md->msg_lspid);
1912 target_md->msg_lrpid = tswapl(host_md->msg_lrpid);
1913 unlock_user_struct(target_md, target_addr, 1);
bellard579a97f2007-11-11 14:26:47 +00001914 return 0;
ths1bc012f2007-06-03 14:27:49 +00001915}
1916
aurel321c54ff92008-10-13 21:08:44 +00001917struct target_msginfo {
1918 int msgpool;
1919 int msgmap;
1920 int msgmax;
1921 int msgmnb;
1922 int msgmni;
1923 int msgssz;
1924 int msgtql;
1925 unsigned short int msgseg;
1926};
1927
1928static inline abi_long host_to_target_msginfo(abi_ulong target_addr,
1929 struct msginfo *host_msginfo)
1930{
1931 struct target_msginfo *target_msginfo;
1932 if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0))
1933 return -TARGET_EFAULT;
1934 __put_user(host_msginfo->msgpool, &target_msginfo->msgpool);
1935 __put_user(host_msginfo->msgmap, &target_msginfo->msgmap);
1936 __put_user(host_msginfo->msgmax, &target_msginfo->msgmax);
1937 __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb);
1938 __put_user(host_msginfo->msgmni, &target_msginfo->msgmni);
1939 __put_user(host_msginfo->msgssz, &target_msginfo->msgssz);
1940 __put_user(host_msginfo->msgtql, &target_msginfo->msgtql);
1941 __put_user(host_msginfo->msgseg, &target_msginfo->msgseg);
1942 unlock_user_struct(target_msginfo, target_addr, 1);
aurel3200b229a2008-10-24 13:12:52 +00001943 return 0;
aurel321c54ff92008-10-13 21:08:44 +00001944}
1945
1946static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr)
ths1bc012f2007-06-03 14:27:49 +00001947{
1948 struct msqid_ds dsarg;
aurel321c54ff92008-10-13 21:08:44 +00001949 struct msginfo msginfo;
1950 abi_long ret = -TARGET_EINVAL;
1951
1952 cmd &= 0xff;
1953
1954 switch (cmd) {
ths1bc012f2007-06-03 14:27:49 +00001955 case IPC_STAT:
1956 case IPC_SET:
aurel321c54ff92008-10-13 21:08:44 +00001957 case MSG_STAT:
1958 if (target_to_host_msqid_ds(&dsarg,ptr))
1959 return -TARGET_EFAULT;
1960 ret = get_errno(msgctl(msgid, cmd, &dsarg));
1961 if (host_to_target_msqid_ds(ptr,&dsarg))
1962 return -TARGET_EFAULT;
1963 break;
1964 case IPC_RMID:
1965 ret = get_errno(msgctl(msgid, cmd, NULL));
1966 break;
1967 case IPC_INFO:
1968 case MSG_INFO:
1969 ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo));
1970 if (host_to_target_msginfo(ptr, &msginfo))
1971 return -TARGET_EFAULT;
1972 break;
ths1bc012f2007-06-03 14:27:49 +00001973 }
aurel321c54ff92008-10-13 21:08:44 +00001974
ths1bc012f2007-06-03 14:27:49 +00001975 return ret;
1976}
1977
1978struct target_msgbuf {
aurel321c54ff92008-10-13 21:08:44 +00001979 abi_long mtype;
1980 char mtext[1];
ths1bc012f2007-06-03 14:27:49 +00001981};
1982
blueswir1992f48a2007-10-14 16:27:31 +00001983static inline abi_long do_msgsnd(int msqid, abi_long msgp,
1984 unsigned int msgsz, int msgflg)
ths1bc012f2007-06-03 14:27:49 +00001985{
1986 struct target_msgbuf *target_mb;
1987 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00001988 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00001989
bellard579a97f2007-11-11 14:26:47 +00001990 if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0))
1991 return -TARGET_EFAULT;
ths1bc012f2007-06-03 14:27:49 +00001992 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00001993 host_mb->mtype = (abi_long) tswapl(target_mb->mtype);
1994 memcpy(host_mb->mtext, target_mb->mtext, msgsz);
ths1bc012f2007-06-03 14:27:49 +00001995 ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg));
1996 free(host_mb);
1997 unlock_user_struct(target_mb, msgp, 0);
1998
1999 return ret;
2000}
2001
blueswir1992f48a2007-10-14 16:27:31 +00002002static inline abi_long do_msgrcv(int msqid, abi_long msgp,
aurel321c54ff92008-10-13 21:08:44 +00002003 unsigned int msgsz, abi_long msgtyp,
blueswir1992f48a2007-10-14 16:27:31 +00002004 int msgflg)
ths1bc012f2007-06-03 14:27:49 +00002005{
2006 struct target_msgbuf *target_mb;
bellard579a97f2007-11-11 14:26:47 +00002007 char *target_mtext;
ths1bc012f2007-06-03 14:27:49 +00002008 struct msgbuf *host_mb;
blueswir1992f48a2007-10-14 16:27:31 +00002009 abi_long ret = 0;
ths1bc012f2007-06-03 14:27:49 +00002010
bellard579a97f2007-11-11 14:26:47 +00002011 if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0))
2012 return -TARGET_EFAULT;
aurel321c54ff92008-10-13 21:08:44 +00002013
ths1bc012f2007-06-03 14:27:49 +00002014 host_mb = malloc(msgsz+sizeof(long));
aurel321c54ff92008-10-13 21:08:44 +00002015 ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg));
2016
bellard579a97f2007-11-11 14:26:47 +00002017 if (ret > 0) {
2018 abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong);
2019 target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0);
2020 if (!target_mtext) {
2021 ret = -TARGET_EFAULT;
2022 goto end;
2023 }
aurel321c54ff92008-10-13 21:08:44 +00002024 memcpy(target_mb->mtext, host_mb->mtext, ret);
bellard579a97f2007-11-11 14:26:47 +00002025 unlock_user(target_mtext, target_mtext_addr, ret);
2026 }
aurel321c54ff92008-10-13 21:08:44 +00002027
ths1bc012f2007-06-03 14:27:49 +00002028 target_mb->mtype = tswapl(host_mb->mtype);
2029 free(host_mb);
ths1bc012f2007-06-03 14:27:49 +00002030
bellard579a97f2007-11-11 14:26:47 +00002031end:
2032 if (target_mb)
2033 unlock_user_struct(target_mb, msgp, 1);
ths1bc012f2007-06-03 14:27:49 +00002034 return ret;
2035}
2036
aurel321c54ff92008-10-13 21:08:44 +00002037#ifdef TARGET_NR_ipc
pbrook53a59602006-03-25 19:31:22 +00002038/* ??? This only works with linear mappings. */
ths0da46a62007-10-20 20:23:07 +00002039/* do_ipc() must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002040static abi_long do_ipc(unsigned int call, int first,
2041 int second, int third,
2042 abi_long ptr, abi_long fifth)
bellard8853f862004-02-22 14:57:26 +00002043{
2044 int version;
blueswir1992f48a2007-10-14 16:27:31 +00002045 abi_long ret = 0;
bellard8853f862004-02-22 14:57:26 +00002046 struct shmid_ds shm_info;
2047 int i;
2048
2049 version = call >> 16;
2050 call &= 0xffff;
2051
2052 switch (call) {
thsfa294812007-02-02 22:05:00 +00002053 case IPCOP_semop:
bellard579a97f2007-11-11 14:26:47 +00002054 ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second));
thsfa294812007-02-02 22:05:00 +00002055 break;
2056
2057 case IPCOP_semget:
2058 ret = get_errno(semget(first, second, third));
2059 break;
2060
2061 case IPCOP_semctl:
ths3eb6b042007-06-03 14:26:27 +00002062 ret = do_semctl(first, second, third, ptr);
thsfa294812007-02-02 22:05:00 +00002063 break;
2064
2065 case IPCOP_semtimedop:
j_mayer32407102007-09-26 23:01:49 +00002066 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002067 ret = -TARGET_ENOSYS;
thsfa294812007-02-02 22:05:00 +00002068 break;
thsd96372e2007-02-02 22:05:44 +00002069
aurel321c54ff92008-10-13 21:08:44 +00002070 case IPCOP_msgget:
2071 ret = get_errno(msgget(first, second));
2072 break;
thsd96372e2007-02-02 22:05:44 +00002073
aurel321c54ff92008-10-13 21:08:44 +00002074 case IPCOP_msgsnd:
2075 ret = do_msgsnd(first, ptr, second, third);
2076 break;
thsd96372e2007-02-02 22:05:44 +00002077
aurel321c54ff92008-10-13 21:08:44 +00002078 case IPCOP_msgctl:
2079 ret = do_msgctl(first, second, ptr);
2080 break;
thsd96372e2007-02-02 22:05:44 +00002081
aurel321c54ff92008-10-13 21:08:44 +00002082 case IPCOP_msgrcv:
2083 switch (version) {
2084 case 0:
2085 {
2086 struct target_ipc_kludge {
2087 abi_long msgp;
2088 abi_long msgtyp;
2089 } *tmp;
thsd96372e2007-02-02 22:05:44 +00002090
aurel321c54ff92008-10-13 21:08:44 +00002091 if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) {
2092 ret = -TARGET_EFAULT;
2093 break;
ths1bc012f2007-06-03 14:27:49 +00002094 }
aurel321c54ff92008-10-13 21:08:44 +00002095
2096 ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third);
2097
2098 unlock_user_struct(tmp, ptr, 0);
2099 break;
2100 }
2101 default:
2102 ret = do_msgrcv(first, ptr, second, fifth, third);
2103 }
2104 break;
thsd96372e2007-02-02 22:05:44 +00002105
bellard8853f862004-02-22 14:57:26 +00002106 case IPCOP_shmat:
bellard5a4a8982007-11-11 17:39:18 +00002107 {
2108 abi_ulong raddr;
2109 void *host_addr;
2110 /* SHM_* flags are the same on all linux platforms */
2111 host_addr = shmat(first, (void *)g2h(ptr), second);
2112 if (host_addr == (void *)-1) {
2113 ret = get_errno((long)host_addr);
bellard8853f862004-02-22 14:57:26 +00002114 break;
bellard5a4a8982007-11-11 17:39:18 +00002115 }
2116 raddr = h2g((unsigned long)host_addr);
2117 /* find out the length of the shared memory segment */
2118
2119 ret = get_errno(shmctl(first, IPC_STAT, &shm_info));
2120 if (is_error(ret)) {
2121 /* can't get length, bail out */
2122 shmdt(host_addr);
2123 break;
2124 }
2125 page_set_flags(raddr, raddr + shm_info.shm_segsz,
2126 PAGE_VALID | PAGE_READ |
2127 ((second & SHM_RDONLY)? 0: PAGE_WRITE));
2128 for (i = 0; i < N_SHM_REGIONS; ++i) {
2129 if (shm_regions[i].start == 0) {
2130 shm_regions[i].start = raddr;
2131 shm_regions[i].size = shm_info.shm_segsz;
2132 break;
2133 }
2134 }
bellard2f619692007-11-16 10:46:05 +00002135 if (put_user_ual(raddr, third))
bellard5a4a8982007-11-11 17:39:18 +00002136 return -TARGET_EFAULT;
2137 ret = 0;
2138 }
bellard8853f862004-02-22 14:57:26 +00002139 break;
2140 case IPCOP_shmdt:
2141 for (i = 0; i < N_SHM_REGIONS; ++i) {
2142 if (shm_regions[i].start == ptr) {
2143 shm_regions[i].start = 0;
2144 page_set_flags(ptr, shm_regions[i].size, 0);
2145 break;
2146 }
2147 }
bellard5a4a8982007-11-11 17:39:18 +00002148 ret = get_errno(shmdt((void *)g2h(ptr)));
bellard8853f862004-02-22 14:57:26 +00002149 break;
2150
2151 case IPCOP_shmget:
2152 /* IPC_* flag values are the same on all linux platforms */
2153 ret = get_errno(shmget(first, second, third));
2154 break;
2155
2156 /* IPC_* and SHM_* command values are the same on all linux platforms */
2157 case IPCOP_shmctl:
2158 switch(second) {
2159 case IPC_RMID:
2160 case SHM_LOCK:
2161 case SHM_UNLOCK:
2162 ret = get_errno(shmctl(first, second, NULL));
2163 break;
2164 default:
2165 goto unimplemented;
2166 }
2167 break;
2168 default:
2169 unimplemented:
j_mayer32407102007-09-26 23:01:49 +00002170 gemu_log("Unsupported ipc call: %d (version %d)\n", call, version);
ths0da46a62007-10-20 20:23:07 +00002171 ret = -TARGET_ENOSYS;
bellard8853f862004-02-22 14:57:26 +00002172 break;
2173 }
2174 return ret;
2175}
j_mayer32407102007-09-26 23:01:49 +00002176#endif
bellard8853f862004-02-22 14:57:26 +00002177
bellard31e31b82003-02-18 22:55:36 +00002178/* kernel structure types definitions */
2179#define IFNAMSIZ 16
2180
2181#define STRUCT(name, list...) STRUCT_ ## name,
2182#define STRUCT_SPECIAL(name) STRUCT_ ## name,
2183enum {
2184#include "syscall_types.h"
2185};
2186#undef STRUCT
2187#undef STRUCT_SPECIAL
2188
blueswir160dd3162008-10-05 11:45:25 +00002189#define STRUCT(name, list...) static const argtype struct_ ## name ## _def[] = { list, TYPE_NULL };
bellard31e31b82003-02-18 22:55:36 +00002190#define STRUCT_SPECIAL(name)
2191#include "syscall_types.h"
2192#undef STRUCT
2193#undef STRUCT_SPECIAL
2194
2195typedef struct IOCTLEntry {
bellard2ab83ea2003-06-15 19:56:46 +00002196 unsigned int target_cmd;
2197 unsigned int host_cmd;
bellard31e31b82003-02-18 22:55:36 +00002198 const char *name;
2199 int access;
bellard1a9353d2003-03-16 20:28:50 +00002200 const argtype arg_type[5];
bellard31e31b82003-02-18 22:55:36 +00002201} IOCTLEntry;
2202
2203#define IOC_R 0x0001
2204#define IOC_W 0x0002
2205#define IOC_RW (IOC_R | IOC_W)
2206
2207#define MAX_STRUCT_SIZE 4096
2208
blueswir19f106a72008-10-05 10:52:52 +00002209static IOCTLEntry ioctl_entries[] = {
bellard31e31b82003-02-18 22:55:36 +00002210#define IOCTL(cmd, access, types...) \
2211 { TARGET_ ## cmd, cmd, #cmd, access, { types } },
2212#include "ioctls.h"
2213 { 0, 0, },
2214};
2215
pbrook53a59602006-03-25 19:31:22 +00002216/* ??? Implement proper locking for ioctls. */
ths0da46a62007-10-20 20:23:07 +00002217/* do_ioctl() Must return target values and target errnos. */
blueswir1992f48a2007-10-14 16:27:31 +00002218static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
bellard31e31b82003-02-18 22:55:36 +00002219{
2220 const IOCTLEntry *ie;
2221 const argtype *arg_type;
blueswir1992f48a2007-10-14 16:27:31 +00002222 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00002223 uint8_t buf_temp[MAX_STRUCT_SIZE];
pbrook53a59602006-03-25 19:31:22 +00002224 int target_size;
2225 void *argptr;
bellard31e31b82003-02-18 22:55:36 +00002226
2227 ie = ioctl_entries;
2228 for(;;) {
2229 if (ie->target_cmd == 0) {
j_mayer32407102007-09-26 23:01:49 +00002230 gemu_log("Unsupported ioctl: cmd=0x%04lx\n", (long)cmd);
ths0da46a62007-10-20 20:23:07 +00002231 return -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002232 }
2233 if (ie->target_cmd == cmd)
2234 break;
2235 ie++;
2236 }
2237 arg_type = ie->arg_type;
bellard9de5e442003-03-23 16:49:39 +00002238#if defined(DEBUG)
j_mayer32407102007-09-26 23:01:49 +00002239 gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
bellard72f03902003-02-18 23:33:18 +00002240#endif
bellard31e31b82003-02-18 22:55:36 +00002241 switch(arg_type[0]) {
2242 case TYPE_NULL:
2243 /* no argument */
2244 ret = get_errno(ioctl(fd, ie->host_cmd));
2245 break;
2246 case TYPE_PTRVOID:
2247 case TYPE_INT:
2248 /* int argment */
2249 ret = get_errno(ioctl(fd, ie->host_cmd, arg));
2250 break;
2251 case TYPE_PTR:
2252 arg_type++;
pbrook53a59602006-03-25 19:31:22 +00002253 target_size = thunk_type_size(arg_type, 0);
bellard31e31b82003-02-18 22:55:36 +00002254 switch(ie->access) {
2255 case IOC_R:
2256 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2257 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002258 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2259 if (!argptr)
2260 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002261 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2262 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002263 }
2264 break;
2265 case IOC_W:
bellard579a97f2007-11-11 14:26:47 +00002266 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2267 if (!argptr)
2268 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002269 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2270 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002271 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2272 break;
2273 default:
2274 case IOC_RW:
bellard579a97f2007-11-11 14:26:47 +00002275 argptr = lock_user(VERIFY_READ, arg, target_size, 1);
2276 if (!argptr)
2277 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002278 thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
2279 unlock_user(argptr, arg, 0);
bellard31e31b82003-02-18 22:55:36 +00002280 ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp));
2281 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00002282 argptr = lock_user(VERIFY_WRITE, arg, target_size, 0);
2283 if (!argptr)
2284 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002285 thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET);
2286 unlock_user(argptr, arg, target_size);
bellard31e31b82003-02-18 22:55:36 +00002287 }
2288 break;
2289 }
2290 break;
2291 default:
j_mayer32407102007-09-26 23:01:49 +00002292 gemu_log("Unsupported ioctl type: cmd=0x%04lx type=%d\n",
2293 (long)cmd, arg_type[0]);
ths0da46a62007-10-20 20:23:07 +00002294 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00002295 break;
2296 }
2297 return ret;
2298}
2299
blueswir1b39bc502008-10-05 10:51:10 +00002300static const bitmask_transtbl iflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002301 { TARGET_IGNBRK, TARGET_IGNBRK, IGNBRK, IGNBRK },
2302 { TARGET_BRKINT, TARGET_BRKINT, BRKINT, BRKINT },
2303 { TARGET_IGNPAR, TARGET_IGNPAR, IGNPAR, IGNPAR },
2304 { TARGET_PARMRK, TARGET_PARMRK, PARMRK, PARMRK },
2305 { TARGET_INPCK, TARGET_INPCK, INPCK, INPCK },
2306 { TARGET_ISTRIP, TARGET_ISTRIP, ISTRIP, ISTRIP },
2307 { TARGET_INLCR, TARGET_INLCR, INLCR, INLCR },
2308 { TARGET_IGNCR, TARGET_IGNCR, IGNCR, IGNCR },
2309 { TARGET_ICRNL, TARGET_ICRNL, ICRNL, ICRNL },
2310 { TARGET_IUCLC, TARGET_IUCLC, IUCLC, IUCLC },
2311 { TARGET_IXON, TARGET_IXON, IXON, IXON },
2312 { TARGET_IXANY, TARGET_IXANY, IXANY, IXANY },
2313 { TARGET_IXOFF, TARGET_IXOFF, IXOFF, IXOFF },
2314 { TARGET_IMAXBEL, TARGET_IMAXBEL, IMAXBEL, IMAXBEL },
2315 { 0, 0, 0, 0 }
2316};
2317
blueswir1b39bc502008-10-05 10:51:10 +00002318static const bitmask_transtbl oflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002319 { TARGET_OPOST, TARGET_OPOST, OPOST, OPOST },
2320 { TARGET_OLCUC, TARGET_OLCUC, OLCUC, OLCUC },
2321 { TARGET_ONLCR, TARGET_ONLCR, ONLCR, ONLCR },
2322 { TARGET_OCRNL, TARGET_OCRNL, OCRNL, OCRNL },
2323 { TARGET_ONOCR, TARGET_ONOCR, ONOCR, ONOCR },
2324 { TARGET_ONLRET, TARGET_ONLRET, ONLRET, ONLRET },
2325 { TARGET_OFILL, TARGET_OFILL, OFILL, OFILL },
2326 { TARGET_OFDEL, TARGET_OFDEL, OFDEL, OFDEL },
2327 { TARGET_NLDLY, TARGET_NL0, NLDLY, NL0 },
2328 { TARGET_NLDLY, TARGET_NL1, NLDLY, NL1 },
2329 { TARGET_CRDLY, TARGET_CR0, CRDLY, CR0 },
2330 { TARGET_CRDLY, TARGET_CR1, CRDLY, CR1 },
2331 { TARGET_CRDLY, TARGET_CR2, CRDLY, CR2 },
2332 { TARGET_CRDLY, TARGET_CR3, CRDLY, CR3 },
2333 { TARGET_TABDLY, TARGET_TAB0, TABDLY, TAB0 },
2334 { TARGET_TABDLY, TARGET_TAB1, TABDLY, TAB1 },
2335 { TARGET_TABDLY, TARGET_TAB2, TABDLY, TAB2 },
2336 { TARGET_TABDLY, TARGET_TAB3, TABDLY, TAB3 },
2337 { TARGET_BSDLY, TARGET_BS0, BSDLY, BS0 },
2338 { TARGET_BSDLY, TARGET_BS1, BSDLY, BS1 },
2339 { TARGET_VTDLY, TARGET_VT0, VTDLY, VT0 },
2340 { TARGET_VTDLY, TARGET_VT1, VTDLY, VT1 },
2341 { TARGET_FFDLY, TARGET_FF0, FFDLY, FF0 },
2342 { TARGET_FFDLY, TARGET_FF1, FFDLY, FF1 },
2343 { 0, 0, 0, 0 }
2344};
2345
blueswir1b39bc502008-10-05 10:51:10 +00002346static const bitmask_transtbl cflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002347 { TARGET_CBAUD, TARGET_B0, CBAUD, B0 },
2348 { TARGET_CBAUD, TARGET_B50, CBAUD, B50 },
2349 { TARGET_CBAUD, TARGET_B75, CBAUD, B75 },
2350 { TARGET_CBAUD, TARGET_B110, CBAUD, B110 },
2351 { TARGET_CBAUD, TARGET_B134, CBAUD, B134 },
2352 { TARGET_CBAUD, TARGET_B150, CBAUD, B150 },
2353 { TARGET_CBAUD, TARGET_B200, CBAUD, B200 },
2354 { TARGET_CBAUD, TARGET_B300, CBAUD, B300 },
2355 { TARGET_CBAUD, TARGET_B600, CBAUD, B600 },
2356 { TARGET_CBAUD, TARGET_B1200, CBAUD, B1200 },
2357 { TARGET_CBAUD, TARGET_B1800, CBAUD, B1800 },
2358 { TARGET_CBAUD, TARGET_B2400, CBAUD, B2400 },
2359 { TARGET_CBAUD, TARGET_B4800, CBAUD, B4800 },
2360 { TARGET_CBAUD, TARGET_B9600, CBAUD, B9600 },
2361 { TARGET_CBAUD, TARGET_B19200, CBAUD, B19200 },
2362 { TARGET_CBAUD, TARGET_B38400, CBAUD, B38400 },
2363 { TARGET_CBAUD, TARGET_B57600, CBAUD, B57600 },
2364 { TARGET_CBAUD, TARGET_B115200, CBAUD, B115200 },
2365 { TARGET_CBAUD, TARGET_B230400, CBAUD, B230400 },
2366 { TARGET_CBAUD, TARGET_B460800, CBAUD, B460800 },
2367 { TARGET_CSIZE, TARGET_CS5, CSIZE, CS5 },
2368 { TARGET_CSIZE, TARGET_CS6, CSIZE, CS6 },
2369 { TARGET_CSIZE, TARGET_CS7, CSIZE, CS7 },
2370 { TARGET_CSIZE, TARGET_CS8, CSIZE, CS8 },
2371 { TARGET_CSTOPB, TARGET_CSTOPB, CSTOPB, CSTOPB },
2372 { TARGET_CREAD, TARGET_CREAD, CREAD, CREAD },
2373 { TARGET_PARENB, TARGET_PARENB, PARENB, PARENB },
2374 { TARGET_PARODD, TARGET_PARODD, PARODD, PARODD },
2375 { TARGET_HUPCL, TARGET_HUPCL, HUPCL, HUPCL },
2376 { TARGET_CLOCAL, TARGET_CLOCAL, CLOCAL, CLOCAL },
2377 { TARGET_CRTSCTS, TARGET_CRTSCTS, CRTSCTS, CRTSCTS },
2378 { 0, 0, 0, 0 }
2379};
2380
blueswir1b39bc502008-10-05 10:51:10 +00002381static const bitmask_transtbl lflag_tbl[] = {
bellard31e31b82003-02-18 22:55:36 +00002382 { TARGET_ISIG, TARGET_ISIG, ISIG, ISIG },
2383 { TARGET_ICANON, TARGET_ICANON, ICANON, ICANON },
2384 { TARGET_XCASE, TARGET_XCASE, XCASE, XCASE },
2385 { TARGET_ECHO, TARGET_ECHO, ECHO, ECHO },
2386 { TARGET_ECHOE, TARGET_ECHOE, ECHOE, ECHOE },
2387 { TARGET_ECHOK, TARGET_ECHOK, ECHOK, ECHOK },
2388 { TARGET_ECHONL, TARGET_ECHONL, ECHONL, ECHONL },
2389 { TARGET_NOFLSH, TARGET_NOFLSH, NOFLSH, NOFLSH },
2390 { TARGET_TOSTOP, TARGET_TOSTOP, TOSTOP, TOSTOP },
2391 { TARGET_ECHOCTL, TARGET_ECHOCTL, ECHOCTL, ECHOCTL },
2392 { TARGET_ECHOPRT, TARGET_ECHOPRT, ECHOPRT, ECHOPRT },
2393 { TARGET_ECHOKE, TARGET_ECHOKE, ECHOKE, ECHOKE },
2394 { TARGET_FLUSHO, TARGET_FLUSHO, FLUSHO, FLUSHO },
2395 { TARGET_PENDIN, TARGET_PENDIN, PENDIN, PENDIN },
2396 { TARGET_IEXTEN, TARGET_IEXTEN, IEXTEN, IEXTEN },
2397 { 0, 0, 0, 0 }
2398};
2399
2400static void target_to_host_termios (void *dst, const void *src)
2401{
2402 struct host_termios *host = dst;
2403 const struct target_termios *target = src;
ths3b46e622007-09-17 08:09:54 +00002404
ths5fafdf22007-09-16 21:08:06 +00002405 host->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002406 target_to_host_bitmask(tswap32(target->c_iflag), iflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002407 host->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002408 target_to_host_bitmask(tswap32(target->c_oflag), oflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002409 host->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002410 target_to_host_bitmask(tswap32(target->c_cflag), cflag_tbl);
ths5fafdf22007-09-16 21:08:06 +00002411 host->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002412 target_to_host_bitmask(tswap32(target->c_lflag), lflag_tbl);
2413 host->c_line = target->c_line;
ths3b46e622007-09-17 08:09:54 +00002414
ths5fafdf22007-09-16 21:08:06 +00002415 host->c_cc[VINTR] = target->c_cc[TARGET_VINTR];
2416 host->c_cc[VQUIT] = target->c_cc[TARGET_VQUIT];
ths3b46e622007-09-17 08:09:54 +00002417 host->c_cc[VERASE] = target->c_cc[TARGET_VERASE];
ths5fafdf22007-09-16 21:08:06 +00002418 host->c_cc[VKILL] = target->c_cc[TARGET_VKILL];
ths3b46e622007-09-17 08:09:54 +00002419 host->c_cc[VEOF] = target->c_cc[TARGET_VEOF];
ths5fafdf22007-09-16 21:08:06 +00002420 host->c_cc[VTIME] = target->c_cc[TARGET_VTIME];
ths3b46e622007-09-17 08:09:54 +00002421 host->c_cc[VMIN] = target->c_cc[TARGET_VMIN];
ths5fafdf22007-09-16 21:08:06 +00002422 host->c_cc[VSWTC] = target->c_cc[TARGET_VSWTC];
ths3b46e622007-09-17 08:09:54 +00002423 host->c_cc[VSTART] = target->c_cc[TARGET_VSTART];
ths5fafdf22007-09-16 21:08:06 +00002424 host->c_cc[VSTOP] = target->c_cc[TARGET_VSTOP];
2425 host->c_cc[VSUSP] = target->c_cc[TARGET_VSUSP];
ths3b46e622007-09-17 08:09:54 +00002426 host->c_cc[VEOL] = target->c_cc[TARGET_VEOL];
2427 host->c_cc[VREPRINT] = target->c_cc[TARGET_VREPRINT];
2428 host->c_cc[VDISCARD] = target->c_cc[TARGET_VDISCARD];
2429 host->c_cc[VWERASE] = target->c_cc[TARGET_VWERASE];
2430 host->c_cc[VLNEXT] = target->c_cc[TARGET_VLNEXT];
ths5fafdf22007-09-16 21:08:06 +00002431 host->c_cc[VEOL2] = target->c_cc[TARGET_VEOL2];
bellard31e31b82003-02-18 22:55:36 +00002432}
ths3b46e622007-09-17 08:09:54 +00002433
bellard31e31b82003-02-18 22:55:36 +00002434static void host_to_target_termios (void *dst, const void *src)
2435{
2436 struct target_termios *target = dst;
2437 const struct host_termios *host = src;
2438
ths5fafdf22007-09-16 21:08:06 +00002439 target->c_iflag =
bellard31e31b82003-02-18 22:55:36 +00002440 tswap32(host_to_target_bitmask(host->c_iflag, iflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002441 target->c_oflag =
bellard31e31b82003-02-18 22:55:36 +00002442 tswap32(host_to_target_bitmask(host->c_oflag, oflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002443 target->c_cflag =
bellard31e31b82003-02-18 22:55:36 +00002444 tswap32(host_to_target_bitmask(host->c_cflag, cflag_tbl));
ths5fafdf22007-09-16 21:08:06 +00002445 target->c_lflag =
bellard31e31b82003-02-18 22:55:36 +00002446 tswap32(host_to_target_bitmask(host->c_lflag, lflag_tbl));
2447 target->c_line = host->c_line;
ths3b46e622007-09-17 08:09:54 +00002448
bellard31e31b82003-02-18 22:55:36 +00002449 target->c_cc[TARGET_VINTR] = host->c_cc[VINTR];
2450 target->c_cc[TARGET_VQUIT] = host->c_cc[VQUIT];
2451 target->c_cc[TARGET_VERASE] = host->c_cc[VERASE];
2452 target->c_cc[TARGET_VKILL] = host->c_cc[VKILL];
2453 target->c_cc[TARGET_VEOF] = host->c_cc[VEOF];
2454 target->c_cc[TARGET_VTIME] = host->c_cc[VTIME];
2455 target->c_cc[TARGET_VMIN] = host->c_cc[VMIN];
2456 target->c_cc[TARGET_VSWTC] = host->c_cc[VSWTC];
2457 target->c_cc[TARGET_VSTART] = host->c_cc[VSTART];
2458 target->c_cc[TARGET_VSTOP] = host->c_cc[VSTOP];
2459 target->c_cc[TARGET_VSUSP] = host->c_cc[VSUSP];
2460 target->c_cc[TARGET_VEOL] = host->c_cc[VEOL];
2461 target->c_cc[TARGET_VREPRINT] = host->c_cc[VREPRINT];
2462 target->c_cc[TARGET_VDISCARD] = host->c_cc[VDISCARD];
2463 target->c_cc[TARGET_VWERASE] = host->c_cc[VWERASE];
2464 target->c_cc[TARGET_VLNEXT] = host->c_cc[VLNEXT];
2465 target->c_cc[TARGET_VEOL2] = host->c_cc[VEOL2];
2466}
2467
blueswir18e853dc2008-10-05 10:49:32 +00002468static const StructEntry struct_termios_def = {
bellard31e31b82003-02-18 22:55:36 +00002469 .convert = { host_to_target_termios, target_to_host_termios },
2470 .size = { sizeof(struct target_termios), sizeof(struct host_termios) },
2471 .align = { __alignof__(struct target_termios), __alignof__(struct host_termios) },
2472};
2473
bellard5286db72003-06-05 00:57:30 +00002474static bitmask_transtbl mmap_flags_tbl[] = {
2475 { TARGET_MAP_SHARED, TARGET_MAP_SHARED, MAP_SHARED, MAP_SHARED },
2476 { TARGET_MAP_PRIVATE, TARGET_MAP_PRIVATE, MAP_PRIVATE, MAP_PRIVATE },
2477 { TARGET_MAP_FIXED, TARGET_MAP_FIXED, MAP_FIXED, MAP_FIXED },
2478 { TARGET_MAP_ANONYMOUS, TARGET_MAP_ANONYMOUS, MAP_ANONYMOUS, MAP_ANONYMOUS },
2479 { TARGET_MAP_GROWSDOWN, TARGET_MAP_GROWSDOWN, MAP_GROWSDOWN, MAP_GROWSDOWN },
2480 { TARGET_MAP_DENYWRITE, TARGET_MAP_DENYWRITE, MAP_DENYWRITE, MAP_DENYWRITE },
2481 { TARGET_MAP_EXECUTABLE, TARGET_MAP_EXECUTABLE, MAP_EXECUTABLE, MAP_EXECUTABLE },
2482 { TARGET_MAP_LOCKED, TARGET_MAP_LOCKED, MAP_LOCKED, MAP_LOCKED },
2483 { 0, 0, 0, 0 }
2484};
2485
bellardffa65c32004-01-04 23:57:22 +00002486static bitmask_transtbl fcntl_flags_tbl[] = {
2487 { TARGET_O_ACCMODE, TARGET_O_WRONLY, O_ACCMODE, O_WRONLY, },
2488 { TARGET_O_ACCMODE, TARGET_O_RDWR, O_ACCMODE, O_RDWR, },
2489 { TARGET_O_CREAT, TARGET_O_CREAT, O_CREAT, O_CREAT, },
2490 { TARGET_O_EXCL, TARGET_O_EXCL, O_EXCL, O_EXCL, },
2491 { TARGET_O_NOCTTY, TARGET_O_NOCTTY, O_NOCTTY, O_NOCTTY, },
2492 { TARGET_O_TRUNC, TARGET_O_TRUNC, O_TRUNC, O_TRUNC, },
2493 { TARGET_O_APPEND, TARGET_O_APPEND, O_APPEND, O_APPEND, },
2494 { TARGET_O_NONBLOCK, TARGET_O_NONBLOCK, O_NONBLOCK, O_NONBLOCK, },
2495 { TARGET_O_SYNC, TARGET_O_SYNC, O_SYNC, O_SYNC, },
2496 { TARGET_FASYNC, TARGET_FASYNC, FASYNC, FASYNC, },
2497 { TARGET_O_DIRECTORY, TARGET_O_DIRECTORY, O_DIRECTORY, O_DIRECTORY, },
2498 { TARGET_O_NOFOLLOW, TARGET_O_NOFOLLOW, O_NOFOLLOW, O_NOFOLLOW, },
2499 { TARGET_O_LARGEFILE, TARGET_O_LARGEFILE, O_LARGEFILE, O_LARGEFILE, },
bellard121061d2004-02-22 11:56:01 +00002500#if defined(O_DIRECT)
bellardffa65c32004-01-04 23:57:22 +00002501 { TARGET_O_DIRECT, TARGET_O_DIRECT, O_DIRECT, O_DIRECT, },
bellard121061d2004-02-22 11:56:01 +00002502#endif
bellardffa65c32004-01-04 23:57:22 +00002503 { 0, 0, 0, 0 }
2504};
2505
bellard2ab83ea2003-06-15 19:56:46 +00002506#if defined(TARGET_I386)
bellard6dbad632003-03-16 18:05:05 +00002507
2508/* NOTE: there is really one LDT for all the threads */
blueswir1b1d8e522008-10-26 13:43:07 +00002509static uint8_t *ldt_table;
bellard6dbad632003-03-16 18:05:05 +00002510
bellard03acab62007-11-11 14:57:14 +00002511static abi_long read_ldt(abi_ulong ptr, unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002512{
2513 int size;
pbrook53a59602006-03-25 19:31:22 +00002514 void *p;
bellard6dbad632003-03-16 18:05:05 +00002515
2516 if (!ldt_table)
2517 return 0;
2518 size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE;
2519 if (size > bytecount)
2520 size = bytecount;
bellard579a97f2007-11-11 14:26:47 +00002521 p = lock_user(VERIFY_WRITE, ptr, size, 0);
2522 if (!p)
bellard03acab62007-11-11 14:57:14 +00002523 return -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00002524 /* ??? Should this by byteswapped? */
pbrook53a59602006-03-25 19:31:22 +00002525 memcpy(p, ldt_table, size);
2526 unlock_user(p, ptr, size);
bellard6dbad632003-03-16 18:05:05 +00002527 return size;
2528}
2529
2530/* XXX: add locking support */
bellard03acab62007-11-11 14:57:14 +00002531static abi_long write_ldt(CPUX86State *env,
2532 abi_ulong ptr, unsigned long bytecount, int oldmode)
bellard6dbad632003-03-16 18:05:05 +00002533{
2534 struct target_modify_ldt_ldt_s ldt_info;
pbrook53a59602006-03-25 19:31:22 +00002535 struct target_modify_ldt_ldt_s *target_ldt_info;
bellard6dbad632003-03-16 18:05:05 +00002536 int seg_32bit, contents, read_exec_only, limit_in_pages;
bellard8d18e892007-11-14 15:18:40 +00002537 int seg_not_present, useable, lm;
bellard6dbad632003-03-16 18:05:05 +00002538 uint32_t *lp, entry_1, entry_2;
2539
2540 if (bytecount != sizeof(ldt_info))
bellard03acab62007-11-11 14:57:14 +00002541 return -TARGET_EINVAL;
bellard579a97f2007-11-11 14:26:47 +00002542 if (!lock_user_struct(VERIFY_READ, target_ldt_info, ptr, 1))
bellard03acab62007-11-11 14:57:14 +00002543 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00002544 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2545 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2546 ldt_info.limit = tswap32(target_ldt_info->limit);
2547 ldt_info.flags = tswap32(target_ldt_info->flags);
2548 unlock_user_struct(target_ldt_info, ptr, 0);
ths3b46e622007-09-17 08:09:54 +00002549
bellard6dbad632003-03-16 18:05:05 +00002550 if (ldt_info.entry_number >= TARGET_LDT_ENTRIES)
bellard03acab62007-11-11 14:57:14 +00002551 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002552 seg_32bit = ldt_info.flags & 1;
2553 contents = (ldt_info.flags >> 1) & 3;
2554 read_exec_only = (ldt_info.flags >> 3) & 1;
2555 limit_in_pages = (ldt_info.flags >> 4) & 1;
2556 seg_not_present = (ldt_info.flags >> 5) & 1;
2557 useable = (ldt_info.flags >> 6) & 1;
bellard8d18e892007-11-14 15:18:40 +00002558#ifdef TARGET_ABI32
2559 lm = 0;
2560#else
2561 lm = (ldt_info.flags >> 7) & 1;
2562#endif
bellard6dbad632003-03-16 18:05:05 +00002563 if (contents == 3) {
2564 if (oldmode)
bellard03acab62007-11-11 14:57:14 +00002565 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002566 if (seg_not_present == 0)
bellard03acab62007-11-11 14:57:14 +00002567 return -TARGET_EINVAL;
bellard6dbad632003-03-16 18:05:05 +00002568 }
2569 /* allocate the LDT */
2570 if (!ldt_table) {
balroge4415702008-11-10 02:55:33 +00002571 env->ldt.base = target_mmap(0,
2572 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE,
2573 PROT_READ|PROT_WRITE,
2574 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
2575 if (env->ldt.base == -1)
bellard03acab62007-11-11 14:57:14 +00002576 return -TARGET_ENOMEM;
balroge4415702008-11-10 02:55:33 +00002577 memset(g2h(env->ldt.base), 0,
2578 TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE);
bellard6dbad632003-03-16 18:05:05 +00002579 env->ldt.limit = 0xffff;
balroge4415702008-11-10 02:55:33 +00002580 ldt_table = g2h(env->ldt.base);
bellard6dbad632003-03-16 18:05:05 +00002581 }
2582
2583 /* NOTE: same code as Linux kernel */
2584 /* Allow LDTs to be cleared by the user. */
2585 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2586 if (oldmode ||
2587 (contents == 0 &&
2588 read_exec_only == 1 &&
2589 seg_32bit == 0 &&
2590 limit_in_pages == 0 &&
2591 seg_not_present == 1 &&
2592 useable == 0 )) {
2593 entry_1 = 0;
2594 entry_2 = 0;
2595 goto install;
2596 }
2597 }
ths3b46e622007-09-17 08:09:54 +00002598
bellard6dbad632003-03-16 18:05:05 +00002599 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2600 (ldt_info.limit & 0x0ffff);
2601 entry_2 = (ldt_info.base_addr & 0xff000000) |
2602 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2603 (ldt_info.limit & 0xf0000) |
2604 ((read_exec_only ^ 1) << 9) |
2605 (contents << 10) |
2606 ((seg_not_present ^ 1) << 15) |
2607 (seg_32bit << 22) |
2608 (limit_in_pages << 23) |
bellard8d18e892007-11-14 15:18:40 +00002609 (lm << 21) |
bellard6dbad632003-03-16 18:05:05 +00002610 0x7000;
2611 if (!oldmode)
2612 entry_2 |= (useable << 20);
bellard14ae3ba2003-05-27 23:25:06 +00002613
bellard6dbad632003-03-16 18:05:05 +00002614 /* Install the new entry ... */
2615install:
2616 lp = (uint32_t *)(ldt_table + (ldt_info.entry_number << 3));
2617 lp[0] = tswap32(entry_1);
2618 lp[1] = tswap32(entry_2);
2619 return 0;
2620}
2621
2622/* specific and weird i386 syscalls */
blueswir18fcd3692008-08-17 20:26:25 +00002623static abi_long do_modify_ldt(CPUX86State *env, int func, abi_ulong ptr,
2624 unsigned long bytecount)
bellard6dbad632003-03-16 18:05:05 +00002625{
bellard03acab62007-11-11 14:57:14 +00002626 abi_long ret;
ths3b46e622007-09-17 08:09:54 +00002627
bellard6dbad632003-03-16 18:05:05 +00002628 switch (func) {
2629 case 0:
2630 ret = read_ldt(ptr, bytecount);
2631 break;
2632 case 1:
2633 ret = write_ldt(env, ptr, bytecount, 1);
2634 break;
2635 case 0x11:
2636 ret = write_ldt(env, ptr, bytecount, 0);
2637 break;
bellard03acab62007-11-11 14:57:14 +00002638 default:
2639 ret = -TARGET_ENOSYS;
2640 break;
bellard6dbad632003-03-16 18:05:05 +00002641 }
2642 return ret;
2643}
bellard1b6b0292003-03-22 17:31:38 +00002644
blueswir14583f582008-08-24 10:35:55 +00002645#if defined(TARGET_I386) && defined(TARGET_ABI32)
blueswir18fcd3692008-08-17 20:26:25 +00002646static abi_long do_set_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002647{
2648 uint64_t *gdt_table = g2h(env->gdt.base);
2649 struct target_modify_ldt_ldt_s ldt_info;
2650 struct target_modify_ldt_ldt_s *target_ldt_info;
2651 int seg_32bit, contents, read_exec_only, limit_in_pages;
2652 int seg_not_present, useable, lm;
2653 uint32_t *lp, entry_1, entry_2;
2654 int i;
2655
2656 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2657 if (!target_ldt_info)
2658 return -TARGET_EFAULT;
2659 ldt_info.entry_number = tswap32(target_ldt_info->entry_number);
2660 ldt_info.base_addr = tswapl(target_ldt_info->base_addr);
2661 ldt_info.limit = tswap32(target_ldt_info->limit);
2662 ldt_info.flags = tswap32(target_ldt_info->flags);
2663 if (ldt_info.entry_number == -1) {
2664 for (i=TARGET_GDT_ENTRY_TLS_MIN; i<=TARGET_GDT_ENTRY_TLS_MAX; i++) {
2665 if (gdt_table[i] == 0) {
2666 ldt_info.entry_number = i;
2667 target_ldt_info->entry_number = tswap32(i);
2668 break;
2669 }
2670 }
2671 }
2672 unlock_user_struct(target_ldt_info, ptr, 1);
2673
2674 if (ldt_info.entry_number < TARGET_GDT_ENTRY_TLS_MIN ||
2675 ldt_info.entry_number > TARGET_GDT_ENTRY_TLS_MAX)
2676 return -TARGET_EINVAL;
2677 seg_32bit = ldt_info.flags & 1;
2678 contents = (ldt_info.flags >> 1) & 3;
2679 read_exec_only = (ldt_info.flags >> 3) & 1;
2680 limit_in_pages = (ldt_info.flags >> 4) & 1;
2681 seg_not_present = (ldt_info.flags >> 5) & 1;
2682 useable = (ldt_info.flags >> 6) & 1;
2683#ifdef TARGET_ABI32
2684 lm = 0;
2685#else
2686 lm = (ldt_info.flags >> 7) & 1;
2687#endif
2688
2689 if (contents == 3) {
2690 if (seg_not_present == 0)
2691 return -TARGET_EINVAL;
2692 }
2693
2694 /* NOTE: same code as Linux kernel */
2695 /* Allow LDTs to be cleared by the user. */
2696 if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
2697 if ((contents == 0 &&
2698 read_exec_only == 1 &&
2699 seg_32bit == 0 &&
2700 limit_in_pages == 0 &&
2701 seg_not_present == 1 &&
2702 useable == 0 )) {
2703 entry_1 = 0;
2704 entry_2 = 0;
2705 goto install;
2706 }
2707 }
2708
2709 entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
2710 (ldt_info.limit & 0x0ffff);
2711 entry_2 = (ldt_info.base_addr & 0xff000000) |
2712 ((ldt_info.base_addr & 0x00ff0000) >> 16) |
2713 (ldt_info.limit & 0xf0000) |
2714 ((read_exec_only ^ 1) << 9) |
2715 (contents << 10) |
2716 ((seg_not_present ^ 1) << 15) |
2717 (seg_32bit << 22) |
2718 (limit_in_pages << 23) |
2719 (useable << 20) |
2720 (lm << 21) |
2721 0x7000;
2722
2723 /* Install the new entry ... */
2724install:
2725 lp = (uint32_t *)(gdt_table + ldt_info.entry_number);
2726 lp[0] = tswap32(entry_1);
2727 lp[1] = tswap32(entry_2);
2728 return 0;
2729}
2730
blueswir18fcd3692008-08-17 20:26:25 +00002731static abi_long do_get_thread_area(CPUX86State *env, abi_ulong ptr)
bellard8d18e892007-11-14 15:18:40 +00002732{
2733 struct target_modify_ldt_ldt_s *target_ldt_info;
2734 uint64_t *gdt_table = g2h(env->gdt.base);
2735 uint32_t base_addr, limit, flags;
2736 int seg_32bit, contents, read_exec_only, limit_in_pages, idx;
2737 int seg_not_present, useable, lm;
2738 uint32_t *lp, entry_1, entry_2;
2739
2740 lock_user_struct(VERIFY_WRITE, target_ldt_info, ptr, 1);
2741 if (!target_ldt_info)
2742 return -TARGET_EFAULT;
2743 idx = tswap32(target_ldt_info->entry_number);
2744 if (idx < TARGET_GDT_ENTRY_TLS_MIN ||
2745 idx > TARGET_GDT_ENTRY_TLS_MAX) {
2746 unlock_user_struct(target_ldt_info, ptr, 1);
2747 return -TARGET_EINVAL;
2748 }
2749 lp = (uint32_t *)(gdt_table + idx);
2750 entry_1 = tswap32(lp[0]);
2751 entry_2 = tswap32(lp[1]);
2752
2753 read_exec_only = ((entry_2 >> 9) & 1) ^ 1;
2754 contents = (entry_2 >> 10) & 3;
2755 seg_not_present = ((entry_2 >> 15) & 1) ^ 1;
2756 seg_32bit = (entry_2 >> 22) & 1;
2757 limit_in_pages = (entry_2 >> 23) & 1;
2758 useable = (entry_2 >> 20) & 1;
2759#ifdef TARGET_ABI32
2760 lm = 0;
2761#else
2762 lm = (entry_2 >> 21) & 1;
2763#endif
2764 flags = (seg_32bit << 0) | (contents << 1) |
2765 (read_exec_only << 3) | (limit_in_pages << 4) |
2766 (seg_not_present << 5) | (useable << 6) | (lm << 7);
2767 limit = (entry_1 & 0xffff) | (entry_2 & 0xf0000);
2768 base_addr = (entry_1 >> 16) |
2769 (entry_2 & 0xff000000) |
2770 ((entry_2 & 0xff) << 16);
2771 target_ldt_info->base_addr = tswapl(base_addr);
2772 target_ldt_info->limit = tswap32(limit);
2773 target_ldt_info->flags = tswap32(flags);
2774 unlock_user_struct(target_ldt_info, ptr, 1);
2775 return 0;
2776}
blueswir14583f582008-08-24 10:35:55 +00002777#endif /* TARGET_I386 && TARGET_ABI32 */
bellard8d18e892007-11-14 15:18:40 +00002778
bellardd2fd1af2007-11-14 18:08:56 +00002779#ifndef TARGET_ABI32
blueswir18fcd3692008-08-17 20:26:25 +00002780static abi_long do_arch_prctl(CPUX86State *env, int code, abi_ulong addr)
bellardd2fd1af2007-11-14 18:08:56 +00002781{
2782 abi_long ret;
2783 abi_ulong val;
2784 int idx;
2785
2786 switch(code) {
2787 case TARGET_ARCH_SET_GS:
2788 case TARGET_ARCH_SET_FS:
2789 if (code == TARGET_ARCH_SET_GS)
2790 idx = R_GS;
2791 else
2792 idx = R_FS;
2793 cpu_x86_load_seg(env, idx, 0);
2794 env->segs[idx].base = addr;
2795 break;
2796 case TARGET_ARCH_GET_GS:
2797 case TARGET_ARCH_GET_FS:
2798 if (code == TARGET_ARCH_GET_GS)
2799 idx = R_GS;
2800 else
2801 idx = R_FS;
2802 val = env->segs[idx].base;
2803 if (put_user(val, addr, abi_ulong))
2804 return -TARGET_EFAULT;
2805 break;
2806 default:
2807 ret = -TARGET_EINVAL;
2808 break;
2809 }
2810 return 0;
2811}
2812#endif
2813
bellard2ab83ea2003-06-15 19:56:46 +00002814#endif /* defined(TARGET_I386) */
2815
pbrookd865bab2008-06-07 22:12:17 +00002816#if defined(USE_NPTL)
2817
2818#define NEW_STACK_SIZE PTHREAD_STACK_MIN
2819
2820static pthread_mutex_t clone_lock = PTHREAD_MUTEX_INITIALIZER;
2821typedef struct {
2822 CPUState *env;
2823 pthread_mutex_t mutex;
2824 pthread_cond_t cond;
2825 pthread_t thread;
2826 uint32_t tid;
2827 abi_ulong child_tidptr;
2828 abi_ulong parent_tidptr;
2829 sigset_t sigmask;
2830} new_thread_info;
2831
2832static void *clone_func(void *arg)
2833{
2834 new_thread_info *info = arg;
2835 CPUState *env;
2836
2837 env = info->env;
2838 thread_env = env;
2839 info->tid = gettid();
2840 if (info->child_tidptr)
2841 put_user_u32(info->tid, info->child_tidptr);
2842 if (info->parent_tidptr)
2843 put_user_u32(info->tid, info->parent_tidptr);
2844 /* Enable signals. */
2845 sigprocmask(SIG_SETMASK, &info->sigmask, NULL);
2846 /* Signal to the parent that we're ready. */
2847 pthread_mutex_lock(&info->mutex);
2848 pthread_cond_broadcast(&info->cond);
2849 pthread_mutex_unlock(&info->mutex);
2850 /* Wait until the parent has finshed initializing the tls state. */
2851 pthread_mutex_lock(&clone_lock);
2852 pthread_mutex_unlock(&clone_lock);
2853 cpu_loop(env);
2854 /* never exits */
2855 return NULL;
2856}
2857#else
bellard1b6b0292003-03-22 17:31:38 +00002858/* this stack is the equivalent of the kernel stack associated with a
2859 thread/process */
2860#define NEW_STACK_SIZE 8192
2861
2862static int clone_func(void *arg)
2863{
bellard2ab83ea2003-06-15 19:56:46 +00002864 CPUState *env = arg;
bellard1b6b0292003-03-22 17:31:38 +00002865 cpu_loop(env);
2866 /* never exits */
2867 return 0;
2868}
pbrookd865bab2008-06-07 22:12:17 +00002869#endif
bellard1b6b0292003-03-22 17:31:38 +00002870
ths0da46a62007-10-20 20:23:07 +00002871/* do_fork() Must return host values and target errnos (unlike most
2872 do_*() functions). */
pbrookd865bab2008-06-07 22:12:17 +00002873static int do_fork(CPUState *env, unsigned int flags, abi_ulong newsp,
2874 abi_ulong parent_tidptr, target_ulong newtls,
2875 abi_ulong child_tidptr)
bellard1b6b0292003-03-22 17:31:38 +00002876{
2877 int ret;
bellard5cd43932003-03-29 16:54:36 +00002878 TaskState *ts;
bellard1b6b0292003-03-22 17:31:38 +00002879 uint8_t *new_stack;
bellard2ab83ea2003-06-15 19:56:46 +00002880 CPUState *new_env;
pbrookd865bab2008-06-07 22:12:17 +00002881#if defined(USE_NPTL)
2882 unsigned int nptl_flags;
2883 sigset_t sigmask;
2884#endif
ths3b46e622007-09-17 08:09:54 +00002885
balrog436d1242008-09-21 02:39:45 +00002886 /* Emulate vfork() with fork() */
2887 if (flags & CLONE_VFORK)
2888 flags &= ~(CLONE_VFORK | CLONE_VM);
2889
bellard1b6b0292003-03-22 17:31:38 +00002890 if (flags & CLONE_VM) {
pbrookbd0c5662008-05-29 14:34:11 +00002891#if defined(USE_NPTL)
pbrookd865bab2008-06-07 22:12:17 +00002892 new_thread_info info;
2893 pthread_attr_t attr;
pbrookbd0c5662008-05-29 14:34:11 +00002894#endif
pbrookc3a92832008-06-09 14:02:50 +00002895 ts = qemu_mallocz(sizeof(TaskState) + NEW_STACK_SIZE);
pbrook624f7972008-05-31 16:11:38 +00002896 init_task_state(ts);
bellard5cd43932003-03-29 16:54:36 +00002897 new_stack = ts->stack;
bellard1b6b0292003-03-22 17:31:38 +00002898 /* we create a new CPU instance. */
thsc5be9f02007-02-28 20:20:53 +00002899 new_env = cpu_copy(env);
pbrook6e68e072008-05-30 17:22:15 +00002900 /* Init regs that differ from the parent. */
2901 cpu_clone_regs(new_env, newsp);
bellard5cd43932003-03-29 16:54:36 +00002902 new_env->opaque = ts;
pbrookd865bab2008-06-07 22:12:17 +00002903#if defined(USE_NPTL)
2904 nptl_flags = flags;
2905 flags &= ~CLONE_NPTL_FLAGS2;
2906
2907 /* TODO: Implement CLONE_CHILD_CLEARTID. */
2908 if (nptl_flags & CLONE_SETTLS)
2909 cpu_set_tls (new_env, newtls);
2910
2911 /* Grab a mutex so that thread setup appears atomic. */
2912 pthread_mutex_lock(&clone_lock);
2913
2914 memset(&info, 0, sizeof(info));
2915 pthread_mutex_init(&info.mutex, NULL);
2916 pthread_mutex_lock(&info.mutex);
2917 pthread_cond_init(&info.cond, NULL);
2918 info.env = new_env;
2919 if (nptl_flags & CLONE_CHILD_SETTID)
2920 info.child_tidptr = child_tidptr;
2921 if (nptl_flags & CLONE_PARENT_SETTID)
2922 info.parent_tidptr = parent_tidptr;
2923
2924 ret = pthread_attr_init(&attr);
2925 ret = pthread_attr_setstack(&attr, new_stack, NEW_STACK_SIZE);
2926 /* It is not safe to deliver signals until the child has finished
2927 initializing, so temporarily block all signals. */
2928 sigfillset(&sigmask);
2929 sigprocmask(SIG_BLOCK, &sigmask, &info.sigmask);
2930
2931 ret = pthread_create(&info.thread, &attr, clone_func, &info);
2932
2933 sigprocmask(SIG_SETMASK, &info.sigmask, NULL);
2934 pthread_attr_destroy(&attr);
2935 if (ret == 0) {
2936 /* Wait for the child to initialize. */
2937 pthread_cond_wait(&info.cond, &info.mutex);
2938 ret = info.tid;
2939 if (flags & CLONE_PARENT_SETTID)
2940 put_user_u32(ret, parent_tidptr);
2941 } else {
2942 ret = -1;
2943 }
2944 pthread_mutex_unlock(&info.mutex);
2945 pthread_cond_destroy(&info.cond);
2946 pthread_mutex_destroy(&info.mutex);
2947 pthread_mutex_unlock(&clone_lock);
2948#else
2949 if (flags & CLONE_NPTL_FLAGS2)
2950 return -EINVAL;
2951 /* This is probably going to die very quickly, but do it anyway. */
bellard27725c12003-04-29 21:08:18 +00002952#ifdef __ia64__
bellardfd4a43e2006-04-24 20:32:17 +00002953 ret = __clone2(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
bellard27725c12003-04-29 21:08:18 +00002954#else
2955 ret = clone(clone_func, new_stack + NEW_STACK_SIZE, flags, new_env);
2956#endif
pbrookd865bab2008-06-07 22:12:17 +00002957#endif
bellard1b6b0292003-03-22 17:31:38 +00002958 } else {
2959 /* if no CLONE_VM, we consider it is a fork */
pbrookd865bab2008-06-07 22:12:17 +00002960 if ((flags & ~(CSIGNAL | CLONE_NPTL_FLAGS2)) != 0)
bellard1b6b0292003-03-22 17:31:38 +00002961 return -EINVAL;
pbrookd865bab2008-06-07 22:12:17 +00002962 fork_start();
bellard1b6b0292003-03-22 17:31:38 +00002963 ret = fork();
pbrookd865bab2008-06-07 22:12:17 +00002964 if (ret == 0) {
aurel322b1319c2008-12-18 22:44:04 +00002965 /* Child Process. */
pbrookd865bab2008-06-07 22:12:17 +00002966 cpu_clone_regs(env, newsp);
2967 fork_end(1);
aurel322b1319c2008-12-18 22:44:04 +00002968#if defined(USE_NPTL)
2969 /* There is a race condition here. The parent process could
2970 theoretically read the TID in the child process before the child
2971 tid is set. This would require using either ptrace
2972 (not implemented) or having *_tidptr to point at a shared memory
2973 mapping. We can't repeat the spinlock hack used above because
2974 the child process gets its own copy of the lock. */
pbrookd865bab2008-06-07 22:12:17 +00002975 if (flags & CLONE_CHILD_SETTID)
2976 put_user_u32(gettid(), child_tidptr);
2977 if (flags & CLONE_PARENT_SETTID)
2978 put_user_u32(gettid(), parent_tidptr);
2979 ts = (TaskState *)env->opaque;
2980 if (flags & CLONE_SETTLS)
2981 cpu_set_tls (env, newtls);
2982 /* TODO: Implement CLONE_CHILD_CLEARTID. */
aurel322b1319c2008-12-18 22:44:04 +00002983#endif
pbrookd865bab2008-06-07 22:12:17 +00002984 } else {
2985 fork_end(0);
2986 }
bellard1b6b0292003-03-22 17:31:38 +00002987 }
2988 return ret;
2989}
2990
blueswir1992f48a2007-10-14 16:27:31 +00002991static abi_long do_fcntl(int fd, int cmd, abi_ulong arg)
bellard7775e9e2003-05-14 22:46:48 +00002992{
2993 struct flock fl;
pbrook53a59602006-03-25 19:31:22 +00002994 struct target_flock *target_fl;
ths43f238d2007-01-05 20:55:49 +00002995 struct flock64 fl64;
2996 struct target_flock64 *target_fl64;
blueswir1992f48a2007-10-14 16:27:31 +00002997 abi_long ret;
pbrook53a59602006-03-25 19:31:22 +00002998
bellard7775e9e2003-05-14 22:46:48 +00002999 switch(cmd) {
3000 case TARGET_F_GETLK:
bellard579a97f2007-11-11 14:26:47 +00003001 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3002 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003003 fl.l_type = tswap16(target_fl->l_type);
3004 fl.l_whence = tswap16(target_fl->l_whence);
3005 fl.l_start = tswapl(target_fl->l_start);
3006 fl.l_len = tswapl(target_fl->l_len);
3007 fl.l_pid = tswapl(target_fl->l_pid);
3008 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003009 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003010 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003011 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg, 0))
3012 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003013 target_fl->l_type = tswap16(fl.l_type);
3014 target_fl->l_whence = tswap16(fl.l_whence);
3015 target_fl->l_start = tswapl(fl.l_start);
3016 target_fl->l_len = tswapl(fl.l_len);
3017 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00003018 unlock_user_struct(target_fl, arg, 1);
bellard7775e9e2003-05-14 22:46:48 +00003019 }
3020 break;
ths3b46e622007-09-17 08:09:54 +00003021
bellard7775e9e2003-05-14 22:46:48 +00003022 case TARGET_F_SETLK:
3023 case TARGET_F_SETLKW:
bellard579a97f2007-11-11 14:26:47 +00003024 if (!lock_user_struct(VERIFY_READ, target_fl, arg, 1))
3025 return -TARGET_EFAULT;
bellard7775e9e2003-05-14 22:46:48 +00003026 fl.l_type = tswap16(target_fl->l_type);
3027 fl.l_whence = tswap16(target_fl->l_whence);
3028 fl.l_start = tswapl(target_fl->l_start);
3029 fl.l_len = tswapl(target_fl->l_len);
3030 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00003031 unlock_user_struct(target_fl, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003032 ret = get_errno(fcntl(fd, cmd, &fl));
bellard7775e9e2003-05-14 22:46:48 +00003033 break;
ths3b46e622007-09-17 08:09:54 +00003034
bellard7775e9e2003-05-14 22:46:48 +00003035 case TARGET_F_GETLK64:
bellard579a97f2007-11-11 14:26:47 +00003036 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3037 return -TARGET_EFAULT;
ths58134272007-03-31 18:59:32 +00003038 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3039 fl64.l_whence = tswap16(target_fl64->l_whence);
3040 fl64.l_start = tswapl(target_fl64->l_start);
3041 fl64.l_len = tswapl(target_fl64->l_len);
3042 fl64.l_pid = tswap16(target_fl64->l_pid);
3043 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003044 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
ths43f238d2007-01-05 20:55:49 +00003045 if (ret == 0) {
bellard579a97f2007-11-11 14:26:47 +00003046 if (!lock_user_struct(VERIFY_WRITE, target_fl64, arg, 0))
3047 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003048 target_fl64->l_type = tswap16(fl64.l_type) >> 1;
3049 target_fl64->l_whence = tswap16(fl64.l_whence);
3050 target_fl64->l_start = tswapl(fl64.l_start);
3051 target_fl64->l_len = tswapl(fl64.l_len);
3052 target_fl64->l_pid = tswapl(fl64.l_pid);
3053 unlock_user_struct(target_fl64, arg, 1);
3054 }
bellard9ee1fa22007-11-11 15:11:19 +00003055 break;
bellard7775e9e2003-05-14 22:46:48 +00003056 case TARGET_F_SETLK64:
3057 case TARGET_F_SETLKW64:
bellard579a97f2007-11-11 14:26:47 +00003058 if (!lock_user_struct(VERIFY_READ, target_fl64, arg, 1))
3059 return -TARGET_EFAULT;
ths43f238d2007-01-05 20:55:49 +00003060 fl64.l_type = tswap16(target_fl64->l_type) >> 1;
3061 fl64.l_whence = tswap16(target_fl64->l_whence);
3062 fl64.l_start = tswapl(target_fl64->l_start);
3063 fl64.l_len = tswapl(target_fl64->l_len);
3064 fl64.l_pid = tswap16(target_fl64->l_pid);
3065 unlock_user_struct(target_fl64, arg, 0);
bellard9ee1fa22007-11-11 15:11:19 +00003066 ret = get_errno(fcntl(fd, cmd >> 1, &fl64));
bellard7775e9e2003-05-14 22:46:48 +00003067 break;
3068
bellardffa65c32004-01-04 23:57:22 +00003069 case F_GETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003070 ret = get_errno(fcntl(fd, cmd, arg));
3071 if (ret >= 0) {
3072 ret = host_to_target_bitmask(ret, fcntl_flags_tbl);
3073 }
bellardffa65c32004-01-04 23:57:22 +00003074 break;
3075
3076 case F_SETFL:
bellard9ee1fa22007-11-11 15:11:19 +00003077 ret = get_errno(fcntl(fd, cmd, target_to_host_bitmask(arg, fcntl_flags_tbl)));
bellardffa65c32004-01-04 23:57:22 +00003078 break;
3079
bellard7775e9e2003-05-14 22:46:48 +00003080 default:
bellard9ee1fa22007-11-11 15:11:19 +00003081 ret = get_errno(fcntl(fd, cmd, arg));
bellard7775e9e2003-05-14 22:46:48 +00003082 break;
3083 }
3084 return ret;
3085}
3086
bellard67867302003-11-23 17:05:30 +00003087#ifdef USE_UID16
bellard7775e9e2003-05-14 22:46:48 +00003088
bellard67867302003-11-23 17:05:30 +00003089static inline int high2lowuid(int uid)
3090{
3091 if (uid > 65535)
3092 return 65534;
3093 else
3094 return uid;
3095}
3096
3097static inline int high2lowgid(int gid)
3098{
3099 if (gid > 65535)
3100 return 65534;
3101 else
3102 return gid;
3103}
3104
3105static inline int low2highuid(int uid)
3106{
3107 if ((int16_t)uid == -1)
3108 return -1;
3109 else
3110 return uid;
3111}
3112
3113static inline int low2highgid(int gid)
3114{
3115 if ((int16_t)gid == -1)
3116 return -1;
3117 else
3118 return gid;
3119}
3120
3121#endif /* USE_UID16 */
bellard1b6b0292003-03-22 17:31:38 +00003122
bellard31e31b82003-02-18 22:55:36 +00003123void syscall_init(void)
3124{
bellard2ab83ea2003-06-15 19:56:46 +00003125 IOCTLEntry *ie;
3126 const argtype *arg_type;
3127 int size;
thsb92c47c2007-11-01 00:07:38 +00003128 int i;
bellard2ab83ea2003-06-15 19:56:46 +00003129
ths5fafdf22007-09-16 21:08:06 +00003130#define STRUCT(name, list...) thunk_register_struct(STRUCT_ ## name, #name, struct_ ## name ## _def);
3131#define STRUCT_SPECIAL(name) thunk_register_struct_direct(STRUCT_ ## name, #name, &struct_ ## name ## _def);
bellard31e31b82003-02-18 22:55:36 +00003132#include "syscall_types.h"
3133#undef STRUCT
3134#undef STRUCT_SPECIAL
bellard2ab83ea2003-06-15 19:56:46 +00003135
3136 /* we patch the ioctl size if necessary. We rely on the fact that
3137 no ioctl has all the bits at '1' in the size field */
3138 ie = ioctl_entries;
3139 while (ie->target_cmd != 0) {
3140 if (((ie->target_cmd >> TARGET_IOC_SIZESHIFT) & TARGET_IOC_SIZEMASK) ==
3141 TARGET_IOC_SIZEMASK) {
3142 arg_type = ie->arg_type;
3143 if (arg_type[0] != TYPE_PTR) {
ths5fafdf22007-09-16 21:08:06 +00003144 fprintf(stderr, "cannot patch size for ioctl 0x%x\n",
bellard2ab83ea2003-06-15 19:56:46 +00003145 ie->target_cmd);
3146 exit(1);
3147 }
3148 arg_type++;
3149 size = thunk_type_size(arg_type, 0);
ths5fafdf22007-09-16 21:08:06 +00003150 ie->target_cmd = (ie->target_cmd &
bellard2ab83ea2003-06-15 19:56:46 +00003151 ~(TARGET_IOC_SIZEMASK << TARGET_IOC_SIZESHIFT)) |
3152 (size << TARGET_IOC_SIZESHIFT);
3153 }
thsb92c47c2007-11-01 00:07:38 +00003154
3155 /* Build target_to_host_errno_table[] table from
3156 * host_to_target_errno_table[]. */
3157 for (i=0; i < ERRNO_TABLE_SIZE; i++)
3158 target_to_host_errno_table[host_to_target_errno_table[i]] = i;
3159
bellard2ab83ea2003-06-15 19:56:46 +00003160 /* automatic consistency check if same arch */
balrog872ea0c2008-09-21 02:31:19 +00003161#if (defined(__i386__) && defined(TARGET_I386) && defined(TARGET_ABI32)) || \
3162 (defined(__x86_64__) && defined(TARGET_X86_64))
3163 if (unlikely(ie->target_cmd != ie->host_cmd)) {
3164 fprintf(stderr, "ERROR: ioctl(%s): target=0x%x host=0x%x\n",
3165 ie->name, ie->target_cmd, ie->host_cmd);
bellard2ab83ea2003-06-15 19:56:46 +00003166 }
3167#endif
3168 ie++;
3169 }
bellard31e31b82003-02-18 22:55:36 +00003170}
bellardc573ff62004-01-04 15:51:36 +00003171
blueswir1992f48a2007-10-14 16:27:31 +00003172#if TARGET_ABI_BITS == 32
pbrookce4defa2006-02-09 16:49:55 +00003173static inline uint64_t target_offset64(uint32_t word0, uint32_t word1)
3174{
thsaf325d32008-06-10 15:29:15 +00003175#ifdef TARGET_WORDS_BIGENDIAN
pbrookce4defa2006-02-09 16:49:55 +00003176 return ((uint64_t)word0 << 32) | word1;
3177#else
3178 return ((uint64_t)word1 << 32) | word0;
3179#endif
3180}
blueswir1992f48a2007-10-14 16:27:31 +00003181#else /* TARGET_ABI_BITS == 32 */
j_mayer32407102007-09-26 23:01:49 +00003182static inline uint64_t target_offset64(uint64_t word0, uint64_t word1)
3183{
3184 return word0;
3185}
blueswir1992f48a2007-10-14 16:27:31 +00003186#endif /* TARGET_ABI_BITS != 32 */
pbrookce4defa2006-02-09 16:49:55 +00003187
3188#ifdef TARGET_NR_truncate64
blueswir1992f48a2007-10-14 16:27:31 +00003189static inline abi_long target_truncate64(void *cpu_env, const char *arg1,
3190 abi_long arg2,
3191 abi_long arg3,
3192 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003193{
3194#ifdef TARGET_ARM
3195 if (((CPUARMState *)cpu_env)->eabi)
3196 {
3197 arg2 = arg3;
3198 arg3 = arg4;
3199 }
3200#endif
3201 return get_errno(truncate64(arg1, target_offset64(arg2, arg3)));
3202}
3203#endif
3204
3205#ifdef TARGET_NR_ftruncate64
blueswir1992f48a2007-10-14 16:27:31 +00003206static inline abi_long target_ftruncate64(void *cpu_env, abi_long arg1,
3207 abi_long arg2,
3208 abi_long arg3,
3209 abi_long arg4)
pbrookce4defa2006-02-09 16:49:55 +00003210{
3211#ifdef TARGET_ARM
3212 if (((CPUARMState *)cpu_env)->eabi)
3213 {
3214 arg2 = arg3;
3215 arg3 = arg4;
3216 }
3217#endif
3218 return get_errno(ftruncate64(arg1, target_offset64(arg2, arg3)));
3219}
3220#endif
3221
bellard579a97f2007-11-11 14:26:47 +00003222static inline abi_long target_to_host_timespec(struct timespec *host_ts,
3223 abi_ulong target_addr)
pbrook53a59602006-03-25 19:31:22 +00003224{
3225 struct target_timespec *target_ts;
3226
bellard579a97f2007-11-11 14:26:47 +00003227 if (!lock_user_struct(VERIFY_READ, target_ts, target_addr, 1))
3228 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003229 host_ts->tv_sec = tswapl(target_ts->tv_sec);
3230 host_ts->tv_nsec = tswapl(target_ts->tv_nsec);
3231 unlock_user_struct(target_ts, target_addr, 0);
bellardb255bfa2008-05-10 21:51:02 +00003232 return 0;
pbrook53a59602006-03-25 19:31:22 +00003233}
3234
bellard579a97f2007-11-11 14:26:47 +00003235static inline abi_long host_to_target_timespec(abi_ulong target_addr,
3236 struct timespec *host_ts)
pbrook53a59602006-03-25 19:31:22 +00003237{
3238 struct target_timespec *target_ts;
3239
bellard579a97f2007-11-11 14:26:47 +00003240 if (!lock_user_struct(VERIFY_WRITE, target_ts, target_addr, 0))
3241 return -TARGET_EFAULT;
pbrook53a59602006-03-25 19:31:22 +00003242 target_ts->tv_sec = tswapl(host_ts->tv_sec);
3243 target_ts->tv_nsec = tswapl(host_ts->tv_nsec);
3244 unlock_user_struct(target_ts, target_addr, 1);
bellardb255bfa2008-05-10 21:51:02 +00003245 return 0;
pbrook53a59602006-03-25 19:31:22 +00003246}
3247
balrog6a24a772008-09-20 02:23:36 +00003248#ifdef TARGET_NR_stat64
3249static inline abi_long host_to_target_stat64(void *cpu_env,
3250 abi_ulong target_addr,
3251 struct stat *host_st)
3252{
3253#ifdef TARGET_ARM
3254 if (((CPUARMState *)cpu_env)->eabi) {
3255 struct target_eabi_stat64 *target_st;
3256
3257 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3258 return -TARGET_EFAULT;
3259 memset(target_st, 0, sizeof(struct target_eabi_stat64));
3260 __put_user(host_st->st_dev, &target_st->st_dev);
3261 __put_user(host_st->st_ino, &target_st->st_ino);
3262#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3263 __put_user(host_st->st_ino, &target_st->__st_ino);
3264#endif
3265 __put_user(host_st->st_mode, &target_st->st_mode);
3266 __put_user(host_st->st_nlink, &target_st->st_nlink);
3267 __put_user(host_st->st_uid, &target_st->st_uid);
3268 __put_user(host_st->st_gid, &target_st->st_gid);
3269 __put_user(host_st->st_rdev, &target_st->st_rdev);
3270 __put_user(host_st->st_size, &target_st->st_size);
3271 __put_user(host_st->st_blksize, &target_st->st_blksize);
3272 __put_user(host_st->st_blocks, &target_st->st_blocks);
3273 __put_user(host_st->st_atime, &target_st->target_st_atime);
3274 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3275 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3276 unlock_user_struct(target_st, target_addr, 1);
3277 } else
3278#endif
3279 {
3280 struct target_stat64 *target_st;
3281
3282 if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0))
3283 return -TARGET_EFAULT;
3284 memset(target_st, 0, sizeof(struct target_stat64));
3285 __put_user(host_st->st_dev, &target_st->st_dev);
3286 __put_user(host_st->st_ino, &target_st->st_ino);
3287#ifdef TARGET_STAT64_HAS_BROKEN_ST_INO
3288 __put_user(host_st->st_ino, &target_st->__st_ino);
3289#endif
3290 __put_user(host_st->st_mode, &target_st->st_mode);
3291 __put_user(host_st->st_nlink, &target_st->st_nlink);
3292 __put_user(host_st->st_uid, &target_st->st_uid);
3293 __put_user(host_st->st_gid, &target_st->st_gid);
3294 __put_user(host_st->st_rdev, &target_st->st_rdev);
3295 /* XXX: better use of kernel struct */
3296 __put_user(host_st->st_size, &target_st->st_size);
3297 __put_user(host_st->st_blksize, &target_st->st_blksize);
3298 __put_user(host_st->st_blocks, &target_st->st_blocks);
3299 __put_user(host_st->st_atime, &target_st->target_st_atime);
3300 __put_user(host_st->st_mtime, &target_st->target_st_mtime);
3301 __put_user(host_st->st_ctime, &target_st->target_st_ctime);
3302 unlock_user_struct(target_st, target_addr, 1);
3303 }
3304
3305 return 0;
3306}
3307#endif
3308
pbrookbd0c5662008-05-29 14:34:11 +00003309#if defined(USE_NPTL)
3310/* ??? Using host futex calls even when target atomic operations
3311 are not really atomic probably breaks things. However implementing
3312 futexes locally would make futexes shared between multiple processes
3313 tricky. However they're probably useless because guest atomic
3314 operations won't work either. */
blueswir18fcd3692008-08-17 20:26:25 +00003315static int do_futex(target_ulong uaddr, int op, int val, target_ulong timeout,
3316 target_ulong uaddr2, int val3)
pbrookbd0c5662008-05-29 14:34:11 +00003317{
3318 struct timespec ts, *pts;
3319
3320 /* ??? We assume FUTEX_* constants are the same on both host
3321 and target. */
3322 switch (op) {
3323 case FUTEX_WAIT:
3324 if (timeout) {
3325 pts = &ts;
3326 target_to_host_timespec(pts, timeout);
3327 } else {
3328 pts = NULL;
3329 }
3330 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAIT, tswap32(val),
3331 pts, NULL, 0));
3332 case FUTEX_WAKE:
3333 return get_errno(sys_futex(g2h(uaddr), FUTEX_WAKE, val, NULL, NULL, 0));
3334 case FUTEX_FD:
3335 return get_errno(sys_futex(g2h(uaddr), FUTEX_FD, val, NULL, NULL, 0));
3336 case FUTEX_REQUEUE:
3337 return get_errno(sys_futex(g2h(uaddr), FUTEX_REQUEUE, val,
3338 NULL, g2h(uaddr2), 0));
3339 case FUTEX_CMP_REQUEUE:
3340 return get_errno(sys_futex(g2h(uaddr), FUTEX_CMP_REQUEUE, val,
3341 NULL, g2h(uaddr2), tswap32(val3)));
3342 default:
3343 return -TARGET_ENOSYS;
3344 }
3345}
3346#endif
3347
pbrooka745ec62008-05-06 15:36:17 +00003348int get_osversion(void)
3349{
3350 static int osversion;
3351 struct new_utsname buf;
3352 const char *s;
3353 int i, n, tmp;
3354 if (osversion)
3355 return osversion;
3356 if (qemu_uname_release && *qemu_uname_release) {
3357 s = qemu_uname_release;
3358 } else {
3359 if (sys_uname(&buf))
3360 return 0;
3361 s = buf.release;
3362 }
3363 tmp = 0;
3364 for (i = 0; i < 3; i++) {
3365 n = 0;
3366 while (*s >= '0' && *s <= '9') {
3367 n *= 10;
3368 n += *s - '0';
3369 s++;
3370 }
3371 tmp = (tmp << 8) + n;
3372 if (*s == '.')
3373 s++;
3374 }
3375 osversion = tmp;
3376 return osversion;
3377}
3378
ths0da46a62007-10-20 20:23:07 +00003379/* do_syscall() should always have a single exit point at the end so
3380 that actions, such as logging of syscall results, can be performed.
3381 All errnos that do_syscall() returns must be -TARGET_<errcode>. */
blueswir1992f48a2007-10-14 16:27:31 +00003382abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
3383 abi_long arg2, abi_long arg3, abi_long arg4,
3384 abi_long arg5, abi_long arg6)
bellard31e31b82003-02-18 22:55:36 +00003385{
blueswir1992f48a2007-10-14 16:27:31 +00003386 abi_long ret;
bellard31e31b82003-02-18 22:55:36 +00003387 struct stat st;
bellard56c8f682005-11-28 22:28:41 +00003388 struct statfs stfs;
pbrook53a59602006-03-25 19:31:22 +00003389 void *p;
ths3b46e622007-09-17 08:09:54 +00003390
bellard72f03902003-02-18 23:33:18 +00003391#ifdef DEBUG
bellardc573ff62004-01-04 15:51:36 +00003392 gemu_log("syscall %d", num);
bellard72f03902003-02-18 23:33:18 +00003393#endif
thsb92c47c2007-11-01 00:07:38 +00003394 if(do_strace)
3395 print_syscall(num, arg1, arg2, arg3, arg4, arg5, arg6);
3396
bellard31e31b82003-02-18 22:55:36 +00003397 switch(num) {
3398 case TARGET_NR_exit:
bellard7d132992003-03-06 23:23:54 +00003399#ifdef HAVE_GPROF
3400 _mcleanup();
3401#endif
bellarde9009672005-04-26 20:42:36 +00003402 gdb_exit(cpu_env, arg1);
bellard1b6b0292003-03-22 17:31:38 +00003403 /* XXX: should free thread stack and CPU env */
balroga2f86d82008-10-28 10:18:28 +00003404 sys_exit(arg1);
bellard31e31b82003-02-18 22:55:36 +00003405 ret = 0; /* avoid warning */
3406 break;
3407 case TARGET_NR_read:
bellard579a97f2007-11-11 14:26:47 +00003408 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
3409 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003410 ret = get_errno(read(arg1, p, arg3));
3411 unlock_user(p, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00003412 break;
3413 case TARGET_NR_write:
bellard579a97f2007-11-11 14:26:47 +00003414 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
3415 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003416 ret = get_errno(write(arg1, p, arg3));
3417 unlock_user(p, arg2, 0);
bellard31e31b82003-02-18 22:55:36 +00003418 break;
3419 case TARGET_NR_open:
bellard2f619692007-11-16 10:46:05 +00003420 if (!(p = lock_user_string(arg1)))
3421 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003422 ret = get_errno(open(path(p),
bellardffa65c32004-01-04 23:57:22 +00003423 target_to_host_bitmask(arg2, fcntl_flags_tbl),
3424 arg3));
pbrook53a59602006-03-25 19:31:22 +00003425 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003426 break;
ths82424832007-09-24 09:21:55 +00003427#if defined(TARGET_NR_openat) && defined(__NR_openat)
3428 case TARGET_NR_openat:
bellard579a97f2007-11-11 14:26:47 +00003429 if (!(p = lock_user_string(arg2)))
3430 goto efault;
3431 ret = get_errno(sys_openat(arg1,
3432 path(p),
3433 target_to_host_bitmask(arg3, fcntl_flags_tbl),
3434 arg4));
3435 unlock_user(p, arg2, 0);
ths82424832007-09-24 09:21:55 +00003436 break;
3437#endif
bellard31e31b82003-02-18 22:55:36 +00003438 case TARGET_NR_close:
3439 ret = get_errno(close(arg1));
3440 break;
3441 case TARGET_NR_brk:
pbrook53a59602006-03-25 19:31:22 +00003442 ret = do_brk(arg1);
bellard31e31b82003-02-18 22:55:36 +00003443 break;
3444 case TARGET_NR_fork:
pbrookd865bab2008-06-07 22:12:17 +00003445 ret = get_errno(do_fork(cpu_env, SIGCHLD, 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00003446 break;
thse5febef2007-04-01 18:31:35 +00003447#ifdef TARGET_NR_waitpid
bellard31e31b82003-02-18 22:55:36 +00003448 case TARGET_NR_waitpid:
3449 {
pbrook53a59602006-03-25 19:31:22 +00003450 int status;
3451 ret = get_errno(waitpid(arg1, &status, arg3));
bellard2f619692007-11-16 10:46:05 +00003452 if (!is_error(ret) && arg2
3453 && put_user_s32(status, arg2))
3454 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003455 }
3456 break;
thse5febef2007-04-01 18:31:35 +00003457#endif
pbrookf0cbb612008-05-30 18:20:05 +00003458#ifdef TARGET_NR_waitid
3459 case TARGET_NR_waitid:
3460 {
3461 siginfo_t info;
3462 info.si_pid = 0;
3463 ret = get_errno(waitid(arg1, arg2, &info, arg4));
3464 if (!is_error(ret) && arg3 && info.si_pid != 0) {
3465 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_siginfo_t), 0)))
3466 goto efault;
3467 host_to_target_siginfo(p, &info);
3468 unlock_user(p, arg3, sizeof(target_siginfo_t));
3469 }
3470 }
3471 break;
3472#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003473#ifdef TARGET_NR_creat /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003474 case TARGET_NR_creat:
bellard579a97f2007-11-11 14:26:47 +00003475 if (!(p = lock_user_string(arg1)))
3476 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003477 ret = get_errno(creat(p, arg2));
3478 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003479 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003480#endif
bellard31e31b82003-02-18 22:55:36 +00003481 case TARGET_NR_link:
pbrook53a59602006-03-25 19:31:22 +00003482 {
3483 void * p2;
3484 p = lock_user_string(arg1);
3485 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003486 if (!p || !p2)
3487 ret = -TARGET_EFAULT;
3488 else
3489 ret = get_errno(link(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003490 unlock_user(p2, arg2, 0);
3491 unlock_user(p, arg1, 0);
3492 }
bellard31e31b82003-02-18 22:55:36 +00003493 break;
ths64f0ce42007-09-24 09:25:06 +00003494#if defined(TARGET_NR_linkat) && defined(__NR_linkat)
3495 case TARGET_NR_linkat:
ths64f0ce42007-09-24 09:25:06 +00003496 {
3497 void * p2 = NULL;
bellard579a97f2007-11-11 14:26:47 +00003498 if (!arg2 || !arg4)
3499 goto efault;
ths64f0ce42007-09-24 09:25:06 +00003500 p = lock_user_string(arg2);
3501 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003502 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003503 ret = -TARGET_EFAULT;
ths64f0ce42007-09-24 09:25:06 +00003504 else
3505 ret = get_errno(sys_linkat(arg1, p, arg3, p2, arg5));
bellard579a97f2007-11-11 14:26:47 +00003506 unlock_user(p, arg2, 0);
3507 unlock_user(p2, arg4, 0);
ths64f0ce42007-09-24 09:25:06 +00003508 }
3509 break;
3510#endif
bellard31e31b82003-02-18 22:55:36 +00003511 case TARGET_NR_unlink:
bellard579a97f2007-11-11 14:26:47 +00003512 if (!(p = lock_user_string(arg1)))
3513 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003514 ret = get_errno(unlink(p));
3515 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003516 break;
ths8170f562007-09-24 09:24:11 +00003517#if defined(TARGET_NR_unlinkat) && defined(__NR_unlinkat)
3518 case TARGET_NR_unlinkat:
bellard579a97f2007-11-11 14:26:47 +00003519 if (!(p = lock_user_string(arg2)))
3520 goto efault;
3521 ret = get_errno(sys_unlinkat(arg1, p, arg3));
3522 unlock_user(p, arg2, 0);
balroged494d82007-12-11 23:23:52 +00003523 break;
balrogb7d35e62007-12-12 00:40:24 +00003524#endif
bellard31e31b82003-02-18 22:55:36 +00003525 case TARGET_NR_execve:
bellard7854b052003-03-29 17:22:23 +00003526 {
3527 char **argp, **envp;
bellardf7341ff2003-03-30 21:00:25 +00003528 int argc, envc;
blueswir1992f48a2007-10-14 16:27:31 +00003529 abi_ulong gp;
3530 abi_ulong guest_argp;
3531 abi_ulong guest_envp;
3532 abi_ulong addr;
bellard7854b052003-03-29 17:22:23 +00003533 char **q;
3534
bellardf7341ff2003-03-30 21:00:25 +00003535 argc = 0;
pbrook53a59602006-03-25 19:31:22 +00003536 guest_argp = arg2;
pbrookda94d262008-05-30 18:24:00 +00003537 for (gp = guest_argp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003538 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003539 goto efault;
ths03aa1972007-12-02 06:28:08 +00003540 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003541 break;
bellard7854b052003-03-29 17:22:23 +00003542 argc++;
bellard2f619692007-11-16 10:46:05 +00003543 }
bellardf7341ff2003-03-30 21:00:25 +00003544 envc = 0;
pbrook53a59602006-03-25 19:31:22 +00003545 guest_envp = arg3;
pbrookda94d262008-05-30 18:24:00 +00003546 for (gp = guest_envp; gp; gp += sizeof(abi_ulong)) {
ths03aa1972007-12-02 06:28:08 +00003547 if (get_user_ual(addr, gp))
bellard2f619692007-11-16 10:46:05 +00003548 goto efault;
ths03aa1972007-12-02 06:28:08 +00003549 if (!addr)
bellard2f619692007-11-16 10:46:05 +00003550 break;
bellard7854b052003-03-29 17:22:23 +00003551 envc++;
bellard2f619692007-11-16 10:46:05 +00003552 }
bellard7854b052003-03-29 17:22:23 +00003553
bellardf7341ff2003-03-30 21:00:25 +00003554 argp = alloca((argc + 1) * sizeof(void *));
3555 envp = alloca((envc + 1) * sizeof(void *));
bellard7854b052003-03-29 17:22:23 +00003556
pbrookda94d262008-05-30 18:24:00 +00003557 for (gp = guest_argp, q = argp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003558 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003559 if (get_user_ual(addr, gp))
3560 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003561 if (!addr)
3562 break;
bellard2f619692007-11-16 10:46:05 +00003563 if (!(*q = lock_user_string(addr)))
3564 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003565 }
bellardf7341ff2003-03-30 21:00:25 +00003566 *q = NULL;
3567
pbrookda94d262008-05-30 18:24:00 +00003568 for (gp = guest_envp, q = envp; gp;
blueswir1992f48a2007-10-14 16:27:31 +00003569 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003570 if (get_user_ual(addr, gp))
3571 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003572 if (!addr)
3573 break;
bellard2f619692007-11-16 10:46:05 +00003574 if (!(*q = lock_user_string(addr)))
3575 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003576 }
bellardf7341ff2003-03-30 21:00:25 +00003577 *q = NULL;
bellard7854b052003-03-29 17:22:23 +00003578
bellard2f619692007-11-16 10:46:05 +00003579 if (!(p = lock_user_string(arg1)))
3580 goto execve_efault;
pbrook53a59602006-03-25 19:31:22 +00003581 ret = get_errno(execve(p, argp, envp));
3582 unlock_user(p, arg1, 0);
3583
bellard2f619692007-11-16 10:46:05 +00003584 goto execve_end;
3585
3586 execve_efault:
3587 ret = -TARGET_EFAULT;
3588
3589 execve_end:
pbrook53a59602006-03-25 19:31:22 +00003590 for (gp = guest_argp, q = argp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003591 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003592 if (get_user_ual(addr, gp)
3593 || !addr)
3594 break;
pbrook53a59602006-03-25 19:31:22 +00003595 unlock_user(*q, addr, 0);
3596 }
3597 for (gp = guest_envp, q = envp; *q;
blueswir1992f48a2007-10-14 16:27:31 +00003598 gp += sizeof(abi_ulong), q++) {
bellard2f619692007-11-16 10:46:05 +00003599 if (get_user_ual(addr, gp)
3600 || !addr)
3601 break;
pbrook53a59602006-03-25 19:31:22 +00003602 unlock_user(*q, addr, 0);
3603 }
bellard7854b052003-03-29 17:22:23 +00003604 }
bellard31e31b82003-02-18 22:55:36 +00003605 break;
3606 case TARGET_NR_chdir:
bellard579a97f2007-11-11 14:26:47 +00003607 if (!(p = lock_user_string(arg1)))
3608 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003609 ret = get_errno(chdir(p));
3610 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003611 break;
bellarda315a142005-01-30 22:59:18 +00003612#ifdef TARGET_NR_time
bellard31e31b82003-02-18 22:55:36 +00003613 case TARGET_NR_time:
3614 {
pbrook53a59602006-03-25 19:31:22 +00003615 time_t host_time;
3616 ret = get_errno(time(&host_time));
bellard2f619692007-11-16 10:46:05 +00003617 if (!is_error(ret)
3618 && arg1
3619 && put_user_sal(host_time, arg1))
3620 goto efault;
bellard31e31b82003-02-18 22:55:36 +00003621 }
3622 break;
bellarda315a142005-01-30 22:59:18 +00003623#endif
bellard31e31b82003-02-18 22:55:36 +00003624 case TARGET_NR_mknod:
bellard579a97f2007-11-11 14:26:47 +00003625 if (!(p = lock_user_string(arg1)))
3626 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003627 ret = get_errno(mknod(p, arg2, arg3));
3628 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003629 break;
ths75ac37a2007-09-24 09:23:05 +00003630#if defined(TARGET_NR_mknodat) && defined(__NR_mknodat)
3631 case TARGET_NR_mknodat:
bellard579a97f2007-11-11 14:26:47 +00003632 if (!(p = lock_user_string(arg2)))
3633 goto efault;
3634 ret = get_errno(sys_mknodat(arg1, p, arg3, arg4));
3635 unlock_user(p, arg2, 0);
ths75ac37a2007-09-24 09:23:05 +00003636 break;
3637#endif
bellard31e31b82003-02-18 22:55:36 +00003638 case TARGET_NR_chmod:
bellard579a97f2007-11-11 14:26:47 +00003639 if (!(p = lock_user_string(arg1)))
3640 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003641 ret = get_errno(chmod(p, arg2));
3642 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003643 break;
bellardebc05482003-09-30 21:08:41 +00003644#ifdef TARGET_NR_break
bellard31e31b82003-02-18 22:55:36 +00003645 case TARGET_NR_break:
3646 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003647#endif
3648#ifdef TARGET_NR_oldstat
bellard31e31b82003-02-18 22:55:36 +00003649 case TARGET_NR_oldstat:
3650 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003651#endif
bellard31e31b82003-02-18 22:55:36 +00003652 case TARGET_NR_lseek:
3653 ret = get_errno(lseek(arg1, arg2, arg3));
3654 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003655#ifdef TARGET_NR_getxpid
3656 case TARGET_NR_getxpid:
3657#else
bellard31e31b82003-02-18 22:55:36 +00003658 case TARGET_NR_getpid:
j_mayer7a3148a2007-04-05 07:13:51 +00003659#endif
bellard31e31b82003-02-18 22:55:36 +00003660 ret = get_errno(getpid());
3661 break;
3662 case TARGET_NR_mount:
ths80265912007-02-17 22:25:41 +00003663 {
3664 /* need to look at the data field */
3665 void *p2, *p3;
3666 p = lock_user_string(arg1);
3667 p2 = lock_user_string(arg2);
3668 p3 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00003669 if (!p || !p2 || !p3)
3670 ret = -TARGET_EFAULT;
3671 else
3672 /* FIXME - arg5 should be locked, but it isn't clear how to
3673 * do that since it's not guaranteed to be a NULL-terminated
3674 * string.
3675 */
3676 ret = get_errno(mount(p, p2, p3, (unsigned long)arg4, g2h(arg5)));
3677 unlock_user(p, arg1, 0);
3678 unlock_user(p2, arg2, 0);
3679 unlock_user(p3, arg3, 0);
ths80265912007-02-17 22:25:41 +00003680 break;
3681 }
thse5febef2007-04-01 18:31:35 +00003682#ifdef TARGET_NR_umount
bellard31e31b82003-02-18 22:55:36 +00003683 case TARGET_NR_umount:
bellard579a97f2007-11-11 14:26:47 +00003684 if (!(p = lock_user_string(arg1)))
3685 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003686 ret = get_errno(umount(p));
3687 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003688 break;
thse5febef2007-04-01 18:31:35 +00003689#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003690#ifdef TARGET_NR_stime /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003691 case TARGET_NR_stime:
3692 {
pbrook53a59602006-03-25 19:31:22 +00003693 time_t host_time;
bellard2f619692007-11-16 10:46:05 +00003694 if (get_user_sal(host_time, arg1))
3695 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003696 ret = get_errno(stime(&host_time));
bellard31e31b82003-02-18 22:55:36 +00003697 }
3698 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003699#endif
bellard31e31b82003-02-18 22:55:36 +00003700 case TARGET_NR_ptrace:
3701 goto unimplemented;
j_mayer7a3148a2007-04-05 07:13:51 +00003702#ifdef TARGET_NR_alarm /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003703 case TARGET_NR_alarm:
3704 ret = alarm(arg1);
3705 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003706#endif
bellardebc05482003-09-30 21:08:41 +00003707#ifdef TARGET_NR_oldfstat
bellard31e31b82003-02-18 22:55:36 +00003708 case TARGET_NR_oldfstat:
3709 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003710#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003711#ifdef TARGET_NR_pause /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003712 case TARGET_NR_pause:
3713 ret = get_errno(pause());
3714 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003715#endif
thse5febef2007-04-01 18:31:35 +00003716#ifdef TARGET_NR_utime
bellard31e31b82003-02-18 22:55:36 +00003717 case TARGET_NR_utime:
bellardebc05482003-09-30 21:08:41 +00003718 {
pbrook53a59602006-03-25 19:31:22 +00003719 struct utimbuf tbuf, *host_tbuf;
3720 struct target_utimbuf *target_tbuf;
3721 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003722 if (!lock_user_struct(VERIFY_READ, target_tbuf, arg2, 1))
3723 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003724 tbuf.actime = tswapl(target_tbuf->actime);
3725 tbuf.modtime = tswapl(target_tbuf->modtime);
3726 unlock_user_struct(target_tbuf, arg2, 0);
3727 host_tbuf = &tbuf;
bellardf72e8ff2004-05-03 19:23:07 +00003728 } else {
pbrook53a59602006-03-25 19:31:22 +00003729 host_tbuf = NULL;
bellardf72e8ff2004-05-03 19:23:07 +00003730 }
bellard579a97f2007-11-11 14:26:47 +00003731 if (!(p = lock_user_string(arg1)))
3732 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003733 ret = get_errno(utime(p, host_tbuf));
3734 unlock_user(p, arg1, 0);
bellardebc05482003-09-30 21:08:41 +00003735 }
3736 break;
thse5febef2007-04-01 18:31:35 +00003737#endif
bellard978a66f2004-12-06 22:58:05 +00003738 case TARGET_NR_utimes:
3739 {
bellard978a66f2004-12-06 22:58:05 +00003740 struct timeval *tvp, tv[2];
pbrook53a59602006-03-25 19:31:22 +00003741 if (arg2) {
ths788f5ec2007-12-09 02:37:05 +00003742 if (copy_from_user_timeval(&tv[0], arg2)
3743 || copy_from_user_timeval(&tv[1],
3744 arg2 + sizeof(struct target_timeval)))
3745 goto efault;
bellard978a66f2004-12-06 22:58:05 +00003746 tvp = tv;
3747 } else {
3748 tvp = NULL;
3749 }
bellard579a97f2007-11-11 14:26:47 +00003750 if (!(p = lock_user_string(arg1)))
3751 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003752 ret = get_errno(utimes(p, tvp));
3753 unlock_user(p, arg1, 0);
bellard978a66f2004-12-06 22:58:05 +00003754 }
3755 break;
balrogac8a6552008-09-20 02:25:39 +00003756#if defined(TARGET_NR_futimesat) && defined(__NR_futimesat)
3757 case TARGET_NR_futimesat:
3758 {
3759 struct timeval *tvp, tv[2];
3760 if (arg3) {
3761 if (copy_from_user_timeval(&tv[0], arg3)
3762 || copy_from_user_timeval(&tv[1],
3763 arg3 + sizeof(struct target_timeval)))
3764 goto efault;
3765 tvp = tv;
3766 } else {
3767 tvp = NULL;
3768 }
3769 if (!(p = lock_user_string(arg2)))
3770 goto efault;
3771 ret = get_errno(sys_futimesat(arg1, path(p), tvp));
3772 unlock_user(p, arg2, 0);
3773 }
3774 break;
3775#endif
bellardebc05482003-09-30 21:08:41 +00003776#ifdef TARGET_NR_stty
bellard31e31b82003-02-18 22:55:36 +00003777 case TARGET_NR_stty:
3778 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003779#endif
3780#ifdef TARGET_NR_gtty
bellard31e31b82003-02-18 22:55:36 +00003781 case TARGET_NR_gtty:
3782 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003783#endif
bellard31e31b82003-02-18 22:55:36 +00003784 case TARGET_NR_access:
bellard579a97f2007-11-11 14:26:47 +00003785 if (!(p = lock_user_string(arg1)))
3786 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003787 ret = get_errno(access(p, arg2));
3788 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003789 break;
ths92a34c12007-09-24 09:27:49 +00003790#if defined(TARGET_NR_faccessat) && defined(__NR_faccessat)
3791 case TARGET_NR_faccessat:
bellard579a97f2007-11-11 14:26:47 +00003792 if (!(p = lock_user_string(arg2)))
3793 goto efault;
3794 ret = get_errno(sys_faccessat(arg1, p, arg3, arg4));
3795 unlock_user(p, arg2, 0);
ths92a34c12007-09-24 09:27:49 +00003796 break;
3797#endif
j_mayer7a3148a2007-04-05 07:13:51 +00003798#ifdef TARGET_NR_nice /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003799 case TARGET_NR_nice:
3800 ret = get_errno(nice(arg1));
3801 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003802#endif
bellardebc05482003-09-30 21:08:41 +00003803#ifdef TARGET_NR_ftime
bellard31e31b82003-02-18 22:55:36 +00003804 case TARGET_NR_ftime:
3805 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003806#endif
bellard31e31b82003-02-18 22:55:36 +00003807 case TARGET_NR_sync:
bellard04369ff2003-03-20 22:33:23 +00003808 sync();
3809 ret = 0;
bellard31e31b82003-02-18 22:55:36 +00003810 break;
3811 case TARGET_NR_kill:
pbrook4cb05962008-05-30 18:05:19 +00003812 ret = get_errno(kill(arg1, target_to_host_signal(arg2)));
bellard31e31b82003-02-18 22:55:36 +00003813 break;
3814 case TARGET_NR_rename:
pbrook53a59602006-03-25 19:31:22 +00003815 {
3816 void *p2;
3817 p = lock_user_string(arg1);
3818 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00003819 if (!p || !p2)
3820 ret = -TARGET_EFAULT;
3821 else
3822 ret = get_errno(rename(p, p2));
pbrook53a59602006-03-25 19:31:22 +00003823 unlock_user(p2, arg2, 0);
3824 unlock_user(p, arg1, 0);
3825 }
bellard31e31b82003-02-18 22:55:36 +00003826 break;
ths722183f2007-09-24 09:24:37 +00003827#if defined(TARGET_NR_renameat) && defined(__NR_renameat)
3828 case TARGET_NR_renameat:
ths722183f2007-09-24 09:24:37 +00003829 {
bellard579a97f2007-11-11 14:26:47 +00003830 void *p2;
ths722183f2007-09-24 09:24:37 +00003831 p = lock_user_string(arg2);
3832 p2 = lock_user_string(arg4);
bellard579a97f2007-11-11 14:26:47 +00003833 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00003834 ret = -TARGET_EFAULT;
ths722183f2007-09-24 09:24:37 +00003835 else
3836 ret = get_errno(sys_renameat(arg1, p, arg3, p2));
bellard579a97f2007-11-11 14:26:47 +00003837 unlock_user(p2, arg4, 0);
3838 unlock_user(p, arg2, 0);
ths722183f2007-09-24 09:24:37 +00003839 }
3840 break;
3841#endif
bellard31e31b82003-02-18 22:55:36 +00003842 case TARGET_NR_mkdir:
bellard579a97f2007-11-11 14:26:47 +00003843 if (!(p = lock_user_string(arg1)))
3844 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003845 ret = get_errno(mkdir(p, arg2));
3846 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003847 break;
ths4472ad02007-09-24 09:22:32 +00003848#if defined(TARGET_NR_mkdirat) && defined(__NR_mkdirat)
3849 case TARGET_NR_mkdirat:
bellard579a97f2007-11-11 14:26:47 +00003850 if (!(p = lock_user_string(arg2)))
3851 goto efault;
3852 ret = get_errno(sys_mkdirat(arg1, p, arg3));
3853 unlock_user(p, arg2, 0);
ths4472ad02007-09-24 09:22:32 +00003854 break;
3855#endif
bellard31e31b82003-02-18 22:55:36 +00003856 case TARGET_NR_rmdir:
bellard579a97f2007-11-11 14:26:47 +00003857 if (!(p = lock_user_string(arg1)))
3858 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003859 ret = get_errno(rmdir(p));
3860 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003861 break;
3862 case TARGET_NR_dup:
3863 ret = get_errno(dup(arg1));
3864 break;
3865 case TARGET_NR_pipe:
3866 {
pbrook53a59602006-03-25 19:31:22 +00003867 int host_pipe[2];
3868 ret = get_errno(pipe(host_pipe));
bellard31e31b82003-02-18 22:55:36 +00003869 if (!is_error(ret)) {
thsc12ab052007-06-01 11:50:36 +00003870#if defined(TARGET_MIPS)
thsead93602007-09-06 00:18:15 +00003871 CPUMIPSState *env = (CPUMIPSState*)cpu_env;
thsb5dc7732008-06-27 10:02:35 +00003872 env->active_tc.gpr[3] = host_pipe[1];
thsc12ab052007-06-01 11:50:36 +00003873 ret = host_pipe[0];
aurel32b5eff352008-03-11 23:30:22 +00003874#elif defined(TARGET_SH4)
3875 ((CPUSH4State*)cpu_env)->gregs[1] = host_pipe[1];
3876 ret = host_pipe[0];
thsc12ab052007-06-01 11:50:36 +00003877#else
bellard2f619692007-11-16 10:46:05 +00003878 if (put_user_s32(host_pipe[0], arg1)
3879 || put_user_s32(host_pipe[1], arg1 + sizeof(host_pipe[0])))
3880 goto efault;
thsc12ab052007-06-01 11:50:36 +00003881#endif
bellard31e31b82003-02-18 22:55:36 +00003882 }
3883 }
3884 break;
3885 case TARGET_NR_times:
bellard32f36bc2003-03-30 21:29:48 +00003886 {
pbrook53a59602006-03-25 19:31:22 +00003887 struct target_tms *tmsp;
bellard32f36bc2003-03-30 21:29:48 +00003888 struct tms tms;
3889 ret = get_errno(times(&tms));
pbrook53a59602006-03-25 19:31:22 +00003890 if (arg1) {
bellard579a97f2007-11-11 14:26:47 +00003891 tmsp = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_tms), 0);
3892 if (!tmsp)
3893 goto efault;
bellardc596ed12003-07-13 17:32:31 +00003894 tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime));
3895 tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime));
3896 tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime));
3897 tmsp->tms_cstime = tswapl(host_to_target_clock_t(tms.tms_cstime));
bellard32f36bc2003-03-30 21:29:48 +00003898 }
bellardc596ed12003-07-13 17:32:31 +00003899 if (!is_error(ret))
3900 ret = host_to_target_clock_t(ret);
bellard32f36bc2003-03-30 21:29:48 +00003901 }
3902 break;
bellardebc05482003-09-30 21:08:41 +00003903#ifdef TARGET_NR_prof
bellard31e31b82003-02-18 22:55:36 +00003904 case TARGET_NR_prof:
3905 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003906#endif
thse5febef2007-04-01 18:31:35 +00003907#ifdef TARGET_NR_signal
bellard31e31b82003-02-18 22:55:36 +00003908 case TARGET_NR_signal:
3909 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00003910#endif
bellard31e31b82003-02-18 22:55:36 +00003911 case TARGET_NR_acct:
bellard579a97f2007-11-11 14:26:47 +00003912 if (!(p = lock_user_string(arg1)))
3913 goto efault;
pbrook24836682006-04-16 14:14:53 +00003914 ret = get_errno(acct(path(p)));
3915 unlock_user(p, arg1, 0);
3916 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003917#ifdef TARGET_NR_umount2 /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003918 case TARGET_NR_umount2:
bellard579a97f2007-11-11 14:26:47 +00003919 if (!(p = lock_user_string(arg1)))
3920 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003921 ret = get_errno(umount2(p, arg2));
3922 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003923 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003924#endif
bellardebc05482003-09-30 21:08:41 +00003925#ifdef TARGET_NR_lock
bellard31e31b82003-02-18 22:55:36 +00003926 case TARGET_NR_lock:
3927 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003928#endif
bellard31e31b82003-02-18 22:55:36 +00003929 case TARGET_NR_ioctl:
3930 ret = do_ioctl(arg1, arg2, arg3);
3931 break;
3932 case TARGET_NR_fcntl:
bellard9ee1fa22007-11-11 15:11:19 +00003933 ret = do_fcntl(arg1, arg2, arg3);
bellard31e31b82003-02-18 22:55:36 +00003934 break;
bellardebc05482003-09-30 21:08:41 +00003935#ifdef TARGET_NR_mpx
bellard31e31b82003-02-18 22:55:36 +00003936 case TARGET_NR_mpx:
3937 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003938#endif
bellard31e31b82003-02-18 22:55:36 +00003939 case TARGET_NR_setpgid:
3940 ret = get_errno(setpgid(arg1, arg2));
3941 break;
bellardebc05482003-09-30 21:08:41 +00003942#ifdef TARGET_NR_ulimit
bellard31e31b82003-02-18 22:55:36 +00003943 case TARGET_NR_ulimit:
3944 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003945#endif
3946#ifdef TARGET_NR_oldolduname
bellard31e31b82003-02-18 22:55:36 +00003947 case TARGET_NR_oldolduname:
3948 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00003949#endif
bellard31e31b82003-02-18 22:55:36 +00003950 case TARGET_NR_umask:
3951 ret = get_errno(umask(arg1));
3952 break;
3953 case TARGET_NR_chroot:
bellard579a97f2007-11-11 14:26:47 +00003954 if (!(p = lock_user_string(arg1)))
3955 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003956 ret = get_errno(chroot(p));
3957 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00003958 break;
3959 case TARGET_NR_ustat:
3960 goto unimplemented;
3961 case TARGET_NR_dup2:
3962 ret = get_errno(dup2(arg1, arg2));
3963 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003964#ifdef TARGET_NR_getppid /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00003965 case TARGET_NR_getppid:
3966 ret = get_errno(getppid());
3967 break;
j_mayer7a3148a2007-04-05 07:13:51 +00003968#endif
bellard31e31b82003-02-18 22:55:36 +00003969 case TARGET_NR_getpgrp:
3970 ret = get_errno(getpgrp());
3971 break;
3972 case TARGET_NR_setsid:
3973 ret = get_errno(setsid());
3974 break;
thse5febef2007-04-01 18:31:35 +00003975#ifdef TARGET_NR_sigaction
bellard31e31b82003-02-18 22:55:36 +00003976 case TARGET_NR_sigaction:
bellard31e31b82003-02-18 22:55:36 +00003977 {
ths388bb212007-05-13 13:58:00 +00003978#if !defined(TARGET_MIPS)
pbrook53a59602006-03-25 19:31:22 +00003979 struct target_old_sigaction *old_act;
bellard66fb9762003-03-23 01:06:05 +00003980 struct target_sigaction act, oact, *pact;
pbrook53a59602006-03-25 19:31:22 +00003981 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00003982 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
3983 goto efault;
bellard66fb9762003-03-23 01:06:05 +00003984 act._sa_handler = old_act->_sa_handler;
3985 target_siginitset(&act.sa_mask, old_act->sa_mask);
3986 act.sa_flags = old_act->sa_flags;
3987 act.sa_restorer = old_act->sa_restorer;
pbrook53a59602006-03-25 19:31:22 +00003988 unlock_user_struct(old_act, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00003989 pact = &act;
3990 } else {
3991 pact = NULL;
3992 }
3993 ret = get_errno(do_sigaction(arg1, pact, &oact));
pbrook53a59602006-03-25 19:31:22 +00003994 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00003995 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
3996 goto efault;
pbrook53a59602006-03-25 19:31:22 +00003997 old_act->_sa_handler = oact._sa_handler;
3998 old_act->sa_mask = oact.sa_mask.sig[0];
3999 old_act->sa_flags = oact.sa_flags;
4000 old_act->sa_restorer = oact.sa_restorer;
4001 unlock_user_struct(old_act, arg3, 1);
bellard66fb9762003-03-23 01:06:05 +00004002 }
ths388bb212007-05-13 13:58:00 +00004003#else
bellard106ec872006-06-27 21:08:10 +00004004 struct target_sigaction act, oact, *pact, *old_act;
4005
4006 if (arg2) {
bellard579a97f2007-11-11 14:26:47 +00004007 if (!lock_user_struct(VERIFY_READ, old_act, arg2, 1))
4008 goto efault;
bellard106ec872006-06-27 21:08:10 +00004009 act._sa_handler = old_act->_sa_handler;
4010 target_siginitset(&act.sa_mask, old_act->sa_mask.sig[0]);
4011 act.sa_flags = old_act->sa_flags;
4012 unlock_user_struct(old_act, arg2, 0);
4013 pact = &act;
4014 } else {
4015 pact = NULL;
4016 }
4017
4018 ret = get_errno(do_sigaction(arg1, pact, &oact));
4019
4020 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004021 if (!lock_user_struct(VERIFY_WRITE, old_act, arg3, 0))
4022 goto efault;
bellard106ec872006-06-27 21:08:10 +00004023 old_act->_sa_handler = oact._sa_handler;
4024 old_act->sa_flags = oact.sa_flags;
4025 old_act->sa_mask.sig[0] = oact.sa_mask.sig[0];
4026 old_act->sa_mask.sig[1] = 0;
4027 old_act->sa_mask.sig[2] = 0;
4028 old_act->sa_mask.sig[3] = 0;
4029 unlock_user_struct(old_act, arg3, 1);
4030 }
ths388bb212007-05-13 13:58:00 +00004031#endif
bellard31e31b82003-02-18 22:55:36 +00004032 }
4033 break;
thse5febef2007-04-01 18:31:35 +00004034#endif
bellard66fb9762003-03-23 01:06:05 +00004035 case TARGET_NR_rt_sigaction:
pbrook53a59602006-03-25 19:31:22 +00004036 {
4037 struct target_sigaction *act;
4038 struct target_sigaction *oact;
4039
bellard579a97f2007-11-11 14:26:47 +00004040 if (arg2) {
4041 if (!lock_user_struct(VERIFY_READ, act, arg2, 1))
4042 goto efault;
4043 } else
pbrook53a59602006-03-25 19:31:22 +00004044 act = NULL;
bellard579a97f2007-11-11 14:26:47 +00004045 if (arg3) {
4046 if (!lock_user_struct(VERIFY_WRITE, oact, arg3, 0)) {
4047 ret = -TARGET_EFAULT;
4048 goto rt_sigaction_fail;
4049 }
4050 } else
pbrook53a59602006-03-25 19:31:22 +00004051 oact = NULL;
4052 ret = get_errno(do_sigaction(arg1, act, oact));
bellard579a97f2007-11-11 14:26:47 +00004053 rt_sigaction_fail:
4054 if (act)
pbrook53a59602006-03-25 19:31:22 +00004055 unlock_user_struct(act, arg2, 0);
bellard579a97f2007-11-11 14:26:47 +00004056 if (oact)
pbrook53a59602006-03-25 19:31:22 +00004057 unlock_user_struct(oact, arg3, 1);
4058 }
bellard66fb9762003-03-23 01:06:05 +00004059 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004060#ifdef TARGET_NR_sgetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004061 case TARGET_NR_sgetmask:
bellard66fb9762003-03-23 01:06:05 +00004062 {
4063 sigset_t cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004064 abi_ulong target_set;
bellard66fb9762003-03-23 01:06:05 +00004065 sigprocmask(0, NULL, &cur_set);
4066 host_to_target_old_sigset(&target_set, &cur_set);
4067 ret = target_set;
4068 }
4069 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004070#endif
4071#ifdef TARGET_NR_ssetmask /* not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004072 case TARGET_NR_ssetmask:
bellard66fb9762003-03-23 01:06:05 +00004073 {
4074 sigset_t set, oset, cur_set;
blueswir1992f48a2007-10-14 16:27:31 +00004075 abi_ulong target_set = arg1;
bellard66fb9762003-03-23 01:06:05 +00004076 sigprocmask(0, NULL, &cur_set);
4077 target_to_host_old_sigset(&set, &target_set);
4078 sigorset(&set, &set, &cur_set);
4079 sigprocmask(SIG_SETMASK, &set, &oset);
4080 host_to_target_old_sigset(&target_set, &oset);
4081 ret = target_set;
4082 }
4083 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004084#endif
thse5febef2007-04-01 18:31:35 +00004085#ifdef TARGET_NR_sigprocmask
bellard66fb9762003-03-23 01:06:05 +00004086 case TARGET_NR_sigprocmask:
4087 {
4088 int how = arg1;
4089 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004090
pbrook53a59602006-03-25 19:31:22 +00004091 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004092 switch(how) {
4093 case TARGET_SIG_BLOCK:
4094 how = SIG_BLOCK;
4095 break;
4096 case TARGET_SIG_UNBLOCK:
4097 how = SIG_UNBLOCK;
4098 break;
4099 case TARGET_SIG_SETMASK:
4100 how = SIG_SETMASK;
4101 break;
4102 default:
ths0da46a62007-10-20 20:23:07 +00004103 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004104 goto fail;
4105 }
bellard579a97f2007-11-11 14:26:47 +00004106 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4107 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004108 target_to_host_old_sigset(&set, p);
4109 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004110 set_ptr = &set;
4111 } else {
4112 how = 0;
4113 set_ptr = NULL;
4114 }
4115 ret = get_errno(sigprocmask(arg1, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004116 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004117 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4118 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004119 host_to_target_old_sigset(p, &oldset);
4120 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004121 }
4122 }
4123 break;
thse5febef2007-04-01 18:31:35 +00004124#endif
bellard66fb9762003-03-23 01:06:05 +00004125 case TARGET_NR_rt_sigprocmask:
4126 {
4127 int how = arg1;
4128 sigset_t set, oldset, *set_ptr;
ths3b46e622007-09-17 08:09:54 +00004129
pbrook53a59602006-03-25 19:31:22 +00004130 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004131 switch(how) {
4132 case TARGET_SIG_BLOCK:
4133 how = SIG_BLOCK;
4134 break;
4135 case TARGET_SIG_UNBLOCK:
4136 how = SIG_UNBLOCK;
4137 break;
4138 case TARGET_SIG_SETMASK:
4139 how = SIG_SETMASK;
4140 break;
4141 default:
ths0da46a62007-10-20 20:23:07 +00004142 ret = -TARGET_EINVAL;
bellard66fb9762003-03-23 01:06:05 +00004143 goto fail;
4144 }
bellard579a97f2007-11-11 14:26:47 +00004145 if (!(p = lock_user(VERIFY_READ, arg2, sizeof(target_sigset_t), 1)))
4146 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004147 target_to_host_sigset(&set, p);
4148 unlock_user(p, arg2, 0);
bellard66fb9762003-03-23 01:06:05 +00004149 set_ptr = &set;
4150 } else {
4151 how = 0;
4152 set_ptr = NULL;
4153 }
4154 ret = get_errno(sigprocmask(how, set_ptr, &oldset));
pbrook53a59602006-03-25 19:31:22 +00004155 if (!is_error(ret) && arg3) {
bellard579a97f2007-11-11 14:26:47 +00004156 if (!(p = lock_user(VERIFY_WRITE, arg3, sizeof(target_sigset_t), 0)))
4157 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004158 host_to_target_sigset(p, &oldset);
4159 unlock_user(p, arg3, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004160 }
4161 }
4162 break;
thse5febef2007-04-01 18:31:35 +00004163#ifdef TARGET_NR_sigpending
bellard66fb9762003-03-23 01:06:05 +00004164 case TARGET_NR_sigpending:
4165 {
4166 sigset_t set;
4167 ret = get_errno(sigpending(&set));
4168 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004169 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4170 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004171 host_to_target_old_sigset(p, &set);
4172 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004173 }
4174 }
4175 break;
thse5febef2007-04-01 18:31:35 +00004176#endif
bellard66fb9762003-03-23 01:06:05 +00004177 case TARGET_NR_rt_sigpending:
4178 {
4179 sigset_t set;
4180 ret = get_errno(sigpending(&set));
4181 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004182 if (!(p = lock_user(VERIFY_WRITE, arg1, sizeof(target_sigset_t), 0)))
4183 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004184 host_to_target_sigset(p, &set);
4185 unlock_user(p, arg1, sizeof(target_sigset_t));
bellard66fb9762003-03-23 01:06:05 +00004186 }
4187 }
4188 break;
thse5febef2007-04-01 18:31:35 +00004189#ifdef TARGET_NR_sigsuspend
bellard66fb9762003-03-23 01:06:05 +00004190 case TARGET_NR_sigsuspend:
4191 {
4192 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004193 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4194 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004195 target_to_host_old_sigset(&set, p);
4196 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004197 ret = get_errno(sigsuspend(&set));
4198 }
4199 break;
thse5febef2007-04-01 18:31:35 +00004200#endif
bellard66fb9762003-03-23 01:06:05 +00004201 case TARGET_NR_rt_sigsuspend:
4202 {
4203 sigset_t set;
bellard579a97f2007-11-11 14:26:47 +00004204 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4205 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004206 target_to_host_sigset(&set, p);
4207 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004208 ret = get_errno(sigsuspend(&set));
4209 }
4210 break;
4211 case TARGET_NR_rt_sigtimedwait:
4212 {
bellard66fb9762003-03-23 01:06:05 +00004213 sigset_t set;
4214 struct timespec uts, *puts;
4215 siginfo_t uinfo;
ths3b46e622007-09-17 08:09:54 +00004216
bellard579a97f2007-11-11 14:26:47 +00004217 if (!(p = lock_user(VERIFY_READ, arg1, sizeof(target_sigset_t), 1)))
4218 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004219 target_to_host_sigset(&set, p);
4220 unlock_user(p, arg1, 0);
4221 if (arg3) {
bellard66fb9762003-03-23 01:06:05 +00004222 puts = &uts;
pbrook53a59602006-03-25 19:31:22 +00004223 target_to_host_timespec(puts, arg3);
bellard66fb9762003-03-23 01:06:05 +00004224 } else {
4225 puts = NULL;
4226 }
4227 ret = get_errno(sigtimedwait(&set, &uinfo, puts));
pbrook53a59602006-03-25 19:31:22 +00004228 if (!is_error(ret) && arg2) {
pbrooke1e3f302008-05-30 21:53:38 +00004229 if (!(p = lock_user(VERIFY_WRITE, arg2, sizeof(target_siginfo_t), 0)))
bellard579a97f2007-11-11 14:26:47 +00004230 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004231 host_to_target_siginfo(p, &uinfo);
pbrooke1e3f302008-05-30 21:53:38 +00004232 unlock_user(p, arg2, sizeof(target_siginfo_t));
bellard66fb9762003-03-23 01:06:05 +00004233 }
4234 }
4235 break;
4236 case TARGET_NR_rt_sigqueueinfo:
4237 {
4238 siginfo_t uinfo;
bellard579a97f2007-11-11 14:26:47 +00004239 if (!(p = lock_user(VERIFY_READ, arg3, sizeof(target_sigset_t), 1)))
4240 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004241 target_to_host_siginfo(&uinfo, p);
4242 unlock_user(p, arg1, 0);
bellard66fb9762003-03-23 01:06:05 +00004243 ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo));
4244 }
4245 break;
thse5febef2007-04-01 18:31:35 +00004246#ifdef TARGET_NR_sigreturn
bellard66fb9762003-03-23 01:06:05 +00004247 case TARGET_NR_sigreturn:
4248 /* NOTE: ret is eax, so not transcoding must be done */
4249 ret = do_sigreturn(cpu_env);
4250 break;
thse5febef2007-04-01 18:31:35 +00004251#endif
bellard66fb9762003-03-23 01:06:05 +00004252 case TARGET_NR_rt_sigreturn:
4253 /* NOTE: ret is eax, so not transcoding must be done */
4254 ret = do_rt_sigreturn(cpu_env);
4255 break;
bellard31e31b82003-02-18 22:55:36 +00004256 case TARGET_NR_sethostname:
bellard579a97f2007-11-11 14:26:47 +00004257 if (!(p = lock_user_string(arg1)))
4258 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004259 ret = get_errno(sethostname(p, arg2));
4260 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004261 break;
4262 case TARGET_NR_setrlimit:
bellard9de5e442003-03-23 16:49:39 +00004263 {
4264 /* XXX: convert resource ? */
4265 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004266 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004267 struct rlimit rlim;
bellard579a97f2007-11-11 14:26:47 +00004268 if (!lock_user_struct(VERIFY_READ, target_rlim, arg2, 1))
4269 goto efault;
bellard9de5e442003-03-23 16:49:39 +00004270 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4271 rlim.rlim_max = tswapl(target_rlim->rlim_max);
pbrook53a59602006-03-25 19:31:22 +00004272 unlock_user_struct(target_rlim, arg2, 0);
bellard9de5e442003-03-23 16:49:39 +00004273 ret = get_errno(setrlimit(resource, &rlim));
4274 }
4275 break;
bellard31e31b82003-02-18 22:55:36 +00004276 case TARGET_NR_getrlimit:
bellard9de5e442003-03-23 16:49:39 +00004277 {
4278 /* XXX: convert resource ? */
4279 int resource = arg1;
pbrook53a59602006-03-25 19:31:22 +00004280 struct target_rlimit *target_rlim;
bellard9de5e442003-03-23 16:49:39 +00004281 struct rlimit rlim;
ths3b46e622007-09-17 08:09:54 +00004282
bellard9de5e442003-03-23 16:49:39 +00004283 ret = get_errno(getrlimit(resource, &rlim));
4284 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00004285 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
4286 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004287 rlim.rlim_cur = tswapl(target_rlim->rlim_cur);
4288 rlim.rlim_max = tswapl(target_rlim->rlim_max);
4289 unlock_user_struct(target_rlim, arg2, 1);
bellard9de5e442003-03-23 16:49:39 +00004290 }
4291 }
4292 break;
bellard31e31b82003-02-18 22:55:36 +00004293 case TARGET_NR_getrusage:
bellardb4091862003-05-16 15:39:34 +00004294 {
4295 struct rusage rusage;
bellardb4091862003-05-16 15:39:34 +00004296 ret = get_errno(getrusage(arg1, &rusage));
4297 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004298 host_to_target_rusage(arg2, &rusage);
bellardb4091862003-05-16 15:39:34 +00004299 }
4300 }
4301 break;
bellard31e31b82003-02-18 22:55:36 +00004302 case TARGET_NR_gettimeofday:
4303 {
bellard31e31b82003-02-18 22:55:36 +00004304 struct timeval tv;
4305 ret = get_errno(gettimeofday(&tv, NULL));
4306 if (!is_error(ret)) {
ths788f5ec2007-12-09 02:37:05 +00004307 if (copy_to_user_timeval(arg1, &tv))
4308 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004309 }
4310 }
4311 break;
4312 case TARGET_NR_settimeofday:
4313 {
bellard31e31b82003-02-18 22:55:36 +00004314 struct timeval tv;
ths788f5ec2007-12-09 02:37:05 +00004315 if (copy_from_user_timeval(&tv, arg1))
4316 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004317 ret = get_errno(settimeofday(&tv, NULL));
4318 }
4319 break;
bellard048f6b42005-11-26 18:47:20 +00004320#ifdef TARGET_NR_select
bellard31e31b82003-02-18 22:55:36 +00004321 case TARGET_NR_select:
bellardf2674e32003-07-09 12:26:09 +00004322 {
pbrook53a59602006-03-25 19:31:22 +00004323 struct target_sel_arg_struct *sel;
blueswir1992f48a2007-10-14 16:27:31 +00004324 abi_ulong inp, outp, exp, tvp;
pbrook53a59602006-03-25 19:31:22 +00004325 long nsel;
4326
bellard579a97f2007-11-11 14:26:47 +00004327 if (!lock_user_struct(VERIFY_READ, sel, arg1, 1))
4328 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004329 nsel = tswapl(sel->n);
4330 inp = tswapl(sel->inp);
4331 outp = tswapl(sel->outp);
4332 exp = tswapl(sel->exp);
4333 tvp = tswapl(sel->tvp);
4334 unlock_user_struct(sel, arg1, 0);
4335 ret = do_select(nsel, inp, outp, exp, tvp);
bellardf2674e32003-07-09 12:26:09 +00004336 }
4337 break;
bellard048f6b42005-11-26 18:47:20 +00004338#endif
bellard31e31b82003-02-18 22:55:36 +00004339 case TARGET_NR_symlink:
pbrook53a59602006-03-25 19:31:22 +00004340 {
4341 void *p2;
4342 p = lock_user_string(arg1);
4343 p2 = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004344 if (!p || !p2)
4345 ret = -TARGET_EFAULT;
4346 else
4347 ret = get_errno(symlink(p, p2));
pbrook53a59602006-03-25 19:31:22 +00004348 unlock_user(p2, arg2, 0);
4349 unlock_user(p, arg1, 0);
4350 }
bellard31e31b82003-02-18 22:55:36 +00004351 break;
thsf0b62432007-09-24 09:25:40 +00004352#if defined(TARGET_NR_symlinkat) && defined(__NR_symlinkat)
4353 case TARGET_NR_symlinkat:
thsf0b62432007-09-24 09:25:40 +00004354 {
bellard579a97f2007-11-11 14:26:47 +00004355 void *p2;
thsf0b62432007-09-24 09:25:40 +00004356 p = lock_user_string(arg1);
4357 p2 = lock_user_string(arg3);
bellard579a97f2007-11-11 14:26:47 +00004358 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004359 ret = -TARGET_EFAULT;
thsf0b62432007-09-24 09:25:40 +00004360 else
4361 ret = get_errno(sys_symlinkat(p, arg2, p2));
bellard579a97f2007-11-11 14:26:47 +00004362 unlock_user(p2, arg3, 0);
4363 unlock_user(p, arg1, 0);
thsf0b62432007-09-24 09:25:40 +00004364 }
4365 break;
4366#endif
bellardebc05482003-09-30 21:08:41 +00004367#ifdef TARGET_NR_oldlstat
bellard31e31b82003-02-18 22:55:36 +00004368 case TARGET_NR_oldlstat:
4369 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004370#endif
bellard31e31b82003-02-18 22:55:36 +00004371 case TARGET_NR_readlink:
pbrook53a59602006-03-25 19:31:22 +00004372 {
4373 void *p2;
4374 p = lock_user_string(arg1);
bellard579a97f2007-11-11 14:26:47 +00004375 p2 = lock_user(VERIFY_WRITE, arg2, arg3, 0);
4376 if (!p || !p2)
4377 ret = -TARGET_EFAULT;
4378 else
4379 ret = get_errno(readlink(path(p), p2, arg3));
pbrook53a59602006-03-25 19:31:22 +00004380 unlock_user(p2, arg2, ret);
4381 unlock_user(p, arg1, 0);
4382 }
bellard31e31b82003-02-18 22:55:36 +00004383 break;
ths5e0ccb12007-09-24 09:26:10 +00004384#if defined(TARGET_NR_readlinkat) && defined(__NR_readlinkat)
4385 case TARGET_NR_readlinkat:
ths5e0ccb12007-09-24 09:26:10 +00004386 {
bellard579a97f2007-11-11 14:26:47 +00004387 void *p2;
ths5e0ccb12007-09-24 09:26:10 +00004388 p = lock_user_string(arg2);
bellard579a97f2007-11-11 14:26:47 +00004389 p2 = lock_user(VERIFY_WRITE, arg3, arg4, 0);
4390 if (!p || !p2)
ths0da46a62007-10-20 20:23:07 +00004391 ret = -TARGET_EFAULT;
ths5e0ccb12007-09-24 09:26:10 +00004392 else
4393 ret = get_errno(sys_readlinkat(arg1, path(p), p2, arg4));
bellard579a97f2007-11-11 14:26:47 +00004394 unlock_user(p2, arg3, ret);
4395 unlock_user(p, arg2, 0);
ths5e0ccb12007-09-24 09:26:10 +00004396 }
4397 break;
4398#endif
thse5febef2007-04-01 18:31:35 +00004399#ifdef TARGET_NR_uselib
bellard31e31b82003-02-18 22:55:36 +00004400 case TARGET_NR_uselib:
4401 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004402#endif
4403#ifdef TARGET_NR_swapon
bellard31e31b82003-02-18 22:55:36 +00004404 case TARGET_NR_swapon:
bellard579a97f2007-11-11 14:26:47 +00004405 if (!(p = lock_user_string(arg1)))
4406 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004407 ret = get_errno(swapon(p, arg2));
4408 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004409 break;
thse5febef2007-04-01 18:31:35 +00004410#endif
bellard31e31b82003-02-18 22:55:36 +00004411 case TARGET_NR_reboot:
4412 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004413#ifdef TARGET_NR_readdir
bellard31e31b82003-02-18 22:55:36 +00004414 case TARGET_NR_readdir:
4415 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004416#endif
4417#ifdef TARGET_NR_mmap
bellard31e31b82003-02-18 22:55:36 +00004418 case TARGET_NR_mmap:
bellardd2fd1af2007-11-14 18:08:56 +00004419#if (defined(TARGET_I386) && defined(TARGET_ABI32)) || defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_CRIS)
bellard31e31b82003-02-18 22:55:36 +00004420 {
blueswir1992f48a2007-10-14 16:27:31 +00004421 abi_ulong *v;
4422 abi_ulong v1, v2, v3, v4, v5, v6;
bellard579a97f2007-11-11 14:26:47 +00004423 if (!(v = lock_user(VERIFY_READ, arg1, 6 * sizeof(abi_ulong), 1)))
4424 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004425 v1 = tswapl(v[0]);
4426 v2 = tswapl(v[1]);
4427 v3 = tswapl(v[2]);
4428 v4 = tswapl(v[3]);
4429 v5 = tswapl(v[4]);
4430 v6 = tswapl(v[5]);
4431 unlock_user(v, arg1, 0);
ths5fafdf22007-09-16 21:08:06 +00004432 ret = get_errno(target_mmap(v1, v2, v3,
bellard5286db72003-06-05 00:57:30 +00004433 target_to_host_bitmask(v4, mmap_flags_tbl),
4434 v5, v6));
bellard31e31b82003-02-18 22:55:36 +00004435 }
bellard31e31b82003-02-18 22:55:36 +00004436#else
ths5fafdf22007-09-16 21:08:06 +00004437 ret = get_errno(target_mmap(arg1, arg2, arg3,
4438 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard6fb883e2003-07-09 17:12:39 +00004439 arg5,
4440 arg6));
bellard31e31b82003-02-18 22:55:36 +00004441#endif
bellard6fb883e2003-07-09 17:12:39 +00004442 break;
thse5febef2007-04-01 18:31:35 +00004443#endif
bellarda315a142005-01-30 22:59:18 +00004444#ifdef TARGET_NR_mmap2
bellard6fb883e2003-07-09 17:12:39 +00004445 case TARGET_NR_mmap2:
pbrookbb7ec042008-03-25 22:28:25 +00004446#ifndef MMAP_SHIFT
bellardc573ff62004-01-04 15:51:36 +00004447#define MMAP_SHIFT 12
bellardc573ff62004-01-04 15:51:36 +00004448#endif
ths5fafdf22007-09-16 21:08:06 +00004449 ret = get_errno(target_mmap(arg1, arg2, arg3,
4450 target_to_host_bitmask(arg4, mmap_flags_tbl),
bellard5286db72003-06-05 00:57:30 +00004451 arg5,
bellardc573ff62004-01-04 15:51:36 +00004452 arg6 << MMAP_SHIFT));
bellard31e31b82003-02-18 22:55:36 +00004453 break;
bellarda315a142005-01-30 22:59:18 +00004454#endif
bellard31e31b82003-02-18 22:55:36 +00004455 case TARGET_NR_munmap:
bellard54936002003-05-13 00:25:15 +00004456 ret = get_errno(target_munmap(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00004457 break;
bellard9de5e442003-03-23 16:49:39 +00004458 case TARGET_NR_mprotect:
bellard54936002003-05-13 00:25:15 +00004459 ret = get_errno(target_mprotect(arg1, arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004460 break;
thse5febef2007-04-01 18:31:35 +00004461#ifdef TARGET_NR_mremap
bellard9de5e442003-03-23 16:49:39 +00004462 case TARGET_NR_mremap:
bellard54936002003-05-13 00:25:15 +00004463 ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5));
bellard9de5e442003-03-23 16:49:39 +00004464 break;
thse5febef2007-04-01 18:31:35 +00004465#endif
pbrook53a59602006-03-25 19:31:22 +00004466 /* ??? msync/mlock/munlock are broken for softmmu. */
thse5febef2007-04-01 18:31:35 +00004467#ifdef TARGET_NR_msync
bellard9de5e442003-03-23 16:49:39 +00004468 case TARGET_NR_msync:
pbrook53a59602006-03-25 19:31:22 +00004469 ret = get_errno(msync(g2h(arg1), arg2, arg3));
bellard9de5e442003-03-23 16:49:39 +00004470 break;
thse5febef2007-04-01 18:31:35 +00004471#endif
4472#ifdef TARGET_NR_mlock
bellard9de5e442003-03-23 16:49:39 +00004473 case TARGET_NR_mlock:
pbrook53a59602006-03-25 19:31:22 +00004474 ret = get_errno(mlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004475 break;
thse5febef2007-04-01 18:31:35 +00004476#endif
4477#ifdef TARGET_NR_munlock
bellard9de5e442003-03-23 16:49:39 +00004478 case TARGET_NR_munlock:
pbrook53a59602006-03-25 19:31:22 +00004479 ret = get_errno(munlock(g2h(arg1), arg2));
bellard9de5e442003-03-23 16:49:39 +00004480 break;
thse5febef2007-04-01 18:31:35 +00004481#endif
4482#ifdef TARGET_NR_mlockall
bellard9de5e442003-03-23 16:49:39 +00004483 case TARGET_NR_mlockall:
4484 ret = get_errno(mlockall(arg1));
4485 break;
thse5febef2007-04-01 18:31:35 +00004486#endif
4487#ifdef TARGET_NR_munlockall
bellard9de5e442003-03-23 16:49:39 +00004488 case TARGET_NR_munlockall:
4489 ret = get_errno(munlockall());
4490 break;
thse5febef2007-04-01 18:31:35 +00004491#endif
bellard31e31b82003-02-18 22:55:36 +00004492 case TARGET_NR_truncate:
bellard579a97f2007-11-11 14:26:47 +00004493 if (!(p = lock_user_string(arg1)))
4494 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004495 ret = get_errno(truncate(p, arg2));
4496 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004497 break;
4498 case TARGET_NR_ftruncate:
4499 ret = get_errno(ftruncate(arg1, arg2));
4500 break;
4501 case TARGET_NR_fchmod:
4502 ret = get_errno(fchmod(arg1, arg2));
4503 break;
ths814d7972007-09-24 09:26:51 +00004504#if defined(TARGET_NR_fchmodat) && defined(__NR_fchmodat)
4505 case TARGET_NR_fchmodat:
bellard579a97f2007-11-11 14:26:47 +00004506 if (!(p = lock_user_string(arg2)))
4507 goto efault;
4508 ret = get_errno(sys_fchmodat(arg1, p, arg3, arg4));
4509 unlock_user(p, arg2, 0);
ths814d7972007-09-24 09:26:51 +00004510 break;
4511#endif
bellard31e31b82003-02-18 22:55:36 +00004512 case TARGET_NR_getpriority:
thsc6cda172007-10-09 03:42:34 +00004513 /* libc does special remapping of the return value of
4514 * sys_getpriority() so it's just easiest to call
4515 * sys_getpriority() directly rather than through libc. */
4516 ret = sys_getpriority(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004517 break;
4518 case TARGET_NR_setpriority:
4519 ret = get_errno(setpriority(arg1, arg2, arg3));
4520 break;
bellardebc05482003-09-30 21:08:41 +00004521#ifdef TARGET_NR_profil
bellard31e31b82003-02-18 22:55:36 +00004522 case TARGET_NR_profil:
4523 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004524#endif
bellard31e31b82003-02-18 22:55:36 +00004525 case TARGET_NR_statfs:
bellard579a97f2007-11-11 14:26:47 +00004526 if (!(p = lock_user_string(arg1)))
4527 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004528 ret = get_errno(statfs(path(p), &stfs));
4529 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004530 convert_statfs:
4531 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004532 struct target_statfs *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004533
bellard579a97f2007-11-11 14:26:47 +00004534 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg2, 0))
4535 goto efault;
4536 __put_user(stfs.f_type, &target_stfs->f_type);
4537 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4538 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4539 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4540 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4541 __put_user(stfs.f_files, &target_stfs->f_files);
4542 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4543 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4544 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4545 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
pbrook53a59602006-03-25 19:31:22 +00004546 unlock_user_struct(target_stfs, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004547 }
4548 break;
4549 case TARGET_NR_fstatfs:
bellard56c8f682005-11-28 22:28:41 +00004550 ret = get_errno(fstatfs(arg1, &stfs));
bellard31e31b82003-02-18 22:55:36 +00004551 goto convert_statfs;
bellard56c8f682005-11-28 22:28:41 +00004552#ifdef TARGET_NR_statfs64
4553 case TARGET_NR_statfs64:
bellard579a97f2007-11-11 14:26:47 +00004554 if (!(p = lock_user_string(arg1)))
4555 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004556 ret = get_errno(statfs(path(p), &stfs));
4557 unlock_user(p, arg1, 0);
bellard56c8f682005-11-28 22:28:41 +00004558 convert_statfs64:
4559 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004560 struct target_statfs64 *target_stfs;
ths3b46e622007-09-17 08:09:54 +00004561
bellard579a97f2007-11-11 14:26:47 +00004562 if (!lock_user_struct(VERIFY_WRITE, target_stfs, arg3, 0))
4563 goto efault;
4564 __put_user(stfs.f_type, &target_stfs->f_type);
4565 __put_user(stfs.f_bsize, &target_stfs->f_bsize);
4566 __put_user(stfs.f_blocks, &target_stfs->f_blocks);
4567 __put_user(stfs.f_bfree, &target_stfs->f_bfree);
4568 __put_user(stfs.f_bavail, &target_stfs->f_bavail);
4569 __put_user(stfs.f_files, &target_stfs->f_files);
4570 __put_user(stfs.f_ffree, &target_stfs->f_ffree);
4571 __put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid.val[0]);
4572 __put_user(stfs.f_fsid.__val[1], &target_stfs->f_fsid.val[1]);
4573 __put_user(stfs.f_namelen, &target_stfs->f_namelen);
4574 unlock_user_struct(target_stfs, arg3, 1);
bellard56c8f682005-11-28 22:28:41 +00004575 }
4576 break;
4577 case TARGET_NR_fstatfs64:
4578 ret = get_errno(fstatfs(arg1, &stfs));
4579 goto convert_statfs64;
4580#endif
bellardebc05482003-09-30 21:08:41 +00004581#ifdef TARGET_NR_ioperm
bellard31e31b82003-02-18 22:55:36 +00004582 case TARGET_NR_ioperm:
4583 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004584#endif
thse5febef2007-04-01 18:31:35 +00004585#ifdef TARGET_NR_socketcall
bellard31e31b82003-02-18 22:55:36 +00004586 case TARGET_NR_socketcall:
pbrook53a59602006-03-25 19:31:22 +00004587 ret = do_socketcall(arg1, arg2);
bellard31e31b82003-02-18 22:55:36 +00004588 break;
thse5febef2007-04-01 18:31:35 +00004589#endif
bellard3532fa72006-06-24 15:06:03 +00004590#ifdef TARGET_NR_accept
4591 case TARGET_NR_accept:
pbrook1be9e1d2006-11-19 15:26:04 +00004592 ret = do_accept(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004593 break;
4594#endif
4595#ifdef TARGET_NR_bind
4596 case TARGET_NR_bind:
4597 ret = do_bind(arg1, arg2, arg3);
4598 break;
4599#endif
4600#ifdef TARGET_NR_connect
4601 case TARGET_NR_connect:
4602 ret = do_connect(arg1, arg2, arg3);
4603 break;
4604#endif
4605#ifdef TARGET_NR_getpeername
4606 case TARGET_NR_getpeername:
pbrook1be9e1d2006-11-19 15:26:04 +00004607 ret = do_getpeername(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004608 break;
4609#endif
4610#ifdef TARGET_NR_getsockname
4611 case TARGET_NR_getsockname:
pbrook1be9e1d2006-11-19 15:26:04 +00004612 ret = do_getsockname(arg1, arg2, arg3);
bellard3532fa72006-06-24 15:06:03 +00004613 break;
4614#endif
4615#ifdef TARGET_NR_getsockopt
4616 case TARGET_NR_getsockopt:
4617 ret = do_getsockopt(arg1, arg2, arg3, arg4, arg5);
4618 break;
4619#endif
4620#ifdef TARGET_NR_listen
4621 case TARGET_NR_listen:
pbrook1be9e1d2006-11-19 15:26:04 +00004622 ret = get_errno(listen(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004623 break;
4624#endif
4625#ifdef TARGET_NR_recv
4626 case TARGET_NR_recv:
pbrook214201b2007-03-17 01:27:24 +00004627 ret = do_recvfrom(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004628 break;
4629#endif
4630#ifdef TARGET_NR_recvfrom
4631 case TARGET_NR_recvfrom:
pbrook214201b2007-03-17 01:27:24 +00004632 ret = do_recvfrom(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004633 break;
4634#endif
4635#ifdef TARGET_NR_recvmsg
4636 case TARGET_NR_recvmsg:
4637 ret = do_sendrecvmsg(arg1, arg2, arg3, 0);
4638 break;
4639#endif
4640#ifdef TARGET_NR_send
4641 case TARGET_NR_send:
pbrook1be9e1d2006-11-19 15:26:04 +00004642 ret = do_sendto(arg1, arg2, arg3, arg4, 0, 0);
bellard3532fa72006-06-24 15:06:03 +00004643 break;
4644#endif
4645#ifdef TARGET_NR_sendmsg
4646 case TARGET_NR_sendmsg:
4647 ret = do_sendrecvmsg(arg1, arg2, arg3, 1);
4648 break;
4649#endif
4650#ifdef TARGET_NR_sendto
4651 case TARGET_NR_sendto:
pbrook1be9e1d2006-11-19 15:26:04 +00004652 ret = do_sendto(arg1, arg2, arg3, arg4, arg5, arg6);
bellard3532fa72006-06-24 15:06:03 +00004653 break;
4654#endif
4655#ifdef TARGET_NR_shutdown
4656 case TARGET_NR_shutdown:
pbrook1be9e1d2006-11-19 15:26:04 +00004657 ret = get_errno(shutdown(arg1, arg2));
bellard3532fa72006-06-24 15:06:03 +00004658 break;
4659#endif
4660#ifdef TARGET_NR_socket
4661 case TARGET_NR_socket:
4662 ret = do_socket(arg1, arg2, arg3);
4663 break;
4664#endif
4665#ifdef TARGET_NR_socketpair
4666 case TARGET_NR_socketpair:
pbrook1be9e1d2006-11-19 15:26:04 +00004667 ret = do_socketpair(arg1, arg2, arg3, arg4);
bellard3532fa72006-06-24 15:06:03 +00004668 break;
4669#endif
4670#ifdef TARGET_NR_setsockopt
4671 case TARGET_NR_setsockopt:
4672 ret = do_setsockopt(arg1, arg2, arg3, arg4, (socklen_t) arg5);
4673 break;
4674#endif
ths7494b0f2007-02-11 18:26:53 +00004675
bellard31e31b82003-02-18 22:55:36 +00004676 case TARGET_NR_syslog:
bellard579a97f2007-11-11 14:26:47 +00004677 if (!(p = lock_user_string(arg2)))
4678 goto efault;
thse5574482007-02-11 20:03:13 +00004679 ret = get_errno(sys_syslog((int)arg1, p, (int)arg3));
4680 unlock_user(p, arg2, 0);
ths7494b0f2007-02-11 18:26:53 +00004681 break;
4682
bellard31e31b82003-02-18 22:55:36 +00004683 case TARGET_NR_setitimer:
bellard66fb9762003-03-23 01:06:05 +00004684 {
bellard66fb9762003-03-23 01:06:05 +00004685 struct itimerval value, ovalue, *pvalue;
4686
pbrook53a59602006-03-25 19:31:22 +00004687 if (arg2) {
bellard66fb9762003-03-23 01:06:05 +00004688 pvalue = &value;
ths788f5ec2007-12-09 02:37:05 +00004689 if (copy_from_user_timeval(&pvalue->it_interval, arg2)
4690 || copy_from_user_timeval(&pvalue->it_value,
4691 arg2 + sizeof(struct target_timeval)))
4692 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004693 } else {
4694 pvalue = NULL;
4695 }
4696 ret = get_errno(setitimer(arg1, pvalue, &ovalue));
pbrook53a59602006-03-25 19:31:22 +00004697 if (!is_error(ret) && arg3) {
ths788f5ec2007-12-09 02:37:05 +00004698 if (copy_to_user_timeval(arg3,
4699 &ovalue.it_interval)
4700 || copy_to_user_timeval(arg3 + sizeof(struct target_timeval),
4701 &ovalue.it_value))
4702 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004703 }
4704 }
4705 break;
bellard31e31b82003-02-18 22:55:36 +00004706 case TARGET_NR_getitimer:
bellard66fb9762003-03-23 01:06:05 +00004707 {
bellard66fb9762003-03-23 01:06:05 +00004708 struct itimerval value;
ths3b46e622007-09-17 08:09:54 +00004709
bellard66fb9762003-03-23 01:06:05 +00004710 ret = get_errno(getitimer(arg1, &value));
pbrook53a59602006-03-25 19:31:22 +00004711 if (!is_error(ret) && arg2) {
ths788f5ec2007-12-09 02:37:05 +00004712 if (copy_to_user_timeval(arg2,
4713 &value.it_interval)
4714 || copy_to_user_timeval(arg2 + sizeof(struct target_timeval),
4715 &value.it_value))
4716 goto efault;
bellard66fb9762003-03-23 01:06:05 +00004717 }
4718 }
4719 break;
bellard31e31b82003-02-18 22:55:36 +00004720 case TARGET_NR_stat:
bellard579a97f2007-11-11 14:26:47 +00004721 if (!(p = lock_user_string(arg1)))
4722 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004723 ret = get_errno(stat(path(p), &st));
4724 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004725 goto do_stat;
4726 case TARGET_NR_lstat:
bellard579a97f2007-11-11 14:26:47 +00004727 if (!(p = lock_user_string(arg1)))
4728 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004729 ret = get_errno(lstat(path(p), &st));
4730 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004731 goto do_stat;
4732 case TARGET_NR_fstat:
4733 {
4734 ret = get_errno(fstat(arg1, &st));
4735 do_stat:
4736 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00004737 struct target_stat *target_st;
thse3584652007-06-01 11:49:38 +00004738
bellard579a97f2007-11-11 14:26:47 +00004739 if (!lock_user_struct(VERIFY_WRITE, target_st, arg2, 0))
4740 goto efault;
bellardd2fd1af2007-11-14 18:08:56 +00004741 __put_user(st.st_dev, &target_st->st_dev);
4742 __put_user(st.st_ino, &target_st->st_ino);
4743 __put_user(st.st_mode, &target_st->st_mode);
4744 __put_user(st.st_uid, &target_st->st_uid);
4745 __put_user(st.st_gid, &target_st->st_gid);
4746 __put_user(st.st_nlink, &target_st->st_nlink);
4747 __put_user(st.st_rdev, &target_st->st_rdev);
4748 __put_user(st.st_size, &target_st->st_size);
4749 __put_user(st.st_blksize, &target_st->st_blksize);
4750 __put_user(st.st_blocks, &target_st->st_blocks);
4751 __put_user(st.st_atime, &target_st->target_st_atime);
4752 __put_user(st.st_mtime, &target_st->target_st_mtime);
4753 __put_user(st.st_ctime, &target_st->target_st_ctime);
pbrook53a59602006-03-25 19:31:22 +00004754 unlock_user_struct(target_st, arg2, 1);
bellard31e31b82003-02-18 22:55:36 +00004755 }
4756 }
4757 break;
bellardebc05482003-09-30 21:08:41 +00004758#ifdef TARGET_NR_olduname
bellard31e31b82003-02-18 22:55:36 +00004759 case TARGET_NR_olduname:
4760 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004761#endif
4762#ifdef TARGET_NR_iopl
bellard31e31b82003-02-18 22:55:36 +00004763 case TARGET_NR_iopl:
4764 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004765#endif
bellard31e31b82003-02-18 22:55:36 +00004766 case TARGET_NR_vhangup:
4767 ret = get_errno(vhangup());
4768 break;
bellardebc05482003-09-30 21:08:41 +00004769#ifdef TARGET_NR_idle
bellard31e31b82003-02-18 22:55:36 +00004770 case TARGET_NR_idle:
4771 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00004772#endif
bellard42ad6ae2005-01-03 22:48:11 +00004773#ifdef TARGET_NR_syscall
4774 case TARGET_NR_syscall:
4775 ret = do_syscall(cpu_env,arg1 & 0xffff,arg2,arg3,arg4,arg5,arg6,0);
4776 break;
4777#endif
bellard31e31b82003-02-18 22:55:36 +00004778 case TARGET_NR_wait4:
4779 {
4780 int status;
blueswir1992f48a2007-10-14 16:27:31 +00004781 abi_long status_ptr = arg2;
bellard31e31b82003-02-18 22:55:36 +00004782 struct rusage rusage, *rusage_ptr;
blueswir1992f48a2007-10-14 16:27:31 +00004783 abi_ulong target_rusage = arg4;
bellard31e31b82003-02-18 22:55:36 +00004784 if (target_rusage)
4785 rusage_ptr = &rusage;
4786 else
4787 rusage_ptr = NULL;
4788 ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr));
4789 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00004790 if (status_ptr) {
4791 if (put_user_s32(status, status_ptr))
4792 goto efault;
bellard31e31b82003-02-18 22:55:36 +00004793 }
bellard2f619692007-11-16 10:46:05 +00004794 if (target_rusage)
4795 host_to_target_rusage(target_rusage, &rusage);
bellard31e31b82003-02-18 22:55:36 +00004796 }
4797 }
4798 break;
thse5febef2007-04-01 18:31:35 +00004799#ifdef TARGET_NR_swapoff
bellard31e31b82003-02-18 22:55:36 +00004800 case TARGET_NR_swapoff:
bellard579a97f2007-11-11 14:26:47 +00004801 if (!(p = lock_user_string(arg1)))
4802 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004803 ret = get_errno(swapoff(p));
4804 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004805 break;
thse5febef2007-04-01 18:31:35 +00004806#endif
bellard31e31b82003-02-18 22:55:36 +00004807 case TARGET_NR_sysinfo:
bellarda5448a72004-06-19 16:59:03 +00004808 {
pbrook53a59602006-03-25 19:31:22 +00004809 struct target_sysinfo *target_value;
bellarda5448a72004-06-19 16:59:03 +00004810 struct sysinfo value;
4811 ret = get_errno(sysinfo(&value));
pbrook53a59602006-03-25 19:31:22 +00004812 if (!is_error(ret) && arg1)
bellarda5448a72004-06-19 16:59:03 +00004813 {
bellard579a97f2007-11-11 14:26:47 +00004814 if (!lock_user_struct(VERIFY_WRITE, target_value, arg1, 0))
4815 goto efault;
bellarda5448a72004-06-19 16:59:03 +00004816 __put_user(value.uptime, &target_value->uptime);
4817 __put_user(value.loads[0], &target_value->loads[0]);
4818 __put_user(value.loads[1], &target_value->loads[1]);
4819 __put_user(value.loads[2], &target_value->loads[2]);
4820 __put_user(value.totalram, &target_value->totalram);
4821 __put_user(value.freeram, &target_value->freeram);
4822 __put_user(value.sharedram, &target_value->sharedram);
4823 __put_user(value.bufferram, &target_value->bufferram);
4824 __put_user(value.totalswap, &target_value->totalswap);
4825 __put_user(value.freeswap, &target_value->freeswap);
4826 __put_user(value.procs, &target_value->procs);
4827 __put_user(value.totalhigh, &target_value->totalhigh);
4828 __put_user(value.freehigh, &target_value->freehigh);
4829 __put_user(value.mem_unit, &target_value->mem_unit);
pbrook53a59602006-03-25 19:31:22 +00004830 unlock_user_struct(target_value, arg1, 1);
bellarda5448a72004-06-19 16:59:03 +00004831 }
4832 }
4833 break;
thse5febef2007-04-01 18:31:35 +00004834#ifdef TARGET_NR_ipc
bellard31e31b82003-02-18 22:55:36 +00004835 case TARGET_NR_ipc:
bellard8853f862004-02-22 14:57:26 +00004836 ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
4837 break;
thse5febef2007-04-01 18:31:35 +00004838#endif
aurel32eeb438c2008-10-13 21:08:55 +00004839
4840#ifdef TARGET_NR_msgctl
4841 case TARGET_NR_msgctl:
4842 ret = do_msgctl(arg1, arg2, arg3);
4843 break;
4844#endif
4845#ifdef TARGET_NR_msgget
4846 case TARGET_NR_msgget:
4847 ret = get_errno(msgget(arg1, arg2));
4848 break;
4849#endif
4850#ifdef TARGET_NR_msgrcv
4851 case TARGET_NR_msgrcv:
4852 ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5);
4853 break;
4854#endif
4855#ifdef TARGET_NR_msgsnd
4856 case TARGET_NR_msgsnd:
4857 ret = do_msgsnd(arg1, arg2, arg3, arg4);
4858 break;
4859#endif
bellard31e31b82003-02-18 22:55:36 +00004860 case TARGET_NR_fsync:
4861 ret = get_errno(fsync(arg1));
4862 break;
bellard31e31b82003-02-18 22:55:36 +00004863 case TARGET_NR_clone:
aurel320b6d3ae2008-09-15 07:43:43 +00004864#if defined(TARGET_SH4)
4865 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg5, arg4));
edgar_iglb15ad612009-01-07 19:43:47 +00004866#elif defined(TARGET_CRIS)
4867 ret = get_errno(do_fork(cpu_env, arg2, arg1, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004868#else
pbrookd865bab2008-06-07 22:12:17 +00004869 ret = get_errno(do_fork(cpu_env, arg1, arg2, arg3, arg4, arg5));
aurel320b6d3ae2008-09-15 07:43:43 +00004870#endif
bellard1b6b0292003-03-22 17:31:38 +00004871 break;
bellardec86b0f2003-04-11 00:15:04 +00004872#ifdef __NR_exit_group
4873 /* new thread calls */
4874 case TARGET_NR_exit_group:
aurel326d946cd2008-11-06 16:15:18 +00004875#ifdef HAVE_GPROF
4876 _mcleanup();
4877#endif
bellarde9009672005-04-26 20:42:36 +00004878 gdb_exit(cpu_env, arg1);
bellardec86b0f2003-04-11 00:15:04 +00004879 ret = get_errno(exit_group(arg1));
4880 break;
4881#endif
bellard31e31b82003-02-18 22:55:36 +00004882 case TARGET_NR_setdomainname:
bellard579a97f2007-11-11 14:26:47 +00004883 if (!(p = lock_user_string(arg1)))
4884 goto efault;
pbrook53a59602006-03-25 19:31:22 +00004885 ret = get_errno(setdomainname(p, arg2));
4886 unlock_user(p, arg1, 0);
bellard31e31b82003-02-18 22:55:36 +00004887 break;
4888 case TARGET_NR_uname:
4889 /* no need to transcode because we use the linux syscall */
bellard29e619b2004-09-13 21:41:04 +00004890 {
4891 struct new_utsname * buf;
ths3b46e622007-09-17 08:09:54 +00004892
bellard579a97f2007-11-11 14:26:47 +00004893 if (!lock_user_struct(VERIFY_WRITE, buf, arg1, 0))
4894 goto efault;
bellard29e619b2004-09-13 21:41:04 +00004895 ret = get_errno(sys_uname(buf));
4896 if (!is_error(ret)) {
4897 /* Overrite the native machine name with whatever is being
4898 emulated. */
4899 strcpy (buf->machine, UNAME_MACHINE);
pbrookc5937222006-05-14 11:30:38 +00004900 /* Allow the user to override the reported release. */
4901 if (qemu_uname_release && *qemu_uname_release)
4902 strcpy (buf->release, qemu_uname_release);
bellard29e619b2004-09-13 21:41:04 +00004903 }
pbrook53a59602006-03-25 19:31:22 +00004904 unlock_user_struct(buf, arg1, 1);
bellard29e619b2004-09-13 21:41:04 +00004905 }
bellard31e31b82003-02-18 22:55:36 +00004906 break;
bellard6dbad632003-03-16 18:05:05 +00004907#ifdef TARGET_I386
bellard31e31b82003-02-18 22:55:36 +00004908 case TARGET_NR_modify_ldt:
bellard03acab62007-11-11 14:57:14 +00004909 ret = do_modify_ldt(cpu_env, arg1, arg2, arg3);
bellard5cd43932003-03-29 16:54:36 +00004910 break;
j_mayer84409dd2007-04-06 08:56:50 +00004911#if !defined(TARGET_X86_64)
bellard5cd43932003-03-29 16:54:36 +00004912 case TARGET_NR_vm86old:
4913 goto unimplemented;
4914 case TARGET_NR_vm86:
pbrook53a59602006-03-25 19:31:22 +00004915 ret = do_vm86(cpu_env, arg1, arg2);
bellard6dbad632003-03-16 18:05:05 +00004916 break;
4917#endif
j_mayer84409dd2007-04-06 08:56:50 +00004918#endif
bellard31e31b82003-02-18 22:55:36 +00004919 case TARGET_NR_adjtimex:
4920 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004921#ifdef TARGET_NR_create_module
bellard31e31b82003-02-18 22:55:36 +00004922 case TARGET_NR_create_module:
thse5febef2007-04-01 18:31:35 +00004923#endif
bellard31e31b82003-02-18 22:55:36 +00004924 case TARGET_NR_init_module:
4925 case TARGET_NR_delete_module:
thse5febef2007-04-01 18:31:35 +00004926#ifdef TARGET_NR_get_kernel_syms
bellard31e31b82003-02-18 22:55:36 +00004927 case TARGET_NR_get_kernel_syms:
thse5febef2007-04-01 18:31:35 +00004928#endif
bellard31e31b82003-02-18 22:55:36 +00004929 goto unimplemented;
4930 case TARGET_NR_quotactl:
4931 goto unimplemented;
4932 case TARGET_NR_getpgid:
4933 ret = get_errno(getpgid(arg1));
4934 break;
4935 case TARGET_NR_fchdir:
4936 ret = get_errno(fchdir(arg1));
4937 break;
j_mayer84409dd2007-04-06 08:56:50 +00004938#ifdef TARGET_NR_bdflush /* not on x86_64 */
bellard31e31b82003-02-18 22:55:36 +00004939 case TARGET_NR_bdflush:
4940 goto unimplemented;
j_mayer84409dd2007-04-06 08:56:50 +00004941#endif
thse5febef2007-04-01 18:31:35 +00004942#ifdef TARGET_NR_sysfs
bellard31e31b82003-02-18 22:55:36 +00004943 case TARGET_NR_sysfs:
4944 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004945#endif
bellard31e31b82003-02-18 22:55:36 +00004946 case TARGET_NR_personality:
bellard1b6b0292003-03-22 17:31:38 +00004947 ret = get_errno(personality(arg1));
bellard31e31b82003-02-18 22:55:36 +00004948 break;
thse5febef2007-04-01 18:31:35 +00004949#ifdef TARGET_NR_afs_syscall
bellard31e31b82003-02-18 22:55:36 +00004950 case TARGET_NR_afs_syscall:
4951 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00004952#endif
j_mayer7a3148a2007-04-05 07:13:51 +00004953#ifdef TARGET_NR__llseek /* Not on alpha */
bellard31e31b82003-02-18 22:55:36 +00004954 case TARGET_NR__llseek:
4955 {
bellard4f2ac232004-04-26 19:44:02 +00004956#if defined (__x86_64__)
4957 ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5));
bellard2f619692007-11-16 10:46:05 +00004958 if (put_user_s64(ret, arg4))
4959 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004960#else
bellard31e31b82003-02-18 22:55:36 +00004961 int64_t res;
4962 ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5));
bellard2f619692007-11-16 10:46:05 +00004963 if (put_user_s64(res, arg4))
4964 goto efault;
bellard4f2ac232004-04-26 19:44:02 +00004965#endif
bellard31e31b82003-02-18 22:55:36 +00004966 }
4967 break;
j_mayer7a3148a2007-04-05 07:13:51 +00004968#endif
bellard31e31b82003-02-18 22:55:36 +00004969 case TARGET_NR_getdents:
blueswir1992f48a2007-10-14 16:27:31 +00004970#if TARGET_ABI_BITS != 32
pbrook53a59602006-03-25 19:31:22 +00004971 goto unimplemented;
blueswir1992f48a2007-10-14 16:27:31 +00004972#elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64
bellard4add45b2003-06-05 01:52:59 +00004973 {
pbrook53a59602006-03-25 19:31:22 +00004974 struct target_dirent *target_dirp;
aurel326556a832008-10-13 21:08:17 +00004975 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00004976 abi_long count = arg3;
bellard4add45b2003-06-05 01:52:59 +00004977
4978 dirp = malloc(count);
ths0da46a62007-10-20 20:23:07 +00004979 if (!dirp) {
bellard579a97f2007-11-11 14:26:47 +00004980 ret = -TARGET_ENOMEM;
ths0da46a62007-10-20 20:23:07 +00004981 goto fail;
4982 }
ths3b46e622007-09-17 08:09:54 +00004983
bellard4add45b2003-06-05 01:52:59 +00004984 ret = get_errno(sys_getdents(arg1, dirp, count));
4985 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00004986 struct linux_dirent *de;
bellard4add45b2003-06-05 01:52:59 +00004987 struct target_dirent *tde;
4988 int len = ret;
4989 int reclen, treclen;
4990 int count1, tnamelen;
4991
4992 count1 = 0;
4993 de = dirp;
bellard579a97f2007-11-11 14:26:47 +00004994 if (!(target_dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
4995 goto efault;
bellard4add45b2003-06-05 01:52:59 +00004996 tde = target_dirp;
4997 while (len > 0) {
4998 reclen = de->d_reclen;
blueswir1992f48a2007-10-14 16:27:31 +00004999 treclen = reclen - (2 * (sizeof(long) - sizeof(abi_long)));
bellard4add45b2003-06-05 01:52:59 +00005000 tde->d_reclen = tswap16(treclen);
5001 tde->d_ino = tswapl(de->d_ino);
5002 tde->d_off = tswapl(de->d_off);
blueswir1992f48a2007-10-14 16:27:31 +00005003 tnamelen = treclen - (2 * sizeof(abi_long) + 2);
bellard4add45b2003-06-05 01:52:59 +00005004 if (tnamelen > 256)
5005 tnamelen = 256;
bellard80a9d032005-01-03 23:31:27 +00005006 /* XXX: may not be correct */
blueswir1be15b142008-10-25 11:21:28 +00005007 pstrcpy(tde->d_name, tnamelen, de->d_name);
aurel326556a832008-10-13 21:08:17 +00005008 de = (struct linux_dirent *)((char *)de + reclen);
bellard4add45b2003-06-05 01:52:59 +00005009 len -= reclen;
j_mayer1c5bf3b2007-04-14 12:17:59 +00005010 tde = (struct target_dirent *)((char *)tde + treclen);
bellard4add45b2003-06-05 01:52:59 +00005011 count1 += treclen;
5012 }
5013 ret = count1;
bellard579a97f2007-11-11 14:26:47 +00005014 unlock_user(target_dirp, arg2, ret);
bellard4add45b2003-06-05 01:52:59 +00005015 }
5016 free(dirp);
5017 }
5018#else
bellard31e31b82003-02-18 22:55:36 +00005019 {
aurel326556a832008-10-13 21:08:17 +00005020 struct linux_dirent *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005021 abi_long count = arg3;
bellarddab2ed92003-03-22 15:23:14 +00005022
bellard579a97f2007-11-11 14:26:47 +00005023 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5024 goto efault;
bellard72f03902003-02-18 23:33:18 +00005025 ret = get_errno(sys_getdents(arg1, dirp, count));
bellard31e31b82003-02-18 22:55:36 +00005026 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005027 struct linux_dirent *de;
bellard31e31b82003-02-18 22:55:36 +00005028 int len = ret;
5029 int reclen;
5030 de = dirp;
5031 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005032 reclen = de->d_reclen;
bellard31e31b82003-02-18 22:55:36 +00005033 if (reclen > len)
5034 break;
bellard8083a3e2003-03-24 23:12:16 +00005035 de->d_reclen = tswap16(reclen);
bellard31e31b82003-02-18 22:55:36 +00005036 tswapls(&de->d_ino);
5037 tswapls(&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005038 de = (struct linux_dirent *)((char *)de + reclen);
bellard31e31b82003-02-18 22:55:36 +00005039 len -= reclen;
5040 }
5041 }
pbrook53a59602006-03-25 19:31:22 +00005042 unlock_user(dirp, arg2, ret);
bellard31e31b82003-02-18 22:55:36 +00005043 }
bellard4add45b2003-06-05 01:52:59 +00005044#endif
bellard31e31b82003-02-18 22:55:36 +00005045 break;
ths3ae43202007-09-16 21:39:48 +00005046#if defined(TARGET_NR_getdents64) && defined(__NR_getdents64)
bellarddab2ed92003-03-22 15:23:14 +00005047 case TARGET_NR_getdents64:
5048 {
aurel326556a832008-10-13 21:08:17 +00005049 struct linux_dirent64 *dirp;
blueswir1992f48a2007-10-14 16:27:31 +00005050 abi_long count = arg3;
bellard579a97f2007-11-11 14:26:47 +00005051 if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0)))
5052 goto efault;
bellarddab2ed92003-03-22 15:23:14 +00005053 ret = get_errno(sys_getdents64(arg1, dirp, count));
5054 if (!is_error(ret)) {
aurel326556a832008-10-13 21:08:17 +00005055 struct linux_dirent64 *de;
bellarddab2ed92003-03-22 15:23:14 +00005056 int len = ret;
5057 int reclen;
5058 de = dirp;
5059 while (len > 0) {
bellard8083a3e2003-03-24 23:12:16 +00005060 reclen = de->d_reclen;
bellarddab2ed92003-03-22 15:23:14 +00005061 if (reclen > len)
5062 break;
bellard8083a3e2003-03-24 23:12:16 +00005063 de->d_reclen = tswap16(reclen);
bellard8582a532007-11-11 23:11:36 +00005064 tswap64s((uint64_t *)&de->d_ino);
5065 tswap64s((uint64_t *)&de->d_off);
aurel326556a832008-10-13 21:08:17 +00005066 de = (struct linux_dirent64 *)((char *)de + reclen);
bellarddab2ed92003-03-22 15:23:14 +00005067 len -= reclen;
5068 }
5069 }
pbrook53a59602006-03-25 19:31:22 +00005070 unlock_user(dirp, arg2, ret);
bellarddab2ed92003-03-22 15:23:14 +00005071 }
5072 break;
bellarda541f292004-04-12 20:39:29 +00005073#endif /* TARGET_NR_getdents64 */
thse5febef2007-04-01 18:31:35 +00005074#ifdef TARGET_NR__newselect
bellard31e31b82003-02-18 22:55:36 +00005075 case TARGET_NR__newselect:
pbrook53a59602006-03-25 19:31:22 +00005076 ret = do_select(arg1, arg2, arg3, arg4, arg5);
bellard31e31b82003-02-18 22:55:36 +00005077 break;
thse5febef2007-04-01 18:31:35 +00005078#endif
5079#ifdef TARGET_NR_poll
bellard9de5e442003-03-23 16:49:39 +00005080 case TARGET_NR_poll:
5081 {
pbrook53a59602006-03-25 19:31:22 +00005082 struct target_pollfd *target_pfd;
bellard9de5e442003-03-23 16:49:39 +00005083 unsigned int nfds = arg2;
5084 int timeout = arg3;
5085 struct pollfd *pfd;
bellard7854b052003-03-29 17:22:23 +00005086 unsigned int i;
bellard9de5e442003-03-23 16:49:39 +00005087
bellard579a97f2007-11-11 14:26:47 +00005088 target_pfd = lock_user(VERIFY_WRITE, arg1, sizeof(struct target_pollfd) * nfds, 1);
5089 if (!target_pfd)
5090 goto efault;
bellard9de5e442003-03-23 16:49:39 +00005091 pfd = alloca(sizeof(struct pollfd) * nfds);
5092 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005093 pfd[i].fd = tswap32(target_pfd[i].fd);
5094 pfd[i].events = tswap16(target_pfd[i].events);
bellard9de5e442003-03-23 16:49:39 +00005095 }
5096 ret = get_errno(poll(pfd, nfds, timeout));
5097 if (!is_error(ret)) {
5098 for(i = 0; i < nfds; i++) {
bellard5cd43932003-03-29 16:54:36 +00005099 target_pfd[i].revents = tswap16(pfd[i].revents);
bellard9de5e442003-03-23 16:49:39 +00005100 }
pbrook53a59602006-03-25 19:31:22 +00005101 ret += nfds * (sizeof(struct target_pollfd)
5102 - sizeof(struct pollfd));
bellard9de5e442003-03-23 16:49:39 +00005103 }
pbrook53a59602006-03-25 19:31:22 +00005104 unlock_user(target_pfd, arg1, ret);
bellard9de5e442003-03-23 16:49:39 +00005105 }
5106 break;
thse5febef2007-04-01 18:31:35 +00005107#endif
bellard31e31b82003-02-18 22:55:36 +00005108 case TARGET_NR_flock:
bellard9de5e442003-03-23 16:49:39 +00005109 /* NOTE: the flock constant seems to be the same for every
5110 Linux platform */
5111 ret = get_errno(flock(arg1, arg2));
bellard31e31b82003-02-18 22:55:36 +00005112 break;
5113 case TARGET_NR_readv:
5114 {
5115 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005116 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005117
5118 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005119 if (lock_iovec(VERIFY_WRITE, vec, arg2, count, 0) < 0)
5120 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005121 ret = get_errno(readv(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005122 unlock_iovec(vec, arg2, count, 1);
bellard31e31b82003-02-18 22:55:36 +00005123 }
5124 break;
5125 case TARGET_NR_writev:
5126 {
5127 int count = arg3;
bellard31e31b82003-02-18 22:55:36 +00005128 struct iovec *vec;
bellard31e31b82003-02-18 22:55:36 +00005129
5130 vec = alloca(count * sizeof(struct iovec));
bellard41df8412008-02-04 22:26:57 +00005131 if (lock_iovec(VERIFY_READ, vec, arg2, count, 1) < 0)
5132 goto efault;
bellard31e31b82003-02-18 22:55:36 +00005133 ret = get_errno(writev(arg1, vec, count));
pbrook53a59602006-03-25 19:31:22 +00005134 unlock_iovec(vec, arg2, count, 0);
bellard31e31b82003-02-18 22:55:36 +00005135 }
5136 break;
5137 case TARGET_NR_getsid:
5138 ret = get_errno(getsid(arg1));
5139 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005140#if defined(TARGET_NR_fdatasync) /* Not on alpha (osf_datasync ?) */
bellard31e31b82003-02-18 22:55:36 +00005141 case TARGET_NR_fdatasync:
bellard5cd43932003-03-29 16:54:36 +00005142 ret = get_errno(fdatasync(arg1));
5143 break;
j_mayer7a3148a2007-04-05 07:13:51 +00005144#endif
bellard31e31b82003-02-18 22:55:36 +00005145 case TARGET_NR__sysctl:
ths0da46a62007-10-20 20:23:07 +00005146 /* We don't implement this, but ENOTDIR is always a safe
bellard29e619b2004-09-13 21:41:04 +00005147 return value. */
ths0da46a62007-10-20 20:23:07 +00005148 ret = -TARGET_ENOTDIR;
5149 break;
bellard31e31b82003-02-18 22:55:36 +00005150 case TARGET_NR_sched_setparam:
bellard5cd43932003-03-29 16:54:36 +00005151 {
pbrook53a59602006-03-25 19:31:22 +00005152 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005153 struct sched_param schp;
pbrook53a59602006-03-25 19:31:22 +00005154
bellard579a97f2007-11-11 14:26:47 +00005155 if (!lock_user_struct(VERIFY_READ, target_schp, arg2, 1))
5156 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005157 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005158 unlock_user_struct(target_schp, arg2, 0);
bellard5cd43932003-03-29 16:54:36 +00005159 ret = get_errno(sched_setparam(arg1, &schp));
5160 }
5161 break;
bellard31e31b82003-02-18 22:55:36 +00005162 case TARGET_NR_sched_getparam:
bellard5cd43932003-03-29 16:54:36 +00005163 {
pbrook53a59602006-03-25 19:31:22 +00005164 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005165 struct sched_param schp;
5166 ret = get_errno(sched_getparam(arg1, &schp));
5167 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005168 if (!lock_user_struct(VERIFY_WRITE, target_schp, arg2, 0))
5169 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005170 target_schp->sched_priority = tswap32(schp.sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005171 unlock_user_struct(target_schp, arg2, 1);
bellard5cd43932003-03-29 16:54:36 +00005172 }
5173 }
5174 break;
bellard31e31b82003-02-18 22:55:36 +00005175 case TARGET_NR_sched_setscheduler:
bellard5cd43932003-03-29 16:54:36 +00005176 {
pbrook53a59602006-03-25 19:31:22 +00005177 struct sched_param *target_schp;
bellard5cd43932003-03-29 16:54:36 +00005178 struct sched_param schp;
bellard579a97f2007-11-11 14:26:47 +00005179 if (!lock_user_struct(VERIFY_READ, target_schp, arg3, 1))
5180 goto efault;
bellard5cd43932003-03-29 16:54:36 +00005181 schp.sched_priority = tswap32(target_schp->sched_priority);
pbrook53a59602006-03-25 19:31:22 +00005182 unlock_user_struct(target_schp, arg3, 0);
bellard5cd43932003-03-29 16:54:36 +00005183 ret = get_errno(sched_setscheduler(arg1, arg2, &schp));
5184 }
5185 break;
bellard31e31b82003-02-18 22:55:36 +00005186 case TARGET_NR_sched_getscheduler:
bellard5cd43932003-03-29 16:54:36 +00005187 ret = get_errno(sched_getscheduler(arg1));
5188 break;
bellard31e31b82003-02-18 22:55:36 +00005189 case TARGET_NR_sched_yield:
5190 ret = get_errno(sched_yield());
5191 break;
5192 case TARGET_NR_sched_get_priority_max:
bellard5cd43932003-03-29 16:54:36 +00005193 ret = get_errno(sched_get_priority_max(arg1));
5194 break;
bellard31e31b82003-02-18 22:55:36 +00005195 case TARGET_NR_sched_get_priority_min:
bellard5cd43932003-03-29 16:54:36 +00005196 ret = get_errno(sched_get_priority_min(arg1));
5197 break;
bellard31e31b82003-02-18 22:55:36 +00005198 case TARGET_NR_sched_rr_get_interval:
bellard5cd43932003-03-29 16:54:36 +00005199 {
bellard5cd43932003-03-29 16:54:36 +00005200 struct timespec ts;
5201 ret = get_errno(sched_rr_get_interval(arg1, &ts));
5202 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005203 host_to_target_timespec(arg2, &ts);
bellard5cd43932003-03-29 16:54:36 +00005204 }
5205 }
5206 break;
bellard31e31b82003-02-18 22:55:36 +00005207 case TARGET_NR_nanosleep:
bellard1b6b0292003-03-22 17:31:38 +00005208 {
bellard1b6b0292003-03-22 17:31:38 +00005209 struct timespec req, rem;
pbrook53a59602006-03-25 19:31:22 +00005210 target_to_host_timespec(&req, arg1);
bellard1b6b0292003-03-22 17:31:38 +00005211 ret = get_errno(nanosleep(&req, &rem));
pbrook53a59602006-03-25 19:31:22 +00005212 if (is_error(ret) && arg2) {
5213 host_to_target_timespec(arg2, &rem);
bellard1b6b0292003-03-22 17:31:38 +00005214 }
5215 }
5216 break;
thse5febef2007-04-01 18:31:35 +00005217#ifdef TARGET_NR_query_module
bellard31e31b82003-02-18 22:55:36 +00005218 case TARGET_NR_query_module:
bellard5cd43932003-03-29 16:54:36 +00005219 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005220#endif
5221#ifdef TARGET_NR_nfsservctl
bellard31e31b82003-02-18 22:55:36 +00005222 case TARGET_NR_nfsservctl:
bellard5cd43932003-03-29 16:54:36 +00005223 goto unimplemented;
thse5febef2007-04-01 18:31:35 +00005224#endif
bellard31e31b82003-02-18 22:55:36 +00005225 case TARGET_NR_prctl:
thse5574482007-02-11 20:03:13 +00005226 switch (arg1)
5227 {
5228 case PR_GET_PDEATHSIG:
5229 {
5230 int deathsig;
5231 ret = get_errno(prctl(arg1, &deathsig, arg3, arg4, arg5));
bellard2f619692007-11-16 10:46:05 +00005232 if (!is_error(ret) && arg2
5233 && put_user_ual(deathsig, arg2))
5234 goto efault;
thse5574482007-02-11 20:03:13 +00005235 }
5236 break;
5237 default:
5238 ret = get_errno(prctl(arg1, arg2, arg3, arg4, arg5));
5239 break;
5240 }
ths39b9aae2007-02-11 18:36:44 +00005241 break;
bellardd2fd1af2007-11-14 18:08:56 +00005242#ifdef TARGET_NR_arch_prctl
5243 case TARGET_NR_arch_prctl:
5244#if defined(TARGET_I386) && !defined(TARGET_ABI32)
5245 ret = do_arch_prctl(cpu_env, arg1, arg2);
5246 break;
5247#else
5248 goto unimplemented;
5249#endif
5250#endif
bellard67867302003-11-23 17:05:30 +00005251#ifdef TARGET_NR_pread
bellard31e31b82003-02-18 22:55:36 +00005252 case TARGET_NR_pread:
balroga4ae00b2008-09-20 03:14:14 +00005253#ifdef TARGET_ARM
5254 if (((CPUARMState *)cpu_env)->eabi)
5255 arg4 = arg5;
5256#endif
bellard579a97f2007-11-11 14:26:47 +00005257 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5258 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005259 ret = get_errno(pread(arg1, p, arg3, arg4));
5260 unlock_user(p, arg2, ret);
bellard206f0fa2003-05-14 19:01:56 +00005261 break;
bellard31e31b82003-02-18 22:55:36 +00005262 case TARGET_NR_pwrite:
balroga4ae00b2008-09-20 03:14:14 +00005263#ifdef TARGET_ARM
5264 if (((CPUARMState *)cpu_env)->eabi)
5265 arg4 = arg5;
5266#endif
bellard579a97f2007-11-11 14:26:47 +00005267 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5268 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005269 ret = get_errno(pwrite(arg1, p, arg3, arg4));
5270 unlock_user(p, arg2, 0);
bellard206f0fa2003-05-14 19:01:56 +00005271 break;
bellard67867302003-11-23 17:05:30 +00005272#endif
aurel32f2c7ba12008-03-28 22:32:06 +00005273#ifdef TARGET_NR_pread64
5274 case TARGET_NR_pread64:
5275 if (!(p = lock_user(VERIFY_WRITE, arg2, arg3, 0)))
5276 goto efault;
5277 ret = get_errno(pread64(arg1, p, arg3, target_offset64(arg4, arg5)));
5278 unlock_user(p, arg2, ret);
5279 break;
5280 case TARGET_NR_pwrite64:
5281 if (!(p = lock_user(VERIFY_READ, arg2, arg3, 1)))
5282 goto efault;
5283 ret = get_errno(pwrite64(arg1, p, arg3, target_offset64(arg4, arg5)));
5284 unlock_user(p, arg2, 0);
5285 break;
5286#endif
bellard31e31b82003-02-18 22:55:36 +00005287 case TARGET_NR_getcwd:
bellard579a97f2007-11-11 14:26:47 +00005288 if (!(p = lock_user(VERIFY_WRITE, arg1, arg2, 0)))
5289 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005290 ret = get_errno(sys_getcwd1(p, arg2));
5291 unlock_user(p, arg1, ret);
bellard31e31b82003-02-18 22:55:36 +00005292 break;
5293 case TARGET_NR_capget:
bellard5cd43932003-03-29 16:54:36 +00005294 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005295 case TARGET_NR_capset:
bellard5cd43932003-03-29 16:54:36 +00005296 goto unimplemented;
bellard31e31b82003-02-18 22:55:36 +00005297 case TARGET_NR_sigaltstack:
ths198a74d2007-09-27 16:44:32 +00005298#if defined(TARGET_I386) || defined(TARGET_ARM) || defined(TARGET_MIPS) || \
5299 defined(TARGET_SPARC) || defined(TARGET_PPC) || defined(TARGET_ALPHA)
bellard579a97f2007-11-11 14:26:47 +00005300 ret = do_sigaltstack(arg1, arg2, get_sp_from_cpustate((CPUState *)cpu_env));
thsa04e1342007-09-27 13:57:58 +00005301 break;
5302#else
bellard5cd43932003-03-29 16:54:36 +00005303 goto unimplemented;
thsa04e1342007-09-27 13:57:58 +00005304#endif
bellard31e31b82003-02-18 22:55:36 +00005305 case TARGET_NR_sendfile:
bellard5cd43932003-03-29 16:54:36 +00005306 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005307#ifdef TARGET_NR_getpmsg
bellard31e31b82003-02-18 22:55:36 +00005308 case TARGET_NR_getpmsg:
bellard5cd43932003-03-29 16:54:36 +00005309 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005310#endif
5311#ifdef TARGET_NR_putpmsg
bellard31e31b82003-02-18 22:55:36 +00005312 case TARGET_NR_putpmsg:
bellard5cd43932003-03-29 16:54:36 +00005313 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005314#endif
bellard048f6b42005-11-26 18:47:20 +00005315#ifdef TARGET_NR_vfork
bellard31e31b82003-02-18 22:55:36 +00005316 case TARGET_NR_vfork:
pbrookd865bab2008-06-07 22:12:17 +00005317 ret = get_errno(do_fork(cpu_env, CLONE_VFORK | CLONE_VM | SIGCHLD,
5318 0, 0, 0, 0));
bellard31e31b82003-02-18 22:55:36 +00005319 break;
bellard048f6b42005-11-26 18:47:20 +00005320#endif
bellardebc05482003-09-30 21:08:41 +00005321#ifdef TARGET_NR_ugetrlimit
bellard31e31b82003-02-18 22:55:36 +00005322 case TARGET_NR_ugetrlimit:
bellard728584b2003-04-29 20:43:36 +00005323 {
5324 struct rlimit rlim;
5325 ret = get_errno(getrlimit(arg1, &rlim));
5326 if (!is_error(ret)) {
pbrook53a59602006-03-25 19:31:22 +00005327 struct target_rlimit *target_rlim;
bellard579a97f2007-11-11 14:26:47 +00005328 if (!lock_user_struct(VERIFY_WRITE, target_rlim, arg2, 0))
5329 goto efault;
bellard728584b2003-04-29 20:43:36 +00005330 target_rlim->rlim_cur = tswapl(rlim.rlim_cur);
5331 target_rlim->rlim_max = tswapl(rlim.rlim_max);
pbrook53a59602006-03-25 19:31:22 +00005332 unlock_user_struct(target_rlim, arg2, 1);
bellard728584b2003-04-29 20:43:36 +00005333 }
5334 break;
5335 }
bellardebc05482003-09-30 21:08:41 +00005336#endif
bellarda315a142005-01-30 22:59:18 +00005337#ifdef TARGET_NR_truncate64
bellard31e31b82003-02-18 22:55:36 +00005338 case TARGET_NR_truncate64:
bellard579a97f2007-11-11 14:26:47 +00005339 if (!(p = lock_user_string(arg1)))
5340 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005341 ret = target_truncate64(cpu_env, p, arg2, arg3, arg4);
5342 unlock_user(p, arg1, 0);
bellard667f38b2005-07-23 14:46:27 +00005343 break;
bellarda315a142005-01-30 22:59:18 +00005344#endif
5345#ifdef TARGET_NR_ftruncate64
bellard31e31b82003-02-18 22:55:36 +00005346 case TARGET_NR_ftruncate64:
pbrookce4defa2006-02-09 16:49:55 +00005347 ret = target_ftruncate64(cpu_env, arg1, arg2, arg3, arg4);
bellard667f38b2005-07-23 14:46:27 +00005348 break;
bellarda315a142005-01-30 22:59:18 +00005349#endif
5350#ifdef TARGET_NR_stat64
bellard31e31b82003-02-18 22:55:36 +00005351 case TARGET_NR_stat64:
bellard579a97f2007-11-11 14:26:47 +00005352 if (!(p = lock_user_string(arg1)))
5353 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005354 ret = get_errno(stat(path(p), &st));
5355 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005356 if (!is_error(ret))
5357 ret = host_to_target_stat64(cpu_env, arg2, &st);
5358 break;
bellarda315a142005-01-30 22:59:18 +00005359#endif
5360#ifdef TARGET_NR_lstat64
bellard31e31b82003-02-18 22:55:36 +00005361 case TARGET_NR_lstat64:
bellard579a97f2007-11-11 14:26:47 +00005362 if (!(p = lock_user_string(arg1)))
5363 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005364 ret = get_errno(lstat(path(p), &st));
5365 unlock_user(p, arg1, 0);
balrog6a24a772008-09-20 02:23:36 +00005366 if (!is_error(ret))
5367 ret = host_to_target_stat64(cpu_env, arg2, &st);
5368 break;
bellarda315a142005-01-30 22:59:18 +00005369#endif
5370#ifdef TARGET_NR_fstat64
bellard31e31b82003-02-18 22:55:36 +00005371 case TARGET_NR_fstat64:
balrog6a24a772008-09-20 02:23:36 +00005372 ret = get_errno(fstat(arg1, &st));
5373 if (!is_error(ret))
5374 ret = host_to_target_stat64(cpu_env, arg2, &st);
5375 break;
bellardec86b0f2003-04-11 00:15:04 +00005376#endif
balrog6a24a772008-09-20 02:23:36 +00005377#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64)
5378 case TARGET_NR_fstatat64:
5379 if (!(p = lock_user_string(arg2)))
5380 goto efault;
5381 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4));
5382 if (!is_error(ret))
5383 ret = host_to_target_stat64(cpu_env, arg3, &st);
bellard60cd49d2003-03-16 22:53:56 +00005384 break;
bellarda315a142005-01-30 22:59:18 +00005385#endif
bellard67867302003-11-23 17:05:30 +00005386#ifdef USE_UID16
5387 case TARGET_NR_lchown:
bellard579a97f2007-11-11 14:26:47 +00005388 if (!(p = lock_user_string(arg1)))
5389 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005390 ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3)));
5391 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005392 break;
5393 case TARGET_NR_getuid:
5394 ret = get_errno(high2lowuid(getuid()));
5395 break;
5396 case TARGET_NR_getgid:
5397 ret = get_errno(high2lowgid(getgid()));
5398 break;
5399 case TARGET_NR_geteuid:
5400 ret = get_errno(high2lowuid(geteuid()));
5401 break;
5402 case TARGET_NR_getegid:
5403 ret = get_errno(high2lowgid(getegid()));
5404 break;
5405 case TARGET_NR_setreuid:
5406 ret = get_errno(setreuid(low2highuid(arg1), low2highuid(arg2)));
5407 break;
5408 case TARGET_NR_setregid:
5409 ret = get_errno(setregid(low2highgid(arg1), low2highgid(arg2)));
5410 break;
5411 case TARGET_NR_getgroups:
5412 {
5413 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005414 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005415 gid_t *grouplist;
5416 int i;
5417
5418 grouplist = alloca(gidsetsize * sizeof(gid_t));
5419 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005420 if (gidsetsize == 0)
5421 break;
bellard67867302003-11-23 17:05:30 +00005422 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005423 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 2, 0);
5424 if (!target_grouplist)
5425 goto efault;
balroga2155fc2008-09-20 02:12:08 +00005426 for(i = 0;i < ret; i++)
bellard67867302003-11-23 17:05:30 +00005427 target_grouplist[i] = tswap16(grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005428 unlock_user(target_grouplist, arg2, gidsetsize * 2);
bellard67867302003-11-23 17:05:30 +00005429 }
5430 }
5431 break;
5432 case TARGET_NR_setgroups:
5433 {
5434 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005435 uint16_t *target_grouplist;
bellard67867302003-11-23 17:05:30 +00005436 gid_t *grouplist;
5437 int i;
5438
5439 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005440 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 2, 1);
5441 if (!target_grouplist) {
5442 ret = -TARGET_EFAULT;
5443 goto fail;
5444 }
bellard67867302003-11-23 17:05:30 +00005445 for(i = 0;i < gidsetsize; i++)
5446 grouplist[i] = tswap16(target_grouplist[i]);
pbrook53a59602006-03-25 19:31:22 +00005447 unlock_user(target_grouplist, arg2, 0);
bellard67867302003-11-23 17:05:30 +00005448 ret = get_errno(setgroups(gidsetsize, grouplist));
5449 }
5450 break;
5451 case TARGET_NR_fchown:
5452 ret = get_errno(fchown(arg1, low2highuid(arg2), low2highgid(arg3)));
5453 break;
thsccfa72b2007-09-24 09:23:34 +00005454#if defined(TARGET_NR_fchownat) && defined(__NR_fchownat)
5455 case TARGET_NR_fchownat:
bellard579a97f2007-11-11 14:26:47 +00005456 if (!(p = lock_user_string(arg2)))
5457 goto efault;
5458 ret = get_errno(sys_fchownat(arg1, p, low2highuid(arg3), low2highgid(arg4), arg5));
5459 unlock_user(p, arg2, 0);
thsccfa72b2007-09-24 09:23:34 +00005460 break;
5461#endif
bellard67867302003-11-23 17:05:30 +00005462#ifdef TARGET_NR_setresuid
5463 case TARGET_NR_setresuid:
ths5fafdf22007-09-16 21:08:06 +00005464 ret = get_errno(setresuid(low2highuid(arg1),
5465 low2highuid(arg2),
bellard67867302003-11-23 17:05:30 +00005466 low2highuid(arg3)));
5467 break;
5468#endif
5469#ifdef TARGET_NR_getresuid
5470 case TARGET_NR_getresuid:
5471 {
pbrook53a59602006-03-25 19:31:22 +00005472 uid_t ruid, euid, suid;
bellard67867302003-11-23 17:05:30 +00005473 ret = get_errno(getresuid(&ruid, &euid, &suid));
5474 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005475 if (put_user_u16(high2lowuid(ruid), arg1)
5476 || put_user_u16(high2lowuid(euid), arg2)
5477 || put_user_u16(high2lowuid(suid), arg3))
5478 goto efault;
bellard67867302003-11-23 17:05:30 +00005479 }
5480 }
5481 break;
5482#endif
5483#ifdef TARGET_NR_getresgid
5484 case TARGET_NR_setresgid:
ths5fafdf22007-09-16 21:08:06 +00005485 ret = get_errno(setresgid(low2highgid(arg1),
5486 low2highgid(arg2),
bellard67867302003-11-23 17:05:30 +00005487 low2highgid(arg3)));
5488 break;
5489#endif
5490#ifdef TARGET_NR_getresgid
5491 case TARGET_NR_getresgid:
5492 {
pbrook53a59602006-03-25 19:31:22 +00005493 gid_t rgid, egid, sgid;
bellard67867302003-11-23 17:05:30 +00005494 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5495 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005496 if (put_user_u16(high2lowgid(rgid), arg1)
5497 || put_user_u16(high2lowgid(egid), arg2)
5498 || put_user_u16(high2lowgid(sgid), arg3))
5499 goto efault;
bellard67867302003-11-23 17:05:30 +00005500 }
5501 }
5502 break;
5503#endif
5504 case TARGET_NR_chown:
bellard579a97f2007-11-11 14:26:47 +00005505 if (!(p = lock_user_string(arg1)))
5506 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005507 ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3)));
5508 unlock_user(p, arg1, 0);
bellard67867302003-11-23 17:05:30 +00005509 break;
5510 case TARGET_NR_setuid:
5511 ret = get_errno(setuid(low2highuid(arg1)));
5512 break;
5513 case TARGET_NR_setgid:
5514 ret = get_errno(setgid(low2highgid(arg1)));
5515 break;
5516 case TARGET_NR_setfsuid:
5517 ret = get_errno(setfsuid(arg1));
5518 break;
5519 case TARGET_NR_setfsgid:
5520 ret = get_errno(setfsgid(arg1));
5521 break;
5522#endif /* USE_UID16 */
5523
bellarda315a142005-01-30 22:59:18 +00005524#ifdef TARGET_NR_lchown32
bellard31e31b82003-02-18 22:55:36 +00005525 case TARGET_NR_lchown32:
bellard579a97f2007-11-11 14:26:47 +00005526 if (!(p = lock_user_string(arg1)))
5527 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005528 ret = get_errno(lchown(p, arg2, arg3));
5529 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005530 break;
bellarda315a142005-01-30 22:59:18 +00005531#endif
5532#ifdef TARGET_NR_getuid32
bellard31e31b82003-02-18 22:55:36 +00005533 case TARGET_NR_getuid32:
bellardb03c60f2003-03-23 17:19:56 +00005534 ret = get_errno(getuid());
5535 break;
bellarda315a142005-01-30 22:59:18 +00005536#endif
aurel3264b4d282008-11-14 17:20:15 +00005537
5538#if defined(TARGET_NR_getxuid) && defined(TARGET_ALPHA)
5539 /* Alpha specific */
5540 case TARGET_NR_getxuid:
5541 {
5542 uid_t euid;
5543 euid=geteuid();
5544 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=euid;
5545 }
5546 ret = get_errno(getuid());
5547 break;
5548#endif
5549#if defined(TARGET_NR_getxgid) && defined(TARGET_ALPHA)
5550 /* Alpha specific */
5551 case TARGET_NR_getxgid:
5552 {
5553 uid_t egid;
5554 egid=getegid();
5555 ((CPUAlphaState *)cpu_env)->ir[IR_A4]=egid;
5556 }
5557 ret = get_errno(getgid());
5558 break;
5559#endif
5560
bellarda315a142005-01-30 22:59:18 +00005561#ifdef TARGET_NR_getgid32
bellard31e31b82003-02-18 22:55:36 +00005562 case TARGET_NR_getgid32:
bellardb03c60f2003-03-23 17:19:56 +00005563 ret = get_errno(getgid());
5564 break;
bellarda315a142005-01-30 22:59:18 +00005565#endif
5566#ifdef TARGET_NR_geteuid32
bellard31e31b82003-02-18 22:55:36 +00005567 case TARGET_NR_geteuid32:
bellardb03c60f2003-03-23 17:19:56 +00005568 ret = get_errno(geteuid());
5569 break;
bellarda315a142005-01-30 22:59:18 +00005570#endif
5571#ifdef TARGET_NR_getegid32
bellard31e31b82003-02-18 22:55:36 +00005572 case TARGET_NR_getegid32:
bellardb03c60f2003-03-23 17:19:56 +00005573 ret = get_errno(getegid());
5574 break;
bellarda315a142005-01-30 22:59:18 +00005575#endif
5576#ifdef TARGET_NR_setreuid32
bellard31e31b82003-02-18 22:55:36 +00005577 case TARGET_NR_setreuid32:
bellardb03c60f2003-03-23 17:19:56 +00005578 ret = get_errno(setreuid(arg1, arg2));
5579 break;
bellarda315a142005-01-30 22:59:18 +00005580#endif
5581#ifdef TARGET_NR_setregid32
bellard31e31b82003-02-18 22:55:36 +00005582 case TARGET_NR_setregid32:
bellardb03c60f2003-03-23 17:19:56 +00005583 ret = get_errno(setregid(arg1, arg2));
5584 break;
bellarda315a142005-01-30 22:59:18 +00005585#endif
5586#ifdef TARGET_NR_getgroups32
bellard31e31b82003-02-18 22:55:36 +00005587 case TARGET_NR_getgroups32:
bellard99c475a2005-01-31 20:45:13 +00005588 {
5589 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005590 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005591 gid_t *grouplist;
5592 int i;
5593
5594 grouplist = alloca(gidsetsize * sizeof(gid_t));
5595 ret = get_errno(getgroups(gidsetsize, grouplist));
balrogcb3bc232008-09-20 02:08:13 +00005596 if (gidsetsize == 0)
5597 break;
bellard99c475a2005-01-31 20:45:13 +00005598 if (!is_error(ret)) {
bellard579a97f2007-11-11 14:26:47 +00005599 target_grouplist = lock_user(VERIFY_WRITE, arg2, gidsetsize * 4, 0);
5600 if (!target_grouplist) {
5601 ret = -TARGET_EFAULT;
5602 goto fail;
5603 }
balroga2155fc2008-09-20 02:12:08 +00005604 for(i = 0;i < ret; i++)
pbrook53a59602006-03-25 19:31:22 +00005605 target_grouplist[i] = tswap32(grouplist[i]);
5606 unlock_user(target_grouplist, arg2, gidsetsize * 4);
bellard99c475a2005-01-31 20:45:13 +00005607 }
5608 }
5609 break;
bellarda315a142005-01-30 22:59:18 +00005610#endif
5611#ifdef TARGET_NR_setgroups32
bellard31e31b82003-02-18 22:55:36 +00005612 case TARGET_NR_setgroups32:
bellard99c475a2005-01-31 20:45:13 +00005613 {
5614 int gidsetsize = arg1;
pbrook53a59602006-03-25 19:31:22 +00005615 uint32_t *target_grouplist;
bellard99c475a2005-01-31 20:45:13 +00005616 gid_t *grouplist;
5617 int i;
ths3b46e622007-09-17 08:09:54 +00005618
bellard99c475a2005-01-31 20:45:13 +00005619 grouplist = alloca(gidsetsize * sizeof(gid_t));
bellard579a97f2007-11-11 14:26:47 +00005620 target_grouplist = lock_user(VERIFY_READ, arg2, gidsetsize * 4, 1);
5621 if (!target_grouplist) {
5622 ret = -TARGET_EFAULT;
5623 goto fail;
5624 }
bellard99c475a2005-01-31 20:45:13 +00005625 for(i = 0;i < gidsetsize; i++)
pbrook53a59602006-03-25 19:31:22 +00005626 grouplist[i] = tswap32(target_grouplist[i]);
5627 unlock_user(target_grouplist, arg2, 0);
bellard99c475a2005-01-31 20:45:13 +00005628 ret = get_errno(setgroups(gidsetsize, grouplist));
5629 }
5630 break;
bellarda315a142005-01-30 22:59:18 +00005631#endif
5632#ifdef TARGET_NR_fchown32
bellard31e31b82003-02-18 22:55:36 +00005633 case TARGET_NR_fchown32:
bellardb03c60f2003-03-23 17:19:56 +00005634 ret = get_errno(fchown(arg1, arg2, arg3));
5635 break;
bellarda315a142005-01-30 22:59:18 +00005636#endif
5637#ifdef TARGET_NR_setresuid32
bellard31e31b82003-02-18 22:55:36 +00005638 case TARGET_NR_setresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005639 ret = get_errno(setresuid(arg1, arg2, arg3));
5640 break;
bellarda315a142005-01-30 22:59:18 +00005641#endif
5642#ifdef TARGET_NR_getresuid32
bellard31e31b82003-02-18 22:55:36 +00005643 case TARGET_NR_getresuid32:
bellardb03c60f2003-03-23 17:19:56 +00005644 {
pbrook53a59602006-03-25 19:31:22 +00005645 uid_t ruid, euid, suid;
bellardb03c60f2003-03-23 17:19:56 +00005646 ret = get_errno(getresuid(&ruid, &euid, &suid));
5647 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005648 if (put_user_u32(ruid, arg1)
5649 || put_user_u32(euid, arg2)
5650 || put_user_u32(suid, arg3))
5651 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005652 }
5653 }
5654 break;
bellarda315a142005-01-30 22:59:18 +00005655#endif
5656#ifdef TARGET_NR_setresgid32
bellard31e31b82003-02-18 22:55:36 +00005657 case TARGET_NR_setresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005658 ret = get_errno(setresgid(arg1, arg2, arg3));
5659 break;
bellarda315a142005-01-30 22:59:18 +00005660#endif
5661#ifdef TARGET_NR_getresgid32
bellard31e31b82003-02-18 22:55:36 +00005662 case TARGET_NR_getresgid32:
bellardb03c60f2003-03-23 17:19:56 +00005663 {
pbrook53a59602006-03-25 19:31:22 +00005664 gid_t rgid, egid, sgid;
bellardb03c60f2003-03-23 17:19:56 +00005665 ret = get_errno(getresgid(&rgid, &egid, &sgid));
5666 if (!is_error(ret)) {
bellard2f619692007-11-16 10:46:05 +00005667 if (put_user_u32(rgid, arg1)
5668 || put_user_u32(egid, arg2)
5669 || put_user_u32(sgid, arg3))
5670 goto efault;
bellardb03c60f2003-03-23 17:19:56 +00005671 }
5672 }
5673 break;
bellarda315a142005-01-30 22:59:18 +00005674#endif
5675#ifdef TARGET_NR_chown32
bellard31e31b82003-02-18 22:55:36 +00005676 case TARGET_NR_chown32:
bellard579a97f2007-11-11 14:26:47 +00005677 if (!(p = lock_user_string(arg1)))
5678 goto efault;
pbrook53a59602006-03-25 19:31:22 +00005679 ret = get_errno(chown(p, arg2, arg3));
5680 unlock_user(p, arg1, 0);
bellardb03c60f2003-03-23 17:19:56 +00005681 break;
bellarda315a142005-01-30 22:59:18 +00005682#endif
5683#ifdef TARGET_NR_setuid32
bellard31e31b82003-02-18 22:55:36 +00005684 case TARGET_NR_setuid32:
bellardb03c60f2003-03-23 17:19:56 +00005685 ret = get_errno(setuid(arg1));
5686 break;
bellarda315a142005-01-30 22:59:18 +00005687#endif
5688#ifdef TARGET_NR_setgid32
bellard31e31b82003-02-18 22:55:36 +00005689 case TARGET_NR_setgid32:
bellardb03c60f2003-03-23 17:19:56 +00005690 ret = get_errno(setgid(arg1));
5691 break;
bellarda315a142005-01-30 22:59:18 +00005692#endif
5693#ifdef TARGET_NR_setfsuid32
bellard31e31b82003-02-18 22:55:36 +00005694 case TARGET_NR_setfsuid32:
bellardb03c60f2003-03-23 17:19:56 +00005695 ret = get_errno(setfsuid(arg1));
5696 break;
bellarda315a142005-01-30 22:59:18 +00005697#endif
5698#ifdef TARGET_NR_setfsgid32
bellard31e31b82003-02-18 22:55:36 +00005699 case TARGET_NR_setfsgid32:
bellardb03c60f2003-03-23 17:19:56 +00005700 ret = get_errno(setfsgid(arg1));
5701 break;
bellarda315a142005-01-30 22:59:18 +00005702#endif
bellard67867302003-11-23 17:05:30 +00005703
bellard31e31b82003-02-18 22:55:36 +00005704 case TARGET_NR_pivot_root:
bellardb03c60f2003-03-23 17:19:56 +00005705 goto unimplemented;
bellardffa65c32004-01-04 23:57:22 +00005706#ifdef TARGET_NR_mincore
bellard31e31b82003-02-18 22:55:36 +00005707 case TARGET_NR_mincore:
aurel3204bb9ac2008-10-01 21:46:41 +00005708 {
5709 void *a;
5710 ret = -TARGET_EFAULT;
5711 if (!(a = lock_user(VERIFY_READ, arg1,arg2, 0)))
5712 goto efault;
5713 if (!(p = lock_user_string(arg3)))
5714 goto mincore_fail;
5715 ret = get_errno(mincore(a, arg2, p));
5716 unlock_user(p, arg3, ret);
5717 mincore_fail:
5718 unlock_user(a, arg1, 0);
5719 }
5720 break;
bellardffa65c32004-01-04 23:57:22 +00005721#endif
aurel32408321b2008-10-01 21:46:32 +00005722#ifdef TARGET_NR_arm_fadvise64_64
5723 case TARGET_NR_arm_fadvise64_64:
5724 {
5725 /*
5726 * arm_fadvise64_64 looks like fadvise64_64 but
5727 * with different argument order
5728 */
5729 abi_long temp;
5730 temp = arg3;
5731 arg3 = arg4;
5732 arg4 = temp;
5733 }
5734#endif
5735#if defined(TARGET_NR_fadvise64_64) || defined(TARGET_NR_arm_fadvise64_64)
5736#ifdef TARGET_NR_fadvise64_64
5737 case TARGET_NR_fadvise64_64:
5738#endif
5739 /* This is a hint, so ignoring and returning success is ok. */
5740 ret = get_errno(0);
5741 break;
5742#endif
bellardffa65c32004-01-04 23:57:22 +00005743#ifdef TARGET_NR_madvise
bellard31e31b82003-02-18 22:55:36 +00005744 case TARGET_NR_madvise:
pbrook24836682006-04-16 14:14:53 +00005745 /* A straight passthrough may not be safe because qemu sometimes
5746 turns private flie-backed mappings into anonymous mappings.
5747 This will break MADV_DONTNEED.
5748 This is a hint, so ignoring and returning success is ok. */
5749 ret = get_errno(0);
5750 break;
bellardffa65c32004-01-04 23:57:22 +00005751#endif
blueswir1992f48a2007-10-14 16:27:31 +00005752#if TARGET_ABI_BITS == 32
bellard31e31b82003-02-18 22:55:36 +00005753 case TARGET_NR_fcntl64:
bellard77e46722003-04-29 20:39:06 +00005754 {
thsb1e341e2007-03-20 21:50:52 +00005755 int cmd;
bellard77e46722003-04-29 20:39:06 +00005756 struct flock64 fl;
pbrook53a59602006-03-25 19:31:22 +00005757 struct target_flock64 *target_fl;
pbrookce4defa2006-02-09 16:49:55 +00005758#ifdef TARGET_ARM
pbrook53a59602006-03-25 19:31:22 +00005759 struct target_eabi_flock64 *target_efl;
pbrookce4defa2006-02-09 16:49:55 +00005760#endif
bellard77e46722003-04-29 20:39:06 +00005761
thsb1e341e2007-03-20 21:50:52 +00005762 switch(arg2){
5763 case TARGET_F_GETLK64:
5764 cmd = F_GETLK64;
thsa7222582007-03-22 15:08:55 +00005765 break;
thsb1e341e2007-03-20 21:50:52 +00005766 case TARGET_F_SETLK64:
5767 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005768 break;
thsb1e341e2007-03-20 21:50:52 +00005769 case TARGET_F_SETLKW64:
5770 cmd = F_SETLK64;
thsa7222582007-03-22 15:08:55 +00005771 break;
thsb1e341e2007-03-20 21:50:52 +00005772 default:
5773 cmd = arg2;
thsa7222582007-03-22 15:08:55 +00005774 break;
thsb1e341e2007-03-20 21:50:52 +00005775 }
5776
bellard60cd49d2003-03-16 22:53:56 +00005777 switch(arg2) {
thsb1e341e2007-03-20 21:50:52 +00005778 case TARGET_F_GETLK64:
ths58134272007-03-31 18:59:32 +00005779#ifdef TARGET_ARM
5780 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005781 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5782 goto efault;
ths58134272007-03-31 18:59:32 +00005783 fl.l_type = tswap16(target_efl->l_type);
5784 fl.l_whence = tswap16(target_efl->l_whence);
5785 fl.l_start = tswap64(target_efl->l_start);
5786 fl.l_len = tswap64(target_efl->l_len);
5787 fl.l_pid = tswapl(target_efl->l_pid);
5788 unlock_user_struct(target_efl, arg3, 0);
5789 } else
5790#endif
5791 {
bellard9ee1fa22007-11-11 15:11:19 +00005792 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5793 goto efault;
ths58134272007-03-31 18:59:32 +00005794 fl.l_type = tswap16(target_fl->l_type);
5795 fl.l_whence = tswap16(target_fl->l_whence);
5796 fl.l_start = tswap64(target_fl->l_start);
5797 fl.l_len = tswap64(target_fl->l_len);
5798 fl.l_pid = tswapl(target_fl->l_pid);
5799 unlock_user_struct(target_fl, arg3, 0);
5800 }
thsb1e341e2007-03-20 21:50:52 +00005801 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005802 if (ret == 0) {
pbrookce4defa2006-02-09 16:49:55 +00005803#ifdef TARGET_ARM
5804 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005805 if (!lock_user_struct(VERIFY_WRITE, target_efl, arg3, 0))
5806 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005807 target_efl->l_type = tswap16(fl.l_type);
5808 target_efl->l_whence = tswap16(fl.l_whence);
5809 target_efl->l_start = tswap64(fl.l_start);
5810 target_efl->l_len = tswap64(fl.l_len);
5811 target_efl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005812 unlock_user_struct(target_efl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005813 } else
5814#endif
5815 {
bellard9ee1fa22007-11-11 15:11:19 +00005816 if (!lock_user_struct(VERIFY_WRITE, target_fl, arg3, 0))
5817 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005818 target_fl->l_type = tswap16(fl.l_type);
5819 target_fl->l_whence = tswap16(fl.l_whence);
5820 target_fl->l_start = tswap64(fl.l_start);
5821 target_fl->l_len = tswap64(fl.l_len);
5822 target_fl->l_pid = tswapl(fl.l_pid);
pbrook53a59602006-03-25 19:31:22 +00005823 unlock_user_struct(target_fl, arg3, 1);
pbrookce4defa2006-02-09 16:49:55 +00005824 }
bellard77e46722003-04-29 20:39:06 +00005825 }
5826 break;
5827
thsb1e341e2007-03-20 21:50:52 +00005828 case TARGET_F_SETLK64:
5829 case TARGET_F_SETLKW64:
pbrookce4defa2006-02-09 16:49:55 +00005830#ifdef TARGET_ARM
5831 if (((CPUARMState *)cpu_env)->eabi) {
bellard9ee1fa22007-11-11 15:11:19 +00005832 if (!lock_user_struct(VERIFY_READ, target_efl, arg3, 1))
5833 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005834 fl.l_type = tswap16(target_efl->l_type);
5835 fl.l_whence = tswap16(target_efl->l_whence);
5836 fl.l_start = tswap64(target_efl->l_start);
5837 fl.l_len = tswap64(target_efl->l_len);
5838 fl.l_pid = tswapl(target_efl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005839 unlock_user_struct(target_efl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005840 } else
5841#endif
5842 {
bellard9ee1fa22007-11-11 15:11:19 +00005843 if (!lock_user_struct(VERIFY_READ, target_fl, arg3, 1))
5844 goto efault;
pbrookce4defa2006-02-09 16:49:55 +00005845 fl.l_type = tswap16(target_fl->l_type);
5846 fl.l_whence = tswap16(target_fl->l_whence);
5847 fl.l_start = tswap64(target_fl->l_start);
5848 fl.l_len = tswap64(target_fl->l_len);
5849 fl.l_pid = tswapl(target_fl->l_pid);
pbrook53a59602006-03-25 19:31:22 +00005850 unlock_user_struct(target_fl, arg3, 0);
pbrookce4defa2006-02-09 16:49:55 +00005851 }
thsb1e341e2007-03-20 21:50:52 +00005852 ret = get_errno(fcntl(arg1, cmd, &fl));
bellard77e46722003-04-29 20:39:06 +00005853 break;
bellard60cd49d2003-03-16 22:53:56 +00005854 default:
bellard9ee1fa22007-11-11 15:11:19 +00005855 ret = do_fcntl(arg1, cmd, arg3);
bellard60cd49d2003-03-16 22:53:56 +00005856 break;
5857 }
bellard77e46722003-04-29 20:39:06 +00005858 break;
5859 }
bellard60cd49d2003-03-16 22:53:56 +00005860#endif
ths7d600c82006-12-08 01:32:58 +00005861#ifdef TARGET_NR_cacheflush
5862 case TARGET_NR_cacheflush:
5863 /* self-modifying code is handled automatically, so nothing needed */
5864 ret = 0;
5865 break;
5866#endif
bellardebc05482003-09-30 21:08:41 +00005867#ifdef TARGET_NR_security
bellard31e31b82003-02-18 22:55:36 +00005868 case TARGET_NR_security:
5869 goto unimplemented;
bellardebc05482003-09-30 21:08:41 +00005870#endif
bellardc573ff62004-01-04 15:51:36 +00005871#ifdef TARGET_NR_getpagesize
5872 case TARGET_NR_getpagesize:
5873 ret = TARGET_PAGE_SIZE;
5874 break;
5875#endif
bellard31e31b82003-02-18 22:55:36 +00005876 case TARGET_NR_gettid:
5877 ret = get_errno(gettid());
5878 break;
thse5febef2007-04-01 18:31:35 +00005879#ifdef TARGET_NR_readahead
bellard31e31b82003-02-18 22:55:36 +00005880 case TARGET_NR_readahead:
aurel322054ac92008-10-13 21:08:07 +00005881#if TARGET_ABI_BITS == 32
5882#ifdef TARGET_ARM
5883 if (((CPUARMState *)cpu_env)->eabi)
5884 {
5885 arg2 = arg3;
5886 arg3 = arg4;
5887 arg4 = arg5;
5888 }
5889#endif
5890 ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4));
5891#else
5892 ret = get_errno(readahead(arg1, arg2, arg3));
5893#endif
5894 break;
thse5febef2007-04-01 18:31:35 +00005895#endif
bellardebc05482003-09-30 21:08:41 +00005896#ifdef TARGET_NR_setxattr
bellard31e31b82003-02-18 22:55:36 +00005897 case TARGET_NR_setxattr:
5898 case TARGET_NR_lsetxattr:
5899 case TARGET_NR_fsetxattr:
5900 case TARGET_NR_getxattr:
5901 case TARGET_NR_lgetxattr:
5902 case TARGET_NR_fgetxattr:
5903 case TARGET_NR_listxattr:
5904 case TARGET_NR_llistxattr:
5905 case TARGET_NR_flistxattr:
5906 case TARGET_NR_removexattr:
5907 case TARGET_NR_lremovexattr:
5908 case TARGET_NR_fremovexattr:
bellard5cd43932003-03-29 16:54:36 +00005909 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005910#endif
5911#ifdef TARGET_NR_set_thread_area
bellard5cd43932003-03-29 16:54:36 +00005912 case TARGET_NR_set_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005913#if defined(TARGET_MIPS)
ths6f5b89a2007-03-02 20:48:00 +00005914 ((CPUMIPSState *) cpu_env)->tls_value = arg1;
5915 ret = 0;
5916 break;
edgar_iglef967792009-01-07 14:19:38 +00005917#elif defined(TARGET_CRIS)
5918 if (arg1 & 0xff)
5919 ret = -TARGET_EINVAL;
5920 else {
5921 ((CPUCRISState *) cpu_env)->pregs[PR_PID] = arg1;
5922 ret = 0;
5923 }
5924 break;
bellard8d18e892007-11-14 15:18:40 +00005925#elif defined(TARGET_I386) && defined(TARGET_ABI32)
5926 ret = do_set_thread_area(cpu_env, arg1);
5927 break;
ths6f5b89a2007-03-02 20:48:00 +00005928#else
5929 goto unimplemented_nowarn;
5930#endif
5931#endif
5932#ifdef TARGET_NR_get_thread_area
bellard5cd43932003-03-29 16:54:36 +00005933 case TARGET_NR_get_thread_area:
bellard8d18e892007-11-14 15:18:40 +00005934#if defined(TARGET_I386) && defined(TARGET_ABI32)
5935 ret = do_get_thread_area(cpu_env, arg1);
5936#else
bellard5cd43932003-03-29 16:54:36 +00005937 goto unimplemented_nowarn;
bellardebc05482003-09-30 21:08:41 +00005938#endif
bellard8d18e892007-11-14 15:18:40 +00005939#endif
bellard48dc41e2006-06-21 18:15:50 +00005940#ifdef TARGET_NR_getdomainname
5941 case TARGET_NR_getdomainname:
5942 goto unimplemented_nowarn;
5943#endif
ths6f5b89a2007-03-02 20:48:00 +00005944
thsb5906f92007-03-19 13:32:45 +00005945#ifdef TARGET_NR_clock_gettime
5946 case TARGET_NR_clock_gettime:
5947 {
5948 struct timespec ts;
5949 ret = get_errno(clock_gettime(arg1, &ts));
5950 if (!is_error(ret)) {
5951 host_to_target_timespec(arg2, &ts);
5952 }
5953 break;
5954 }
5955#endif
5956#ifdef TARGET_NR_clock_getres
5957 case TARGET_NR_clock_getres:
5958 {
5959 struct timespec ts;
5960 ret = get_errno(clock_getres(arg1, &ts));
5961 if (!is_error(ret)) {
5962 host_to_target_timespec(arg2, &ts);
5963 }
5964 break;
5965 }
5966#endif
pbrook63d76512008-05-29 13:43:29 +00005967#ifdef TARGET_NR_clock_nanosleep
5968 case TARGET_NR_clock_nanosleep:
5969 {
5970 struct timespec ts;
5971 target_to_host_timespec(&ts, arg3);
5972 ret = get_errno(clock_nanosleep(arg1, arg2, &ts, arg4 ? &ts : NULL));
5973 if (arg4)
5974 host_to_target_timespec(arg4, &ts);
5975 break;
5976 }
5977#endif
thsb5906f92007-03-19 13:32:45 +00005978
ths6f5b89a2007-03-02 20:48:00 +00005979#if defined(TARGET_NR_set_tid_address) && defined(__NR_set_tid_address)
5980 case TARGET_NR_set_tid_address:
bellard579a97f2007-11-11 14:26:47 +00005981 ret = get_errno(set_tid_address((int *)g2h(arg1)));
5982 break;
ths6f5b89a2007-03-02 20:48:00 +00005983#endif
5984
ths3ae43202007-09-16 21:39:48 +00005985#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
ths4cae1d12007-07-12 11:06:53 +00005986 case TARGET_NR_tkill:
pbrook4cb05962008-05-30 18:05:19 +00005987 ret = get_errno(sys_tkill((int)arg1, target_to_host_signal(arg2)));
ths4cae1d12007-07-12 11:06:53 +00005988 break;
5989#endif
5990
ths3ae43202007-09-16 21:39:48 +00005991#if defined(TARGET_NR_tgkill) && defined(__NR_tgkill)
ths71455572007-06-21 21:45:30 +00005992 case TARGET_NR_tgkill:
pbrook4cb05962008-05-30 18:05:19 +00005993 ret = get_errno(sys_tgkill((int)arg1, (int)arg2,
5994 target_to_host_signal(arg3)));
ths71455572007-06-21 21:45:30 +00005995 break;
5996#endif
5997
ths4f2b1fe2007-06-21 21:57:12 +00005998#ifdef TARGET_NR_set_robust_list
5999 case TARGET_NR_set_robust_list:
6000 goto unimplemented_nowarn;
6001#endif
6002
ths9007f0e2007-09-25 17:50:37 +00006003#if defined(TARGET_NR_utimensat) && defined(__NR_utimensat)
6004 case TARGET_NR_utimensat:
6005 {
6006 struct timespec ts[2];
6007 target_to_host_timespec(ts, arg3);
6008 target_to_host_timespec(ts+1, arg3+sizeof(struct target_timespec));
6009 if (!arg2)
6010 ret = get_errno(sys_utimensat(arg1, NULL, ts, arg4));
6011 else {
bellard579a97f2007-11-11 14:26:47 +00006012 if (!(p = lock_user_string(arg2))) {
ths0da46a62007-10-20 20:23:07 +00006013 ret = -TARGET_EFAULT;
bellard579a97f2007-11-11 14:26:47 +00006014 goto fail;
6015 }
6016 ret = get_errno(sys_utimensat(arg1, path(p), ts, arg4));
6017 unlock_user(p, arg2, 0);
ths9007f0e2007-09-25 17:50:37 +00006018 }
6019 }
6020 break;
6021#endif
pbrookbd0c5662008-05-29 14:34:11 +00006022#if defined(USE_NPTL)
6023 case TARGET_NR_futex:
6024 ret = do_futex(arg1, arg2, arg3, arg4, arg5, arg6);
6025 break;
6026#endif
aurel3239b59762008-10-01 21:46:50 +00006027#ifdef TARGET_NR_inotify_init
6028 case TARGET_NR_inotify_init:
6029 ret = get_errno(sys_inotify_init());
6030 break;
6031#endif
6032#ifdef TARGET_NR_inotify_add_watch
6033 case TARGET_NR_inotify_add_watch:
6034 p = lock_user_string(arg2);
6035 ret = get_errno(sys_inotify_add_watch(arg1, path(p), arg3));
6036 unlock_user(p, arg2, 0);
6037 break;
6038#endif
6039#ifdef TARGET_NR_inotify_rm_watch
6040 case TARGET_NR_inotify_rm_watch:
6041 ret = get_errno(sys_inotify_rm_watch(arg1, arg2));
6042 break;
6043#endif
ths9007f0e2007-09-25 17:50:37 +00006044
bellard31e31b82003-02-18 22:55:36 +00006045 default:
6046 unimplemented:
bellard5cd43932003-03-29 16:54:36 +00006047 gemu_log("qemu: Unsupported syscall: %d\n", num);
ths4f2b1fe2007-06-21 21:57:12 +00006048#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 +00006049 unimplemented_nowarn:
bellard80a9d032005-01-03 23:31:27 +00006050#endif
ths0da46a62007-10-20 20:23:07 +00006051 ret = -TARGET_ENOSYS;
bellard31e31b82003-02-18 22:55:36 +00006052 break;
6053 }
bellard579a97f2007-11-11 14:26:47 +00006054fail:
bellardc573ff62004-01-04 15:51:36 +00006055#ifdef DEBUG
6056 gemu_log(" = %ld\n", ret);
6057#endif
thsb92c47c2007-11-01 00:07:38 +00006058 if(do_strace)
6059 print_syscall_ret(num, ret);
bellard31e31b82003-02-18 22:55:36 +00006060 return ret;
bellard579a97f2007-11-11 14:26:47 +00006061efault:
6062 ret = -TARGET_EFAULT;
6063 goto fail;
bellard31e31b82003-02-18 22:55:36 +00006064}