linux mmap2

Patrick Bihan-Faou bsdcvs-emul at mindstep.com
Thu Feb 26 00:07:40 PST 2004


Reid Linnemann wrote:

>Hey all, I've got a little dilemma I need some hints with...
>
>I am running FreeBSD 4.9-STABLE, and trying to get a linux binary operating 
>that uses mmap2. I've read a conversation kenneth culver had about his efforts, 
>and from what I can tell mmap2 is implemented in -CURRENT - but not in -STABLE. 
>Is there any way I can grab the -CURRENT version of the linuxulator, or 
>cut'n'paste the changes kenneth made, and get mmap2 working? I had found, and 
>later lost, kenneths record of changes he made to the linuxulator - if anyone 
>can point me to them I would appreciate that as well.
>
>  
>
In addition to mmap2 you'll probably need the ftruncate64 call. Here is 
a patch for FreeBSD 4.9 RELEASE that will add a few usefull syscalls. 
The implementation usually comes from FreeBSD 5.x or other not yet 
commited PRs. It has worked for me so far.

Patrick.

-------------- next part --------------
# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	.
#	./sys
#	./sys/compat
#	./sys/compat/linux
#	./sys/compat/linux/linux_file.c.patch
#	./sys/compat/linux/linux_ipc.c.patch
#	./sys/i386
#	./sys/i386/linux
#	./sys/i386/linux/linux.h.patch
#	./sys/i386/linux/linux_dummy.c.patch
#	./sys/i386/linux/linux_machdep.c.patch
#	./sys/i386/linux/linux_sysvec.c.patch
#
echo c - .
mkdir -p . > /dev/null 2>&1
echo c - ./sys
mkdir -p ./sys > /dev/null 2>&1
echo c - ./sys/compat
mkdir -p ./sys/compat > /dev/null 2>&1
echo c - ./sys/compat/linux
mkdir -p ./sys/compat/linux > /dev/null 2>&1
echo x - ./sys/compat/linux/linux_file.c.patch
sed 's/^X//' >./sys/compat/linux/linux_file.c.patch << 'SHAR-EOF-MARKER-73db4bcbd0dbd2530319f0beaf7528fd'
X--- linux_file.c.orig
X+++ linux_file.c
X@@ -654,6 +654,26 @@
X }
X 
X int
X+linux_truncate64(struct proc *p, struct linux_truncate64_args *args)
X+{
X+	struct truncate_args bsd;
X+	caddr_t sg;
X+
X+	sg = stackgap_init();
X+	CHECKALTEXIST(p, &sg, args->path);
X+
X+#ifdef DEBUG
X+	if (ldebug(truncate))
X+		printf(ARGS(truncate, "%s, %ld"), args->path,
X+		    (long)args->length);
X+#endif
X+	bsd.path = args->path;
X+	bsd.length = args->length; 
X+
X+	return truncate(p, &bsd);
X+}
X+
X+int
X linux_link(struct proc *p, struct linux_link_args *args)
X {
X     struct link_args bsd;
SHAR-EOF-MARKER-73db4bcbd0dbd2530319f0beaf7528fd
echo x - ./sys/compat/linux/linux_ipc.c.patch
sed 's/^X//' >./sys/compat/linux/linux_ipc.c.patch << 'SHAR-EOF-MARKER-567afdfde5ef3c7f68f72519ac8d7ca7'
X--- linux_ipc.c.orig
X+++ linux_ipc.c
X@@ -80,6 +80,20 @@
X 	l_ushort	seq;
X };
X 
X+struct l_ipc64_perm {
X+	l_key_t		key;
X+	l_uid_t		uid;
X+	l_gid_t		gid;
X+	l_uid_t		cuid;
X+	l_gid_t		cgid;
X+	l_ushort	mode;
X+	l_ushort	__pad1;
X+	l_ushort	seq;
X+	l_ushort	__pad2;
X+	l_ulong		__unused1;
X+	l_ulong		__unused2;
X+};
X+
X static void
X linux_to_bsd_ipc_perm(struct l_ipc_perm *lpp, struct ipc_perm *bpp)
X {
X@@ -92,6 +106,18 @@
X     bpp->seq = lpp->seq;
X }
X 
X+static void
X+linux_to_bsd_ipc64_perm(struct l_ipc64_perm *lpp, struct ipc_perm *bpp)
X+{
X+    bpp->key = lpp->key;
X+    bpp->uid = lpp->uid;
X+    bpp->gid = lpp->gid;
X+    bpp->cuid = lpp->cuid;
X+    bpp->cgid = lpp->cgid;
X+    bpp->mode = lpp->mode;
X+    bpp->seq = lpp->seq;
X+}
X+
X 
X static void
X bsd_to_linux_ipc_perm(struct ipc_perm *bpp, struct l_ipc_perm *lpp)
X@@ -105,6 +131,18 @@
X     lpp->seq = bpp->seq;
X }
X 
X+static void
X+bsd_to_linux_ipc64_perm(struct ipc_perm *bpp, struct l_ipc64_perm *lpp)
X+{
X+    lpp->key = bpp->key;
X+    lpp->uid = bpp->uid;
X+    lpp->gid = bpp->gid;
X+    lpp->cuid = bpp->cuid;
X+    lpp->cgid = bpp->cgid;
X+    lpp->mode = bpp->mode;
X+    lpp->seq = bpp->seq;
X+}
X+
X struct l_semid_ds {
X 	struct l_ipc_perm	sem_perm;
X 	l_time_t		sem_otime;
X@@ -116,6 +154,17 @@
X 	l_ushort		sem_nsems;
X };
X 
X+struct l_semid64_ds {
X+	struct l_ipc64_perm	sem_perm;
X+	l_time_t		sem_otime;
X+	l_time_t		sem_ctime;
X+	void			*sem_base;
X+	void			*sem_pending;
X+	void			*sem_pending_last;
X+	void			*undo;
X+	l_ushort		sem_nsems;
X+};
X+
X struct l_shmid_ds {
X 	struct l_ipc_perm	shm_perm;
X 	l_int			shm_segsz;
X@@ -130,6 +179,20 @@
X 	void			*private3;
X };
X 
X+struct l_shmid64_ds {
X+	struct l_ipc64_perm	shm_perm;
X+	l_int			shm_segsz;
X+	l_time_t		shm_atime;
X+	l_time_t		shm_dtime;
X+	l_time_t		shm_ctime;
X+	l_ushort		shm_cpid;
X+	l_ushort		shm_lpid;
X+	l_short			shm_nattch;
X+	l_ushort		private1;
X+	void			*private2;
X+	void			*private3;
X+};
X+
X static void
X linux_to_bsd_semid_ds(struct l_semid_ds *lsp, struct semid_ds *bsp)
X {
X@@ -141,6 +204,16 @@
X }
X 
X static void
X+linux_to_bsd_semid64_ds(struct l_semid64_ds *lsp, struct semid_ds *bsp)
X+{
X+    linux_to_bsd_ipc64_perm(&lsp->sem_perm, &bsp->sem_perm);
X+    bsp->sem_otime = lsp->sem_otime;
X+    bsp->sem_ctime = lsp->sem_ctime;
X+    bsp->sem_nsems = lsp->sem_nsems;
X+    bsp->sem_base = lsp->sem_base;
X+}
X+
X+static void
X bsd_to_linux_semid_ds(struct semid_ds *bsp, struct l_semid_ds *lsp)
X {
X 	bsd_to_linux_ipc_perm(&bsp->sem_perm, &lsp->sem_perm);
X@@ -151,6 +224,16 @@
X }
X 
X static void
X+bsd_to_linux_semid64_ds(struct semid_ds *bsp, struct l_semid64_ds *lsp)
X+{
X+	bsd_to_linux_ipc64_perm(&bsp->sem_perm, &lsp->sem_perm);
X+	lsp->sem_otime = bsp->sem_otime;
X+	lsp->sem_ctime = bsp->sem_ctime;
X+	lsp->sem_nsems = bsp->sem_nsems;
X+	lsp->sem_base = bsp->sem_base;
X+}
X+
X+static void
X linux_to_bsd_shmid_ds(struct l_shmid_ds *lsp, struct shmid_ds *bsp)
X {
X     linux_to_bsd_ipc_perm(&lsp->shm_perm, &bsp->shm_perm);
X@@ -163,6 +246,19 @@
X     bsp->shm_ctime = lsp->shm_ctime;
X     bsp->shm_internal = lsp->private3;	/* this goes (yet) SOS */
X }
X+static void
X+linux_to_bsd_shmid64_ds(struct l_shmid64_ds *lsp, struct shmid_ds *bsp)
X+{
X+    linux_to_bsd_ipc64_perm(&lsp->shm_perm, &bsp->shm_perm);
X+    bsp->shm_segsz = lsp->shm_segsz;
X+    bsp->shm_lpid = lsp->shm_lpid;
X+    bsp->shm_cpid = lsp->shm_cpid;
X+    bsp->shm_nattch = lsp->shm_nattch;
X+    bsp->shm_atime = lsp->shm_atime;
X+    bsp->shm_dtime = lsp->shm_dtime;
X+    bsp->shm_ctime = lsp->shm_ctime;
X+    bsp->shm_internal = lsp->private3;	/* this goes (yet) SOS */
X+}
X 
X static void
X bsd_to_linux_shmid_ds(struct shmid_ds *bsp, struct l_shmid_ds *lsp)
X@@ -178,6 +274,20 @@
X     lsp->private3 = bsp->shm_internal;	/* this goes (yet) SOS */
X }
X 
X+static void
X+bsd_to_linux_shmid64_ds(struct shmid_ds *bsp, struct l_shmid64_ds *lsp)
X+{
X+    bsd_to_linux_ipc64_perm(&bsp->shm_perm, &lsp->shm_perm);
X+    lsp->shm_segsz = bsp->shm_segsz;
X+    lsp->shm_lpid = bsp->shm_lpid;
X+    lsp->shm_cpid = bsp->shm_cpid;
X+    lsp->shm_nattch = bsp->shm_nattch;
X+    lsp->shm_atime = bsp->shm_atime;
X+    lsp->shm_dtime = bsp->shm_dtime;
X+    lsp->shm_ctime = bsp->shm_ctime;
X+    lsp->private3 = bsp->shm_internal;	/* this goes (yet) SOS */
X+}
X+
X int
X linux_semop(struct proc *p, struct linux_semop_args *args)
X {
X@@ -212,6 +322,7 @@
X linux_semctl(struct proc *p, struct linux_semctl_args *args)
X {
X 	struct l_semid_ds linux_semid;
X+	struct l_semid64_ds linux_semid64;
X 	struct __semctl_args /* {
X 		int		semid;
X 		int		semnum;
X@@ -261,6 +372,15 @@
X 		unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X 		linux_to_bsd_semid_ds(&linux_semid, unptr->buf);
X 		return __semctl(p, &bsd_args);
X+	case LINUX_IPC_SET|LINUX_IPC_64:
X+		bsd_args.cmd = IPC_SET;
X+		error = copyin((caddr_t)args->arg.buf, &linux_semid64,
X+		    sizeof(linux_semid64));
X+		if (error)
X+			return (error);
X+		unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X+		linux_to_bsd_semid64_ds(&linux_semid64, unptr->buf);
X+		return __semctl(p, &bsd_args);
X 	case LINUX_IPC_STAT:
X 		bsd_args.cmd = IPC_STAT;
X 		unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X@@ -272,6 +392,17 @@
X 		bsd_to_linux_semid_ds(unptr->buf, &linux_semid);
X 		return copyout(&linux_semid, (caddr_t)args->arg.buf,
X 					    sizeof(linux_semid));
X+	case LINUX_IPC_STAT|LINUX_IPC_64:
X+		bsd_args.cmd = IPC_STAT;
X+		unptr->buf = stackgap_alloc(&sg, sizeof(struct semid_ds));
X+		error = __semctl(p, &bsd_args);
X+		if (error)
X+			return error;
X+		p->p_retval[0] = IXSEQ_TO_IPCID(bsd_args.semid, 
X+							unptr->buf->sem_perm);
X+		bsd_to_linux_semid64_ds(unptr->buf, &linux_semid64);
X+		return copyout(&linux_semid64, (caddr_t)args->arg.buf,
X+					    sizeof(linux_semid64));
X 	case LINUX_IPC_INFO:
X 	case LINUX_SEM_INFO:
X 		error = copyin((caddr_t)args->arg.buf, &linux_seminfo, 
X@@ -421,6 +552,7 @@
X linux_shmctl(struct proc *p, struct linux_shmctl_args *args)
X {
X     struct l_shmid_ds linux_shmid;
X+    struct l_shmid64_ds linux_shmid64;
X     struct shmctl_args /* {
X 	int shmid;
X 	int cmd;
X@@ -439,6 +571,15 @@
X 	bsd_to_linux_shmid_ds(bsd_args.buf, &linux_shmid);
X 	return copyout(&linux_shmid, (caddr_t)args->buf, sizeof(linux_shmid));
X 
X+    case LINUX_IPC_STAT|LINUX_IPC_64:
X+	bsd_args.shmid = args->shmid;
X+	bsd_args.cmd = IPC_STAT;
X+	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+	if ((error = shmctl(p, &bsd_args)))
X+	    return error;
X+	bsd_to_linux_shmid64_ds(bsd_args.buf, &linux_shmid64);
X+	return copyout(&linux_shmid64, (caddr_t)args->buf, sizeof(linux_shmid64));
X+
X     case LINUX_IPC_SET:
X 	if ((error = copyin((caddr_t)args->buf, &linux_shmid,
X 		sizeof(linux_shmid))))
X@@ -449,6 +590,16 @@
X 	bsd_args.cmd = IPC_SET;
X 	return shmctl(p, &bsd_args);
X 
X+    case LINUX_IPC_SET|LINUX_IPC_64:
X+	if ((error = copyin((caddr_t)args->buf, &linux_shmid64,
X+		sizeof(linux_shmid64))))
X+	    return error;
X+	bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+	linux_to_bsd_shmid64_ds(&linux_shmid64, bsd_args.buf);
X+	bsd_args.shmid = args->shmid;
X+	bsd_args.cmd = IPC_SET;
X+	return shmctl(p, &bsd_args);
X+
X     case LINUX_IPC_RMID:
X 	bsd_args.shmid = args->shmid;
X 	bsd_args.cmd = IPC_RMID;
X@@ -460,6 +611,20 @@
X 		return error;
X 	    bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X 	    linux_to_bsd_shmid_ds(&linux_shmid, bsd_args.buf);
X+	}
X+	return shmctl(p, &bsd_args);
X+
X+    case LINUX_IPC_RMID|LINUX_IPC_64:
X+	bsd_args.shmid = args->shmid;
X+	bsd_args.cmd = IPC_RMID;
X+	if (args->buf == NULL)
X+	    bsd_args.buf = NULL;
X+	else {
X+	    if ((error = copyin((caddr_t)args->buf, &linux_shmid64, 
X+		    		sizeof(linux_shmid64))))
X+		return error;
X+	    bsd_args.buf = (struct shmid_ds*)stackgap_alloc(&sg, sizeof(struct shmid_ds));
X+	    linux_to_bsd_shmid64_ds(&linux_shmid64, bsd_args.buf);
X 	}
X 	return shmctl(p, &bsd_args);
X 
SHAR-EOF-MARKER-567afdfde5ef3c7f68f72519ac8d7ca7
echo c - ./sys/i386
mkdir -p ./sys/i386 > /dev/null 2>&1
echo c - ./sys/i386/linux
mkdir -p ./sys/i386/linux > /dev/null 2>&1
echo x - ./sys/i386/linux/linux.h.patch
sed 's/^X//' >./sys/i386/linux/linux.h.patch << 'SHAR-EOF-MARKER-0e3d93c3f5eb4a3d5b1172cad960e4ba'
X--- linux.h.orig
X+++ linux.h
X@@ -532,6 +532,9 @@
X #define	LINUX_IPC_STAT		2
X #define	LINUX_IPC_INFO		3
X 
X+#define LINUX_IPC_OLD		0
X+#define LINUX_IPC_64		0x0100
X+
X #define	LINUX_SHM_LOCK		11
X #define	LINUX_SHM_UNLOCK	12
X #define	LINUX_SHM_STAT		13
SHAR-EOF-MARKER-0e3d93c3f5eb4a3d5b1172cad960e4ba
echo x - ./sys/i386/linux/linux_dummy.c.patch
sed 's/^X//' >./sys/i386/linux/linux_dummy.c.patch << 'SHAR-EOF-MARKER-1b3f6aae2a39aa5043a0bf5f1e7e0cb4'
X--- linux_dummy.c.orig
X+++ linux_dummy.c
X@@ -64,8 +64,8 @@
X DUMMY(capget);
X DUMMY(capset);
X DUMMY(sendfile);
X-DUMMY(mmap2);
X-DUMMY(truncate64);
X+/*DUMMY(mmap2);*/
X+/*DUMMY(truncate64);*/
X DUMMY(setfsuid);
X DUMMY(setfsgid);
X DUMMY(pivot_root);
SHAR-EOF-MARKER-1b3f6aae2a39aa5043a0bf5f1e7e0cb4
echo x - ./sys/i386/linux/linux_machdep.c.patch
sed 's/^X//' >./sys/i386/linux/linux_machdep.c.patch << 'SHAR-EOF-MARKER-013eaf3882bdcd8e8dd36a2101827a2e'
X--- linux_machdep.c.orig
X+++ linux_machdep.c
X@@ -381,6 +381,120 @@
X #define GUARD_SIZE  (4 * PAGE_SIZE)
X 
X int
X+linux_mmap2(struct proc *p, struct linux_mmap2_args *linux_args)
X+{
X+	struct mmap_args /* {
X+		caddr_t addr;
X+		size_t len;
X+		int prot;
X+		int flags;
X+		int fd;
X+		long pad;
X+		off_t pos;
X+	} */ bsd_args;
X+
X+#ifdef DEBUG
X+	if (ldebug(mmap2))
X+		printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
X+		    (void *)linux_args->addr, linux_args->len, linux_args->prot,
X+		    linux_args->flags, linux_args->fd, linux_args->pos);
X+#endif
X+	    
X+	bsd_args.flags = 0;
X+	if (linux_args->flags & LINUX_MAP_SHARED)
X+		bsd_args.flags |= MAP_SHARED;
X+	if (linux_args->flags & LINUX_MAP_PRIVATE)
X+		bsd_args.flags |= MAP_PRIVATE;
X+	if (linux_args->flags & LINUX_MAP_FIXED)
X+		bsd_args.flags |= MAP_FIXED;
X+	if (linux_args->flags & LINUX_MAP_ANON)
X+		bsd_args.flags |= MAP_ANON;
X+	else
X+		bsd_args.flags |= MAP_NOSYNC;
X+	if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
X+		bsd_args.flags |= MAP_STACK;
X+
X+		/* The linux MAP_GROWSDOWN option does not limit auto
X+		 * growth of the region.  Linux mmap with this option
X+		 * takes as addr the inital BOS, and as len, the initial
X+		 * region size.  It can then grow down from addr without
X+		 * limit.  However, linux threads has an implicit internal
X+		 * limit to stack size of STACK_SIZE.  Its just not
X+		 * enforced explicitly in linux.  But, here we impose
X+		 * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
X+		 * region, since we can do this with our mmap.
X+		 *
X+		 * Our mmap with MAP_STACK takes addr as the maximum
X+		 * downsize limit on BOS, and as len the max size of
X+		 * the region.  It them maps the top SGROWSIZ bytes,
X+		 * and autgrows the region down, up to the limit
X+		 * in addr.
X+		 *
X+		 * If we don't use the MAP_STACK option, the effect
X+		 * of this code is to allocate a stack region of a
X+		 * fixed size of (STACK_SIZE - GUARD_SIZE).
X+		 */
X+
X+		/* This gives us TOS */
X+		bsd_args.addr = (caddr_t)(linux_args->addr + linux_args->len);
X+
X+		if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
X+			/* Some linux apps will attempt to mmap
X+			 * thread stacks near the top of their
X+			 * address space.  If their TOS is greater
X+			 * than vm_maxsaddr, vm_map_growstack()
X+			 * will confuse the thread stack with the
X+			 * process stack and deliver a SEGV if they
X+			 * attempt to grow the thread stack past their
X+			 * current stacksize rlimit.  To avoid this,
X+			 * adjust vm_maxsaddr upwards to reflect
X+			 * the current stacksize rlimit rather
X+			 * than the maximum possible stacksize.
X+			 * It would be better to adjust the
X+			 * mmap'ed region, but some apps do not check
X+			 * mmap's return value.
X+			 */
X+			p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
X+			    p->p_rlimit[RLIMIT_STACK].rlim_cur;
X+		}
X+
X+		/* This gives us our maximum stack size */
X+		if (linux_args->len > STACK_SIZE - GUARD_SIZE)
X+			bsd_args.len = linux_args->len;
X+		else
X+			bsd_args.len  = STACK_SIZE - GUARD_SIZE;
X+
X+		/* This gives us a new BOS.  If we're using VM_STACK, then
X+		 * mmap will just map the top SGROWSIZ bytes, and let
X+		 * the stack grow down to the limit at BOS.  If we're
X+		 * not using VM_STACK we map the full stack, since we
X+		 * don't have a way to autogrow it.
X+		 */
X+		bsd_args.addr -= bsd_args.len;
X+	} else {
X+		bsd_args.addr = (caddr_t)linux_args->addr;
X+		bsd_args.len  = linux_args->len;
X+	}
X+
X+	bsd_args.prot = linux_args->prot | PROT_READ;	/* always required */
X+	if (linux_args->flags & LINUX_MAP_ANON)
X+		bsd_args.fd = -1;
X+	else
X+		bsd_args.fd = linux_args->fd;
X+	bsd_args.pos = ctob(linux_args->pgoff);
X+	bsd_args.pad = 0;
X+
X+#ifdef DEBUG
X+	if (ldebug(mmap2))
X+		printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n",
X+		    (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
X+		    bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
X+#endif
X+
X+	return (mmap(p, &bsd_args));
X+}
X+
X+int
X linux_mmap(struct proc *p, struct linux_mmap_args *args)
X {
X 	struct mmap_args /* {
SHAR-EOF-MARKER-013eaf3882bdcd8e8dd36a2101827a2e
echo x - ./sys/i386/linux/linux_sysvec.c.patch
sed 's/^X//' >./sys/i386/linux/linux_sysvec.c.patch << 'SHAR-EOF-MARKER-5063296fed19fdb032d23975e4efcbfc'
X--- linux_sysvec.c.orig
X+++ linux_sysvec.c
X@@ -722,6 +722,7 @@
X 	args[2] = tf->tf_edx;
X 	args[3] = tf->tf_esi;
X 	args[4] = tf->tf_edi;
X+	args[5] = tf->tf_ebp;	/* tf_ebp taken from linux glibc sources */
X 	*params = NULL;		/* no copyin */
X }
X 
SHAR-EOF-MARKER-5063296fed19fdb032d23975e4efcbfc
exit



More information about the freebsd-emulation mailing list