Semaphore structure mapping, by Stuart Anderson.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 3 Jun 2007 14:26:27 +0000 (14:26 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Sun, 3 Jun 2007 14:26:27 +0000 (14:26 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2929 c046a42c-6fe2-441c-8c8c-71466251a162

linux-user/alpha/syscall.h
linux-user/i386/syscall.h
linux-user/ppc/syscall.h
linux-user/syscall.c

index def680e..6435817 100644 (file)
@@ -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"
index cc0942b..6e288b8 100644 (file)
@@ -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"
index eea8a7c..d150af4 100644 (file)
@@ -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"
index 1ec81ce..5d6bf8e 100644 (file)
@@ -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: