342 lines
11 KiB
Diff
342 lines
11 KiB
Diff
Index: qemu/linux-user/syscall.c
|
|
================================================================================
|
|
--- qemu/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>
|
|
@@ -164,6 +167,7 @@
|
|
#define __NR_sys_utimensat __NR_utimensat
|
|
#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
|
|
@@ -235,6 +239,10 @@
|
|
#ifdef __NR_sys_clone
|
|
_syscall5(int,sys_clone, int, flags, void *, child_stack, int *, parent_tidptr, void *, newtls, int *, child_tidptr)
|
|
#endif
|
|
+#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
|
|
#ifdef __NR_sys_sched_getaffinity
|
|
_syscall3(int,sys_sched_getaffinity,pid_t,pid,unsigned int,cpusetsize,void*,mask)
|
|
#endif
|
|
@@ -1464,6 +1472,21 @@
|
|
abi_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;
|
|
@@ -1476,6 +1499,18 @@
|
|
abi_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 abi_long target_to_host_ipc_perm(struct ipc_perm *host_ip,
|
|
abi_ulong target_addr)
|
|
{
|
|
@@ -1514,6 +1549,43 @@
|
|
return 0;
|
|
}
|
|
|
|
+static inline abi_long 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(VERIFY_READ, 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);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static inline abi_long 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(VERIFY_WRITE, 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);
|
|
+ return 0;
|
|
+}
|
|
+
|
|
static inline abi_long target_to_host_semid_ds(struct semid_ds *host_sd,
|
|
abi_ulong target_addr)
|
|
{
|
|
@@ -1544,6 +1616,32 @@
|
|
return 0;
|
|
}
|
|
|
|
+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(VERIFY_READ, 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(VERIFY_WRITE, 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;
|
|
@@ -1556,6 +1654,10 @@
|
|
unsigned short int *array;
|
|
};
|
|
|
|
+#ifndef IPC_64
|
|
+#define IPC_64 0x100
|
|
+#endif
|
|
+
|
|
static inline abi_long target_to_host_semun(int cmd,
|
|
union semun *host_su,
|
|
abi_ulong target_addr,
|
|
@@ -1568,7 +1670,15 @@
|
|
case IPC_SET:
|
|
if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
|
|
return -TARGET_EFAULT;
|
|
- 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:
|
|
+ if (!lock_user_struct(VERIFY_READ, target_su, target_addr, 1))
|
|
+ return -TARGET_EFAULT;
|
|
+ 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;
|
|
@@ -1604,7 +1714,14 @@
|
|
case IPC_SET:
|
|
if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
|
|
return -TARGET_EFAULT;
|
|
- 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:
|
|
+ if (lock_user_struct(VERIFY_WRITE, target_su, target_addr, 0))
|
|
+ return -TARGET_EFAULT;
|
|
+ host_to_target_semid64_ds(tswapl(target_su->buf),(struct semid64_ds*)ds);
|
|
unlock_user_struct(target_su, target_addr, 1);
|
|
break;
|
|
case GETVAL:
|
|
@@ -1632,7 +1749,8 @@
|
|
{
|
|
union semun arg;
|
|
struct semid_ds dsarg;
|
|
- int cmd = third&0xff;
|
|
+ struct semid64_ds dsarg64;
|
|
+ int cmd = third; // &0xff;
|
|
abi_long ret = 0;
|
|
|
|
switch( cmd ) {
|
|
@@ -1661,13 +1779,23 @@
|
|
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;
|
|
@@ -1691,6 +1819,41 @@
|
|
abi_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 abi_long target_to_host_msqid_ds(struct msqid_ds *host_md,
|
|
abi_ulong target_addr)
|
|
{
|
|
@@ -1919,11 +2082,59 @@
|
|
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(VERIFY_WRITE, 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(VERIFY_READ, 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;
|