342 lines
12 KiB
Diff
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;
|