365 lines
12 KiB
Diff
365 lines
12 KiB
Diff
Index: qemu/linux-user/syscall.c
|
|
================================================================================
|
|
--- qemu-0.10.1/linux-user/syscall.c
|
|
+++ qemu-0.10.1/linux-user/syscall.c
|
|
@@ -29,7 +29,7 @@
|
|
#include <fcntl.h>
|
|
#include <time.h>
|
|
#include <limits.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>
|
|
@@ -158,6 +161,7 @@
|
|
|
|
#define __NR_sys_exit __NR_exit
|
|
#define __NR_sys_sched_getaffinity __NR_sched_getaffinity
|
|
+#define __NR_sys_ipc __NR_ipc
|
|
#define __NR_sys_uname __NR_uname
|
|
#define __NR_sys_faccessat __NR_faccessat
|
|
#define __NR_sys_fchmodat __NR_fchmodat
|
|
@@ -266,6 +270,10 @@
|
|
#if defined(TARGET_NR_tkill) && defined(__NR_tkill)
|
|
_syscall2(int,sys_tkill,int,tid,int,sig)
|
|
#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
|
|
@@ -1687,6 +1695,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)
|
|
{
|
|
@@ -1725,6 +1745,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)
|
|
{
|
|
@@ -1755,6 +1812,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;
|
|
@@ -1767,6 +1850,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,
|
|
@@ -1779,7 +1866,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;
|
|
@@ -1815,7 +1910,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:
|
|
@@ -1843,7 +1945,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 ) {
|
|
@@ -1872,13 +1975,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;
|
|
@@ -1908,6 +2021,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)
|
|
{
|
|
@@ -2193,11 +2341,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;
|
|
--- qemu-0.10.1/linux-user/syscall_defs.h
|
|
+++ qemu-0.10.1/linux-user/syscall_defs.h
|
|
@@ -2001,3 +2001,18 @@
|
|
#include "socket.h"
|
|
|
|
#include "errno_defs.h"
|
|
+
|
|
+struct target_ipc64_perm
|
|
+{
|
|
+ int key;
|
|
+ uint32_t uid;
|
|
+ uint32_t gid;
|
|
+ uint32_t cuid;
|
|
+ uint32_t cgid;
|
|
+ unsigned short mode;
|
|
+ unsigned short __pad1;
|
|
+ unsigned short seq;
|
|
+ unsigned short __pad2;
|
|
+ abi_ulong __unused1;
|
|
+ abi_ulong __unused2;
|
|
+};
|
|
--- qemu-0.10.1/linux-user/x86_64/syscall.h
|
|
+++ qemu-0.10.1/linux-user/x86_64/syscall.h
|
|
@@ -61,21 +61,6 @@
|
|
};
|
|
#endif
|
|
|
|
-struct target_ipc64_perm
|
|
-{
|
|
- int key;
|
|
- uint32_t uid;
|
|
- uint32_t gid;
|
|
- uint32_t cuid;
|
|
- uint32_t cgid;
|
|
- unsigned short mode;
|
|
- unsigned short __pad1;
|
|
- unsigned short seq;
|
|
- unsigned short __pad2;
|
|
- abi_ulong __unused1;
|
|
- abi_ulong __unused2;
|
|
-};
|
|
-
|
|
struct target_msqid64_ds {
|
|
struct target_ipc64_perm msg_perm;
|
|
unsigned int msg_stime; /* last msgsnd time */
|