All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH] ipc endianness and ipc_64 fixes
@ 2007-07-02 17:46 Alexander Graf
  0 siblings, 0 replies; only message in thread
From: Alexander Graf @ 2007-07-02 17:46 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 318 bytes --]

ipc_semop

This patch fixes an endianness issue with the semop-call.

ipc

This patch implements IPC_64 semantics to the semctl and shmctl calls.
This was tested on ppc host and i386 target and might work on others as
well. This is necessary to get alsa running.

As always: comments and suggestions appreciated

Alex

[-- Attachment #2: ipc --]
[-- Type: text/plain, Size: 12025 bytes --]

Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c
+++ qemu/linux-user/syscall.c
@@ -29,7 +29,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <time.h>
-#include <sys/types.h>
+#include <linux/types.h>
 #include <sys/ipc.h>
 #include <sys/msg.h>
 #include <sys/wait.h>
@@ -46,6 +46,9 @@
 #include <sys/uio.h>
 #include <sys/poll.h>
 #include <sys/times.h>
+#include <asm/ipcbuf.h>
+#include <asm/shmbuf.h>
+#include <asm/sembuf.h>
 #include <sys/shm.h>
 #include <sys/sem.h>
 #include <sys/statfs.h>
@@ -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;

[-- Attachment #3: ipc_semop --]
[-- Type: text/plain, Size: 872 bytes --]

Index: qemu/linux-user/syscall.c
===================================================================
--- qemu.orig/linux-user/syscall.c
+++ qemu/linux-user/syscall.c
@@ -1573,9 +1732,19 @@ static long do_ipc(long call, long first
 
     switch (call) {
     case IPCOP_semop:
-        ret = get_errno(semop(first,(struct sembuf *) ptr, second));
+    {
+	struct sembuf *target_sops;
+	int i;
+	lock_user_struct(target_sops, ptr, 0);
+	for(i=0; i<second; i++) {
+		target_sops[i].sem_num = tswap16(target_sops[i].sem_num);
+		target_sops[i].sem_op  = tswap16(target_sops[i].sem_op);
+		target_sops[i].sem_flg = tswap16(target_sops[i].sem_flg);
+	}
+        ret = get_errno(semop(first, target_sops, second));
+	unlock_user_struct(target_sops, ptr, 0);
         break;
-
+    }
     case IPCOP_semget:
         ret = get_errno(semget(first, second, third));
         break;

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2007-07-02 17:43 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-07-02 17:46 [Qemu-devel] [PATCH] ipc endianness and ipc_64 fixes Alexander Graf

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.