Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/compat/linux Define linux_usertrap function, and set it ...



details:   https://anonhg.NetBSD.org/src/rev/e08a71b670b0
branches:  trunk
changeset: 581017:e08a71b670b0
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Fri May 20 12:48:26 2005 +0000

description:
Define linux_usertrap function, and set it in struct emul. For all
but amd64, it just returns 0, doing nothing.

For amd64, it implements vsyscalls through cheating: if the faulting
address is in the vsyscall area (which is statically known on Linux/amd64),
and the intruction pointer is too, it must have been a vsyscall. In that
case, retrieve the return address from the user stack, fix up %rip and
%rsp, and just execute the normal system call. It will return as if
the vsyscall has been executed.

diffstat:

 sys/compat/linux/arch/alpha/linux_machdep.c      |   9 ++-
 sys/compat/linux/arch/amd64/linux_exec_machdep.c |   8 +-
 sys/compat/linux/arch/amd64/linux_machdep.c      |  74 +++++++++++++++++++++--
 sys/compat/linux/arch/amd64/linux_machdep.h      |   6 +-
 sys/compat/linux/arch/arm/linux_machdep.c        |  10 ++-
 sys/compat/linux/arch/i386/linux_machdep.c       |  10 ++-
 sys/compat/linux/arch/m68k/linux_machdep.c       |  10 ++-
 sys/compat/linux/arch/mips/linux_machdep.c       |  10 ++-
 sys/compat/linux/arch/powerpc/linux_machdep.c    |  10 ++-
 sys/compat/linux/common/linux_exec.c             |   6 +-
 sys/compat/linux/common/linux_exec.h             |   3 +-
 11 files changed, 126 insertions(+), 30 deletions(-)

diffs (truncated from 388 to 300 lines):

diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/alpha/linux_machdep.c
--- a/sys/compat/linux/arch/alpha/linux_machdep.c       Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/alpha/linux_machdep.c       Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.30 2003/10/10 02:26:54 matt Exp $  */
+/*     $NetBSD: linux_machdep.c,v 1.31 2005/05/20 12:48:26 fvdl Exp $  */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -42,7 +42,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.30 2003/10/10 02:26:54 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.31 2005/05/20 12:48:26 fvdl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -532,3 +532,8 @@
        return dev;
 }
 
+int
+linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
+{
+       return 0;
+}
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/amd64/linux_exec_machdep.c
--- a/sys/compat/linux/arch/amd64/linux_exec_machdep.c  Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/amd64/linux_exec_machdep.c  Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_exec_machdep.c,v 1.1 2005/05/03 16:26:30 manu Exp $ */
+/*     $NetBSD: linux_exec_machdep.c,v 1.2 2005/05/20 12:48:27 fvdl Exp $ */
 
 /*-
  * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.1 2005/05/03 16:26:30 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.2 2005/05/20 12:48:27 fvdl Exp $");
 
 #ifdef __amd64__
 #define ELFSIZE 64
@@ -84,15 +84,11 @@
                max_stack_size = MAXSSIZ;
                if (epp->ep_minsaddr > LINUX_USRSTACK32)
                        epp->ep_minsaddr = LINUX_USRSTACK32;
-               else
-                       printf("epp->ep_minsaddr = 0x%lx\n", epp->ep_minsaddr);
        } else {
                epp->ep_minsaddr = USRSTACK;
                max_stack_size = MAXSSIZ;
                if (epp->ep_minsaddr > LINUX_USRSTACK)
                        epp->ep_minsaddr = LINUX_USRSTACK;
-               else
-                       printf("epp->ep_minsaddr = 0x%lx\n", epp->ep_minsaddr);
 
        }
 
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/amd64/linux_machdep.c
--- a/sys/compat/linux/arch/amd64/linux_machdep.c       Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/amd64/linux_machdep.c       Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.3 2005/05/19 21:16:29 manu Exp $ */
+/*     $NetBSD: linux_machdep.c,v 1.4 2005/05/20 12:48:27 fvdl Exp $ */
 
 /*-
  * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
@@ -33,7 +33,7 @@
 
 #include <sys/cdefs.h>
 
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.3 2005/05/19 21:16:29 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.4 2005/05/20 12:48:27 fvdl Exp $");
 
 #include <sys/param.h>
 #include <sys/types.h>
@@ -58,9 +58,9 @@
 #include <compat/linux/common/linux_ioctl.h>
 #include <compat/linux/common/linux_prctl.h>
 #include <compat/linux/common/linux_machdep.h>
+#include <compat/linux/linux_syscall.h>
 #include <compat/linux/linux_syscallargs.h>
 
-
 void
 linux_setregs(l, epp, stack) 
         struct lwp *l;
@@ -79,10 +79,11 @@
        pcb->pcb_savefpu.fp_fxsave.fx_fcw = __NetBSD_NPXCW__;
        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr = __INITIAL_MXCSR__;
        pcb->pcb_savefpu.fp_fxsave.fx_mxcsr_mask = __INITIAL_MXCSR_MASK__;
+       pcb->pcb_fs = 0;
+       pcb->pcb_gs = 0;
 
        l->l_proc->p_flag &= ~P_32;
 
-       printf("stack = 0x%lx, entry = 0x%lx\n", stack, epp->ep_entry);
        tf = l->l_md.md_regs;
        tf->tf_rax = 0;
        tf->tf_rbx = 0;
@@ -101,9 +102,9 @@
        tf->tf_r14 = 0;
        tf->tf_r15 = 0;
        tf->tf_rip = epp->ep_entry;
-       tf->tf_rflags = PSL_MBO | PSL_I;
-       tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
-       tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
+       tf->tf_rflags = PSL_USERSET;
+       tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+       tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
        tf->tf_ds = 0;
        tf->tf_es = 0;
        tf->tf_fs = 0;
@@ -130,7 +131,7 @@
        linux_sigset_t lmask;
        char *sp;
        int error;
-       
+
        /* Do we need to jump onto the signal stack? */
        onstack =
            (p->p_sigctx.ps_sigstk.ss_flags & (SS_DISABLE | SS_ONSTACK)) == 0 &&
@@ -524,3 +525,60 @@
 
        return 0;
 }
+
+const int linux_vsyscall_to_syscall[] = {
+       LINUX_SYS_gettimeofday,
+       LINUX_SYS_time,
+       LINUX_SYS_nosys,
+       LINUX_SYS_nosys,
+};
+
+int
+linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
+{
+       struct trapframe *tf = arg;
+       uint64_t retaddr;
+       int vsyscallnr;
+
+       /*
+        * Check for a vsyscall. %rip must be the fault address,
+        * and the address must be in the Linux vsyscall area.
+        * Also, vsyscalls are only done at 1024-byte boundaries.
+        */
+
+       if (__predict_true(trapaddr < LINUX_VSYSCALL_START))
+               return 0;
+
+       if (trapaddr != tf->tf_rip)
+               return 0;
+
+       if ((tf->tf_rip & (LINUX_VSYSCALL_SIZE - 1)) != 0)
+               return 0;
+
+       vsyscallnr = (tf->tf_rip - LINUX_VSYSCALL_START) / LINUX_VSYSCALL_SIZE;
+
+       if (vsyscallnr > LINUX_VSYSCALL_MAXNR)
+               return 0;
+
+       /*
+        * Get the return address from the top of the stack,
+        * and fix up the return address.
+        * This assumes the faulting instruction was callq *reg,
+        * which is the only way that vsyscalls are ever entered.
+        */
+       if (copyin((void *)tf->tf_rsp, &retaddr, sizeof retaddr) != 0)
+               return 0;
+       tf->tf_rip = retaddr;
+       tf->tf_rax = linux_vsyscall_to_syscall[vsyscallnr];
+       tf->tf_rsp += 8;        /* "pop" the return address */
+
+#if 0
+       printf("usertrap: rip %p rsp %p retaddr %p vsys %d sys %d\n",
+           (void *)tf->tf_rip, (void *)tf->tf_rsp, (void *)retaddr,
+           vsyscallnr, (int)tf->tf_rax);
+#endif
+
+       (*l->l_proc->p_md.md_syscall)(tf);
+
+       return 1;
+}
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/amd64/linux_machdep.h
--- a/sys/compat/linux/arch/amd64/linux_machdep.h       Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/amd64/linux_machdep.h       Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.h,v 1.1 2005/05/03 16:26:30 manu Exp $ */
+/*     $NetBSD: linux_machdep.h,v 1.2 2005/05/20 12:48:27 fvdl Exp $ */
 
 /*-
  * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved.
@@ -107,4 +107,8 @@
 __END_DECLS
 #endif /* !_KERNEL */
 
+#define LINUX_VSYSCALL_START   0xffffffffff600000
+#define LINUX_VSYSCALL_SIZE    1024
+#define LINUX_VSYSCALL_MAXNR   3
+
 #endif /* _AMD64_LINUX_MACHDEP_H */
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/arm/linux_machdep.c
--- a/sys/compat/linux/arch/arm/linux_machdep.c Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/arm/linux_machdep.c Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.14 2005/02/26 23:10:19 perry Exp $ */
+/*     $NetBSD: linux_machdep.c,v 1.15 2005/05/20 12:48:27 fvdl Exp $  */
 
 /*-
  * Copyright (c) 1995, 2000 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 
 #include <sys/param.h>
 
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.14 2005/02/26 23:10:19 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.15 2005/05/20 12:48:27 fvdl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -318,3 +318,9 @@
        /* XXX NJWLWP */
        return sys_ioctl(curlwp, &bia, retval);
 }
+
+int
+linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
+{
+       return 0;
+}
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/i386/linux_machdep.c
--- a/sys/compat/linux/arch/i386/linux_machdep.c        Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/i386/linux_machdep.c        Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.106 2005/02/26 23:10:19 perry Exp $        */
+/*     $NetBSD: linux_machdep.c,v 1.107 2005/05/20 12:48:27 fvdl Exp $ */
 
 /*-
  * Copyright (c) 1995, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.106 2005/02/26 23:10:19 perry Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.107 2005/05/20 12:48:27 fvdl Exp $");
 
 #if defined(_KERNEL_OPT)
 #include "opt_vm86.h"
@@ -1167,3 +1167,9 @@
        *retval = 0;
        return 0;
 }
+
+int
+linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
+{
+       return 0;
+}
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/m68k/linux_machdep.c
--- a/sys/compat/linux/arch/m68k/linux_machdep.c        Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/m68k/linux_machdep.c        Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.22 2003/09/28 00:15:13 cl Exp $    */
+/*     $NetBSD: linux_machdep.c,v 1.23 2005/05/20 12:48:27 fvdl Exp $  */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.22 2003/09/28 00:15:13 cl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.23 2005/05/20 12:48:27 fvdl Exp $");
 
 #define COMPAT_LINUX 1
 
@@ -910,3 +910,9 @@
        SCARG(&bia, com) = com;
        return sys_ioctl(curlwp, &bia, retval);
 }
+
+int
+linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg)
+{
+       return 0;
+}
diff -r 197e337ff72e -r e08a71b670b0 sys/compat/linux/arch/mips/linux_machdep.c
--- a/sys/compat/linux/arch/mips/linux_machdep.c        Fri May 20 12:44:50 2005 +0000
+++ b/sys/compat/linux/arch/mips/linux_machdep.c        Fri May 20 12:48:26 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: linux_machdep.c,v 1.22 2005/02/26 23:10:19 perry Exp $ */
+/*     $NetBSD: linux_machdep.c,v 1.23 2005/05/20 12:48:27 fvdl Exp $ */
 
 /*-
  * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
  */
 



Home | Main Index | Thread Index | Old Index