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