qemu/qemu-cvs-ipc.patch

342 lines
12 KiB
Diff

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;