kern/45785: Linux WineX seems to require a few new linux
syscalls
No Name
arundel at h3c.de
Mon Aug 23 13:40:31 PDT 2004
The following reply was made to PR kern/45785; it has been noted by GNATS.
From: No Name <arundel at h3c.de>
To: FreeBSD-gnats-submit at freebsd.org
Cc:
Subject: Re: kern/45785: Linux WineX seems to require a few new linux syscalls
Date: Mon, 23 Aug 2004 22:41:53 +0200 (CEST)
>Submitter-Id: current-users
>Originator: No Name
>Organization:
>Confidential: no
>Synopsis: Re: kern/45785: Linux WineX seems to require a few new linux syscalls
>Severity: non-critical
>Priority: medium
>Category: kern
>Class: sw-bug
>Release: FreeBSD 4.10-STABLE i386
>Environment:
System: FreeBSD skatecity 4.10-STABLE FreeBSD 4.10-STABLE #0: Mon Aug 23 20:56:48 CEST 2004 arundel at skatecity:/usr/obj/usr/src/sys/ARUNDEL i386
>Description:
I don't know abou the current state of mmap2 in -STABLE, but I got really pissed with the constant error output to tty.
Since the original patch by Kenneth does not apply 100% clean to RELENG_4 I made a few dirty changes to it.
Surprisingly I got an increas of roughly 70 frames running this patch and quake3-linux (timedemo 1 - four.dm_68).
>How-To-Repeat:
>Fix:
--- mmap2-patch.diff begins here ---
--- compat/linux/linux_file.c.orig Mon Aug 23 21:19:35 2004
+++ compat/linux/linux_file.c Mon Aug 23 21:39:21 2004
@@ -685,6 +685,37 @@
}
int
+linux_truncate64(struct proc *p, struct linux_truncate64_args *args)
+{
+ struct truncate_args bsd;
+ caddr_t sg;
+
+ sg = stackgap_init();
+ CHECKALTEXIST(p, &sg, args->path);
+
+#ifdef DEBUG
+ if (ldebug(truncate))
+ printf(ARGS(truncate, "%s, %ld"), args->path,
+ (long)args->length);
+#endif
+ bsd.path = args->path;
+ bsd.length = args->length;
+
+ return truncate(p, &bsd);
+}
+
+int
+linux_ftruncate64(struct proc *p, struct linux_ftruncate64_args *args)
+{
+ struct ftruncate_args bsd;
+
+ bsd.fd = args->fd;
+ bsd.length = args->length;
+
+ return ftruncate(p, &bsd);
+}
+
+int
linux_link(struct proc *p, struct linux_link_args *args)
{
struct link_args bsd;
--- i386/linux/linux_dummy.c.orig Mon Aug 23 21:19:35 2004
+++ i386/linux/linux_dummy.c Mon Aug 23 21:37:54 2004
@@ -64,8 +64,6 @@
DUMMY(capget);
DUMMY(capset);
DUMMY(sendfile);
-DUMMY(mmap2);
-DUMMY(truncate64);
DUMMY(setfsuid);
DUMMY(setfsgid);
DUMMY(pivot_root);
--- i386/linux/linux_machdep.c.orig Mon Aug 23 21:19:35 2004
+++ i386/linux/linux_machdep.c Mon Aug 23 21:41:57 2004
@@ -381,6 +381,120 @@
#define GUARD_SIZE (4 * PAGE_SIZE)
int
+linux_mmap2(struct proc *p, struct linux_mmap2_args *linux_args)
+{
+ struct mmap_args /* {
+ caddr_t addr;
+ size_t len;
+ int prot;
+ int flags;
+ int fd;
+ long pad;
+ off_t pos;
+ } */ bsd_args;
+
+#ifdef DEBUG
+ if (ldebug(mmap2))
+ printf(ARGS(mmap2, "%p, %d, %d, 0x%08x, %d, %d"),
+ (void *)linux_args->addr, linux_args->len, linux_args->prot,
+ linux_args->flags, linux_args->fd, linux_args->pos);
+#endif
+
+ bsd_args.flags = 0;
+ if (linux_args->flags & LINUX_MAP_SHARED)
+ bsd_args.flags |= MAP_SHARED;
+ if (linux_args->flags & LINUX_MAP_PRIVATE)
+ bsd_args.flags |= MAP_PRIVATE;
+ if (linux_args->flags & LINUX_MAP_FIXED)
+ bsd_args.flags |= MAP_FIXED;
+ if (linux_args->flags & LINUX_MAP_ANON)
+ bsd_args.flags |= MAP_ANON;
+ else
+ bsd_args.flags |= MAP_NOSYNC;
+ if (linux_args->flags & LINUX_MAP_GROWSDOWN) {
+ bsd_args.flags |= MAP_STACK;
+
+ /* The linux MAP_GROWSDOWN option does not limit auto
+ * growth of the region. Linux mmap with this option
+ * takes as addr the inital BOS, and as len, the initial
+ * region size. It can then grow down from addr without
+ * limit. However, linux threads has an implicit internal
+ * limit to stack size of STACK_SIZE. Its just not
+ * enforced explicitly in linux. But, here we impose
+ * a limit of (STACK_SIZE - GUARD_SIZE) on the stack
+ * region, since we can do this with our mmap.
+ *
+ * Our mmap with MAP_STACK takes addr as the maximum
+ * downsize limit on BOS, and as len the max size of
+ * the region. It them maps the top SGROWSIZ bytes,
+ * and autgrows the region down, up to the limit
+ * in addr.
+ *
+ * If we don't use the MAP_STACK option, the effect
+ * of this code is to allocate a stack region of a
+ * fixed size of (STACK_SIZE - GUARD_SIZE).
+ */
+
+ /* This gives us TOS */
+ bsd_args.addr = (caddr_t)(linux_args->addr + linux_args->len);
+
+ if (bsd_args.addr > p->p_vmspace->vm_maxsaddr) {
+ /* Some linux apps will attempt to mmap
+ * thread stacks near the top of their
+ * address space. If their TOS is greater
+ * than vm_maxsaddr, vm_map_growstack()
+ * will confuse the thread stack with the
+ * process stack and deliver a SEGV if they
+ * attempt to grow the thread stack past their
+ * current stacksize rlimit. To avoid this,
+ * adjust vm_maxsaddr upwards to reflect
+ * the current stacksize rlimit rather
+ * than the maximum possible stacksize.
+ * It would be better to adjust the
+ * mmap'ed region, but some apps do not check
+ * mmap's return value.
+ */
+ p->p_vmspace->vm_maxsaddr = (char *)USRSTACK -
+ p->p_rlimit[RLIMIT_STACK].rlim_cur;
+ }
+
+ /* This gives us our maximum stack size */
+ if (linux_args->len > STACK_SIZE - GUARD_SIZE)
+ bsd_args.len = linux_args->len;
+ else
+ bsd_args.len = STACK_SIZE - GUARD_SIZE;
+
+ /* This gives us a new BOS. If we're using VM_STACK, then
+ * mmap will just map the top SGROWSIZ bytes, and let
+ * the stack grow down to the limit at BOS. If we're
+ * not using VM_STACK we map the full stack, since we
+ * don't have a way to autogrow it.
+ */
+ bsd_args.addr -= bsd_args.len;
+ } else {
+ bsd_args.addr = (caddr_t)linux_args->addr;
+ bsd_args.len = linux_args->len;
+ }
+
+ bsd_args.prot = linux_args->prot | PROT_READ; /* always required */
+ if (linux_args->flags & LINUX_MAP_ANON)
+ bsd_args.fd = -1;
+ else
+ bsd_args.fd = linux_args->fd;
+ bsd_args.pos = ctob(linux_args->pgoff);
+ bsd_args.pad = 0;
+
+#ifdef DEBUG
+ if (ldebug(mmap2))
+ printf("-> (%p, %d, %d, 0x%08x, %d, %d)\n",
+ (void *)bsd_args.addr, bsd_args.len, bsd_args.prot,
+ bsd_args.flags, bsd_args.fd, (int)bsd_args.pos);
+#endif
+
+ return (mmap(p, &bsd_args));
+}
+
+int
linux_mmap(struct proc *p, struct linux_mmap_args *args)
{
struct mmap_args /* {
@@ -790,7 +904,7 @@
return (error);
}
-int
+/* int
linux_ftruncate64(struct proc *p, struct linux_ftruncate64_args *args)
{
struct ftruncate_args sa;
@@ -804,4 +918,4 @@
sa.pad = 0;
sa.length = args->length;
return ftruncate(p, &sa);
-}
+} */
--- i386/linux/linux_sysvec.c.orig Mon Aug 23 21:19:35 2004
+++ i386/linux/linux_sysvec.c Mon Aug 23 21:33:06 2004
@@ -722,6 +722,7 @@
args[2] = tf->tf_edx;
args[3] = tf->tf_esi;
args[4] = tf->tf_edi;
+ args[5] = tf->tf_ebp; /* tf_ebp taken from linux glibc sources */
*params = NULL; /* no copyin */
}
--- mmap2-patch.diff ends here ---
More information about the freebsd-emulation
mailing list