diff options
-rw-r--r-- | linux-user/alpha/syscall.h | 74 | ||||
-rw-r--r-- | linux-user/i386/syscall.h | 76 | ||||
-rw-r--r-- | linux-user/ppc/syscall.h | 76 | ||||
-rw-r--r-- | linux-user/syscall.c | 206 |
4 files changed, 203 insertions, 229 deletions
diff --git a/linux-user/alpha/syscall.h b/linux-user/alpha/syscall.h index def680e5a7..6435817881 100644 --- a/linux-user/alpha/syscall.h +++ b/linux-user/alpha/syscall.h @@ -38,78 +38,4 @@ struct target_pt_regs { target_ulong unique; }; -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { - int val; - unsigned int buf; /* really struct semid_ds * */ - unsigned int array; /* really unsigned short * */ - unsigned int __buf; /* really struct seminfo * */ - unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "alpha" diff --git a/linux-user/i386/syscall.h b/linux-user/i386/syscall.h index cc0942b811..6e288b8041 100644 --- a/linux-user/i386/syscall.h +++ b/linux-user/i386/syscall.h @@ -142,80 +142,4 @@ struct target_vm86plus_struct { struct target_vm86plus_info_struct vm86plus; }; -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { - int val; - unsigned int buf; /* really struct semid_ds * */ - unsigned int array; /* really unsigned short * */ - unsigned int __buf; /* really struct seminfo * */ - unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "i686" diff --git a/linux-user/ppc/syscall.h b/linux-user/ppc/syscall.h index eea8a7c9ab..d150af44cb 100644 --- a/linux-user/ppc/syscall.h +++ b/linux-user/ppc/syscall.h @@ -51,80 +51,4 @@ struct target_revectored_struct { * flags masks */ -/* ipcs */ - -#define TARGET_SEMOP 1 -#define TARGET_SEMGET 2 -#define TARGET_SEMCTL 3 -#define TARGET_MSGSND 11 -#define TARGET_MSGRCV 12 -#define TARGET_MSGGET 13 -#define TARGET_MSGCTL 14 -#define TARGET_SHMAT 21 -#define TARGET_SHMDT 22 -#define TARGET_SHMGET 23 -#define TARGET_SHMCTL 24 - -struct target_msgbuf { - int mtype; - char mtext[1]; -}; - -struct target_ipc_kludge { - unsigned int msgp; /* Really (struct msgbuf *) */ - int msgtyp; -}; - -struct target_ipc_perm { - int key; - unsigned short uid; - unsigned short gid; - unsigned short cuid; - unsigned short cgid; - unsigned short mode; - unsigned short seq; -}; - -struct target_msqid_ds { - struct target_ipc_perm msg_perm; - unsigned int msg_first; /* really struct target_msg* */ - unsigned int msg_last; /* really struct target_msg* */ - unsigned int msg_stime; /* really target_time_t */ - unsigned int msg_rtime; /* really target_time_t */ - unsigned int msg_ctime; /* really target_time_t */ - unsigned int wwait; /* really struct wait_queue* */ - unsigned int rwait; /* really struct wait_queue* */ - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - unsigned short msg_lspid; - unsigned short msg_lrpid; -}; - -struct target_shmid_ds { - struct target_ipc_perm shm_perm; - int shm_segsz; - unsigned int shm_atime; /* really target_time_t */ - unsigned int shm_dtime; /* really target_time_t */ - unsigned int shm_ctime; /* really target_time_t */ - unsigned short shm_cpid; - unsigned short shm_lpid; - short shm_nattch; - unsigned short shm_npages; - unsigned long *shm_pages; - void *attaches; /* really struct shm_desc * */ -}; - -#define TARGET_IPC_RMID 0 -#define TARGET_IPC_SET 1 -#define TARGET_IPC_STAT 2 - -union target_semun { - int val; - unsigned int buf; /* really struct semid_ds * */ - unsigned int array; /* really unsigned short * */ - unsigned int __buf; /* really struct seminfo * */ - unsigned int __pad; /* really void* */ -}; - #define UNAME_MACHINE "ppc" diff --git a/linux-user/syscall.c b/linux-user/syscall.c index 1ec81ce5be..5d6bf8e946 100644 --- a/linux-user/syscall.c +++ b/linux-user/syscall.c @@ -1230,12 +1230,213 @@ static struct shm_region { uint32_t size; } shm_regions[N_SHM_REGIONS]; +struct target_ipc_perm +{ + target_long __key; + target_ulong uid; + target_ulong gid; + target_ulong cuid; + target_ulong cgid; + unsigned short int mode; + unsigned short int __pad1; + unsigned short int __seq; + unsigned short int __pad2; + target_ulong __unused1; + target_ulong __unused2; +}; + +struct target_semid_ds +{ + struct target_ipc_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) +{ + struct target_ipc_perm *target_ip; + struct target_semid_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 = tswapl(target_ip->mode); + unlock_user_struct(target_sd, target_addr, 0); +} + +static inline void host_to_target_ipc_perm(target_ulong target_addr, + struct ipc_perm *host_ip) +{ + struct target_ipc_perm *target_ip; + struct target_semid_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 = tswapl(host_ip->mode); + 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) +{ + struct target_semid_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 1); + target_to_host_ipc_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_semid_ds(target_ulong target_addr, + struct semid_ds *host_sd) +{ + struct target_semid_ds *target_sd; + + lock_user_struct(target_sd, target_addr, 0); + host_to_target_ipc_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 senid_ds *buf; + struct semid_ds *buf; unsigned short *array; }; +union target_semun { + int val; + target_long buf; + unsigned short int *array; +}; + +static inline void target_to_host_semun(unsigned long cmd, + union semun *host_su, + target_ulong target_addr, + struct semid_ds *ds) +{ + union target_semun *target_su; + + switch( cmd ) { + case IPC_STAT: + case IPC_SET: + lock_user_struct(target_su, target_addr, 1); + 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: + lock_user_struct(target_su, target_addr, 1); + host_su->val = tswapl(target_su->val); + unlock_user_struct(target_su, target_addr, 0); + break; + case GETALL: + case SETALL: + lock_user_struct(target_su, target_addr, 1); + *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); + } +} + +static inline void host_to_target_semun(unsigned long cmd, + target_ulong target_addr, + union semun *host_su, + struct semid_ds *ds) +{ + union target_semun *target_su; + + switch( cmd ) { + case IPC_STAT: + case IPC_SET: + lock_user_struct(target_su, target_addr, 0); + host_to_target_semid_ds(target_su->buf,ds); + unlock_user_struct(target_su, target_addr, 1); + break; + case GETVAL: + case SETVAL: + lock_user_struct(target_su, target_addr, 0); + target_su->val = tswapl(host_su->val); + unlock_user_struct(target_su, target_addr, 1); + break; + case GETALL: + case SETALL: + lock_user_struct(target_su, target_addr, 0); + *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); + } +} + +static inline long do_semctl(long first, long second, long third, long ptr) +{ + union semun arg; + struct semid_ds dsarg; + int cmd = third&0xff; + long ret = 0; + + 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)); + } + + return ret; +} + /* ??? This only works with linear mappings. */ static long do_ipc(long call, long first, long second, long third, long ptr, long fifth) @@ -1259,8 +1460,7 @@ static long do_ipc(long call, long first, long second, long third, break; case IPCOP_semctl: - ret = get_errno(semctl(first, second, third, ((union semun*)ptr)->val)); - + ret = do_semctl(first, second, third, ptr); break; case IPCOP_semtimedop: |