This is a refresh (vs 5/28 cvs) of a patch sent several weeks ago. This
patch implments the structure handling for the semaphore IPC related
structures used by semctl().

This was tested using LTP on an ARM target.

Were there any objections to this patch?



                                Stuart

Stuart R. Anderson                               [EMAIL PROTECTED]
Network & Software Engineering                   http://www.netsweng.com/
1024D/37A79149:                                  0791 D3B8 9A4C 2CDC A31F
                                                 BD03 0A62 E534 37A7 9149
Index: qemu/linux-user/i386/syscall.h
===================================================================
--- qemu.orig/linux-user/i386/syscall.h	2007-03-23 09:05:19.000000000 -0400
+++ qemu/linux-user/i386/syscall.h	2007-03-23 09:05:32.000000000 -0400
@@ -142,80 +142,4 @@
 	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: qemu/linux-user/ppc/syscall.h
===================================================================
--- qemu.orig/linux-user/ppc/syscall.h	2007-03-23 09:05:19.000000000 -0400
+++ qemu/linux-user/ppc/syscall.h	2007-03-23 09:05:32.000000000 -0400
@@ -51,80 +51,4 @@
  * 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: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c	2007-03-23 09:05:19.000000000 -0400
+++ qemu/linux-user/syscall.c	2007-03-23 09:05:49.000000000 -0400
@@ -1123,12 +1123,205 @@
     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;
+	target_long 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 GETALL:
+	case SETALL:
+	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;
+	default:
+	   host_su->array = tswapl(target_su->array);
+    }
+}
+
+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 GETALL:
+	case SETALL:
+	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;
+        default:
+	   target_su->array = tswapl(host_su->array);
+    }
+}
+
+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)
@@ -1152,8 +1345,7 @@
         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:

Reply via email to