Index: qemu/linux-user/syscall.c =================================================================== --- qemu.orig/linux-user/syscall.c +++ qemu/linux-user/syscall.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include @@ -46,6 +46,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -150,6 +153,7 @@ type name (type1 arg1,type2 arg2,type3 a #define __NR_sys_tgkill __NR_tgkill #define __NR_sys_clone __NR_clone #define __NR_sys_sched_getaffinity __NR_sched_getaffinity +#define __NR_sys_ipc __NR_ipc #if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__) #define __NR__llseek __NR_lseek @@ -172,6 +176,10 @@ _syscall3(int,sys_rt_sigqueueinfo,int,pi _syscall3(int,sys_syslog,int,type,char*,bufp,int,len) _syscall3(int,sys_tgkill,int,tgid,int,pid,int,sig) _syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, void *, newtls, int *, child_tidptr) +#ifdef __NR_ipc +_syscall6(int,sys_ipc, long, call, long, first, long, second, long, third, void *, ptr, long, fifth) +#define semctl(a,b,c,d) sys_ipc(IPCOP_semctl,a,b,c,&d,0l) +#endif _syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask) #ifdef __NR_exit_group _syscall1(int,exit_group,int,error_code) @@ -1255,6 +1263,21 @@ struct target_ipc_perm target_ulong __unused2; }; +struct target_ipc64_perm +{ + int key; + unsigned int uid; + unsigned int gid; + unsigned int cuid; + unsigned int cgid; + unsigned short mode; + unsigned short __pad1; + unsigned short seq; + unsigned short __pad2; + target_ulong __unused1; + target_ulong __unused2; +}; + struct target_semid_ds { struct target_ipc_perm sem_perm; @@ -1267,6 +1290,18 @@ struct target_semid_ds target_ulong __unused4; }; +struct target_semid64_ds +{ + struct target_ipc64_perm sem_perm; + target_ulong sem_otime; + target_ulong __unused1; + target_ulong sem_ctime; + target_ulong __unused2; + target_ulong sem_nsems; + target_ulong __unused3; + target_ulong __unused4; +}; + static inline void target_to_host_ipc_perm(struct ipc_perm *host_ip, target_ulong target_addr) { @@ -1301,6 +1336,41 @@ static inline void host_to_target_ipc_pe unlock_user_struct(target_sd, target_addr, 1); } +static inline void target_to_host_ipc64_perm( struct ipc64_perm *host_ip, target_ulong target_addr ) +{ + struct target_ipc64_perm *target_ip; + struct target_semid64_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 1); + target_ip=&(target_sd->sem_perm); + host_ip->key = tswapl(target_ip->key); + host_ip->uid = tswapl(target_ip->uid); + host_ip->gid = tswapl(target_ip->gid); + host_ip->cuid = tswapl(target_ip->cuid); + host_ip->cgid = tswapl(target_ip->cgid); + host_ip->mode = tswap16(target_ip->mode); + host_ip->seq = tswap16(target_ip->seq); + unlock_user_struct(target_sd, target_addr, 1); +} + +static inline void host_to_target_ipc64_perm(target_ulong target_addr, + struct ipc64_perm *host_ip) +{ + struct target_ipc64_perm *target_ip; + struct target_semid64_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 0); + target_ip = &(target_sd->sem_perm); + target_ip->key = tswapl(host_ip->key); + target_ip->uid = tswapl(host_ip->uid); + target_ip->gid = tswapl(host_ip->gid); + target_ip->cuid = tswapl(host_ip->cuid); + target_ip->cgid = tswapl(host_ip->cgid); + target_ip->mode = tswap16(host_ip->mode); + target_ip->seq = tswap16(host_ip->seq); + unlock_user_struct(target_sd, target_addr, 1); +} + static inline void target_to_host_semid_ds(struct semid_ds *host_sd, target_ulong target_addr) { @@ -1327,6 +1397,32 @@ static inline void host_to_target_semid_ unlock_user_struct(target_sd, target_addr, 1); } +static inline void target_to_host_semid64_ds(struct semid64_ds *host_sd, + target_ulong target_addr) +{ + struct target_semid64_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 1); + target_to_host_ipc64_perm(&(host_sd->sem_perm),target_addr); + 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); + unlock_user_struct(target_sd, target_addr, 0); +} + +static inline void host_to_target_semid64_ds(target_ulong target_addr, + struct semid64_ds *host_sd) +{ + struct target_semid64_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 0); + host_to_target_ipc64_perm(target_addr,&(host_sd->sem_perm)); + 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); + unlock_user_struct(target_sd, target_addr, 1); +} + union semun { int val; struct semid_ds *buf; @@ -1339,6 +1435,10 @@ union target_semun { unsigned short int *array; }; +#ifndef IPC_64 +#define IPC_64 0x100 +#endif + static inline void target_to_host_semun(unsigned long cmd, union semun *host_su, target_ulong target_addr, @@ -1350,7 +1450,16 @@ static inline void target_to_host_semun( case IPC_STAT: case IPC_SET: lock_user_struct(target_su, target_addr, 1); - target_to_host_semid_ds(ds,target_su->buf); + target_to_host_semid_ds(ds,tswapl(target_su->buf)); + host_su->buf = ds; + unlock_user_struct(target_su, target_addr, 0); + break; + case IPC_STAT + IPC_64: + case IPC_SET + IPC_64: + lock_user_struct(target_su, target_addr, 1); + + //target_to_host_semid_ds(ds,tswapl(target_su->buf)); + target_to_host_semid64_ds((struct semid64_ds *)ds,tswapl(target_su->buf)); host_su->buf = ds; unlock_user_struct(target_su, target_addr, 0); break; @@ -1382,7 +1491,14 @@ static inline void host_to_target_semun( case IPC_STAT: case IPC_SET: lock_user_struct(target_su, target_addr, 0); - host_to_target_semid_ds(target_su->buf,ds); + host_to_target_semid_ds(tswapl(target_su->buf),ds); + unlock_user_struct(target_su, target_addr, 1); + break; + case IPC_STAT + IPC_64: + case IPC_SET + IPC_64: + lock_user_struct(target_su, target_addr, 0); + //host_to_target_semid_ds(tswapl(target_su->buf),ds); + host_to_target_semid64_ds(tswapl(target_su->buf),(struct semid64_ds *)ds); unlock_user_struct(target_su, target_addr, 1); break; case GETVAL: @@ -1406,7 +1522,8 @@ static inline long do_semctl(long first, { union semun arg; struct semid_ds dsarg; - int cmd = third&0xff; + struct semid64_ds dsarg64; + int cmd = third; // & 0xff; long ret = 0; switch( cmd ) { @@ -1435,13 +1552,23 @@ static inline long do_semctl(long first, ret = get_errno(semctl(first, second, cmd, arg)); host_to_target_semun(cmd,ptr,&arg,&dsarg); break; + case IPC_STAT + IPC_64: + target_to_host_semun(cmd,&arg,ptr,(struct semid_ds *)&dsarg64); + ret = get_errno(semctl(first, second, cmd, arg)); + host_to_target_semun(cmd,ptr,&arg,(struct semid_ds *)&dsarg64); + 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: + case IPC_SET + IPC_64: + target_to_host_semun(cmd,&arg,ptr,(struct semid_ds *)&dsarg64); ret = get_errno(semctl(first, second, cmd, arg)); + host_to_target_semun(cmd,ptr,&arg,(struct semid_ds *)&dsarg64); + break; + default: + ret = get_errno(semctl(first, second, cmd & 0xff, arg)); } return ret; @@ -1465,6 +1592,42 @@ struct target_msqid_ds target_ulong __unused5; }; + +struct target_shmid64_ds { + struct target_ipc64_perm shm_perm; /* operation perms */ + target_ulong shm_segsz; /* size of segment (bytes) */ + target_ulong shm_atime; /* last attach time */ + target_ulong __unused1; + target_ulong shm_dtime; /* last detach time */ + target_ulong __unused2; + target_ulong shm_ctime; /* last change time */ + target_ulong __unused3; + int32_t shm_cpid; /* pid of creator */ + int32_t shm_lpid; /* pid of last operator */ + target_ulong shm_nattch; /* no. of current attaches */ + target_ulong __unused4; + target_ulong __unused5; +}; + +/* Data structure describing a set of semaphores. */ +struct target_shmid_ds + { + struct target_ipc_perm shm_perm; /* operation permission struct */ + unsigned int __unused1; + target_ulong shm_atime; /* time of last shmat() */ + unsigned int __unused2; + target_ulong shm_dtime; /* time of last shmdt() */ + unsigned int __unused3; + target_ulong shm_ctime; /* time of last change by shmctl() */ + unsigned int __unused4; + target_ulong shm_segsz; /* size of segment in bytes */ + unsigned int shm_cpid; /* pid of creator */ + unsigned int shm_lpid; /* pid of last shmop */ + target_ulong shm_nattch; /* number of current attaches */ + unsigned long __unused5; + unsigned long __unused6; + }; + static inline void target_to_host_msqid_ds(struct msqid_ds *host_md, target_ulong target_addr) { @@ -1665,11 +1828,59 @@ static long do_ipc(long call, long first case IPCOP_shmctl: switch(second) { case IPC_RMID: + case IPC_RMID + IPC_64: case SHM_LOCK: + case SHM_LOCK + IPC_64: case SHM_UNLOCK: + case SHM_UNLOCK + IPC_64: ret = get_errno(shmctl(first, second, NULL)); break; + case IPC_STAT + IPC_64: + { + struct shmid64_ds buf; + struct target_shmid64_ds *target_buf; +#ifdef DEBUG + gemu_log("qemu: doing IPC_STAT\n"); +#endif + lock_user_struct(target_buf, ptr, 1); + ret = get_errno(shmctl(first, second, (struct shmid_ds*)&buf)); + + host_to_target_ipc64_perm(ptr, &buf.shm_perm); + target_buf->shm_atime = tswapl(buf.shm_atime); + target_buf->shm_dtime = tswapl(buf.shm_dtime); + target_buf->shm_ctime = tswapl(buf.shm_ctime); + target_buf->shm_segsz = tswapl(buf.shm_segsz); + target_buf->shm_cpid = tswap32(buf.shm_cpid); + target_buf->shm_lpid = tswap32(buf.shm_lpid); + target_buf->shm_nattch = tswapl(buf.shm_nattch); + unlock_user_struct(target_buf, ptr, 0); + break; + } + case IPC_SET + IPC_64: + { + struct shmid64_ds buf; + struct target_shmid64_ds *target_buf; +#ifdef DEBUG + gemu_log("qemu: doing IPC_SET\n"); +#endif + lock_user_struct(target_buf, ptr, 1); + + target_to_host_ipc64_perm(&buf.shm_perm, ptr); + buf.shm_atime = tswapl(target_buf->shm_atime); + buf.shm_dtime = tswapl(target_buf->shm_dtime); + buf.shm_ctime = tswapl(target_buf->shm_ctime); + buf.shm_segsz = tswapl(target_buf->shm_segsz); + buf.shm_cpid = tswap32(target_buf->shm_cpid); + buf.shm_lpid = tswap32(target_buf->shm_lpid); + buf.shm_nattch = tswapl(target_buf->shm_nattch); + + ret = get_errno(shmctl(first, second, (struct shmid_ds*)&buf)); + + unlock_user_struct(target_buf, ptr, 0); + break; + } default: + gemu_log("Unsopported shmctl(%ld,%#lx)\n", second, second); goto unimplemented; } break;