* [Qemu-devel] [PATCH] Add readahead syscall @ 2008-10-08 18:54 Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Add readahead syscall Aurelien Jarno 0 siblings, 2 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f1f050e..dc7e561 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5761,7 +5761,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_readahead case TARGET_NR_readahead: - goto unimplemented; +#if TARGET_ABI_BITS == 32 +#ifdef TARGET_ARM + if (((CPUARMState *)cpu_env)->eabi) + { + arg2 = arg3; + arg3 = arg4; + arg4 = arg5; + } +#endif + ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4)); +#else + ret = get_errno(readahead(arg1, arg2, arg3)); +#endif + break; #endif #ifdef TARGET_NR_setxattr case TARGET_NR_setxattr: -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix getdents* syscalls 2008-10-08 18:54 [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Aurelien Jarno 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Add readahead syscall Aurelien Jarno 1 sibling, 2 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov glibc's structs dirent and dirent64 is different from in-kernel dirent and dirent64. Kernel headers doesn't provide structs dirent(64) any more. So we should add it to qemu headers. To avoid conflict with glibc it called struct linux_dirent(64). Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 27 +++++++++++++-------------- linux-user/syscall_defs.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index dc7e561..40e985a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -28,7 +28,6 @@ #include <fcntl.h> #include <time.h> #include <limits.h> -#include <dirent.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> @@ -94,8 +93,8 @@ #endif //#include <linux/msdos_fs.h> -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2]) #undef _syscall0 @@ -216,10 +215,10 @@ _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname, #endif _syscall2(int,sys_getcwd1,char *,buf,size_t,size) #if TARGET_ABI_BITS == 32 -_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count); +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); #endif #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) -_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count); +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); #endif _syscall2(int, sys_getpriority, int, which, int, who); #if !defined (__x86_64__) @@ -4879,7 +4878,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 { struct target_dirent *target_dirp; - struct dirent *dirp; + struct linux_dirent *dirp; abi_long count = arg3; dirp = malloc(count); @@ -4890,7 +4889,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(sys_getdents(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent *de; + struct linux_dirent *de; struct target_dirent *tde; int len = ret; int reclen, treclen; @@ -4912,7 +4911,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, tnamelen = 256; /* XXX: may not be correct */ strncpy(tde->d_name, de->d_name, tnamelen); - de = (struct dirent *)((char *)de + reclen); + de = (struct linux_dirent *)((char *)de + reclen); len -= reclen; tde = (struct target_dirent *)((char *)tde + treclen); count1 += treclen; @@ -4924,14 +4923,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } #else { - struct dirent *dirp; + struct linux_dirent *dirp; abi_long count = arg3; if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) goto efault; ret = get_errno(sys_getdents(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent *de; + struct linux_dirent *de; int len = ret; int reclen; de = dirp; @@ -4942,7 +4941,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, de->d_reclen = tswap16(reclen); tswapls(&de->d_ino); tswapls(&de->d_off); - de = (struct dirent *)((char *)de + reclen); + de = (struct linux_dirent *)((char *)de + reclen); len -= reclen; } } @@ -4953,13 +4952,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) case TARGET_NR_getdents64: { - struct dirent64 *dirp; + struct linux_dirent64 *dirp; abi_long count = arg3; if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) goto efault; ret = get_errno(sys_getdents64(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent64 *de; + struct linux_dirent64 *de; int len = ret; int reclen; de = dirp; @@ -4970,7 +4969,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, de->d_reclen = tswap16(reclen); tswap64s((uint64_t *)&de->d_ino); tswap64s((uint64_t *)&de->d_off); - de = (struct dirent64 *)((char *)de + reclen); + de = (struct linux_dirent64 *)((char *)de + reclen); len -= reclen; } } diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index c30bb15..5a58010 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1963,6 +1963,21 @@ struct target_sysinfo { char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; +struct linux_dirent { + long d_ino; + unsigned long d_off; + unsigned short d_reclen; + char d_name[256]; /* We must not include limits.h! */ +}; + +struct linux_dirent64 { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + #include "socket.h" #include "errno_defs.h" -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Aurelien Jarno 1 sibling, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 173 ++++++++++++++++++++++++++++++++++---------------- 1 files changed, 117 insertions(+), 56 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 40e985a..7e67093 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1611,7 +1611,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr) } #endif -#ifdef TARGET_NR_ipc #define N_SHM_REGIONS 32 static struct shm_region { @@ -1845,20 +1844,26 @@ static inline abi_long do_semctl(int first, int second, int third, struct target_msqid_ds { - struct target_ipc_perm msg_perm; - abi_ulong msg_stime; - abi_ulong __unused1; - abi_ulong msg_rtime; - abi_ulong __unused2; - abi_ulong msg_ctime; - abi_ulong __unused3; - abi_ulong __msg_cbytes; - abi_ulong msg_qnum; - abi_ulong msg_qbytes; - abi_ulong msg_lspid; - abi_ulong msg_lrpid; - abi_ulong __unused4; - abi_ulong __unused5; + struct target_ipc_perm msg_perm; + abi_ulong msg_stime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong msg_rtime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong msg_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + abi_ulong __msg_cbytes; + abi_ulong msg_qnum; + abi_ulong msg_qbytes; + abi_ulong msg_lspid; + abi_ulong msg_lrpid; + abi_ulong __unused4; + abi_ulong __unused5; }; static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, @@ -1868,7 +1873,8 @@ static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) return -TARGET_EFAULT; - target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); + if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr)) + return -TARGET_EFAULT; host_md->msg_stime = tswapl(target_md->msg_stime); host_md->msg_rtime = tswapl(target_md->msg_rtime); host_md->msg_ctime = tswapl(target_md->msg_ctime); @@ -1888,7 +1894,8 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) return -TARGET_EFAULT; - host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); + if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm))) + return -TARGET_EFAULT; target_md->msg_stime = tswapl(host_md->msg_stime); target_md->msg_rtime = tswapl(host_md->msg_rtime); target_md->msg_ctime = tswapl(host_md->msg_ctime); @@ -1901,26 +1908,69 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, return 0; } -static inline abi_long do_msgctl(int first, int second, abi_long ptr) +struct target_msginfo { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; +}; + +static inline abi_long host_to_target_msginfo(abi_ulong target_addr, + struct msginfo *host_msginfo) +{ + struct target_msginfo *target_msginfo; + if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); + __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); + __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); + __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); + __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); + __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); + __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); + __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); + unlock_user_struct(target_msginfo, target_addr, 1); +} + +static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr) { struct msqid_ds dsarg; - int cmd = second&0xff; - abi_long ret = 0; - switch( cmd ) { + struct msginfo msginfo; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch (cmd) { case IPC_STAT: case IPC_SET: - target_to_host_msqid_ds(&dsarg,ptr); - ret = get_errno(msgctl(first, cmd, &dsarg)); - host_to_target_msqid_ds(ptr,&dsarg); - default: - ret = get_errno(msgctl(first, cmd, &dsarg)); + case MSG_STAT: + if (target_to_host_msqid_ds(&dsarg,ptr)) + return -TARGET_EFAULT; + ret = get_errno(msgctl(msgid, cmd, &dsarg)); + if (host_to_target_msqid_ds(ptr,&dsarg)) + return -TARGET_EFAULT; + break; + case IPC_RMID: + ret = get_errno(msgctl(msgid, cmd, NULL)); + break; + case IPC_INFO: + case MSG_INFO: + ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); + if (host_to_target_msginfo(ptr, &msginfo)) + return -TARGET_EFAULT; + break; } + return ret; } struct target_msgbuf { - abi_ulong mtype; - char mtext[1]; + abi_long mtype; + char mtext[1]; }; static inline abi_long do_msgsnd(int msqid, abi_long msgp, @@ -1933,8 +1983,8 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) return -TARGET_EFAULT; host_mb = malloc(msgsz+sizeof(long)); - host_mb->mtype = tswapl(target_mb->mtype); - memcpy(host_mb->mtext,target_mb->mtext,msgsz); + host_mb->mtype = (abi_long) tswapl(target_mb->mtype); + memcpy(host_mb->mtext, target_mb->mtext, msgsz); ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); free(host_mb); unlock_user_struct(target_mb, msgp, 0); @@ -1943,7 +1993,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, } static inline abi_long do_msgrcv(int msqid, abi_long msgp, - unsigned int msgsz, int msgtype, + unsigned int msgsz, abi_long msgtyp, int msgflg) { struct target_msgbuf *target_mb; @@ -1953,8 +2003,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) return -TARGET_EFAULT; + host_mb = malloc(msgsz+sizeof(long)); - ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); + ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg)); + if (ret > 0) { abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); @@ -1962,9 +2014,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, ret = -TARGET_EFAULT; goto end; } - memcpy(target_mb->mtext, host_mb->mtext, ret); + memcpy(target_mb->mtext, host_mb->mtext, ret); unlock_user(target_mtext, target_mtext_addr, ret); } + target_mb->mtype = tswapl(host_mb->mtype); free(host_mb); @@ -1974,6 +2027,7 @@ end: return ret; } +#ifdef TARGET_NR_ipc /* ??? This only works with linear mappings. */ /* do_ipc() must return target values and target errnos. */ static abi_long do_ipc(unsigned int call, int first, @@ -2006,34 +2060,41 @@ static abi_long do_ipc(unsigned int call, int first, ret = -TARGET_ENOSYS; break; - case IPCOP_msgget: - ret = get_errno(msgget(first, second)); - break; + case IPCOP_msgget: + ret = get_errno(msgget(first, second)); + break; - case IPCOP_msgsnd: - ret = do_msgsnd(first, ptr, second, third); - break; + case IPCOP_msgsnd: + ret = do_msgsnd(first, ptr, second, third); + break; - case IPCOP_msgctl: - ret = do_msgctl(first, second, ptr); - break; + case IPCOP_msgctl: + ret = do_msgctl(first, second, ptr); + break; - case IPCOP_msgrcv: - { - /* XXX: this code is not correct */ - struct ipc_kludge - { - void *__unbounded msgp; - long int msgtyp; - }; + case IPCOP_msgrcv: + switch (version) { + case 0: + { + struct target_ipc_kludge { + abi_long msgp; + abi_long msgtyp; + } *tmp; - struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr); - struct msgbuf *msgp = (struct msgbuf *) foo->msgp; + if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { + ret = -TARGET_EFAULT; + break; + } - ret = do_msgrcv(first, (long)msgp, second, 0, third); + ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third); - } - break; + unlock_user_struct(tmp, ptr, 0); + break; + } + default: + ret = do_msgrcv(first, ptr, second, fifth, third); + } + break; case IPCOP_shmat: { -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement msg* syscalls 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7e67093..cf0834f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4829,6 +4829,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif + +#ifdef TARGET_NR_msgctl + case TARGET_NR_msgctl: + ret = do_msgctl(arg1, arg2, arg3); + break; +#endif +#ifdef TARGET_NR_msgget + case TARGET_NR_msgget: + ret = get_errno(msgget(arg1, arg2)); + break; +#endif +#ifdef TARGET_NR_msgrcv + case TARGET_NR_msgrcv: + ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5); + break; +#endif +#ifdef TARGET_NR_msgsnd + case TARGET_NR_msgsnd: + ret = do_msgsnd(arg1, arg2, arg3, arg4); + break; +#endif case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov 2008-10-09 17:41 ` [Qemu-devel] [PATCH, v2] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 0 siblings, 2 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 319 +++++++++++++++++++++++++++++++------------------- 1 files changed, 198 insertions(+), 121 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cf0834f..54c53c2 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1635,14 +1635,14 @@ struct target_ipc_perm struct target_semid_ds { - struct target_ipc_perm sem_perm; - abi_ulong sem_otime; - abi_ulong __unused1; - abi_ulong sem_ctime; - abi_ulong __unused2; - abi_ulong sem_nsems; - abi_ulong __unused3; - abi_ulong __unused4; + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong __unused1; + abi_ulong sem_ctime; + abi_ulong __unused2; + abi_ulong sem_nsems; + abi_ulong __unused3; + abi_ulong __unused4; }; static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, @@ -1690,7 +1690,8 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) return -TARGET_EFAULT; - target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); + if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) + return -TARGET_EFAULT; host_sd->sem_nsems = tswapl(target_sd->sem_nsems); host_sd->sem_otime = tswapl(target_sd->sem_otime); host_sd->sem_ctime = tswapl(target_sd->sem_ctime); @@ -1705,7 +1706,8 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) return -TARGET_EFAULT; - host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); + if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) + return -TARGET_EFAULT;; target_sd->sem_nsems = tswapl(host_sd->sem_nsems); target_sd->sem_otime = tswapl(host_sd->sem_otime); target_sd->sem_ctime = tswapl(host_sd->sem_ctime); @@ -1713,135 +1715,215 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, return 0; } +struct target_seminfo { + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +static inline abi_long host_to_target_seminfo(abi_ulong target_addr, + struct seminfo *host_seminfo) +{ + struct target_seminfo *target_seminfo; + if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_seminfo->semmap, &target_seminfo->semmap); + __put_user(host_seminfo->semmni, &target_seminfo->semmni); + __put_user(host_seminfo->semmns, &target_seminfo->semmns); + __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); + __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); + __put_user(host_seminfo->semopm, &target_seminfo->semopm); + __put_user(host_seminfo->semume, &target_seminfo->semume); + __put_user(host_seminfo->semusz, &target_seminfo->semusz); + __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); + __put_user(host_seminfo->semaem, &target_seminfo->semaem); + unlock_user_struct(target_seminfo, target_addr, 1); + return 0; +} + union semun { - int val; - struct semid_ds *buf; - unsigned short *array; + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; }; union target_semun { - int val; - abi_long buf; - unsigned short int *array; + int val; + abi_ulong buf; + abi_ulong array; + abi_ulong __buf; }; -static inline abi_long target_to_host_semun(int cmd, - union semun *host_su, - abi_ulong target_addr, - struct semid_ds *ds) +static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, + abi_ulong target_addr) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - target_to_host_semid_ds(ds,target_su->buf); - host_su->buf = ds; - unlock_user_struct(target_su, target_addr, 0); - break; - case GETVAL: - case SETVAL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - host_su->val = tswapl(target_su->val); - unlock_user_struct(target_su, target_addr, 0); - break; - case GETALL: - case SETALL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - *host_su->array = tswap16(*target_su->array); - unlock_user_struct(target_su, target_addr, 0); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + *host_array = malloc(nsems*sizeof(unsigned short)); + array = lock_user(VERIFY_READ, target_addr, + nsems*sizeof(unsigned short), 1); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __get_user((*host_array)[i], &array[i]); } + unlock_user(array, target_addr, 0); + return 0; } -static inline abi_long host_to_target_semun(int cmd, - abi_ulong target_addr, - union semun *host_su, - struct semid_ds *ds) +static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - host_to_target_semid_ds(target_su->buf,ds); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETVAL: - case SETVAL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - target_su->val = tswapl(host_su->val); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETALL: - case SETALL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - *target_su->array = tswap16(*host_su->array); - unlock_user_struct(target_su, target_addr, 1); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + array = lock_user(VERIFY_WRITE, target_addr, + nsems*sizeof(unsigned short), 0); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __put_user((*host_array)[i], &array[i]); } + free(*host_array); + unlock_user(array, target_addr, 1); + return 0; } -static inline abi_long do_semctl(int first, int second, int third, - abi_long ptr) +static inline abi_long do_semctl(int semid, int semnum, int cmd, + union target_semun target_su) { union semun arg; struct semid_ds dsarg; - int cmd = third&0xff; - abi_long ret = 0; + unsigned short *array; + struct seminfo seminfo; + abi_long ret = -TARGET_EINVAL; + abi_long err; - switch( cmd ) { - case GETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case GETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_STAT: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_SET: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - default: - ret = get_errno(semctl(first, second, cmd, arg)); + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + case SEM_STAT: + err = target_to_host_semid_ds(&dsarg, target_su.buf); + if (err) + return err; + arg.buf = &dsarg; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semid_ds(target_su.buf, &dsarg); + if (err) + return err; + break; + case GETVAL: + case SETVAL: + arg.val = tswapl(target_su.val); + ret = get_errno(semctl(semid, semnum, cmd, arg)); + target_su.val = tswapl(arg.val); + break; + case GETALL: + case SETALL: + err = target_to_host_semarray(semid, &array, target_su.array); + if (err) + return err; + arg.array = array; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semarray(semid, target_su.array, &array); + if (err) + return err; + break; + case IPC_INFO: + case SEM_INFO: + arg.__buf = &seminfo; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_seminfo(target_su.__buf, &seminfo); + if (err) + return err; + break; + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + ret = get_errno(semctl(semid, semnum, cmd, NULL)); + break; } return ret; } +struct target_sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; +}; + +static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, + abi_ulong target_addr, + unsigned nsops) +{ + struct target_sembuf *target_sembuf; + int i; + + target_sembuf = lock_user(VERIFY_READ, target_addr, + nsops*sizeof(struct target_sembuf), 1); + if (!target_sembuf) + return -TARGET_EFAULT; + + for(i=0; i<nsops; i++) { + __put_user(target_sembuf[i].sem_num, &host_sembuf[i].sem_num); + __put_user(target_sembuf[i].sem_op, &host_sembuf[i].sem_op); + __put_user(target_sembuf[i].sem_flg, &host_sembuf[i].sem_flg); + } + + unlock_user(target_sembuf, target_addr, 0); + + return 0; +} + +static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +{ + struct sembuf sops[nsops]; + + if (target_to_host_sembuf(sops, ptr, nsops)) + return -TARGET_EFAULT; + + return semop(semid, sops, nsops); +} + struct target_msqid_ds { struct target_ipc_perm msg_perm; @@ -2044,7 +2126,7 @@ static abi_long do_ipc(unsigned int call, int first, switch (call) { case IPCOP_semop: - ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second)); + ret = do_semop(first, ptr, second); break; case IPCOP_semget: @@ -2052,12 +2134,7 @@ static abi_long do_ipc(unsigned int call, int first, break; case IPCOP_semctl: - ret = do_semctl(first, second, third, ptr); - break; - - case IPCOP_semtimedop: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; + ret = do_semctl(first, second, third, (union target_semun) ptr); break; case IPCOP_msgget: -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement sem* syscalls 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov 2008-10-09 17:42 ` [Qemu-devel] [PATCH, v2] Implement sem* syscalls Kirill A. Shutemov 2008-10-09 17:41 ` [Qemu-devel] [PATCH, v2] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 1 sibling, 2 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 54c53c2..33dc269 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4906,7 +4906,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif - +#ifdef TARGET_NR_semget + case TARGET_NR_semget: + ret = get_errno(semget(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semop + case TARGET_NR_semop: + ret = get_errno(do_semop(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semctl + case TARGET_NR_semctl: + ret = do_semctl(arg1, arg2, arg3, (union target_semun)arg4); + break; +#endif #ifdef TARGET_NR_msgctl case TARGET_NR_msgctl: ret = do_msgctl(arg1, arg2, arg3); -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov 2008-10-09 17:42 ` [Qemu-devel] [PATCH, v2] Implement sem* syscalls Kirill A. Shutemov 1 sibling, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 282 +++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 224 insertions(+), 58 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 33dc269..4ee6087 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2109,6 +2109,206 @@ end: return ret; } +struct target_shmid_ds +{ + struct target_ipc_perm shm_perm; + abi_ulong shm_segsz; + abi_ulong shm_atime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong shm_dtime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong shm_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + int shm_cpid; + int shm_lpid; + abi_ulong shm_nattch; + unsigned long int __unused4; + unsigned long int __unused5; +}; + +static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) + return -TARGET_EFAULT; + if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) + return -TARGET_EFAULT; + __put_user(target_sd->shm_segsz, &host_sd->shm_segsz); + __put_user(target_sd->shm_atime, &host_sd->shm_atime); + __put_user(target_sd->shm_dtime, &host_sd->shm_dtime); + __put_user(target_sd->shm_ctime, &host_sd->shm_ctime); + __put_user(target_sd->shm_cpid, &host_sd->shm_cpid); + __put_user(target_sd->shm_lpid, &host_sd->shm_lpid); + __put_user(target_sd->shm_nattch, &host_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) + return -TARGET_EFAULT; + if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) + return -TARGET_EFAULT; + __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __put_user(host_sd->shm_atime, &target_sd->shm_atime); + __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); + __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 1); + return 0; +} + +struct target_shminfo { + abi_ulong shmmax; + abi_ulong shmmin; + abi_ulong shmmni; + abi_ulong shmseg; + abi_ulong shmall; +}; + +static inline abi_long host_to_target_shminfo(abi_ulong target_addr, + struct shminfo *host_shminfo) +{ + struct target_shminfo *target_shminfo; + if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); + __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); + __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); + __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); + __put_user(host_shminfo->shmall, &target_shminfo->shmall); + unlock_user_struct(target_shminfo, target_addr, 1); +} + +struct target_shm_info { + int used_ids; + abi_ulong shm_tot; + abi_ulong shm_rss; + abi_ulong shm_swp; + abi_ulong swap_attempts; + abi_ulong swap_successes; +}; + +static inline abi_long host_to_target_shm_info(abi_ulong target_addr, + struct shm_info *host_shm_info) +{ + struct target_shm_info *target_shm_info; + if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); + __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); + __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); + __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); + __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts); + __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes); + unlock_user_struct(target_shm_info, target_addr, 1); +} + +static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf) +{ + struct shmid_ds dsarg; + struct shminfo shminfo; + struct shm_info shm_info; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch(cmd) { + case IPC_STAT: + case IPC_SET: + case SHM_STAT: + if (target_to_host_shmid_ds(&dsarg, buf)) + return -TARGET_EFAULT; + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (host_to_target_shmid_ds(buf, &dsarg)) + return -TARGET_EFAULT; + break; + case IPC_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); + if (host_to_target_shminfo(buf, &shminfo)) + return -TARGET_EFAULT; + break; + case SHM_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); + if (host_to_target_shm_info(buf, &shm_info)) + return -TARGET_EFAULT; + break; + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: + ret = get_errno(shmctl(shmid, cmd, NULL)); + break; + } + + return ret; +} + +static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg, + unsigned long *raddr) +{ + abi_long ret; + struct shmid_ds shm_info; + int i; + + /* SHM_* flags are the same on all linux platforms */ + *raddr = (unsigned long) shmat(shmid, g2h(shmaddr), shmflg); + + if (*raddr == -1) { + return get_errno(*raddr); + } + + /* find out the length of the shared memory segment */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* can't get length, bail out */ + shmdt((void *) *raddr); + return get_errno(ret); + } + + page_set_flags(h2g(*raddr), h2g(*raddr) + shm_info.shm_segsz, + PAGE_VALID | PAGE_READ | + ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE)); + + for (i = 0; i < N_SHM_REGIONS; i++) { + if (shm_regions[i].start == 0) { + shm_regions[i].start = h2g(*raddr); + shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + + return 0; +} + +static inline abi_long do_shmdt(abi_ulong shmaddr) +{ + int i; + + for (i = 0; i < N_SHM_REGIONS; ++i) { + if (shm_regions[i].start == shmaddr) { + shm_regions[i].start = 0; + page_set_flags(shmaddr, shm_regions[i].size, 0); + break; + } + } + + return get_errno(shmdt(g2h(shmaddr))); +} + #ifdef TARGET_NR_ipc /* ??? This only works with linear mappings. */ /* do_ipc() must return target values and target errnos. */ @@ -2118,8 +2318,6 @@ static abi_long do_ipc(unsigned int call, int first, { int version; abi_long ret = 0; - struct shmid_ds shm_info; - int i; version = call >> 16; call &= 0xffff; @@ -2174,72 +2372,40 @@ static abi_long do_ipc(unsigned int call, int first, break; case IPCOP_shmat: - { - abi_ulong raddr; - void *host_addr; - /* SHM_* flags are the same on all linux platforms */ - host_addr = shmat(first, (void *)g2h(ptr), second); - if (host_addr == (void *)-1) { - ret = get_errno((long)host_addr); - break; - } - raddr = h2g((unsigned long)host_addr); - /* find out the length of the shared memory segment */ - - ret = get_errno(shmctl(first, IPC_STAT, &shm_info)); - if (is_error(ret)) { - /* can't get length, bail out */ - shmdt(host_addr); - break; - } - page_set_flags(raddr, raddr + shm_info.shm_segsz, - PAGE_VALID | PAGE_READ | - ((second & SHM_RDONLY)? 0: PAGE_WRITE)); - for (i = 0; i < N_SHM_REGIONS; ++i) { - if (shm_regions[i].start == 0) { - shm_regions[i].start = raddr; - shm_regions[i].size = shm_info.shm_segsz; + switch (version) { + default: + { + unsigned long raddr; + + ret = do_shmat(first, ptr, second, &raddr); + if (ret) break; - } + + ret = put_user_ual(raddr, third); + break; } - if (put_user_ual(raddr, third)) - return -TARGET_EFAULT; - ret = 0; + case 1: + ret = -TARGET_EINVAL; + break; } - break; + break; + case IPCOP_shmdt: - for (i = 0; i < N_SHM_REGIONS; ++i) { - if (shm_regions[i].start == ptr) { - shm_regions[i].start = 0; - page_set_flags(ptr, shm_regions[i].size, 0); - break; - } - } - ret = get_errno(shmdt((void *)g2h(ptr))); - break; + ret = do_shmdt(ptr); + break; case IPCOP_shmget: - /* IPC_* flag values are the same on all linux platforms */ - ret = get_errno(shmget(first, second, third)); - break; + ret = get_errno(shmget(first, second, third)); + break; - /* IPC_* and SHM_* command values are the same on all linux platforms */ case IPCOP_shmctl: - switch(second) { - case IPC_RMID: - case SHM_LOCK: - case SHM_UNLOCK: - ret = get_errno(shmctl(first, second, NULL)); - break; - default: - goto unimplemented; - } + ret = do_shmctl(first, second, third); break; + default: - unimplemented: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; - break; + gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); + ret = -TARGET_ENOSYS; + break; } return ret; } -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement shm* syscalls 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 4ee6087..5b69b5d 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5107,6 +5107,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_msgsnd(arg1, arg2, arg3, arg4); break; #endif +#ifdef TARGET_NR_shmget + case TARGET_NR_shmget: + ret = get_errno(shmget(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_shmctl + case TARGET_NR_shmctl: + ret = do_shmctl(arg1, arg2, arg3); + break; +#endif +#ifdef TARGET_NR_shmat + case TARGET_NR_shmat: + { + abi_long err; + unsigned long _ret; + + err = do_shmat(arg1, arg2, arg3, &_ret); + ret = err ? err : _ret; + } + break; +#endif +#ifdef TARGET_NR_shmdt + case TARGET_NR_shmdt: + ret = do_shmdt(arg1); + break; +#endif case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov 2008-10-09 17:40 ` [Qemu-devel] [PATCH, v2] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 0 siblings, 2 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov There are two different syscall names for the same goal. On systems with sizeof(long) == 64 it calls newfstatat. On systems with sizeof(long) == 32 it calls fstatat64. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 21 +++++++++++++++++++-- 1 files changed, 19 insertions(+), 2 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 5b69b5d..6e55a74 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -165,6 +165,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_linkat __NR_linkat #define __NR_sys_mkdirat __NR_mkdirat #define __NR_sys_mknodat __NR_mknodat +#define __NR_sys_newfstatat __NR_newfstatat #define __NR_sys_openat __NR_openat #define __NR_sys_readlinkat __NR_readlinkat #define __NR_sys_renameat __NR_renameat @@ -205,7 +206,8 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, uid_t,owner,gid_t,group,int,flags) #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + defined(__NR_fstatat64) _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname, struct stat *,buf,int,flags) #endif @@ -236,6 +238,11 @@ _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode) _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname, mode_t,mode,dev_t,dev) #endif +#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \ + defined(__NR_newfstatat) +_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname, + struct stat *,buf,int,flags) +#endif #if defined(TARGET_NR_openat) && defined(__NR_openat) _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode) #endif @@ -5645,11 +5652,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = host_to_target_stat64(cpu_env, arg2, &st); break; #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + (defined(__NR_fstatat64) || defined(__NR_newfstatat)) +#ifdef TARGET_NR_fstatat64 + case TARGET_NR_fstatat64: +#endif +#ifdef TARGET_NR_newfstatat case TARGET_NR_fstatat64: +#endif if (!(p = lock_user_string(arg2))) goto efault; +#ifdef __NR_fstatat64 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4)); +#else + ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4)); +#endif if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg3, &st); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov @ 2008-10-08 18:54 ` Kirill A. Shutemov 2008-10-09 17:40 ` [Qemu-devel] [PATCH, v2] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 1 sibling, 0 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-08 18:54 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov It makes qemu compatible with binfmt_misc's flags 'P' and 'O'. 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the original argv[0] with the full path to the binary. When this flag is included, binfmt_misc will add an argument to the argument vector for this purpose, thus preserving the original argv[0]. 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path of the binary to the interpreter as an argument. When this flag is included, binfmt_misc will open the file for reading and pass its descriptor as an argument, instead of the full path, thus allowing the interpreter to execute non-readable binaries. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- configure | 86 ++++++++++++++++++++++++++---------------------- linux-user/linuxload.c | 7 +--- linux-user/main.c | 39 ++++++++++++++++++++- linux-user/qemu.h | 2 +- 4 files changed, 87 insertions(+), 47 deletions(-) diff --git a/configure b/configure index 9192fcf..c58ae9c 100755 --- a/configure +++ b/configure @@ -115,6 +115,7 @@ mixemu="no" bluez="yes" signalfd="no" eventfd="no" +binfmt_misc="no" # OS specific targetos=`uname -s` @@ -351,6 +352,8 @@ for opt do ;; --disable-aio) aio="no" ;; + --enable-binfmt-misc) binfmt_misc="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -455,6 +458,7 @@ echo " --enable-uname-release=R Return R for uname -r in usermode emulation" echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9" echo " --disable-vde disable support for vde network" echo " --disable-aio disable AIO support" +echo " --enable-binfmt-misc makes usermode compatible with binfmt_misc's flags 'P' and 'O'" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -981,55 +985,56 @@ else binsuffix="/bin" fi -echo "Install prefix $prefix" -echo "BIOS directory $prefix$datasuffix" -echo "binary directory $prefix$binsuffix" +echo "Install prefix $prefix" +echo "BIOS directory $prefix$datasuffix" +echo "binary directory $prefix$binsuffix" if test "$mingw32" = "no" ; then -echo "Manual directory $prefix$mansuffix" -echo "ELF interp prefix $interp_prefix" -fi -echo "Source path $source_path" -echo "C compiler $cc" -echo "Host C compiler $host_cc" -echo "ARCH_CFLAGS $ARCH_CFLAGS" -echo "make $make" -echo "install $install" -echo "host CPU $cpu" -echo "host big endian $bigendian" -echo "target list $target_list" -echo "gprof enabled $gprof" -echo "sparse enabled $sparse" -echo "profiler $profiler" -echo "static build $static" -echo "-Werror enabled $werror" +echo "Manual directory $prefix$mansuffix" +echo "ELF interp prefix $interp_prefix" +fi +echo "Source path $source_path" +echo "C compiler $cc" +echo "Host C compiler $host_cc" +echo "ARCH_CFLAGS $ARCH_CFLAGS" +echo "make $make" +echo "install $install" +echo "host CPU $cpu" +echo "host big endian $bigendian" +echo "target list $target_list" +echo "gprof enabled $gprof" +echo "sparse enabled $sparse" +echo "profiler $profiler" +echo "static build $static" +echo "-Werror enabled $werror" if test "$darwin" = "yes" ; then - echo "Cocoa support $cocoa" + echo "Cocoa support $cocoa" fi echo "SDL support $sdl" if test "$sdl" != "no" ; then - echo "SDL static link $sdl_static" -fi -echo "curses support $curses" -echo "mingw32 support $mingw32" -echo "Audio drivers $audio_drv_list" -echo "Extra audio cards $audio_card_list" -echo "Mixer emulation $mixemu" -echo "VNC TLS support $vnc_tls" + echo "SDL static link $sdl_static" +fi +echo "curses support $curses" +echo "mingw32 support $mingw32" +echo "Audio drivers $audio_drv_list" +echo "Extra audio cards $audio_card_list" +echo "Mixer emulation $mixemu" +echo "VNC TLS support $vnc_tls" if test "$vnc_tls" = "yes" ; then - echo " TLS CFLAGS $vnc_tls_cflags" - echo " TLS LIBS $vnc_tls_libs" + echo " TLS CFLAGS $vnc_tls_cflags" + echo " TLS LIBS $vnc_tls_libs" fi if test -n "$sparc_cpu"; then - echo "Target Sparc Arch $sparc_cpu" + echo "Target Sparc Arch $sparc_cpu" fi -echo "kqemu support $kqemu" -echo "brlapi support $brlapi" -echo "Documentation $build_docs" +echo "kqemu support $kqemu" +echo "brlapi support $brlapi" +echo "Documentation $build_docs" [ ! -z "$uname_release" ] && \ -echo "uname -r $uname_release" -echo "NPTL support $nptl" -echo "vde support $vde" -echo "AIO support $aio" +echo "uname -r $uname_release" +echo "NPTL support $nptl" +echo "vde support $vde" +echo "AIO support $aio" +echo "binfmt_misc support $binfmt_misc" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -1592,6 +1597,9 @@ if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h fi +if test "$target_user_only" = "yes" -a "$binfmt_misc" = "yes"; then + echo "#define BINFMT_MISC 1" >> $config_h +fi test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index ada7c69..cbd90f7 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -154,7 +154,7 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, return sp; } -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop) { struct linux_binprm bprm; @@ -164,10 +164,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; - retval = open(filename, O_RDONLY); - if (retval < 0) - return retval; - bprm.fd = retval; + bprm.fd = fd; bprm.filename = (char *)filename; bprm.argc = count(argv); bprm.argv = argv; diff --git a/linux-user/main.c b/linux-user/main.c index fef4bf7..25b2867 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -26,6 +26,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "elf.h" /* For tb_lock */ #include "exec-all.h" @@ -2217,9 +2218,10 @@ void init_task_state(TaskState *ts) ts->sigqueue_table[i].next = NULL; } -int main(int argc, char **argv) +int main(int argc, char **argv, char **envp) { const char *filename; + int fd = -1; const char *cpu_model; struct target_pt_regs regs1, *regs = ®s1; struct image_info info1, *info = &info1; @@ -2380,7 +2382,40 @@ int main(int argc, char **argv) } *dst = NULL; /* NULL terminate target_environ */ - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { +#ifdef BINFMT_MISC +#if HOST_LONG_BITS == 32 +#define Elf_Dyn Elf32_Dyn +#else +#define Elf_Dyn Elf64_Dyn +#endif + { + Elf_Dyn *auxv; + + optind++; /* Handle binfmt_misc's option 'P' */ + + /* Handle binfmt_misc's option 'O' */ + while(*envp++ != NULL); /* skip envp. we are on auxv now */ + for(auxv = (Elf_Dyn *)envp; auxv->d_tag != AT_NULL; auxv++) { + if( auxv->d_tag == AT_EXECFD) { + fd = auxv->d_un.d_val; + break; + } + } + + if (fd < 0) { + printf("Cannot find binary file descriptor\n"); + _exit(1); + } + } +#else + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("Cannot open file %s: %s\n", filename, strerror(errno)); + _exit(1); + } +#endif + + if (loader_exec(fd, filename, argv+optind, target_environ, regs, info) != 0) { printf("Error loading %s\n", filename); _exit(1); } diff --git a/linux-user/qemu.h b/linux-user/qemu.h index a2abe51..52835ec 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -168,7 +168,7 @@ struct linux_binprm { void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop); int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH, v2] Fix fstatat64()/newfstatat() syscall implementation 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov @ 2008-10-09 17:40 ` Kirill A. Shutemov 1 sibling, 0 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-09 17:40 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov There are two different syscall names for the same goal. On systems with sizeof(long) == 64 it calls newfstatat. On systems with sizeof(long) == 32 it calls fstatat64. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 29 +++++++++++++++++++++++++---- 1 files changed, 25 insertions(+), 4 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c85fea4..3fa205f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -165,6 +165,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_linkat __NR_linkat #define __NR_sys_mkdirat __NR_mkdirat #define __NR_sys_mknodat __NR_mknodat +#define __NR_sys_newfstatat __NR_newfstatat #define __NR_sys_openat __NR_openat #define __NR_sys_readlinkat __NR_readlinkat #define __NR_sys_renameat __NR_renameat @@ -205,7 +206,8 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, uid_t,owner,gid_t,group,int,flags) #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + defined(__NR_fstatat64) _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname, struct stat *,buf,int,flags) #endif @@ -236,6 +238,11 @@ _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode) _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname, mode_t,mode,dev_t,dev) #endif +#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \ + defined(__NR_newfstatat) +_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname, + struct stat *,buf,int,flags) +#endif #if defined(TARGET_NR_openat) && defined(__NR_openat) _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode) #endif @@ -3481,7 +3488,7 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr, return 0; } -#ifdef TARGET_NR_stat64 +#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat) static inline abi_long host_to_target_stat64(void *cpu_env, abi_ulong target_addr, struct stat *host_st) @@ -3513,11 +3520,15 @@ static inline abi_long host_to_target_stat64(void *cpu_env, } else #endif { +#if TARGET_LONG_BITS == 64 + struct target_stat *target_st; +#else struct target_stat64 *target_st; +#endif if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) return -TARGET_EFAULT; - memset(target_st, 0, sizeof(struct target_stat64)); + memset(target_st, 0, sizeof(*target_st)); __put_user(host_st->st_dev, &target_st->st_dev); __put_user(host_st->st_ino, &target_st->st_ino); #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO @@ -5645,11 +5656,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = host_to_target_stat64(cpu_env, arg2, &st); break; #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + (defined(__NR_fstatat64) || defined(__NR_newfstatat)) +#ifdef TARGET_NR_fstatat64 case TARGET_NR_fstatat64: +#endif +#ifdef TARGET_NR_newfstatat + case TARGET_NR_newfstatat: +#endif if (!(p = lock_user_string(arg2))) goto efault; +#ifdef __NR_fstatat64 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4)); +#else + ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4)); +#endif if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg3, &st); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH, v2] Implement sem* syscalls 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov @ 2008-10-09 17:42 ` Kirill A. Shutemov 1 sibling, 0 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-09 17:42 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1852f35..1a09d90 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4906,7 +4906,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif - +#ifdef TARGET_NR_semget + case TARGET_NR_semget: + ret = get_errno(semget(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semop + case TARGET_NR_semop: + ret = get_errno(do_semop(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semctl + case TARGET_NR_semctl: + ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4); + break; +#endif #ifdef TARGET_NR_msgctl case TARGET_NR_msgctl: ret = do_msgctl(arg1, arg2, arg3); -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH, v2] Fix and cleanup IPCOP_sem* ipc calls handling 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov @ 2008-10-09 17:41 ` Kirill A. Shutemov 1 sibling, 0 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-09 17:41 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 319 +++++++++++++++++++++++++++++++------------------- 1 files changed, 198 insertions(+), 121 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cf0834f..1852f35 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1635,14 +1635,14 @@ struct target_ipc_perm struct target_semid_ds { - struct target_ipc_perm sem_perm; - abi_ulong sem_otime; - abi_ulong __unused1; - abi_ulong sem_ctime; - abi_ulong __unused2; - abi_ulong sem_nsems; - abi_ulong __unused3; - abi_ulong __unused4; + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong __unused1; + abi_ulong sem_ctime; + abi_ulong __unused2; + abi_ulong sem_nsems; + abi_ulong __unused3; + abi_ulong __unused4; }; static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, @@ -1690,7 +1690,8 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) return -TARGET_EFAULT; - target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); + if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) + return -TARGET_EFAULT; host_sd->sem_nsems = tswapl(target_sd->sem_nsems); host_sd->sem_otime = tswapl(target_sd->sem_otime); host_sd->sem_ctime = tswapl(target_sd->sem_ctime); @@ -1705,7 +1706,8 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) return -TARGET_EFAULT; - host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); + if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) + return -TARGET_EFAULT;; target_sd->sem_nsems = tswapl(host_sd->sem_nsems); target_sd->sem_otime = tswapl(host_sd->sem_otime); target_sd->sem_ctime = tswapl(host_sd->sem_ctime); @@ -1713,135 +1715,215 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, return 0; } +struct target_seminfo { + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +static inline abi_long host_to_target_seminfo(abi_ulong target_addr, + struct seminfo *host_seminfo) +{ + struct target_seminfo *target_seminfo; + if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_seminfo->semmap, &target_seminfo->semmap); + __put_user(host_seminfo->semmni, &target_seminfo->semmni); + __put_user(host_seminfo->semmns, &target_seminfo->semmns); + __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); + __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); + __put_user(host_seminfo->semopm, &target_seminfo->semopm); + __put_user(host_seminfo->semume, &target_seminfo->semume); + __put_user(host_seminfo->semusz, &target_seminfo->semusz); + __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); + __put_user(host_seminfo->semaem, &target_seminfo->semaem); + unlock_user_struct(target_seminfo, target_addr, 1); + return 0; +} + union semun { - int val; - struct semid_ds *buf; - unsigned short *array; + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; }; union target_semun { - int val; - abi_long buf; - unsigned short int *array; + int val; + abi_ulong buf; + abi_ulong array; + abi_ulong __buf; }; -static inline abi_long target_to_host_semun(int cmd, - union semun *host_su, - abi_ulong target_addr, - struct semid_ds *ds) +static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, + abi_ulong target_addr) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - target_to_host_semid_ds(ds,target_su->buf); - host_su->buf = ds; - unlock_user_struct(target_su, target_addr, 0); - break; - case GETVAL: - case SETVAL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - host_su->val = tswapl(target_su->val); - unlock_user_struct(target_su, target_addr, 0); - break; - case GETALL: - case SETALL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - *host_su->array = tswap16(*target_su->array); - unlock_user_struct(target_su, target_addr, 0); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + *host_array = malloc(nsems*sizeof(unsigned short)); + array = lock_user(VERIFY_READ, target_addr, + nsems*sizeof(unsigned short), 1); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __get_user((*host_array)[i], &array[i]); } + unlock_user(array, target_addr, 0); + return 0; } -static inline abi_long host_to_target_semun(int cmd, - abi_ulong target_addr, - union semun *host_su, - struct semid_ds *ds) +static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - host_to_target_semid_ds(target_su->buf,ds); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETVAL: - case SETVAL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - target_su->val = tswapl(host_su->val); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETALL: - case SETALL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - *target_su->array = tswap16(*host_su->array); - unlock_user_struct(target_su, target_addr, 1); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + array = lock_user(VERIFY_WRITE, target_addr, + nsems*sizeof(unsigned short), 0); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __put_user((*host_array)[i], &array[i]); } + free(*host_array); + unlock_user(array, target_addr, 1); + return 0; } -static inline abi_long do_semctl(int first, int second, int third, - abi_long ptr) +static inline abi_long do_semctl(int semid, int semnum, int cmd, + union target_semun target_su) { union semun arg; struct semid_ds dsarg; - int cmd = third&0xff; - abi_long ret = 0; + unsigned short *array; + struct seminfo seminfo; + abi_long ret = -TARGET_EINVAL; + abi_long err; - switch( cmd ) { - case GETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case GETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_STAT: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_SET: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - default: - ret = get_errno(semctl(first, second, cmd, arg)); + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + case SEM_STAT: + err = target_to_host_semid_ds(&dsarg, target_su.buf); + if (err) + return err; + arg.buf = &dsarg; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semid_ds(target_su.buf, &dsarg); + if (err) + return err; + break; + case GETVAL: + case SETVAL: + arg.val = tswapl(target_su.val); + ret = get_errno(semctl(semid, semnum, cmd, arg)); + target_su.val = tswapl(arg.val); + break; + case GETALL: + case SETALL: + err = target_to_host_semarray(semid, &array, target_su.array); + if (err) + return err; + arg.array = array; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semarray(semid, target_su.array, &array); + if (err) + return err; + break; + case IPC_INFO: + case SEM_INFO: + arg.__buf = &seminfo; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_seminfo(target_su.__buf, &seminfo); + if (err) + return err; + break; + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + ret = get_errno(semctl(semid, semnum, cmd, NULL)); + break; } return ret; } +struct target_sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; +}; + +static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, + abi_ulong target_addr, + unsigned nsops) +{ + struct target_sembuf *target_sembuf; + int i; + + target_sembuf = lock_user(VERIFY_READ, target_addr, + nsops*sizeof(struct target_sembuf), 1); + if (!target_sembuf) + return -TARGET_EFAULT; + + for(i=0; i<nsops; i++) { + __put_user(target_sembuf[i].sem_num, &host_sembuf[i].sem_num); + __put_user(target_sembuf[i].sem_op, &host_sembuf[i].sem_op); + __put_user(target_sembuf[i].sem_flg, &host_sembuf[i].sem_flg); + } + + unlock_user(target_sembuf, target_addr, 0); + + return 0; +} + +static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +{ + struct sembuf sops[nsops]; + + if (target_to_host_sembuf(sops, ptr, nsops)) + return -TARGET_EFAULT; + + return semop(semid, sops, nsops); +} + struct target_msqid_ds { struct target_ipc_perm msg_perm; @@ -2044,7 +2126,7 @@ static abi_long do_ipc(unsigned int call, int first, switch (call) { case IPCOP_semop: - ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second)); + ret = do_semop(first, ptr, second); break; case IPCOP_semget: @@ -2052,12 +2134,7 @@ static abi_long do_ipc(unsigned int call, int first, break; case IPCOP_semctl: - ret = do_semctl(first, second, third, ptr); - break; - - case IPCOP_semtimedop: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; + ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr); break; case IPCOP_msgget: -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] Fix getdents* syscalls 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov @ 2008-10-13 21:09 ` Aurelien Jarno 1 sibling, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2008-10-13 21:09 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Applied, thanks. On Wed, Oct 08, 2008 at 09:54:26PM +0300, Kirill A. Shutemov wrote: > glibc's structs dirent and dirent64 is different from in-kernel dirent > and dirent64. Kernel headers doesn't provide structs dirent(64) any > more. So we should add it to qemu headers. > > To avoid conflict with glibc it called struct linux_dirent(64). > > Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> > --- > linux-user/syscall.c | 27 +++++++++++++-------------- > linux-user/syscall_defs.h | 15 +++++++++++++++ > 2 files changed, 28 insertions(+), 14 deletions(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index dc7e561..40e985a 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -28,7 +28,6 @@ > #include <fcntl.h> > #include <time.h> > #include <limits.h> > -#include <dirent.h> > #include <sys/types.h> > #include <sys/ipc.h> > #include <sys/msg.h> > @@ -94,8 +93,8 @@ > #endif > > //#include <linux/msdos_fs.h> > -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) > -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) > +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2]) > +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2]) > > > #undef _syscall0 > @@ -216,10 +215,10 @@ _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname, > #endif > _syscall2(int,sys_getcwd1,char *,buf,size_t,size) > #if TARGET_ABI_BITS == 32 > -_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count); > +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); > #endif > #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) > -_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count); > +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); > #endif > _syscall2(int, sys_getpriority, int, which, int, who); > #if !defined (__x86_64__) > @@ -4879,7 +4878,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 > { > struct target_dirent *target_dirp; > - struct dirent *dirp; > + struct linux_dirent *dirp; > abi_long count = arg3; > > dirp = malloc(count); > @@ -4890,7 +4889,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > > ret = get_errno(sys_getdents(arg1, dirp, count)); > if (!is_error(ret)) { > - struct dirent *de; > + struct linux_dirent *de; > struct target_dirent *tde; > int len = ret; > int reclen, treclen; > @@ -4912,7 +4911,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > tnamelen = 256; > /* XXX: may not be correct */ > strncpy(tde->d_name, de->d_name, tnamelen); > - de = (struct dirent *)((char *)de + reclen); > + de = (struct linux_dirent *)((char *)de + reclen); > len -= reclen; > tde = (struct target_dirent *)((char *)tde + treclen); > count1 += treclen; > @@ -4924,14 +4923,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > } > #else > { > - struct dirent *dirp; > + struct linux_dirent *dirp; > abi_long count = arg3; > > if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) > goto efault; > ret = get_errno(sys_getdents(arg1, dirp, count)); > if (!is_error(ret)) { > - struct dirent *de; > + struct linux_dirent *de; > int len = ret; > int reclen; > de = dirp; > @@ -4942,7 +4941,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > de->d_reclen = tswap16(reclen); > tswapls(&de->d_ino); > tswapls(&de->d_off); > - de = (struct dirent *)((char *)de + reclen); > + de = (struct linux_dirent *)((char *)de + reclen); > len -= reclen; > } > } > @@ -4953,13 +4952,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) > case TARGET_NR_getdents64: > { > - struct dirent64 *dirp; > + struct linux_dirent64 *dirp; > abi_long count = arg3; > if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) > goto efault; > ret = get_errno(sys_getdents64(arg1, dirp, count)); > if (!is_error(ret)) { > - struct dirent64 *de; > + struct linux_dirent64 *de; > int len = ret; > int reclen; > de = dirp; > @@ -4970,7 +4969,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > de->d_reclen = tswap16(reclen); > tswap64s((uint64_t *)&de->d_ino); > tswap64s((uint64_t *)&de->d_off); > - de = (struct dirent64 *)((char *)de + reclen); > + de = (struct linux_dirent64 *)((char *)de + reclen); > len -= reclen; > } > } > diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h > index c30bb15..5a58010 100644 > --- a/linux-user/syscall_defs.h > +++ b/linux-user/syscall_defs.h > @@ -1963,6 +1963,21 @@ struct target_sysinfo { > char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ > }; > > +struct linux_dirent { > + long d_ino; > + unsigned long d_off; > + unsigned short d_reclen; > + char d_name[256]; /* We must not include limits.h! */ > +}; > + > +struct linux_dirent64 { > + uint64_t d_ino; > + int64_t d_off; > + unsigned short d_reclen; > + unsigned char d_type; > + char d_name[256]; > +}; > + > #include "socket.h" > > #include "errno_defs.h" > -- > 1.5.6.5.GIT > > > > -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] Add readahead syscall 2008-10-08 18:54 [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov @ 2008-10-13 21:09 ` Aurelien Jarno 1 sibling, 0 replies; 18+ messages in thread From: Aurelien Jarno @ 2008-10-13 21:09 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov Applied, thanks. On Wed, Oct 08, 2008 at 09:54:25PM +0300, Kirill A. Shutemov wrote: > Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> > --- > linux-user/syscall.c | 15 ++++++++++++++- > 1 files changed, 14 insertions(+), 1 deletions(-) > > diff --git a/linux-user/syscall.c b/linux-user/syscall.c > index f1f050e..dc7e561 100644 > --- a/linux-user/syscall.c > +++ b/linux-user/syscall.c > @@ -5761,7 +5761,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, > break; > #ifdef TARGET_NR_readahead > case TARGET_NR_readahead: > - goto unimplemented; > +#if TARGET_ABI_BITS == 32 > +#ifdef TARGET_ARM > + if (((CPUARMState *)cpu_env)->eabi) > + { > + arg2 = arg3; > + arg3 = arg4; > + arg4 = arg5; > + } > +#endif > + ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4)); > +#else > + ret = get_errno(readahead(arg1, arg2, arg3)); > +#endif > + break; > #endif > #ifdef TARGET_NR_setxattr > case TARGET_NR_setxattr: > -- > 1.5.6.5.GIT > > > > -- .''`. Aurelien Jarno | GPG: 1024D/F1BCDB73 : :' : Debian developer | Electrical Engineer `. `' aurel32@debian.org | aurelien@aurel32.net `- people.debian.org/~aurel32 | www.aurel32.net ^ permalink raw reply [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Add readahead syscall @ 2008-10-13 10:10 Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 15 ++++++++++++++- 1 files changed, 14 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index f1f050e..dc7e561 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5761,7 +5761,20 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, break; #ifdef TARGET_NR_readahead case TARGET_NR_readahead: - goto unimplemented; +#if TARGET_ABI_BITS == 32 +#ifdef TARGET_ARM + if (((CPUARMState *)cpu_env)->eabi) + { + arg2 = arg3; + arg3 = arg4; + arg4 = arg5; + } +#endif + ret = get_errno(readahead(arg1, ((off64_t)arg3 << 32) | arg2, arg4)); +#else + ret = get_errno(readahead(arg1, arg2, arg3)); +#endif + break; #endif #ifdef TARGET_NR_setxattr case TARGET_NR_setxattr: -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix getdents* syscalls 2008-10-13 10:10 Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook glibc's structs dirent and dirent64 is different from in-kernel dirent and dirent64. Kernel headers doesn't provide structs dirent(64) any more. So we should add it to qemu headers. To avoid conflict with glibc it called struct linux_dirent(64). Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 27 +++++++++++++-------------- linux-user/syscall_defs.h | 15 +++++++++++++++ 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index dc7e561..40e985a 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -28,7 +28,6 @@ #include <fcntl.h> #include <time.h> #include <limits.h> -#include <dirent.h> #include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> @@ -94,8 +93,8 @@ #endif //#include <linux/msdos_fs.h> -#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct dirent [2]) -#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct dirent [2]) +#define VFAT_IOCTL_READDIR_BOTH _IOR('r', 1, struct linux_dirent [2]) +#define VFAT_IOCTL_READDIR_SHORT _IOR('r', 2, struct linux_dirent [2]) #undef _syscall0 @@ -216,10 +215,10 @@ _syscall3(int,sys_futimesat,int,dirfd,const char *,pathname, #endif _syscall2(int,sys_getcwd1,char *,buf,size_t,size) #if TARGET_ABI_BITS == 32 -_syscall3(int, sys_getdents, uint, fd, struct dirent *, dirp, uint, count); +_syscall3(int, sys_getdents, uint, fd, struct linux_dirent *, dirp, uint, count); #endif #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) -_syscall3(int, sys_getdents64, uint, fd, struct dirent64 *, dirp, uint, count); +_syscall3(int, sys_getdents64, uint, fd, struct linux_dirent64 *, dirp, uint, count); #endif _syscall2(int, sys_getpriority, int, which, int, who); #if !defined (__x86_64__) @@ -4879,7 +4878,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #elif TARGET_ABI_BITS == 32 && HOST_LONG_BITS == 64 { struct target_dirent *target_dirp; - struct dirent *dirp; + struct linux_dirent *dirp; abi_long count = arg3; dirp = malloc(count); @@ -4890,7 +4889,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = get_errno(sys_getdents(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent *de; + struct linux_dirent *de; struct target_dirent *tde; int len = ret; int reclen, treclen; @@ -4912,7 +4911,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, tnamelen = 256; /* XXX: may not be correct */ strncpy(tde->d_name, de->d_name, tnamelen); - de = (struct dirent *)((char *)de + reclen); + de = (struct linux_dirent *)((char *)de + reclen); len -= reclen; tde = (struct target_dirent *)((char *)tde + treclen); count1 += treclen; @@ -4924,14 +4923,14 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, } #else { - struct dirent *dirp; + struct linux_dirent *dirp; abi_long count = arg3; if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) goto efault; ret = get_errno(sys_getdents(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent *de; + struct linux_dirent *de; int len = ret; int reclen; de = dirp; @@ -4942,7 +4941,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, de->d_reclen = tswap16(reclen); tswapls(&de->d_ino); tswapls(&de->d_off); - de = (struct dirent *)((char *)de + reclen); + de = (struct linux_dirent *)((char *)de + reclen); len -= reclen; } } @@ -4953,13 +4952,13 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, #if defined(TARGET_NR_getdents64) && defined(__NR_getdents64) case TARGET_NR_getdents64: { - struct dirent64 *dirp; + struct linux_dirent64 *dirp; abi_long count = arg3; if (!(dirp = lock_user(VERIFY_WRITE, arg2, count, 0))) goto efault; ret = get_errno(sys_getdents64(arg1, dirp, count)); if (!is_error(ret)) { - struct dirent64 *de; + struct linux_dirent64 *de; int len = ret; int reclen; de = dirp; @@ -4970,7 +4969,7 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, de->d_reclen = tswap16(reclen); tswap64s((uint64_t *)&de->d_ino); tswap64s((uint64_t *)&de->d_off); - de = (struct dirent64 *)((char *)de + reclen); + de = (struct linux_dirent64 *)((char *)de + reclen); len -= reclen; } } diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h index c30bb15..5a58010 100644 --- a/linux-user/syscall_defs.h +++ b/linux-user/syscall_defs.h @@ -1963,6 +1963,21 @@ struct target_sysinfo { char _f[20-2*sizeof(abi_long)-sizeof(int)]; /* Padding: libc5 uses this.. */ }; +struct linux_dirent { + long d_ino; + unsigned long d_off; + unsigned short d_reclen; + char d_name[256]; /* We must not include limits.h! */ +}; + +struct linux_dirent64 { + uint64_t d_ino; + int64_t d_off; + unsigned short d_reclen; + unsigned char d_type; + char d_name[256]; +}; + #include "socket.h" #include "errno_defs.h" -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 173 ++++++++++++++++++++++++++++++++++---------------- 1 files changed, 117 insertions(+), 56 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 40e985a..7e67093 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1611,7 +1611,6 @@ static abi_long do_socketcall(int num, abi_ulong vptr) } #endif -#ifdef TARGET_NR_ipc #define N_SHM_REGIONS 32 static struct shm_region { @@ -1845,20 +1844,26 @@ static inline abi_long do_semctl(int first, int second, int third, struct target_msqid_ds { - struct target_ipc_perm msg_perm; - abi_ulong msg_stime; - abi_ulong __unused1; - abi_ulong msg_rtime; - abi_ulong __unused2; - abi_ulong msg_ctime; - abi_ulong __unused3; - abi_ulong __msg_cbytes; - abi_ulong msg_qnum; - abi_ulong msg_qbytes; - abi_ulong msg_lspid; - abi_ulong msg_lrpid; - abi_ulong __unused4; - abi_ulong __unused5; + struct target_ipc_perm msg_perm; + abi_ulong msg_stime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong msg_rtime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong msg_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + abi_ulong __msg_cbytes; + abi_ulong msg_qnum; + abi_ulong msg_qbytes; + abi_ulong msg_lspid; + abi_ulong msg_lrpid; + abi_ulong __unused4; + abi_ulong __unused5; }; static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, @@ -1868,7 +1873,8 @@ static inline abi_long target_to_host_msqid_ds(struct msqid_ds *host_md, if (!lock_user_struct(VERIFY_READ, target_md, target_addr, 1)) return -TARGET_EFAULT; - target_to_host_ipc_perm(&(host_md->msg_perm),target_addr); + if (target_to_host_ipc_perm(&(host_md->msg_perm),target_addr)) + return -TARGET_EFAULT; host_md->msg_stime = tswapl(target_md->msg_stime); host_md->msg_rtime = tswapl(target_md->msg_rtime); host_md->msg_ctime = tswapl(target_md->msg_ctime); @@ -1888,7 +1894,8 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, if (!lock_user_struct(VERIFY_WRITE, target_md, target_addr, 0)) return -TARGET_EFAULT; - host_to_target_ipc_perm(target_addr,&(host_md->msg_perm)); + if (host_to_target_ipc_perm(target_addr,&(host_md->msg_perm))) + return -TARGET_EFAULT; target_md->msg_stime = tswapl(host_md->msg_stime); target_md->msg_rtime = tswapl(host_md->msg_rtime); target_md->msg_ctime = tswapl(host_md->msg_ctime); @@ -1901,26 +1908,69 @@ static inline abi_long host_to_target_msqid_ds(abi_ulong target_addr, return 0; } -static inline abi_long do_msgctl(int first, int second, abi_long ptr) +struct target_msginfo { + int msgpool; + int msgmap; + int msgmax; + int msgmnb; + int msgmni; + int msgssz; + int msgtql; + unsigned short int msgseg; +}; + +static inline abi_long host_to_target_msginfo(abi_ulong target_addr, + struct msginfo *host_msginfo) +{ + struct target_msginfo *target_msginfo; + if (!lock_user_struct(VERIFY_WRITE, target_msginfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_msginfo->msgpool, &target_msginfo->msgpool); + __put_user(host_msginfo->msgmap, &target_msginfo->msgmap); + __put_user(host_msginfo->msgmax, &target_msginfo->msgmax); + __put_user(host_msginfo->msgmnb, &target_msginfo->msgmnb); + __put_user(host_msginfo->msgmni, &target_msginfo->msgmni); + __put_user(host_msginfo->msgssz, &target_msginfo->msgssz); + __put_user(host_msginfo->msgtql, &target_msginfo->msgtql); + __put_user(host_msginfo->msgseg, &target_msginfo->msgseg); + unlock_user_struct(target_msginfo, target_addr, 1); +} + +static inline abi_long do_msgctl(int msgid, int cmd, abi_long ptr) { struct msqid_ds dsarg; - int cmd = second&0xff; - abi_long ret = 0; - switch( cmd ) { + struct msginfo msginfo; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch (cmd) { case IPC_STAT: case IPC_SET: - target_to_host_msqid_ds(&dsarg,ptr); - ret = get_errno(msgctl(first, cmd, &dsarg)); - host_to_target_msqid_ds(ptr,&dsarg); - default: - ret = get_errno(msgctl(first, cmd, &dsarg)); + case MSG_STAT: + if (target_to_host_msqid_ds(&dsarg,ptr)) + return -TARGET_EFAULT; + ret = get_errno(msgctl(msgid, cmd, &dsarg)); + if (host_to_target_msqid_ds(ptr,&dsarg)) + return -TARGET_EFAULT; + break; + case IPC_RMID: + ret = get_errno(msgctl(msgid, cmd, NULL)); + break; + case IPC_INFO: + case MSG_INFO: + ret = get_errno(msgctl(msgid, cmd, (struct msqid_ds *)&msginfo)); + if (host_to_target_msginfo(ptr, &msginfo)) + return -TARGET_EFAULT; + break; } + return ret; } struct target_msgbuf { - abi_ulong mtype; - char mtext[1]; + abi_long mtype; + char mtext[1]; }; static inline abi_long do_msgsnd(int msqid, abi_long msgp, @@ -1933,8 +1983,8 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_READ, target_mb, msgp, 0)) return -TARGET_EFAULT; host_mb = malloc(msgsz+sizeof(long)); - host_mb->mtype = tswapl(target_mb->mtype); - memcpy(host_mb->mtext,target_mb->mtext,msgsz); + host_mb->mtype = (abi_long) tswapl(target_mb->mtype); + memcpy(host_mb->mtext, target_mb->mtext, msgsz); ret = get_errno(msgsnd(msqid, host_mb, msgsz, msgflg)); free(host_mb); unlock_user_struct(target_mb, msgp, 0); @@ -1943,7 +1993,7 @@ static inline abi_long do_msgsnd(int msqid, abi_long msgp, } static inline abi_long do_msgrcv(int msqid, abi_long msgp, - unsigned int msgsz, int msgtype, + unsigned int msgsz, abi_long msgtyp, int msgflg) { struct target_msgbuf *target_mb; @@ -1953,8 +2003,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, if (!lock_user_struct(VERIFY_WRITE, target_mb, msgp, 0)) return -TARGET_EFAULT; + host_mb = malloc(msgsz+sizeof(long)); - ret = get_errno(msgrcv(msqid, host_mb, msgsz, 1, msgflg)); + ret = get_errno(msgrcv(msqid, host_mb, msgsz, tswapl(msgtyp), msgflg)); + if (ret > 0) { abi_ulong target_mtext_addr = msgp + sizeof(abi_ulong); target_mtext = lock_user(VERIFY_WRITE, target_mtext_addr, ret, 0); @@ -1962,9 +2014,10 @@ static inline abi_long do_msgrcv(int msqid, abi_long msgp, ret = -TARGET_EFAULT; goto end; } - memcpy(target_mb->mtext, host_mb->mtext, ret); + memcpy(target_mb->mtext, host_mb->mtext, ret); unlock_user(target_mtext, target_mtext_addr, ret); } + target_mb->mtype = tswapl(host_mb->mtype); free(host_mb); @@ -1974,6 +2027,7 @@ end: return ret; } +#ifdef TARGET_NR_ipc /* ??? This only works with linear mappings. */ /* do_ipc() must return target values and target errnos. */ static abi_long do_ipc(unsigned int call, int first, @@ -2006,34 +2060,41 @@ static abi_long do_ipc(unsigned int call, int first, ret = -TARGET_ENOSYS; break; - case IPCOP_msgget: - ret = get_errno(msgget(first, second)); - break; + case IPCOP_msgget: + ret = get_errno(msgget(first, second)); + break; - case IPCOP_msgsnd: - ret = do_msgsnd(first, ptr, second, third); - break; + case IPCOP_msgsnd: + ret = do_msgsnd(first, ptr, second, third); + break; - case IPCOP_msgctl: - ret = do_msgctl(first, second, ptr); - break; + case IPCOP_msgctl: + ret = do_msgctl(first, second, ptr); + break; - case IPCOP_msgrcv: - { - /* XXX: this code is not correct */ - struct ipc_kludge - { - void *__unbounded msgp; - long int msgtyp; - }; + case IPCOP_msgrcv: + switch (version) { + case 0: + { + struct target_ipc_kludge { + abi_long msgp; + abi_long msgtyp; + } *tmp; - struct ipc_kludge *foo = (struct ipc_kludge *)g2h(ptr); - struct msgbuf *msgp = (struct msgbuf *) foo->msgp; + if (!lock_user_struct(VERIFY_READ, tmp, ptr, 1)) { + ret = -TARGET_EFAULT; + break; + } - ret = do_msgrcv(first, (long)msgp, second, 0, third); + ret = do_msgrcv(first, tmp->msgp, second, tmp->msgtyp, third); - } - break; + unlock_user_struct(tmp, ptr, 0); + break; + } + default: + ret = do_msgrcv(first, ptr, second, fifth, third); + } + break; case IPCOP_shmat: { -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement msg* syscalls 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 21 +++++++++++++++++++++ 1 files changed, 21 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 7e67093..cf0834f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4829,6 +4829,27 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif + +#ifdef TARGET_NR_msgctl + case TARGET_NR_msgctl: + ret = do_msgctl(arg1, arg2, arg3); + break; +#endif +#ifdef TARGET_NR_msgget + case TARGET_NR_msgget: + ret = get_errno(msgget(arg1, arg2)); + break; +#endif +#ifdef TARGET_NR_msgrcv + case TARGET_NR_msgrcv: + ret = do_msgrcv(arg1, arg2, arg3, arg4, arg5); + break; +#endif +#ifdef TARGET_NR_msgsnd + case TARGET_NR_msgsnd: + ret = do_msgsnd(arg1, arg2, arg3, arg4); + break; +#endif case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 319 +++++++++++++++++++++++++++++++------------------- 1 files changed, 198 insertions(+), 121 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index cf0834f..1852f35 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1635,14 +1635,14 @@ struct target_ipc_perm struct target_semid_ds { - struct target_ipc_perm sem_perm; - abi_ulong sem_otime; - abi_ulong __unused1; - abi_ulong sem_ctime; - abi_ulong __unused2; - abi_ulong sem_nsems; - abi_ulong __unused3; - abi_ulong __unused4; + struct target_ipc_perm sem_perm; + abi_ulong sem_otime; + abi_ulong __unused1; + abi_ulong sem_ctime; + abi_ulong __unused2; + abi_ulong sem_nsems; + abi_ulong __unused3; + abi_ulong __unused4; }; static inline abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip, @@ -1690,7 +1690,8 @@ static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd, if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) return -TARGET_EFAULT; - target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr); + if (target_to_host_ipc_perm(&(host_sd->sem_perm),target_addr)) + return -TARGET_EFAULT; host_sd->sem_nsems = tswapl(target_sd->sem_nsems); host_sd->sem_otime = tswapl(target_sd->sem_otime); host_sd->sem_ctime = tswapl(target_sd->sem_ctime); @@ -1705,7 +1706,8 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) return -TARGET_EFAULT; - host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm)); + if (host_to_target_ipc_perm(target_addr,&(host_sd->sem_perm))) + return -TARGET_EFAULT;; target_sd->sem_nsems = tswapl(host_sd->sem_nsems); target_sd->sem_otime = tswapl(host_sd->sem_otime); target_sd->sem_ctime = tswapl(host_sd->sem_ctime); @@ -1713,135 +1715,215 @@ static inline abi_long host_to_target_semid_ds(abi_ulong target_addr, return 0; } +struct target_seminfo { + int semmap; + int semmni; + int semmns; + int semmnu; + int semmsl; + int semopm; + int semume; + int semusz; + int semvmx; + int semaem; +}; + +static inline abi_long host_to_target_seminfo(abi_ulong target_addr, + struct seminfo *host_seminfo) +{ + struct target_seminfo *target_seminfo; + if (!lock_user_struct(VERIFY_WRITE, target_seminfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_seminfo->semmap, &target_seminfo->semmap); + __put_user(host_seminfo->semmni, &target_seminfo->semmni); + __put_user(host_seminfo->semmns, &target_seminfo->semmns); + __put_user(host_seminfo->semmnu, &target_seminfo->semmnu); + __put_user(host_seminfo->semmsl, &target_seminfo->semmsl); + __put_user(host_seminfo->semopm, &target_seminfo->semopm); + __put_user(host_seminfo->semume, &target_seminfo->semume); + __put_user(host_seminfo->semusz, &target_seminfo->semusz); + __put_user(host_seminfo->semvmx, &target_seminfo->semvmx); + __put_user(host_seminfo->semaem, &target_seminfo->semaem); + unlock_user_struct(target_seminfo, target_addr, 1); + return 0; +} + union semun { - int val; - struct semid_ds *buf; - unsigned short *array; + int val; + struct semid_ds *buf; + unsigned short *array; + struct seminfo *__buf; }; union target_semun { - int val; - abi_long buf; - unsigned short int *array; + int val; + abi_ulong buf; + abi_ulong array; + abi_ulong __buf; }; -static inline abi_long target_to_host_semun(int cmd, - union semun *host_su, - abi_ulong target_addr, - struct semid_ds *ds) +static inline abi_long target_to_host_semarray(int semid, unsigned short **host_array, + abi_ulong target_addr) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - target_to_host_semid_ds(ds,target_su->buf); - host_su->buf = ds; - unlock_user_struct(target_su, target_addr, 0); - break; - case GETVAL: - case SETVAL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - host_su->val = tswapl(target_su->val); - unlock_user_struct(target_su, target_addr, 0); - break; - case GETALL: - case SETALL: - if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1)) - return -TARGET_EFAULT; - *host_su->array = tswap16(*target_su->array); - unlock_user_struct(target_su, target_addr, 0); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + *host_array = malloc(nsems*sizeof(unsigned short)); + array = lock_user(VERIFY_READ, target_addr, + nsems*sizeof(unsigned short), 1); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __get_user((*host_array)[i], &array[i]); } + unlock_user(array, target_addr, 0); + return 0; } -static inline abi_long host_to_target_semun(int cmd, - abi_ulong target_addr, - union semun *host_su, - struct semid_ds *ds) +static inline abi_long host_to_target_semarray(int semid, abi_ulong target_addr, + unsigned short **host_array) { - union target_semun *target_su; - - switch( cmd ) { - case IPC_STAT: - case IPC_SET: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - host_to_target_semid_ds(target_su->buf,ds); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETVAL: - case SETVAL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - target_su->val = tswapl(host_su->val); - unlock_user_struct(target_su, target_addr, 1); - break; - case GETALL: - case SETALL: - if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0)) - return -TARGET_EFAULT; - *target_su->array = tswap16(*host_su->array); - unlock_user_struct(target_su, target_addr, 1); - break; - default: - gemu_log("semun operation not fully supported: %d\n", (int)cmd); + int nsems; + unsigned short *array; + union semun semun; + struct semid_ds semid_ds; + int i, ret; + + semun.buf = &semid_ds; + + ret = semctl(semid, 0, IPC_STAT, semun); + if (ret == -1) + return get_errno(ret); + + nsems = semid_ds.sem_nsems; + + array = lock_user(VERIFY_WRITE, target_addr, + nsems*sizeof(unsigned short), 0); + if (!array) + return -TARGET_EFAULT; + + for(i=0; i<nsems; i++) { + __put_user((*host_array)[i], &array[i]); } + free(*host_array); + unlock_user(array, target_addr, 1); + return 0; } -static inline abi_long do_semctl(int first, int second, int third, - abi_long ptr) +static inline abi_long do_semctl(int semid, int semnum, int cmd, + union target_semun target_su) { union semun arg; struct semid_ds dsarg; - int cmd = third&0xff; - abi_long ret = 0; + unsigned short *array; + struct seminfo seminfo; + abi_long ret = -TARGET_EINVAL; + abi_long err; - switch( cmd ) { - case GETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETVAL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case GETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case SETALL: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_STAT: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - case IPC_SET: - target_to_host_semun(cmd,&arg,ptr,&dsarg); - ret = get_errno(semctl(first, second, cmd, arg)); - host_to_target_semun(cmd,ptr,&arg,&dsarg); - break; - default: - ret = get_errno(semctl(first, second, cmd, arg)); + cmd &= 0xff; + + switch (cmd) { + case IPC_STAT: + case IPC_SET: + case SEM_STAT: + err = target_to_host_semid_ds(&dsarg, target_su.buf); + if (err) + return err; + arg.buf = &dsarg; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semid_ds(target_su.buf, &dsarg); + if (err) + return err; + break; + case GETVAL: + case SETVAL: + arg.val = tswapl(target_su.val); + ret = get_errno(semctl(semid, semnum, cmd, arg)); + target_su.val = tswapl(arg.val); + break; + case GETALL: + case SETALL: + err = target_to_host_semarray(semid, &array, target_su.array); + if (err) + return err; + arg.array = array; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_semarray(semid, target_su.array, &array); + if (err) + return err; + break; + case IPC_INFO: + case SEM_INFO: + arg.__buf = &seminfo; + ret = get_errno(semctl(semid, semnum, cmd, arg)); + err = host_to_target_seminfo(target_su.__buf, &seminfo); + if (err) + return err; + break; + case IPC_RMID: + case GETPID: + case GETNCNT: + case GETZCNT: + ret = get_errno(semctl(semid, semnum, cmd, NULL)); + break; } return ret; } +struct target_sembuf { + unsigned short sem_num; + short sem_op; + short sem_flg; +}; + +static inline abi_long target_to_host_sembuf(struct sembuf *host_sembuf, + abi_ulong target_addr, + unsigned nsops) +{ + struct target_sembuf *target_sembuf; + int i; + + target_sembuf = lock_user(VERIFY_READ, target_addr, + nsops*sizeof(struct target_sembuf), 1); + if (!target_sembuf) + return -TARGET_EFAULT; + + for(i=0; i<nsops; i++) { + __put_user(target_sembuf[i].sem_num, &host_sembuf[i].sem_num); + __put_user(target_sembuf[i].sem_op, &host_sembuf[i].sem_op); + __put_user(target_sembuf[i].sem_flg, &host_sembuf[i].sem_flg); + } + + unlock_user(target_sembuf, target_addr, 0); + + return 0; +} + +static inline abi_long do_semop(int semid, abi_long ptr, unsigned nsops) +{ + struct sembuf sops[nsops]; + + if (target_to_host_sembuf(sops, ptr, nsops)) + return -TARGET_EFAULT; + + return semop(semid, sops, nsops); +} + struct target_msqid_ds { struct target_ipc_perm msg_perm; @@ -2044,7 +2126,7 @@ static abi_long do_ipc(unsigned int call, int first, switch (call) { case IPCOP_semop: - ret = get_errno(semop(first,(struct sembuf *)g2h(ptr), second)); + ret = do_semop(first, ptr, second); break; case IPCOP_semget: @@ -2052,12 +2134,7 @@ static abi_long do_ipc(unsigned int call, int first, break; case IPCOP_semctl: - ret = do_semctl(first, second, third, ptr); - break; - - case IPCOP_semtimedop: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; + ret = do_semctl(first, second, third, (union target_semun)(abi_ulong) ptr); break; case IPCOP_msgget: -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement sem* syscalls 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 16 +++++++++++++++- 1 files changed, 15 insertions(+), 1 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1852f35..1a09d90 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -4906,7 +4906,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6); break; #endif - +#ifdef TARGET_NR_semget + case TARGET_NR_semget: + ret = get_errno(semget(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semop + case TARGET_NR_semop: + ret = get_errno(do_semop(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_semctl + case TARGET_NR_semctl: + ret = do_semctl(arg1, arg2, arg3, (union target_semun)(abi_ulong)arg4); + break; +#endif #ifdef TARGET_NR_msgctl case TARGET_NR_msgctl: ret = do_msgctl(arg1, arg2, arg3); -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 282 +++++++++++++++++++++++++++++++++++++++---------- 1 files changed, 224 insertions(+), 58 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1a09d90..d1fccb4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -2109,6 +2109,206 @@ end: return ret; } +struct target_shmid_ds +{ + struct target_ipc_perm shm_perm; + abi_ulong shm_segsz; + abi_ulong shm_atime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused1; +#endif + abi_ulong shm_dtime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused2; +#endif + abi_ulong shm_ctime; +#if TARGET_ABI_BITS == 32 + abi_ulong __unused3; +#endif + int shm_cpid; + int shm_lpid; + abi_ulong shm_nattch; + unsigned long int __unused4; + unsigned long int __unused5; +}; + +static inline abi_long target_to_host_shmid_ds(struct shmid_ds *host_sd, + abi_ulong target_addr) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_READ, target_sd, target_addr, 1)) + return -TARGET_EFAULT; + if (target_to_host_ipc_perm(&(host_sd->shm_perm), target_addr)) + return -TARGET_EFAULT; + __put_user(target_sd->shm_segsz, &host_sd->shm_segsz); + __put_user(target_sd->shm_atime, &host_sd->shm_atime); + __put_user(target_sd->shm_dtime, &host_sd->shm_dtime); + __put_user(target_sd->shm_ctime, &host_sd->shm_ctime); + __put_user(target_sd->shm_cpid, &host_sd->shm_cpid); + __put_user(target_sd->shm_lpid, &host_sd->shm_lpid); + __put_user(target_sd->shm_nattch, &host_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 0); + return 0; +} + +static inline abi_long host_to_target_shmid_ds(abi_ulong target_addr, + struct shmid_ds *host_sd) +{ + struct target_shmid_ds *target_sd; + + if (!lock_user_struct(VERIFY_WRITE, target_sd, target_addr, 0)) + return -TARGET_EFAULT; + if (host_to_target_ipc_perm(target_addr, &(host_sd->shm_perm))) + return -TARGET_EFAULT; + __put_user(host_sd->shm_segsz, &target_sd->shm_segsz); + __put_user(host_sd->shm_atime, &target_sd->shm_atime); + __put_user(host_sd->shm_dtime, &target_sd->shm_dtime); + __put_user(host_sd->shm_ctime, &target_sd->shm_ctime); + __put_user(host_sd->shm_cpid, &target_sd->shm_cpid); + __put_user(host_sd->shm_lpid, &target_sd->shm_lpid); + __put_user(host_sd->shm_nattch, &target_sd->shm_nattch); + unlock_user_struct(target_sd, target_addr, 1); + return 0; +} + +struct target_shminfo { + abi_ulong shmmax; + abi_ulong shmmin; + abi_ulong shmmni; + abi_ulong shmseg; + abi_ulong shmall; +}; + +static inline abi_long host_to_target_shminfo(abi_ulong target_addr, + struct shminfo *host_shminfo) +{ + struct target_shminfo *target_shminfo; + if (!lock_user_struct(VERIFY_WRITE, target_shminfo, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_shminfo->shmmax, &target_shminfo->shmmax); + __put_user(host_shminfo->shmmin, &target_shminfo->shmmin); + __put_user(host_shminfo->shmmni, &target_shminfo->shmmni); + __put_user(host_shminfo->shmseg, &target_shminfo->shmseg); + __put_user(host_shminfo->shmall, &target_shminfo->shmall); + unlock_user_struct(target_shminfo, target_addr, 1); +} + +struct target_shm_info { + int used_ids; + abi_ulong shm_tot; + abi_ulong shm_rss; + abi_ulong shm_swp; + abi_ulong swap_attempts; + abi_ulong swap_successes; +}; + +static inline abi_long host_to_target_shm_info(abi_ulong target_addr, + struct shm_info *host_shm_info) +{ + struct target_shm_info *target_shm_info; + if (!lock_user_struct(VERIFY_WRITE, target_shm_info, target_addr, 0)) + return -TARGET_EFAULT; + __put_user(host_shm_info->used_ids, &target_shm_info->used_ids); + __put_user(host_shm_info->shm_tot, &target_shm_info->shm_tot); + __put_user(host_shm_info->shm_rss, &target_shm_info->shm_rss); + __put_user(host_shm_info->shm_swp, &target_shm_info->shm_swp); + __put_user(host_shm_info->swap_attempts, &target_shm_info->swap_attempts); + __put_user(host_shm_info->swap_successes, &target_shm_info->swap_successes); + unlock_user_struct(target_shm_info, target_addr, 1); +} + +static inline abi_long do_shmctl(int shmid, int cmd, abi_long buf) +{ + struct shmid_ds dsarg; + struct shminfo shminfo; + struct shm_info shm_info; + abi_long ret = -TARGET_EINVAL; + + cmd &= 0xff; + + switch(cmd) { + case IPC_STAT: + case IPC_SET: + case SHM_STAT: + if (target_to_host_shmid_ds(&dsarg, buf)) + return -TARGET_EFAULT; + ret = get_errno(shmctl(shmid, cmd, &dsarg)); + if (host_to_target_shmid_ds(buf, &dsarg)) + return -TARGET_EFAULT; + break; + case IPC_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shminfo)); + if (host_to_target_shminfo(buf, &shminfo)) + return -TARGET_EFAULT; + break; + case SHM_INFO: + ret = get_errno(shmctl(shmid, cmd, (struct shmid_ds *)&shm_info)); + if (host_to_target_shm_info(buf, &shm_info)) + return -TARGET_EFAULT; + break; + case IPC_RMID: + case SHM_LOCK: + case SHM_UNLOCK: + ret = get_errno(shmctl(shmid, cmd, NULL)); + break; + } + + return ret; +} + +static inline abi_long do_shmat(int shmid, abi_ulong shmaddr, int shmflg, + unsigned long *raddr) +{ + abi_long ret; + struct shmid_ds shm_info; + int i; + + /* SHM_* flags are the same on all linux platforms */ + *raddr = (unsigned long) shmat(shmid, g2h(shmaddr), shmflg); + + if (*raddr == -1) { + return get_errno(*raddr); + } + + /* find out the length of the shared memory segment */ + ret = get_errno(shmctl(shmid, IPC_STAT, &shm_info)); + if (is_error(ret)) { + /* can't get length, bail out */ + shmdt((void *) *raddr); + return get_errno(ret); + } + + page_set_flags(h2g(*raddr), h2g(*raddr) + shm_info.shm_segsz, + PAGE_VALID | PAGE_READ | + ((shmflg & SHM_RDONLY)? 0 : PAGE_WRITE)); + + for (i = 0; i < N_SHM_REGIONS; i++) { + if (shm_regions[i].start == 0) { + shm_regions[i].start = h2g(*raddr); + shm_regions[i].size = shm_info.shm_segsz; + break; + } + } + + return 0; +} + +static inline abi_long do_shmdt(abi_ulong shmaddr) +{ + int i; + + for (i = 0; i < N_SHM_REGIONS; ++i) { + if (shm_regions[i].start == shmaddr) { + shm_regions[i].start = 0; + page_set_flags(shmaddr, shm_regions[i].size, 0); + break; + } + } + + return get_errno(shmdt(g2h(shmaddr))); +} + #ifdef TARGET_NR_ipc /* ??? This only works with linear mappings. */ /* do_ipc() must return target values and target errnos. */ @@ -2118,8 +2318,6 @@ static abi_long do_ipc(unsigned int call, int first, { int version; abi_long ret = 0; - struct shmid_ds shm_info; - int i; version = call >> 16; call &= 0xffff; @@ -2174,72 +2372,40 @@ static abi_long do_ipc(unsigned int call, int first, break; case IPCOP_shmat: - { - abi_ulong raddr; - void *host_addr; - /* SHM_* flags are the same on all linux platforms */ - host_addr = shmat(first, (void *)g2h(ptr), second); - if (host_addr == (void *)-1) { - ret = get_errno((long)host_addr); - break; - } - raddr = h2g((unsigned long)host_addr); - /* find out the length of the shared memory segment */ - - ret = get_errno(shmctl(first, IPC_STAT, &shm_info)); - if (is_error(ret)) { - /* can't get length, bail out */ - shmdt(host_addr); - break; - } - page_set_flags(raddr, raddr + shm_info.shm_segsz, - PAGE_VALID | PAGE_READ | - ((second & SHM_RDONLY)? 0: PAGE_WRITE)); - for (i = 0; i < N_SHM_REGIONS; ++i) { - if (shm_regions[i].start == 0) { - shm_regions[i].start = raddr; - shm_regions[i].size = shm_info.shm_segsz; + switch (version) { + default: + { + unsigned long raddr; + + ret = do_shmat(first, ptr, second, &raddr); + if (ret) break; - } + + ret = put_user_ual(raddr, third); + break; } - if (put_user_ual(raddr, third)) - return -TARGET_EFAULT; - ret = 0; + case 1: + ret = -TARGET_EINVAL; + break; } - break; + break; + case IPCOP_shmdt: - for (i = 0; i < N_SHM_REGIONS; ++i) { - if (shm_regions[i].start == ptr) { - shm_regions[i].start = 0; - page_set_flags(ptr, shm_regions[i].size, 0); - break; - } - } - ret = get_errno(shmdt((void *)g2h(ptr))); - break; + ret = do_shmdt(ptr); + break; case IPCOP_shmget: - /* IPC_* flag values are the same on all linux platforms */ - ret = get_errno(shmget(first, second, third)); - break; + ret = get_errno(shmget(first, second, third)); + break; - /* IPC_* and SHM_* command values are the same on all linux platforms */ case IPCOP_shmctl: - switch(second) { - case IPC_RMID: - case SHM_LOCK: - case SHM_UNLOCK: - ret = get_errno(shmctl(first, second, NULL)); - break; - default: - goto unimplemented; - } + ret = do_shmctl(first, second, third); break; + default: - unimplemented: - gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); - ret = -TARGET_ENOSYS; - break; + gemu_log("Unsupported ipc call: %d (version %d)\n", call, version); + ret = -TARGET_ENOSYS; + break; } return ret; } -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Implement shm* syscalls 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 26 ++++++++++++++++++++++++++ 1 files changed, 26 insertions(+), 0 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index d1fccb4..c85fea4 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -5107,6 +5107,32 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = do_msgsnd(arg1, arg2, arg3, arg4); break; #endif +#ifdef TARGET_NR_shmget + case TARGET_NR_shmget: + ret = get_errno(shmget(arg1, arg2, arg3)); + break; +#endif +#ifdef TARGET_NR_shmctl + case TARGET_NR_shmctl: + ret = do_shmctl(arg1, arg2, arg3); + break; +#endif +#ifdef TARGET_NR_shmat + case TARGET_NR_shmat: + { + abi_long err; + unsigned long _ret; + + err = do_shmat(arg1, arg2, arg3, &_ret); + ret = err ? err : _ret; + } + break; +#endif +#ifdef TARGET_NR_shmdt + case TARGET_NR_shmdt: + ret = do_shmdt(arg1); + break; +#endif case TARGET_NR_fsync: ret = get_errno(fsync(arg1)); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook There are two different syscall names for the same goal. On systems with sizeof(long) == 64 it calls newfstatat. On systems with sizeof(long) == 32 it calls fstatat64. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- linux-user/syscall.c | 29 +++++++++++++++++++++++++---- 1 files changed, 25 insertions(+), 4 deletions(-) diff --git a/linux-user/syscall.c b/linux-user/syscall.c index c85fea4..3fa205f 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -165,6 +165,7 @@ static type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5, \ #define __NR_sys_linkat __NR_linkat #define __NR_sys_mkdirat __NR_mkdirat #define __NR_sys_mknodat __NR_mknodat +#define __NR_sys_newfstatat __NR_newfstatat #define __NR_sys_openat __NR_openat #define __NR_sys_readlinkat __NR_readlinkat #define __NR_sys_renameat __NR_renameat @@ -205,7 +206,8 @@ _syscall4(int,sys_fchmodat,int,dirfd,const char *,pathname, _syscall5(int,sys_fchownat,int,dirfd,const char *,pathname, uid_t,owner,gid_t,group,int,flags) #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + defined(__NR_fstatat64) _syscall4(int,sys_fstatat64,int,dirfd,const char *,pathname, struct stat *,buf,int,flags) #endif @@ -236,6 +238,11 @@ _syscall3(int,sys_mkdirat,int,dirfd,const char *,pathname,mode_t,mode) _syscall4(int,sys_mknodat,int,dirfd,const char *,pathname, mode_t,mode,dev_t,dev) #endif +#if (defined(TARGET_NR_newfstatat) || defined(TARGET_NR_fstatat64) ) && \ + defined(__NR_newfstatat) +_syscall4(int,sys_newfstatat,int,dirfd,const char *,pathname, + struct stat *,buf,int,flags) +#endif #if defined(TARGET_NR_openat) && defined(__NR_openat) _syscall4(int,sys_openat,int,dirfd,const char *,pathname,int,flags,mode_t,mode) #endif @@ -3481,7 +3488,7 @@ static inline abi_long host_to_target_timespec(abi_ulong target_addr, return 0; } -#ifdef TARGET_NR_stat64 +#if defined(TARGET_NR_stat64) || defined(TARGET_NR_newfstatat) static inline abi_long host_to_target_stat64(void *cpu_env, abi_ulong target_addr, struct stat *host_st) @@ -3513,11 +3520,15 @@ static inline abi_long host_to_target_stat64(void *cpu_env, } else #endif { +#if TARGET_LONG_BITS == 64 + struct target_stat *target_st; +#else struct target_stat64 *target_st; +#endif if (!lock_user_struct(VERIFY_WRITE, target_st, target_addr, 0)) return -TARGET_EFAULT; - memset(target_st, 0, sizeof(struct target_stat64)); + memset(target_st, 0, sizeof(*target_st)); __put_user(host_st->st_dev, &target_st->st_dev); __put_user(host_st->st_ino, &target_st->st_ino); #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO @@ -5645,11 +5656,21 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1, ret = host_to_target_stat64(cpu_env, arg2, &st); break; #endif -#if defined(TARGET_NR_fstatat64) && defined(__NR_fstatat64) +#if (defined(TARGET_NR_fstatat64) || defined(TARGET_NR_newfstatat)) && \ + (defined(__NR_fstatat64) || defined(__NR_newfstatat)) +#ifdef TARGET_NR_fstatat64 case TARGET_NR_fstatat64: +#endif +#ifdef TARGET_NR_newfstatat + case TARGET_NR_newfstatat: +#endif if (!(p = lock_user_string(arg2))) goto efault; +#ifdef __NR_fstatat64 ret = get_errno(sys_fstatat64(arg1, path(p), &st, arg4)); +#else + ret = get_errno(sys_newfstatat(arg1, path(p), &st, arg4)); +#endif if (!is_error(ret)) ret = host_to_target_stat64(cpu_env, arg3, &st); break; -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov @ 2008-10-13 10:10 ` Kirill A. Shutemov 0 siblings, 0 replies; 18+ messages in thread From: Kirill A. Shutemov @ 2008-10-13 10:10 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov, Paul Brook It makes qemu compatible with binfmt_misc's flags 'P' and 'O'. 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the original argv[0] with the full path to the binary. When this flag is included, binfmt_misc will add an argument to the argument vector for this purpose, thus preserving the original argv[0]. 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path of the binary to the interpreter as an argument. When this flag is included, binfmt_misc will open the file for reading and pass its descriptor as an argument, instead of the full path, thus allowing the interpreter to execute non-readable binaries. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- configure | 86 ++++++++++++++++++++++++++---------------------- linux-user/linuxload.c | 7 +--- linux-user/main.c | 39 ++++++++++++++++++++- linux-user/qemu.h | 2 +- 4 files changed, 87 insertions(+), 47 deletions(-) diff --git a/configure b/configure index f14739b..0148b72 100755 --- a/configure +++ b/configure @@ -113,6 +113,7 @@ aio="yes" nptl="yes" mixemu="no" bluez="yes" +binfmt_misc="no" # OS specific targetos=`uname -s` @@ -349,6 +350,8 @@ for opt do ;; --disable-aio) aio="no" ;; + --enable-binfmt-misc) binfmt_misc="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -453,6 +456,7 @@ echo " --enable-uname-release=R Return R for uname -r in usermode emulation" echo " --sparc_cpu=V Build qemu for Sparc architecture v7, v8, v8plus, v8plusa, v9" echo " --disable-vde disable support for vde network" echo " --disable-aio disable AIO support" +echo " --enable-binfmt-misc makes usermode compatible with binfmt_misc's flags 'P' and 'O'" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -969,55 +973,56 @@ else binsuffix="/bin" fi -echo "Install prefix $prefix" -echo "BIOS directory $prefix$datasuffix" -echo "binary directory $prefix$binsuffix" +echo "Install prefix $prefix" +echo "BIOS directory $prefix$datasuffix" +echo "binary directory $prefix$binsuffix" if test "$mingw32" = "no" ; then -echo "Manual directory $prefix$mansuffix" -echo "ELF interp prefix $interp_prefix" -fi -echo "Source path $source_path" -echo "C compiler $cc" -echo "Host C compiler $host_cc" -echo "ARCH_CFLAGS $ARCH_CFLAGS" -echo "make $make" -echo "install $install" -echo "host CPU $cpu" -echo "host big endian $bigendian" -echo "target list $target_list" -echo "gprof enabled $gprof" -echo "sparse enabled $sparse" -echo "profiler $profiler" -echo "static build $static" -echo "-Werror enabled $werror" +echo "Manual directory $prefix$mansuffix" +echo "ELF interp prefix $interp_prefix" +fi +echo "Source path $source_path" +echo "C compiler $cc" +echo "Host C compiler $host_cc" +echo "ARCH_CFLAGS $ARCH_CFLAGS" +echo "make $make" +echo "install $install" +echo "host CPU $cpu" +echo "host big endian $bigendian" +echo "target list $target_list" +echo "gprof enabled $gprof" +echo "sparse enabled $sparse" +echo "profiler $profiler" +echo "static build $static" +echo "-Werror enabled $werror" if test "$darwin" = "yes" ; then - echo "Cocoa support $cocoa" + echo "Cocoa support $cocoa" fi echo "SDL support $sdl" if test "$sdl" != "no" ; then - echo "SDL static link $sdl_static" -fi -echo "curses support $curses" -echo "mingw32 support $mingw32" -echo "Audio drivers $audio_drv_list" -echo "Extra audio cards $audio_card_list" -echo "Mixer emulation $mixemu" -echo "VNC TLS support $vnc_tls" + echo "SDL static link $sdl_static" +fi +echo "curses support $curses" +echo "mingw32 support $mingw32" +echo "Audio drivers $audio_drv_list" +echo "Extra audio cards $audio_card_list" +echo "Mixer emulation $mixemu" +echo "VNC TLS support $vnc_tls" if test "$vnc_tls" = "yes" ; then - echo " TLS CFLAGS $vnc_tls_cflags" - echo " TLS LIBS $vnc_tls_libs" + echo " TLS CFLAGS $vnc_tls_cflags" + echo " TLS LIBS $vnc_tls_libs" fi if test -n "$sparc_cpu"; then - echo "Target Sparc Arch $sparc_cpu" + echo "Target Sparc Arch $sparc_cpu" fi -echo "kqemu support $kqemu" -echo "brlapi support $brlapi" -echo "Documentation $build_docs" +echo "kqemu support $kqemu" +echo "brlapi support $brlapi" +echo "Documentation $build_docs" [ ! -z "$uname_release" ] && \ -echo "uname -r $uname_release" -echo "NPTL support $nptl" -echo "vde support $vde" -echo "AIO support $aio" +echo "uname -r $uname_release" +echo "NPTL support $nptl" +echo "vde support $vde" +echo "AIO support $aio" +echo "binfmt_misc support $binfmt_misc" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -1584,6 +1589,9 @@ if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h fi +if test "$target_user_only" = "yes" -a "$binfmt_misc" = "yes"; then + echo "#define BINFMT_MISC 1" >> $config_h +fi test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index ada7c69..cbd90f7 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -154,7 +154,7 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, return sp; } -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop) { struct linux_binprm bprm; @@ -164,10 +164,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; - retval = open(filename, O_RDONLY); - if (retval < 0) - return retval; - bprm.fd = retval; + bprm.fd = fd; bprm.filename = (char *)filename; bprm.argc = count(argv); bprm.argv = argv; diff --git a/linux-user/main.c b/linux-user/main.c index fef4bf7..25b2867 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -26,6 +26,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "elf.h" /* For tb_lock */ #include "exec-all.h" @@ -2217,9 +2218,10 @@ void init_task_state(TaskState *ts) ts->sigqueue_table[i].next = NULL; } -int main(int argc, char **argv) +int main(int argc, char **argv, char **envp) { const char *filename; + int fd = -1; const char *cpu_model; struct target_pt_regs regs1, *regs = ®s1; struct image_info info1, *info = &info1; @@ -2380,7 +2382,40 @@ int main(int argc, char **argv) } *dst = NULL; /* NULL terminate target_environ */ - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { +#ifdef BINFMT_MISC +#if HOST_LONG_BITS == 32 +#define Elf_Dyn Elf32_Dyn +#else +#define Elf_Dyn Elf64_Dyn +#endif + { + Elf_Dyn *auxv; + + optind++; /* Handle binfmt_misc's option 'P' */ + + /* Handle binfmt_misc's option 'O' */ + while(*envp++ != NULL); /* skip envp. we are on auxv now */ + for(auxv = (Elf_Dyn *)envp; auxv->d_tag != AT_NULL; auxv++) { + if( auxv->d_tag == AT_EXECFD) { + fd = auxv->d_un.d_val; + break; + } + } + + if (fd < 0) { + printf("Cannot find binary file descriptor\n"); + _exit(1); + } + } +#else + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("Cannot open file %s: %s\n", filename, strerror(errno)); + _exit(1); + } +#endif + + if (loader_exec(fd, filename, argv+optind, target_environ, regs, info) != 0) { printf("Error loading %s\n", filename); _exit(1); } diff --git a/linux-user/qemu.h b/linux-user/qemu.h index a2abe51..52835ec 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -168,7 +168,7 @@ struct linux_binprm { void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop); int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, -- 1.5.6.5.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option @ 2008-12-03 11:29 Kirill A. Shutemov 2009-01-12 14:18 ` Riku Voipio 0 siblings, 1 reply; 18+ messages in thread From: Kirill A. Shutemov @ 2008-12-03 11:29 UTC (permalink / raw) To: qemu-devel; +Cc: Kirill A. Shutemov It makes qemu compatible with binfmt_misc's flags 'P' and 'O'. 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the original argv[0] with the full path to the binary. When this flag is included, binfmt_misc will add an argument to the argument vector for this purpose, thus preserving the original argv[0]. 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path of the binary to the interpreter as an argument. When this flag is included, binfmt_misc will open the file for reading and pass its descriptor as an argument, instead of the full path, thus allowing the interpreter to execute non-readable binaries. Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> --- configure | 90 ++++++++++++++++++++++++++---------------------- linux-user/linuxload.c | 7 +--- linux-user/main.c | 39 ++++++++++++++++++++- linux-user/qemu.h | 2 +- 4 files changed, 89 insertions(+), 49 deletions(-) diff --git a/configure b/configure index 57b3b5a..aeeae72 100755 --- a/configure +++ b/configure @@ -122,6 +122,7 @@ kvm="yes" kerneldir="" aix="no" blobs="yes" +binfmt_misc="no" # OS specific targetos=`uname -s` @@ -380,6 +381,8 @@ for opt do ;; --kerneldir=*) kerneldir="$optarg" ;; + --enable-binfmt-misc) binfmt_misc="yes" + ;; *) echo "ERROR: unknown option $opt"; show_help="yes" ;; esac @@ -491,6 +494,7 @@ echo " --disable-vde disable support for vde network" echo " --disable-aio disable AIO support" echo " --disable-blobs disable installing provided firmware blobs" echo " --kerneldir=PATH look for kernel includes in PATH" +echo " --enable-binfmt-misc makes usermode compatible with binfmt_misc's flags 'P' and 'O'" echo "" echo "NOTE: The object files are built at the place where configure is launched" exit 1 @@ -1041,57 +1045,58 @@ else binsuffix="/bin" fi -echo "Install prefix $prefix" -echo "BIOS directory $prefix$datasuffix" -echo "binary directory $prefix$binsuffix" +echo "Install prefix $prefix" +echo "BIOS directory $prefix$datasuffix" +echo "binary directory $prefix$binsuffix" if test "$mingw32" = "no" ; then -echo "Manual directory $prefix$mansuffix" -echo "ELF interp prefix $interp_prefix" -fi -echo "Source path $source_path" -echo "C compiler $cc" -echo "Host C compiler $host_cc" -echo "ARCH_CFLAGS $ARCH_CFLAGS" -echo "make $make" -echo "install $install" -echo "host CPU $cpu" -echo "host big endian $bigendian" -echo "target list $target_list" -echo "gprof enabled $gprof" -echo "sparse enabled $sparse" -echo "profiler $profiler" -echo "static build $static" -echo "-Werror enabled $werror" +echo "Manual directory $prefix$mansuffix" +echo "ELF interp prefix $interp_prefix" +fi +echo "Source path $source_path" +echo "C compiler $cc" +echo "Host C compiler $host_cc" +echo "ARCH_CFLAGS $ARCH_CFLAGS" +echo "make $make" +echo "install $install" +echo "host CPU $cpu" +echo "host big endian $bigendian" +echo "target list $target_list" +echo "gprof enabled $gprof" +echo "sparse enabled $sparse" +echo "profiler $profiler" +echo "static build $static" +echo "-Werror enabled $werror" if test "$darwin" = "yes" ; then - echo "Cocoa support $cocoa" + echo "Cocoa support $cocoa" fi echo "SDL support $sdl" if test "$sdl" != "no" ; then - echo "SDL static link $sdl_static" -fi -echo "curses support $curses" -echo "mingw32 support $mingw32" -echo "Audio drivers $audio_drv_list" -echo "Extra audio cards $audio_card_list" -echo "Mixer emulation $mixemu" -echo "VNC TLS support $vnc_tls" + echo "SDL static link $sdl_static" +fi +echo "curses support $curses" +echo "mingw32 support $mingw32" +echo "Audio drivers $audio_drv_list" +echo "Extra audio cards $audio_card_list" +echo "Mixer emulation $mixemu" +echo "VNC TLS support $vnc_tls" if test "$vnc_tls" = "yes" ; then - echo " TLS CFLAGS $vnc_tls_cflags" - echo " TLS LIBS $vnc_tls_libs" + echo " TLS CFLAGS $vnc_tls_cflags" + echo " TLS LIBS $vnc_tls_libs" fi if test -n "$sparc_cpu"; then - echo "Target Sparc Arch $sparc_cpu" + echo "Target Sparc Arch $sparc_cpu" fi -echo "kqemu support $kqemu" -echo "brlapi support $brlapi" -echo "Documentation $build_docs" +echo "kqemu support $kqemu" +echo "brlapi support $brlapi" +echo "Documentation $build_docs" [ ! -z "$uname_release" ] && \ -echo "uname -r $uname_release" -echo "NPTL support $nptl" -echo "vde support $vde" -echo "AIO support $aio" -echo "Install blobs $blobs" -echo "KVM support $kvm" +echo "uname -r $uname_release" +echo "NPTL support $nptl" +echo "vde support $vde" +echo "AIO support $aio" +echo "Install blobs $blobs" +echo "KVM support $kvm" +echo "binfmt_misc support $binfmt_misc" if test $sdl_too_old = "yes"; then echo "-> Your SDL version is too old - please upgrade to have SDL support" @@ -1709,6 +1714,9 @@ if test "$target_bsd_user" = "yes" ; then echo "CONFIG_BSD_USER=yes" >> $config_mak echo "#define CONFIG_BSD_USER 1" >> $config_h fi +if test "$target_user_only" = "yes" -a "$binfmt_misc" = "yes"; then + echo "#define BINFMT_MISC 1" >> $config_h +fi test -f ${config_h}~ && cmp -s $config_h ${config_h}~ && mv ${config_h}~ $config_h diff --git a/linux-user/linuxload.c b/linux-user/linuxload.c index ada7c69..cbd90f7 100644 --- a/linux-user/linuxload.c +++ b/linux-user/linuxload.c @@ -154,7 +154,7 @@ abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, return sp; } -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop) { struct linux_binprm bprm; @@ -164,10 +164,7 @@ int loader_exec(const char * filename, char ** argv, char ** envp, bprm.p = TARGET_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int); for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */ bprm.page[i] = 0; - retval = open(filename, O_RDONLY); - if (retval < 0) - return retval; - bprm.fd = retval; + bprm.fd = fd; bprm.filename = (char *)filename; bprm.argc = count(argv); bprm.argv = argv; diff --git a/linux-user/main.c b/linux-user/main.c index 66be107..6ed9247 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -27,6 +27,7 @@ #include "qemu.h" #include "qemu-common.h" +#include "elf.h" /* For tb_lock */ #include "exec-all.h" @@ -2214,9 +2215,10 @@ void init_task_state(TaskState *ts) ts->sigqueue_table[i].next = NULL; } -int main(int argc, char **argv) +int main(int argc, char **argv, char **envp) { const char *filename; + int fd = -1; const char *cpu_model; struct target_pt_regs regs1, *regs = ®s1; struct image_info info1, *info = &info1; @@ -2377,7 +2379,40 @@ int main(int argc, char **argv) } *dst = NULL; /* NULL terminate target_environ */ - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { +#ifdef BINFMT_MISC +#if HOST_LONG_BITS == 32 +#define Elf_Dyn Elf32_Dyn +#else +#define Elf_Dyn Elf64_Dyn +#endif + { + Elf_Dyn *auxv; + + optind++; /* Handle binfmt_misc's option 'P' */ + + /* Handle binfmt_misc's option 'O' */ + while(*envp++ != NULL); /* skip envp. we are on auxv now */ + for(auxv = (Elf_Dyn *)envp; auxv->d_tag != AT_NULL; auxv++) { + if( auxv->d_tag == AT_EXECFD) { + fd = auxv->d_un.d_val; + break; + } + } + + if (fd < 0) { + printf("Cannot find binary file descriptor\n"); + _exit(1); + } + } +#else + fd = open(filename, O_RDONLY); + if (fd < 0) { + printf("Cannot open file %s: %s\n", filename, strerror(errno)); + _exit(1); + } +#endif + + if (loader_exec(fd, filename, argv+optind, target_environ, regs, info) != 0) { printf("Error loading %s\n", filename); _exit(1); } diff --git a/linux-user/qemu.h b/linux-user/qemu.h index a2abe51..52835ec 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -168,7 +168,7 @@ struct linux_binprm { void do_init_thread(struct target_pt_regs *regs, struct image_info *infop); abi_ulong loader_build_argptr(int envc, int argc, abi_ulong sp, abi_ulong stringp, int push_ptr); -int loader_exec(const char * filename, char ** argv, char ** envp, +int loader_exec(int fd, const char * filename, char ** argv, char ** envp, struct target_pt_regs * regs, struct image_info *infop); int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, -- 1.6.0.2.GIT ^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option 2008-12-03 11:29 Kirill A. Shutemov @ 2009-01-12 14:18 ` Riku Voipio 0 siblings, 0 replies; 18+ messages in thread From: Riku Voipio @ 2009-01-12 14:18 UTC (permalink / raw) To: Kirill A. Shutemov; +Cc: qemu-devel On Wed, Dec 03, 2008 at 01:29:36PM +0200, Kirill A. Shutemov wrote: > It makes qemu compatible with binfmt_misc's flags 'P' and 'O'. > > 'P' - preserve-argv[0]. Legacy behavior of binfmt_misc is to overwrite the > original argv[0] with the full path to the binary. When this flag is > included, binfmt_misc will add an argument to the argument vector for > this purpose, thus preserving the original argv[0]. > > 'O' - open-binary. Legacy behavior of binfmt_misc is to pass the full path > of the binary to the interpreter as an argument. When this flag is > included, binfmt_misc will open the file for reading and pass its > descriptor as an argument, instead of the full path, thus allowing > the interpreter to execute non-readable binaries. > > Signed-off-by: Kirill A. Shutemov <kirill@shutemov.name> > --- > configure | 90 ++++++++++++++++++++++++++---------------------- > linux-user/linuxload.c | 7 +--- > linux-user/main.c | 39 ++++++++++++++++++++- > linux-user/qemu.h | 2 +- > 4 files changed, 89 insertions(+), 49 deletions(-) > > diff --git a/configure b/configure > index 57b3b5a..aeeae72 100755 > --- a/configure > +++ b/configure > @@ -122,6 +122,7 @@ kvm="yes" > kerneldir="" > aix="no" > blobs="yes" > +binfmt_misc="no" > > # OS specific > targetos=`uname -s` > @@ -380,6 +381,8 @@ for opt do > ;; > --kerneldir=*) kerneldir="$optarg" > ;; > + --enable-binfmt-misc) binfmt_misc="yes" > + ;; > *) echo "ERROR: unknown option $opt"; show_help="yes" > ;; > esac > @@ -491,6 +494,7 @@ echo " --disable-vde disable support for vde network" > echo " --disable-aio disable AIO support" > echo " --disable-blobs disable installing provided firmware blobs" > echo " --kerneldir=PATH look for kernel includes in PATH" > +echo " --enable-binfmt-misc makes usermode compatible with binfmt_misc's flags 'P' and 'O'" > echo "" > echo "NOTE: The object files are built at the place where configure is launched" > exit 1 > @@ -1041,57 +1045,58 @@ else > binsuffix="/bin" > fi > > -echo "Install prefix $prefix" > -echo "BIOS directory $prefix$datasuffix" > -echo "binary directory $prefix$binsuffix" > +echo "Install prefix $prefix" > +echo "BIOS directory $prefix$datasuffix" > +echo "binary directory $prefix$binsuffix" Whitespace changes mixed with code changes :-/ > +#include "elf.h" > /* For tb_lock */ > #include "exec-all.h" > > @@ -2214,9 +2215,10 @@ void init_task_state(TaskState *ts) > ts->sigqueue_table[i].next = NULL; > } > > -int main(int argc, char **argv) > +int main(int argc, char **argv, char **envp) > { > const char *filename; > + int fd = -1; > const char *cpu_model; > struct target_pt_regs regs1, *regs = ®s1; > struct image_info info1, *info = &info1; > @@ -2377,7 +2379,40 @@ int main(int argc, char **argv) > } > *dst = NULL; /* NULL terminate target_environ */ > > - if (loader_exec(filename, argv+optind, target_environ, regs, info) != 0) { > +#ifdef BINFMT_MISC > +#if HOST_LONG_BITS == 32 > +#define Elf_Dyn Elf32_Dyn > +#else > +#define Elf_Dyn Elf64_Dyn > +#endif > + { > + Elf_Dyn *auxv; > + > + optind++; /* Handle binfmt_misc's option 'P' */ > + > + /* Handle binfmt_misc's option 'O' */ > + while(*envp++ != NULL); /* skip envp. we are on auxv now */ > + for(auxv = (Elf_Dyn *)envp; auxv->d_tag != AT_NULL; auxv++) { > + if( auxv->d_tag == AT_EXECFD) { > + fd = auxv->d_un.d_val; > + break; > + } > + } > + > + if (fd < 0) { > + printf("Cannot find binary file descriptor\n"); > + _exit(1); > + } > + } > +#else > + fd = open(filename, O_RDONLY); > + if (fd < 0) { > + printf("Cannot open file %s: %s\n", filename, strerror(errno)); > + _exit(1); > + } > +#endif If I read this correctly, it means this patch means that linux-user doesn't work from command line if configured with --enable-binfmt-misc. I think it would be better to add a wrapper (as recommended by binfmt-misc docs in kernel) that sets these binfmt options to new qemu command line arguments ( --argv0, --open-fd). Assuming the binfmt_misc passed FD survives exec, the wrapper should work fine. This wrapper could well be shipped with qemu. ^ permalink raw reply [flat|nested] 18+ messages in thread
end of thread, other threads:[~2009-01-12 14:18 UTC | newest] Thread overview: 18+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2008-10-08 18:54 [Qemu-devel] [PATCH] Add readahead syscall Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 2008-10-08 18:54 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov 2008-10-09 17:40 ` [Qemu-devel] [PATCH, v2] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 2008-10-09 17:42 ` [Qemu-devel] [PATCH, v2] Implement sem* syscalls Kirill A. Shutemov 2008-10-09 17:41 ` [Qemu-devel] [PATCH, v2] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Aurelien Jarno 2008-10-13 21:09 ` [Qemu-devel] [PATCH] Add readahead syscall Aurelien Jarno -- strict thread matches above, loose matches on Subject: below -- 2008-10-13 10:10 Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix getdents* syscalls Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_msg* ipc calls handling Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement msg* syscalls Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_sem* ipc calls handling Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement sem* syscalls Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix and cleanup IPCOP_shm* ipc calls handling Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Implement shm* syscalls Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Fix fstatat64()/newfstatat() syscall implementation Kirill A. Shutemov 2008-10-13 10:10 ` [Qemu-devel] [PATCH] Introduce --enable-binfmt-misc configure option Kirill A. Shutemov 2008-12-03 11:29 Kirill A. Shutemov 2009-01-12 14:18 ` Riku Voipio
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).