[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH] some shm and socket work
From: |
Guillaume Morin |
Subject: |
[Qemu-devel] [PATCH] some shm and socket work |
Date: |
Thu, 19 Feb 2004 21:11:39 -0500 |
User-agent: |
Mutt/1.5.5.1+cvs20040105i |
Hi,
This patch has been coded by Paul McKerras <address@hidden>. It adds
SHM basic and some socketopt stuff.
diff -ur qemu-0.5.2/syscall.c qemu-0.5.2-dev/syscall.c
--- qemu-0.5.2/syscall.c 2004-01-25 10:50:02.000000000 -0500
+++ qemu-0.5.2-dev/syscall.c 2004-02-19 12:24:09.000000000 -0500
@@ -41,8 +41,10 @@
#include <sys/uio.h>
#include <sys/poll.h>
#include <sys/times.h>
+#include <sys/shm.h>
#include <utime.h>
//#include <sys/user.h>
+#include <netinet/ip.h>
#include <netinet/tcp.h>
#define termios host_termios
@@ -346,7 +348,7 @@
target_long v;
if (target_fds) {
- nw = n / TARGET_LONG_BITS;
+ nw = (n + TARGET_LONG_BITS - 1) / TARGET_LONG_BITS;
k = 0;
for(i = 0;i < nw; i++) {
v = 0;
@@ -551,6 +553,9 @@
static long do_setsockopt(int sockfd, int level, int optname,
void *optval, socklen_t optlen)
{
+ if ((unsigned long) optval < 0x1000)
+ return -EFAULT;
+
if (level == SOL_TCP) {
/* TCP options all take an 'int' value. */
int val;
@@ -562,7 +567,18 @@
return get_errno(setsockopt(sockfd, level, optname, &val,
sizeof(val)));
}
- else if (level != SOL_SOCKET) {
+ if (level == SOL_IP && optname == IP_HDRINCL) {
+ int val = 0;
+
+ if (optlen >= sizeof(uint32_t))
+ val = tswap32(*(uint32_t *)optval);
+ else if (optlen >= 1)
+ val = *(unsigned char *)optval;
+
+ return get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val)));
+ }
+
+ if (level != SOL_SOCKET) {
gemu_log("Unsupported setsockopt level: %d\n", level);
return -ENOSYS;
}
@@ -604,6 +620,31 @@
static long do_getsockopt(int sockfd, int level, int optname,
void *optval, socklen_t *optlen)
{
+ int32_t lv, result;
+
+ if (level == SOL_SOCKET) {
+ lv = sizeof(int32_t);
+ switch (optname) {
+ case SO_LINGER:
+ case SO_RCVTIMEO:
+ case SO_SNDTIMEO:
+ case SO_PEERCRED:
+ case SO_PEERNAME:
+ /* These don't just return a single integer */
+ goto unimp;
+ }
+ if (*optlen < 0)
+ return -EINVAL;
+ if (getsockopt(sockfd, level, optname, &result, &lv) == -1)
+ return -errno;
+ result = tswap32(result);
+ if (lv > *optlen)
+ lv = *optlen;
+ memcpy(optval, &result, lv);
+ return 0;
+ }
+
+ unimp:
gemu_log("getsockopt not yet supported\n");
return -ENOSYS;
}
@@ -844,6 +885,84 @@
return ret;
}
+
+#define N_SHM_REGIONS 32
+static struct shm_region {
+ uint32_t start;
+ uint32_t size;
+} shm_regions[N_SHM_REGIONS];
+
+static long do_ipc(long call, long first, long second, long third,
+ long ptr, long fifth)
+{
+ int version;
+ long ret = 0;
+ long raddr;
+ struct shmid_ds shm_info;
+ int i;
+
+ version = call >> 16;
+ call &= 0xffff;
+
+ switch (call) {
+ case IPCOP_shmat:
+ /* SHM_* flags are the same on all linux platforms */
+ raddr = (long) shmat(first, (void *) ptr, second);
+ if (raddr == -1) {
+ ret = -errno;
+ break;
+ }
+
+ /* find out the length of the shared memory segment */
+ if (shmctl(first, IPC_STAT, &shm_info) == -1) {
+ /* can't get length, bail out */
+ shmdt((void *) raddr);
+ ret = -errno;
+ break;
+ }
+ page_set_flags(raddr, raddr + shm_info.shm_segsz,
+ PAGE_VALID + PAGE_READ
+ + ((second & SHM_RDONLY)? 0: PAGE_WRITE));
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].start == 0) {
+ shm_regions[i].start = raddr;
+ shm_regions[i].size = shm_info.shm_segsz;
+ break;
+ }
+ }
+
+ *(uint32_t *)third = tswap32(raddr);
+ break;
+
+ case IPCOP_shmdt:
+ for (i = 0; i < N_SHM_REGIONS; ++i) {
+ if (shm_regions[i].start == ptr) {
+ shm_regions[i].start = 0;
+ page_set_flags(ptr, shm_regions[i].size, 0);
+ break;
+ }
+ }
+ ret = get_errno(shmdt((void *) ptr));
+ break;
+
+ case IPCOP_shmget:
+ /* IPC_* flag values are the same on all linux platforms */
+ ret = get_errno(shmget(first, second, third));
+ break;
+
+ case IPCOP_shmctl:
+ /* IPC_* and SHM_* command values are the same on all linux platforms */
+ ret = -ENOSYS; /* XXX lazy */
+ break;
+
+ default:
+ gemu_log("Unsupported ipc call: %ld (version %d)\n", call, version);
+ ret = -ENOSYS;
+ break;
+ }
+ return ret;
+}
+
/* kernel structure types definitions */
#define IFNAMSIZ 16
@@ -2224,7 +2343,8 @@
case TARGET_NR_sysinfo:
goto unimplemented;
case TARGET_NR_ipc:
- goto unimplemented;
+ ret = do_ipc(arg1, arg2, arg3, arg4, arg5, arg6);
+ break;
case TARGET_NR_fsync:
ret = get_errno(fsync(arg1));
break;
Seulement dans qemu-0.5.2-dev/: syscall.c.orig
diff -ur qemu-0.5.2/syscall_defs.h qemu-0.5.2-dev/syscall_defs.h
--- qemu-0.5.2/syscall_defs.h 2004-01-25 10:50:02.000000000 -0500
+++ qemu-0.5.2-dev/syscall_defs.h 2004-02-19 12:24:09.000000000 -0500
@@ -24,6 +24,19 @@
#define SOCKOP_sendmsg 16
#define SOCKOP_recvmsg 17
+#define IPCOP_semop 1
+#define IPCOP_semget 2
+#define IPCOP_semctl 3
+#define IPCOP_semtimedop 4
+#define IPCOP_msgsnd 11
+#define IPCOP_msgrcv 12
+#define IPCOP_msgget 13
+#define IPCOP_msgctl 14
+#define IPCOP_shmat 21
+#define IPCOP_shmdt 22
+#define IPCOP_shmget 23
+#define IPCOP_shmctl 24
+
/*
* The following is for compatibility across the various Linux
* platforms. The i386 ioctl numbering scheme doesn't really enforce
Guillaume.
PS: Please cc'me if you reply
--
Guillaume Morin <address@hidden>
I love you, I love you like a chocolate cake, like the trains, like the sea.
See me loving you, please. (Dionysos)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Qemu-devel] [PATCH] some shm and socket work,
Guillaume Morin <=