diff options
| author | chs <chs@NetBSD.org> | 2010-07-07 01:30:32 +0000 |
|---|---|---|
| committer | chs <chs@NetBSD.org> | 2010-07-07 01:30:32 +0000 |
| commit | 33fa5ccbbf17bc2390e2d136c34926c6f93ac5d1 (patch) | |
| tree | c52fdcf81396fba59fce0a9c410d0dcc8c104091 /sys | |
| parent | 56acc98394a822ba38a843f6385171e0b1aa5e9a (diff) | |
many changes for COMPAT_LINUX:
- update the linux syscall table for each platform.
- support new-style (NPTL) linux pthreads on all platforms.
clone() with CLONE_THREAD uses 1 process with many LWPs
instead of separate processes.
- move the contents of sys__lwp_setprivate() into a new
lwp_setprivate() and use that everywhere.
- update linux_release[] and linux32_release[] to "2.6.18".
- adjust placement of emul fork/exec/exit hooks as needed
and adjust other emul code to match.
- convert all struct emul definitions to use named initializers.
- change the pid allocator to allow multiple pids to refer to the same proc.
- remove a few fields from struct proc that are no longer needed.
- disable the non-functional "vdso" code in linux32/amd64,
glibc works fine without it.
- fix a race in the futex code where we could miss a wakeup after
a requeue operation.
- redo futex locking to be a little more efficient.
Diffstat (limited to 'sys')
75 files changed, 2306 insertions, 2331 deletions
diff --git a/sys/arch/x86/x86/linux_trap.c b/sys/arch/x86/x86/linux_trap.c index 764eecc06a8..0a4257bc498 100644 --- a/sys/arch/x86/x86/linux_trap.c +++ b/sys/arch/x86/x86/linux_trap.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_trap.c,v 1.9 2010/01/13 15:31:47 njoly Exp $ */ +/* $NetBSD: linux_trap.c,v 1.10 2010/07/07 01:30:32 chs Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -30,11 +30,11 @@ */ /* - * 386 Trap and System call handling + * x86 Trap and System call handling */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.9 2010/01/13 15:31:47 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.10 2010/07/07 01:30:32 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -58,6 +58,24 @@ __KERNEL_RCSID(0, "$NetBSD: linux_trap.c,v 1.9 2010/01/13 15:31:47 njoly Exp $") #include <compat/linux/common/linux_exec.h> +#ifndef DEBUG_LINUX +#define DPRINTF(a) +#else +#define DPRINTF(a) uprintf a +#endif + +struct linux_user_desc { + unsigned int entry_number; + unsigned int base_addr; + unsigned int limit; + unsigned int seg_32bit:1; + unsigned int contents:2; + unsigned int read_exec_only:1; + unsigned int limit_in_pages:1; + unsigned int seg_not_present:1; + unsigned int useable:1; +}; + #define LINUX_T_DIVIDE 0 #define LINUX_T_DEBUG 1 #define LINUX_T_NMI 2 @@ -128,6 +146,7 @@ static const int linux_x86_vec_to_sig[] = { void linux_trapsignal(struct lwp *l, ksiginfo_t *ksi) { + ksiginfo_t nksi; switch (ksi->ksi_signo) { case SIGILL: @@ -138,7 +157,7 @@ linux_trapsignal(struct lwp *l, ksiginfo_t *ksi) case SIGSEGV: KASSERT(KSI_TRAP_P(ksi)); if (ksi->ksi_trap < __arraycount(trapno_to_x86_vec)) { - ksiginfo_t nksi = *ksi; + nksi = *ksi; nksi.ksi_trap = trapno_to_x86_vec[ksi->ksi_trap]; if (nksi.ksi_trap < __arraycount(linux_x86_vec_to_sig)) { nksi.ksi_signo @@ -152,8 +171,38 @@ linux_trapsignal(struct lwp *l, ksiginfo_t *ksi) uprintf("Unhandled trap type %d\n", ksi->ksi_trap); } /*FALLTHROUGH*/ + default: trapsignal(l, ksi); return; } } + +int +linux_lwp_setprivate(struct lwp *l, void *ptr) +{ + struct linux_user_desc info; + int error; + +#ifdef __x86_64__ + if ((l->l_proc->p_flag & PK_32) == 0) { + return lwp_setprivate(l, ptr); + } +#endif + error = copyin(ptr, &info, sizeof(info)); + if (error) + return error; + + DPRINTF(("linux_lwp_setprivate: %i, %x, %x, %i, %i, %i, %i, %i, %i\n", + info.entry_number, info.base_addr, info.limit, info.seg_32bit, + info.contents, info.read_exec_only, info.limit_in_pages, + info.seg_not_present, info.useable)); + + if (info.entry_number != GUGS_SEL) { + info.entry_number = GUGS_SEL; + error = copyout(&info, ptr, sizeof(info)); + if (error) + return error; + } + return lwp_setprivate(l, (void *)(uintptr_t)info.base_addr); +} diff --git a/sys/compat/aoutm68k/aoutm68k_exec.c b/sys/compat/aoutm68k/aoutm68k_exec.c index 4e6090e8cfa..eb2c8e597fb 100644 --- a/sys/compat/aoutm68k/aoutm68k_exec.c +++ b/sys/compat/aoutm68k/aoutm68k_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: aoutm68k_exec.c,v 1.24 2009/06/02 23:21:38 pooka Exp $ */ +/* $NetBSD: aoutm68k_exec.c,v 1.25 2010/07/07 01:30:32 chs Exp $ */ /*- * Copyright (c) 2000 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: aoutm68k_exec.c,v 1.24 2009/06/02 23:21:38 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: aoutm68k_exec.c,v 1.25 2010/07/07 01:30:32 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -55,34 +55,36 @@ void aoutm68k_syscall_intern(struct proc *); struct uvm_object *emul_netbsd_aoutm68k_object; struct emul emul_netbsd_aoutm68k = { - "aoutm68k", - "/emul/aout", + .e_name = "aoutm68k", + .e_path = "/emul/aoutm68k", #ifndef __HAVE_MINIMAL_EMUL - EMUL_HAS_SYS___syscall, - NULL, - AOUTM68K_SYS_syscall, - AOUTM68K_SYS_NSYSENT, + .e_flags = EMUL_HAS_SYS___syscall, + .e_errno = NULL, + .e_nosys = AOUTM68K_SYS_syscall, + .e_nsysent = AOUTM68K_SYS_NSYSENT, #endif - aoutm68k_sysent, + .e_sysent = aoutm68k_sysent, #ifdef SYSCALL_DEBUG - syscallnames, -#else - NULL, + .e_syscallnames = syscallnames, #endif - sendsig, - trapsignal, - NULL, - sigcode, - esigcode, - &emul_netbsd_aoutm68k_object, - setregs, - NULL, - NULL, - NULL, - NULL, - NULL, - aoutm68k_syscall_intern, - NULL, - NULL, - uvm_default_mapaddr, + .e_sendsig = sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = sigcode, + .e_esigcode = esigcode, + .e_sigobject = &emul_netbsd_aoutm68k_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, + .e_syscall_intern = aoutm68k_syscall_intern, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/darwin/darwin_exec.c b/sys/compat/darwin/darwin_exec.c index cb5df9a173e..62403df947f 100644 --- a/sys/compat/darwin/darwin_exec.c +++ b/sys/compat/darwin/darwin_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: darwin_exec.c,v 1.60 2010/01/05 13:22:40 mbalmer Exp $ */ +/* $NetBSD: darwin_exec.c,v 1.61 2010/07/07 01:30:32 chs Exp $ */ /*- * Copyright (c) 2002 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include "opt_compat_darwin.h" /* For COMPAT_DARWIN in mach_port.h */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.60 2010/01/05 13:22:40 mbalmer Exp $"); +__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.61 2010/07/07 01:30:32 chs Exp $"); #include "opt_syscall_debug.h" #include "wsdisplay.h" @@ -76,9 +76,9 @@ extern const struct cdevsw wsdisplay_cdevsw; #endif static void darwin_e_proc_exec(struct proc *, struct exec_package *); -static void darwin_e_proc_fork(struct proc *, struct proc *, int); +static void darwin_e_proc_fork(struct proc *, struct lwp *, int); static void darwin_e_proc_exit(struct proc *); -static void darwin_e_proc_init(struct proc *, struct vmspace *); +static void darwin_e_proc_init(struct proc *); extern struct sysent darwin_sysent[]; #ifdef SYSCALL_DEBUG @@ -91,45 +91,42 @@ void mach_syscall_intern(struct proc *); #endif struct emul emul_darwin = { - "darwin", - "/emul/darwin", + .e_name = "darwin", + .e_path = "/emul/darwin", #ifndef __HAVE_MINIMAL_EMUL - 0, - 0, - DARWIN_SYS_syscall, - DARWIN_SYS_NSYSENT, + .e_flags = 0, + .e_errno = NULL + .e_nosys = DARWIN_SYS_syscall, + .e_nsysent = DARWIN_SYS_NSYSENT, #endif - darwin_sysent, + .e_sysent = darwin_sysent, #ifdef SYSCALL_DEBUG - darwin_syscallnames, -#else - NULL, + .e_syscallnames = darwin_syscallnames, #endif - darwin_sendsig, - darwin_trapsignal, - darwin_tracesig, - NULL, - NULL, - NULL, - setregs, - darwin_e_proc_exec, - darwin_e_proc_fork, - darwin_e_proc_exit, - mach_e_lwp_fork, - mach_e_lwp_exit, + .e_sendsig = darwin_sendsig, + .e_trapsignal = darwin_trapsignal, + .e_tracesig = darwin_tracesig, + .e_sigcode = NULL, + .e_esigcode = NULL, + .e_sigobject = NULL, + .e_setregs = setregs, + .e_proc_exec = darwin_e_proc_exec, + .e_proc_fork = darwin_e_proc_fork, + .e_proc_exit = darwin_e_proc_exit, + .e_lwp_fork = mach_e_lwp_fork, + .e_lwp_exit = mach_e_lwp_exit, #ifdef __HAVE_SYSCALL_INTERN - mach_syscall_intern, + .e_syscall_intern = mach_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, - NULL, - NULL, - 0, - NULL, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; /* @@ -229,7 +226,7 @@ darwin_e_proc_exec(struct proc *p, struct exec_package *epp) { struct darwin_emuldata *ded; - darwin_e_proc_init(p, p->p_vmspace); + darwin_e_proc_init(p); /* Setup the mach_emuldata part of darwin_emuldata */ mach_e_proc_exec(p, epp); @@ -245,27 +242,25 @@ darwin_e_proc_exec(struct proc *p, struct exec_package *epp) } static void -darwin_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) +darwin_e_proc_fork(struct proc *p2, struct lwp *l1, int forkflags) { struct darwin_emuldata *ded1; struct darwin_emuldata *ded2; char *ed1, *ed2; size_t len; - p->p_emuldata = NULL; - - /* Use parent's vmspace because our vmspace may not be setup yet */ - darwin_e_proc_init(p, parent->p_vmspace); + p2->p_emuldata = NULL; + darwin_e_proc_init(p2); /* * Setup the mach_emuldata part of darwin_emuldata * The null third argument asks to not re-allocate * p->p_emuldata again. */ - mach_e_proc_fork1(p, parent, 0); + mach_e_proc_fork1(p2, l1, 0); - ded1 = p->p_emuldata; - ded2 = parent->p_emuldata; + ded1 = p2->p_emuldata; + ded2 = l1->l_proc->p_emuldata; ed1 = (char *)ded1 + sizeof(struct mach_emuldata); ed2 = (char *)ded2 + sizeof(struct mach_emuldata); @@ -280,14 +275,14 @@ darwin_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) ded1->ded_fakepid = 0; } #ifdef DEBUG_DARWIN - printf("pid %d fork'd: fakepid = %d\n", p->p_pid, ded1->ded_fakepid); + printf("pid %d fork'd: fakepid = %d\n", p2->p_pid, ded1->ded_fakepid); #endif return; } static void -darwin_e_proc_init(struct proc *p, struct vmspace *vmspace) +darwin_e_proc_init(struct proc *p) { struct darwin_emuldata *ded; @@ -302,7 +297,7 @@ darwin_e_proc_init(struct proc *p, struct vmspace *vmspace) ded->ded_vramoffset = NULL; /* Initalize the mach_emuldata part of darwin_emuldata */ - mach_e_proc_init(p, vmspace); + mach_e_proc_init(p); return; } diff --git a/sys/compat/freebsd/freebsd_exec.c b/sys/compat/freebsd/freebsd_exec.c index 1371ed2f82a..fd96abfe2a5 100644 --- a/sys/compat/freebsd/freebsd_exec.c +++ b/sys/compat/freebsd/freebsd_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: freebsd_exec.c,v 1.36 2008/11/19 18:36:02 ad Exp $ */ +/* $NetBSD: freebsd_exec.c,v 1.37 2010/07/07 01:30:32 chs Exp $ */ /* * Copyright (c) 1993, 1994 Christopher G. Demetriou @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: freebsd_exec.c,v 1.36 2008/11/19 18:36:02 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: freebsd_exec.c,v 1.37 2010/07/07 01:30:32 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -63,43 +63,42 @@ void syscall(void); #endif struct emul emul_freebsd = { - "freebsd", - "/emul/freebsd", + .e_name = "freebsd", + .e_path = "/emul/freebsd", #ifndef __HAVE_MINIMAL_EMUL - EMUL_HAS_SYS___syscall, - NULL, - FREEBSD_SYS_syscall, - FREEBSD_SYS_NSYSENT, + .e_flags = EMUL_HAS_SYS___syscall, + .e_errno = NULL, + .e_nosys = FREEBSD_SYS_syscall, + .e_nsysent = FREEBSD_SYS_NSYSENT, #endif - freebsd_sysent, + .e_sysent = freebsd_sysent, #ifdef SYSCALL_DEBUG - freebsd_syscallnames, + .e_syscallnames = freebsd_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - freebsd_sendsig, - trapsignal, - NULL, - freebsd_sigcode, - freebsd_esigcode, - &emul_freebsd_object, - freebsd_setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = freebsd_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = freebsd_sigcode, + .e_esigcode = freebsd_esigcode, + .e_sigobject = &emul_freebsd_object, + .e_setregs = freebsd_setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - freebsd_syscall_intern, + .e_syscall_intern = freebsd_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, - NULL, /* e_usertrap */ - NULL, /* e_sa */ - 0, /* e_ucsize */ - NULL, /* e_startlwp */ + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/ibcs2/ibcs2_exec.c b/sys/compat/ibcs2/ibcs2_exec.c index 20d6dbc4652..4cc9e5f419c 100644 --- a/sys/compat/ibcs2/ibcs2_exec.c +++ b/sys/compat/ibcs2/ibcs2_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: ibcs2_exec.c,v 1.73 2009/03/29 01:02:49 mrg Exp $ */ +/* $NetBSD: ibcs2_exec.c,v 1.74 2010/07/07 01:30:32 chs Exp $ */ /* * Copyright (c) 1994, 1995, 1998 Scott Bartram @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ibcs2_exec.c,v 1.73 2009/03/29 01:02:49 mrg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ibcs2_exec.c,v 1.74 2010/07/07 01:30:32 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -77,45 +77,44 @@ int ibcs2_debug = 1; struct uvm_object *emul_ibcs2_object; struct emul emul_ibcs2 = { - "ibcs2", - "/emul/ibcs2", + .e_name = "ibcs2", + .e_path = "/emul/ibcs2", #ifndef __HAVE_MINIMAL_EMUL - 0, - native_to_ibcs2_errno, - IBCS2_SYS_syscall, - IBCS2_SYS_NSYSENT, + .e_flags = 0, + .e_errno = native_to_ibcs2_errno, + .e_nosys = IBCS2_SYS_syscall, + .e_nsysent = IBCS2_SYS_NSYSENT, #endif - ibcs2_sysent, + .e_sysent = ibcs2_sysent, #ifdef SYSCALL_DEBUG - ibcs2_syscallnames, + .e_syscallnames = ibcs2_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - ibcs2_sendsig, - trapsignal, - NULL, /* e_tracesig */ - ibcs2_sigcode, - ibcs2_esigcode, - &emul_ibcs2_object, - ibcs2_setregs, - ibcs2_e_proc_exec, - NULL, /* e_proc_fork */ - NULL, /* e_proc_exit */ - NULL, /* e_lwp_fork */ - NULL, /* e_lwp_exec */ + .e_sendsig = ibcs2_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = ibcs2_sigcode, + .e_esigcode = ibcs2_esigcode, + .e_sigobject = &emul_ibcs2_object, + .e_setregs = ibcs2_setregs, + .e_proc_exec = ibcs2_e_proc_exec, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - ibcs2_syscall_intern, + .e_syscall_intern = ibcs2_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, /* e_sysctlovly */ - NULL, /* e_fault */ - - uvm_default_mapaddr, - NULL, /* e_usertrap */ - NULL, /* e_sa */ - 0, /* e_ucsize */ - NULL, /* e_startlwp */ + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; /* diff --git a/sys/compat/irix/irix_exec.c b/sys/compat/irix/irix_exec.c index 204e73b6f46..cf62ab298f3 100644 --- a/sys/compat/irix/irix_exec.c +++ b/sys/compat/irix/irix_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: irix_exec.c,v 1.57 2010/06/13 04:08:49 yamt Exp $ */ +/* $NetBSD: irix_exec.c,v 1.58 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 2001-2002 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.57 2010/06/13 04:08:49 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.58 2010/07/07 01:30:33 chs Exp $"); #ifdef _KERNEL_OPT #include "opt_syscall_debug.h" @@ -59,9 +59,9 @@ __KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.57 2010/06/13 04:08:49 yamt Exp $"); extern const int native_to_svr4_signo[]; static void irix_e_proc_exec(struct proc *, struct exec_package *); -static void irix_e_proc_fork(struct proc *, struct proc *, int); +static void irix_e_proc_fork(struct proc *, struct lwp *, int); static void irix_e_proc_exit(struct proc *); -static void irix_e_proc_init(struct proc *, struct vmspace *); +static void irix_e_proc_init(struct proc *); extern struct sysent irix_sysent[]; extern const char * const irix_syscallnames[]; @@ -81,41 +81,40 @@ void irix_syscall_intern(struct proc *); char irix_sigcode[] = { 0 }; struct emul emul_irix = { - "irix", - "/emul/irix", + .e_name = "irix", + .e_path = "/emul/irix", #ifndef __HAVE_MINIMAL_EMUL - 0, - native_to_irix_errno, - IRIX_SYS_syscall, - IRIX_SYS_NSYSENT, + .e_flags = 0, + .e_errno = native_to_irix_errno, + .e_nosys = IRIX_SYS_syscall, + .e_nsysent = IRIX_SYS_NSYSENT, #endif - irix_sysent, + .e_sysent = irix_sysent, #ifdef SYSCALL_DEBUG - irix_syscallnames, + .e_syscallnames = irix_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - irix_sendsig, - trapsignal, - NULL, - irix_sigcode, - irix_sigcode, - NULL, - setregs, - irix_e_proc_exec, - irix_e_proc_fork, - irix_e_proc_exit, - NULL, - NULL, + .e_sendsig = irix_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = irix_sigcode, + .e_esigcode = irix_sigcode, + .e_sigobject = NULL, + .e_setregs = setregs, + .e_proc_exec = irix_e_proc_exec, + .e_proc_fork = irix_e_proc_fork, + .e_proc_exit = irix_e_proc_exit, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - irix_syscall_intern, + .e_syscall_intern = irix_syscall_intern, #else - irix_syscall, + .e_syscall = irix_syscall, #endif - NULL, - irix_vm_fault, + .e_fault = irix_vm_fault, - uvm_default_mapaddr, + .e_vm_default_addr = uvm_default_mapaddr, }; /* @@ -137,9 +136,10 @@ irix_n32_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) * per-process emuldata allocation */ static void -irix_e_proc_init(struct proc *p, struct vmspace *vmspace) +irix_e_proc_init(struct proc *p) { struct irix_emuldata *ied; + struct vmspace *vmspace = p->p_vmspace; vaddr_t vm_min; vsize_t vm_len; @@ -164,7 +164,7 @@ irix_e_proc_exec(struct proc *p, struct exec_package *epp) { int error; - irix_e_proc_init(p, p->p_vmspace); + irix_e_proc_init(p); /* Initialize the process private area (PRDA) */ error = irix_prda_init(p); @@ -261,18 +261,17 @@ irix_e_proc_exit(struct proc *p) * fork() hook used to allocate per process structures */ static void -irix_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) +irix_e_proc_fork(struct proc *p2, struct lwp *l1, int forkflags) { struct irix_emuldata *ied1; struct irix_emuldata *ied2; - p->p_emuldata = NULL; + p2->p_emuldata = NULL; - /* Use parent's vmspace because our vmspace may not be setup yet */ - irix_e_proc_init(p, parent->p_vmspace); + irix_e_proc_init(p2); - ied1 = p->p_emuldata; - ied2 = parent->p_emuldata; + ied1 = p2->p_emuldata; + ied2 = l1->l_proc->p_emuldata; (void) memcpy(ied1, ied2, (unsigned) ((char *)&ied1->ied_endcopy - (char *)&ied1->ied_startcopy)); diff --git a/sys/compat/linux/arch/alpha/files.linux_alpha b/sys/compat/linux/arch/alpha/files.linux_alpha index 7aeef7e0962..e9a02b73ae8 100644 --- a/sys/compat/linux/arch/alpha/files.linux_alpha +++ b/sys/compat/linux/arch/alpha/files.linux_alpha @@ -1,4 +1,4 @@ -# $NetBSD: files.linux_alpha,v 1.7 2002/11/13 15:16:29 jdolecek Exp $ +# $NetBSD: files.linux_alpha,v 1.8 2010/07/07 01:30:33 chs Exp $ # # Config file description for alpha-dependent Linux compat code. @@ -7,5 +7,6 @@ file compat/linux/arch/alpha/linux_pipe.c compat_linux file compat/linux/arch/alpha/linux_syscalls.c compat_linux file compat/linux/arch/alpha/linux_sysent.c compat_linux file compat/linux/common/linux_file64.c compat_linux +file compat/linux/common/linux_futex.c compat_linux file compat/linux/common/linux_olduname.c compat_linux file compat/linux/common/linux_sigaction.c compat_linux diff --git a/sys/compat/linux/arch/alpha/linux_machdep.c b/sys/compat/linux/arch/alpha/linux_machdep.c index f9e883cc69e..ddbd1a85a02 100644 --- a/sys/compat/linux/arch/alpha/linux_machdep.c +++ b/sys/compat/linux/arch/alpha/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.45 2009/11/23 00:46:06 rmind Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.46 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.45 2009/11/23 00:46:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.46 2010/07/07 01:30:33 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -91,7 +91,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.45 2009/11/23 00:46:06 rmind Exp */ void -linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { #ifdef DEBUG struct trapframe *tfp = l->l_md.md_tf; diff --git a/sys/compat/linux/arch/alpha/syscalls.master b/sys/compat/linux/arch/alpha/syscalls.master index 9a371b7dfa6..2f7762611b6 100644 --- a/sys/compat/linux/arch/alpha/syscalls.master +++ b/sys/compat/linux/arch/alpha/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.71 2009/11/24 10:42:43 njoly Exp $ + $NetBSD: syscalls.master,v 1.72 2010/07/07 01:30:33 chs Exp $ ; ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -82,7 +82,7 @@ %% 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, void *buf, size_t nbyte); } 4 NOARGS { int|sys||write(int fd, const void *buf, size_t nbyte); } @@ -498,7 +498,8 @@ 310 UNIMPL syslog 311 STD { int|linux_sys||reboot(int magic1, int magic2, \ int cmd, void *arg); } -312 STD { int|linux_sys||clone(int flags, void *stack); } +312 STD { int|linux_sys||clone(int flags, void *stack, \ + void *parent_tidptr, void *child_tidptr, void *tls); } #ifdef EXEC_AOUT 313 STD { int|linux_sys||uselib(const char *path); } #else @@ -603,10 +604,10 @@ 376 UNIMPL pciconfig_iobase 377 STD { int|linux_sys||getdents64(int fd, \ struct linux_dirent64 *dent, unsigned int count); } -378 UNIMPL gettid +378 NOARGS { pid_t|linux_sys||gettid(void); } 379 UNIMPL readahead 380 UNIMPL /* unused */ -381 UNIMPL tkill +381 STD { int|linux_sys||tkill(int tid, int sig); } 382 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } 383 STD { int|linux_sys||lsetxattr(char *path, char *name, \ @@ -628,9 +629,13 @@ 391 STD { int|linux_sys||removexattr(char *path, char *name); } 392 STD { int|linux_sys||lremovexattr(char *path, char *name); } 393 STD { int|linux_sys||fremovexattr(int fd, char *name); } -394 UNIMPL futex -395 UNIMPL sched_setaffinity -396 UNIMPL sched_getaffinity +394 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ + const struct linux_timespec *timeout, int *uaddr2, \ + int val3); } +395 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +396 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } 397 UNIMPL tuxcall 398 UNIMPL io_setup 399 UNIMPL io_destroy @@ -645,7 +650,7 @@ 408 UNIMPL sys_epoll_ctl 409 UNIMPL sys_epoll_wait 410 UNIMPL remap_file_pages -411 UNIMPL set_tid_address +411 STD { int|linux_sys||set_tid_address(int *tid); } 412 UNIMPL restart_syscall 413 UNIMPL fadvise64 414 UNIMPL timer_create @@ -663,7 +668,7 @@ int flags, struct linux_timespec *rqtp, \ struct linux_timespec *rmtp); } 423 UNIMPL semtimedop -424 UNIMPL tgkill +424 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } 425 UNIMPL stat64 426 UNIMPL lstat64 427 UNIMPL fstat64 @@ -677,3 +682,62 @@ 435 UNIMPL mq_timedreceive 436 UNIMPL mq_notify 437 UNIMPL mq_getsetattr +438 UNIMPL waitid +439 UNIMPL add_key +440 UNIMPL request_key +441 UNIMPL keyctl +442 UNIMPL ioprio_set +443 UNIMPL ioprio_get +444 UNIMPL inotify_init +445 UNIMPL inotify_add_watch +446 UNIMPL inotify_rm_watch +447 UNIMPL fdatasync +448 UNIMPL kexec_load +449 UNIMPL migrate_pages +450 UNIMPL openat +451 UNIMPL mkdirat +452 UNIMPL mknodat +453 UNIMPL fchownat +454 UNIMPL futimesat +455 UNIMPL fstatat64 +456 UNIMPL unlinkat +457 UNIMPL renameat +458 UNIMPL linkat +459 UNIMPL symlinkat +460 UNIMPL readlinkat +461 UNIMPL fchmodat +462 UNIMPL faccessat +463 UNIMPL pselect6 +464 UNIMPL ppoll +465 UNIMPL unshare +466 STD { int|linux_sys||set_robust_list( \ + struct linux_robust_list_head *head, size_t len); } +467 STD { int|linux_sys||get_robust_list(int pid, \ + struct linux_robust_list_head **head, \ + size_t *len); } +468 UNIMPL splice +469 UNIMPL sync_file_range +470 UNIMPL tee +471 UNIMPL vmsplice +472 UNIMPL move_pages +473 UNIMPL getcpu +474 UNIMPL epoll_wait +475 UNIMPL utimensat +476 UNIMPL signalfd +477 UNIMPL timerfd +478 UNIMPL eventfd +479 UNIMPL recvmmsg +480 UNIMPL fallocate +481 UNIMPL timerfd_create +482 UNIMPL timerfd_settime +483 UNIMPL timerfd_gettime +484 UNIMPL signalfd4 +485 UNIMPL eventfd2 +486 UNIMPL epoll_create1 +487 UNIMPL dup3 +488 UNIMPL pipe2 +489 UNIMPL inotify_init1 +490 UNIMPL preadv +491 UNIMPL pwritev +492 UNIMPL rt_tgsigqueueinfo +493 UNIMPL perf_counter_open diff --git a/sys/compat/linux/arch/amd64/linux_exec_machdep.c b/sys/compat/linux/arch/amd64/linux_exec_machdep.c index b45d0a9e6ae..944bfecf4b8 100644 --- a/sys/compat/linux/arch/amd64/linux_exec_machdep.c +++ b/sys/compat/linux/arch/amd64/linux_exec_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_exec_machdep.c,v 1.17 2010/02/09 16:46:07 njoly Exp $ */ +/* $NetBSD: linux_exec_machdep.c,v 1.18 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved @@ -32,11 +32,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.17 2010/02/09 16:46:07 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.18 2010/07/07 01:30:33 chs Exp $"); -#ifdef __amd64__ #define ELFSIZE 64 -#endif #include <sys/param.h> #include <sys/systm.h> @@ -251,17 +249,3 @@ ELFNAME2(linux,copyargs)(struct lwp *l, struct exec_package *pack, return 0; } - -#ifdef LINUX_NPTL -int -linux_init_thread_area(struct lwp *l, struct lwp *l2) -{ - register_t retval; - struct linux_sys_arch_prctl_args uap; - struct trapframe *tf = l2->l_md.md_regs; - - SCARG(&uap, code) = LINUX_ARCH_SET_FS; - SCARG(&uap, addr) = tf->tf_r8; - return linux_sys_arch_prctl(l2, &uap, &retval); -} -#endif diff --git a/sys/compat/linux/arch/amd64/linux_machdep.c b/sys/compat/linux/arch/amd64/linux_machdep.c index d7ae76d4029..14d00c360c5 100644 --- a/sys/compat/linux/arch/amd64/linux_machdep.c +++ b/sys/compat/linux/arch/amd64/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.37 2009/11/23 00:46:06 rmind Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.38 2010/07/07 01:30:33 chs 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.37 2009/11/23 00:46:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.38 2010/07/07 01:30:33 chs Exp $"); #include <sys/param.h> #include <sys/types.h> @@ -79,7 +79,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.37 2009/11/23 00:46:06 rmind Exp static void linux_buildcontext(struct lwp *, void *, void *); void -linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; @@ -93,8 +93,6 @@ linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) 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 &= ~PK_32; @@ -121,8 +119,7 @@ linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = 0; tf->tf_es = 0; - tf->tf_fs = 0; - tf->tf_gs = 0; + cpu_fsgs_zero(l); return; } @@ -489,57 +486,20 @@ linux_sys_arch_prctl(struct lwp *l, syscallarg(int) code; syscallarg(unsigned long) addr; } */ - struct pcb *pcb = lwp_getpcb(l); - struct trapframe *tf = l->l_md.md_regs; - int error; - uint64_t taddr; + void *addr = (void *)SCARG(uap, addr); switch(SCARG(uap, code)) { case LINUX_ARCH_SET_GS: - taddr = SCARG(uap, addr); - if (taddr >= VM_MAXUSER_ADDRESS) - return EINVAL; - pcb->pcb_gs = taddr; - pcb->pcb_flags |= PCB_GS64; - if (l == curlwp) - wrmsr(MSR_KERNELGSBASE, taddr); - break; + return x86_set_sdbase(addr, 'g', l, true); case LINUX_ARCH_GET_GS: - if (pcb->pcb_flags & PCB_GS64) - taddr = pcb->pcb_gs; - else { - error = memseg_baseaddr(l, tf->tf_fs, NULL, 0, &taddr); - if (error != 0) - return error; - } - error = copyout(&taddr, (char *)SCARG(uap, addr), 8); - if (error != 0) - return error; - break; + return x86_get_sdbase(addr, 'g'); case LINUX_ARCH_SET_FS: - taddr = SCARG(uap, addr); - if (taddr >= VM_MAXUSER_ADDRESS) - return EINVAL; - pcb->pcb_fs = taddr; - pcb->pcb_flags |= PCB_FS64; - if (l == curlwp) - wrmsr(MSR_FSBASE, taddr); - break; + return x86_set_sdbase(addr, 'f', l, true); case LINUX_ARCH_GET_FS: - if (pcb->pcb_flags & PCB_FS64) - taddr = pcb->pcb_fs; - else { - error = memseg_baseaddr(l, tf->tf_fs, NULL, 0, &taddr); - if (error != 0) - return error; - } - error = copyout(&taddr, (char *)SCARG(uap, addr), 8); - if (error != 0) - return error; - break; + return x86_get_sdbase(addr, 'f'); default: #ifdef DEBUG_LINUX @@ -548,8 +508,7 @@ linux_sys_arch_prctl(struct lwp *l, #endif return EINVAL; } - - return 0; + /* NOTREACHED */ } const int linux_vsyscall_to_syscall[] = { @@ -621,23 +580,3 @@ linux_buildcontext(struct lwp *l, void *catcher, void *f) tf->tf_rsp = (u_int64_t)f; tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL); } - -void * -linux_get_newtls(struct lwp *l) -{ - struct trapframe *tf = l->l_md.md_regs; - - return (void *)tf->tf_r8; -} - -int -linux_set_newtls(struct lwp *l, void *tls) -{ - struct linux_sys_arch_prctl_args cup; - register_t retval; - - SCARG(&cup, code) = LINUX_ARCH_SET_FS; - SCARG(&cup, addr) = (unsigned long)tls; - - return linux_sys_arch_prctl(l, &cup, &retval); -} diff --git a/sys/compat/linux/arch/amd64/linux_machdep.h b/sys/compat/linux/arch/amd64/linux_machdep.h index b93be017dea..0959085467c 100644 --- a/sys/compat/linux/arch/amd64/linux_machdep.h +++ b/sys/compat/linux/arch/amd64/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.12 2008/04/21 22:38:18 njoly Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.13 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -114,10 +114,11 @@ __END_DECLS #define LINUX_VSYSCALL_MAXNR 3 #define LINUX_UNAME_ARCH MACHINE_ARCH -#define LINUX_NPTL #define LINUX_LARGEFILE64 #define LINUX_IPC_FORCE64 +#define LINUX_LWP_SETPRIVATE linux_lwp_setprivate + /* * Used in ugly patch to fake device numbers. */ diff --git a/sys/compat/linux/arch/amd64/syscalls.master b/sys/compat/linux/arch/amd64/syscalls.master index fe81fd9a5ac..a3ce80e80b9 100644 --- a/sys/compat/linux/arch/amd64/syscalls.master +++ b/sys/compat/linux/arch/amd64/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.34 2009/11/24 10:42:43 njoly Exp $ + $NetBSD: syscalls.master,v 1.35 2010/07/07 01:30:33 chs Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -139,7 +139,7 @@ 38 NOARGS { int|compat_50_sys||setitimer(u_int which, \ struct itimerval50 *itv, \ struct itimerval50 *oitv); } -39 STD { pid_t|linux_sys||getpid(void); } +39 STD { pid_t|sys||getpid(void); } 40 UNIMPL sendfile 41 STD { int|linux_sys||socket(int domain, \ int type, int protocol); } @@ -173,12 +173,12 @@ 55 STD { int|linux_sys||getsockopt(int s, int level, \ int optname, void *optval, int *optlen); } 56 STD { int|linux_sys||clone(int flags, void *stack, \ - void *parent_tidptr, void *child_tidptr); } + void *parent_tidptr, void *child_tidptr, void *tls); } 57 NOARGS { int|sys||fork(void); } 58 NOARGS { int|sys|14|vfork(void); } 59 NOARGS { int|sys||execve(const char *path, char **argp, \ char **envp); } -60 NOARGS { int|sys||exit(int rval); } +60 STD { int|linux_sys||exit(int rval); } 61 STD { int|linux_sys||wait4(int pid, int *status, \ int options, struct rusage50 *rusage); } 62 STD { int|linux_sys||kill(int pid, int signum); } @@ -263,7 +263,7 @@ 107 NOARGS { uid_t|sys||geteuid(void); } 108 NOARGS { gid_t|sys||getegid(void); } 109 NOARGS { int|sys||setpgid(int pid, int pgid); } -110 STD { pid_t|linux_sys||getppid(void); } +110 STD { pid_t|sys||getppid(void); } 111 NOARGS { int|sys||getpgrp(void); } 112 NOARGS { int|sys||setsid(void); } 113 NOARGS { int|sys||setreuid(uid_t ruid, uid_t euid); } @@ -490,4 +490,20 @@ 283 UNIMPL timerfd_create 284 UNIMPL eventfd 285 UNIMPL fallocate -286 STD { int|linux_sys||nosys(void); } +286 UNIMPL timerfd_settime +287 UNIMPL timerfd_gettime +288 UNIMPL accept4 +289 UNIMPL signalfd4 +290 UNIMPL eventfd2 +291 UNIMPL epoll_create1 +292 UNIMPL dup3 +293 UNIMPL pipe2 +294 UNIMPL inotify_init1 +295 UNIMPL preadv +296 UNIMPL pwritev +297 UNIMPL rt_tgsigqueueinfo +298 UNIMPL perf_counter_open +299 UNIMPL recvmmsg + +; we want a "nosys" syscall, we'll just add an extra entry for it. +300 STD { int|linux_sys||nosys(void); } diff --git a/sys/compat/linux/arch/arm/linux_commons.c b/sys/compat/linux/arch/arm/linux_commons.c index dc9a5291505..9ee2ef4917f 100644 --- a/sys/compat/linux/arch/arm/linux_commons.c +++ b/sys/compat/linux/arch/arm/linux_commons.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_commons.c,v 1.9 2010/03/02 15:46:19 pooka Exp $ */ +/* $NetBSD: linux_commons.c,v 1.10 2010/07/07 01:30:33 chs Exp $ */ /* * This file includes C files from the common @@ -13,7 +13,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: linux_commons.c,v 1.9 2010/03/02 15:46:19 pooka Exp $"); +__KERNEL_RCSID(1, "$NetBSD: linux_commons.c,v 1.10 2010/07/07 01:30:33 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_sysv.h" @@ -38,3 +38,4 @@ __KERNEL_RCSID(1, "$NetBSD: linux_commons.c,v 1.9 2010/03/02 15:46:19 pooka Exp #include "../../common/linux_olduname.c" #include "../../common/linux_oldolduname.c" #include "../../common/linux_uid16.c" +#include "../../common/linux_futex.c" diff --git a/sys/compat/linux/arch/arm/linux_machdep.c b/sys/compat/linux/arch/arm/linux_machdep.c index a0e9c80552f..d27f680b0ce 100644 --- a/sys/compat/linux/arch/arm/linux_machdep.c +++ b/sys/compat/linux/arch/arm/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.28 2009/11/23 00:46:06 rmind Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.29 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 1995, 2000 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.28 2009/11/23 00:46:06 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.29 2010/07/07 01:30:33 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -67,7 +67,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.28 2009/11/23 00:46:06 rmind Exp #include <compat/linux/linux_syscallargs.h> void -linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { setregs(l, epp, stack); diff --git a/sys/compat/linux/arch/arm/linux_ptrace.c b/sys/compat/linux/arch/arm/linux_ptrace.c index 0ddba157bf2..0034c3dfe0b 100644 --- a/sys/compat/linux/arch/arm/linux_ptrace.c +++ b/sys/compat/linux/arch/arm/linux_ptrace.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_ptrace.c,v 1.15 2010/07/01 02:38:28 rmind Exp $ */ +/* $NetBSD: linux_ptrace.c,v 1.16 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.15 2010/07/01 02:38:28 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.16 2010/07/07 01:30:33 chs Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -101,6 +101,10 @@ linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, } */ struct proc *p = l->l_proc, *t; struct lwp *lt; +#ifdef _ARM_ARCH_6 + struct pcb *pcb; + void *val; +#endif struct reg *regs = NULL; struct linux_reg *linux_regs = NULL; int request, error; @@ -193,7 +197,19 @@ linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, regs->r_pc = linux_regs->uregs[LINUX_REG_PC]; regs->r_cpsr = linux_regs->uregs[LINUX_REG_CPSR]; error = process_write_regs(lt, regs); - /* FALLTHROUGH */ + mutex_exit(t->p_lock); + break; + +#ifdef _ARM_ARCH_6 +#define LINUX_PTRACE_GET_THREAD_AREA 22 + case LINUX_PTRACE_GET_THREAD_AREA: + mutex_exit(t->p_lock); + pcb = lwp_getpcb(l); + val = (void *)pcb->pcb_un.un_32.pcb32_user_pid_ro; + error = copyout(&val, (void *)SCARG(uap, data), sizeof(val)); + break; +#endif + default: mutex_exit(t->p_lock); } diff --git a/sys/compat/linux/arch/arm/linux_sys_machdep.c b/sys/compat/linux/arch/arm/linux_sys_machdep.c index 700ecedae02..7ed0cef6464 100644 --- a/sys/compat/linux/arch/arm/linux_sys_machdep.c +++ b/sys/compat/linux/arch/arm/linux_sys_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sys_machdep.c,v 1.13 2007/12/20 23:02:52 dsl Exp $ */ +/* $NetBSD: linux_sys_machdep.c,v 1.14 2010/07/07 01:30:33 chs Exp $ */ /*- * Copyright (c) 2002 Ben Harris @@ -29,10 +29,12 @@ #include <sys/param.h> -__KERNEL_RCSID(0, "$NetBSD: linux_sys_machdep.c,v 1.13 2007/12/20 23:02:52 dsl Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_sys_machdep.c,v 1.14 2010/07/07 01:30:33 chs Exp $"); #include <sys/systm.h> #include <sys/signalvar.h> +#include <sys/lwp.h> +#include <sys/cpu.h> #include <compat/linux/common/linux_types.h> #include <compat/linux/common/linux_signal.h> @@ -61,6 +63,7 @@ linux_sys_cacheflush(struct lwp *l, const struct linux_sys_cacheflush_args *uap, /* { syscallarg(uintptr_t) from; syscallarg(uintptr_t) to; + syscallarg(int) flags; } */ cpu_icache_sync_range(SCARG(uap, from), @@ -69,3 +72,10 @@ linux_sys_cacheflush(struct lwp *l, const struct linux_sys_cacheflush_args *uap, *retval = 0; return 0; } + +int +linux_sys_set_tls(struct lwp *l, const struct linux_sys_set_tls_args *uap, register_t *retval) +{ + + return lwp_setprivate(l, SCARG(uap, tls)); +} diff --git a/sys/compat/linux/arch/arm/syscalls.master b/sys/compat/linux/arch/arm/syscalls.master index 886dc84414d..da5a0b6f2e9 100644 --- a/sys/compat/linux/arch/arm/syscalls.master +++ b/sys/compat/linux/arch/arm/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.43 2009/11/24 10:42:43 njoly Exp $ + $NetBSD: syscalls.master,v 1.44 2010/07/07 01:30:33 chs Exp $ ; Derived from sys/compat/linux/arch/*/syscalls.master ; and from Linux 2.4.12 arch/arm/kernel/calls.S @@ -54,7 +54,7 @@ %% ; XXX We have to explicitly declare linux_sys_nosys. 0 NOARGS { int|linux_sys||nosys(void); } -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, char *buf, u_int nbyte); } 4 NOARGS { int|sys||write(int fd, char *buf, u_int nbyte); } @@ -217,7 +217,8 @@ void *ptr); } 118 NOARGS { int|sys||fsync(int fd); } 119 STD { int|linux_sys||sigreturn(struct linux_sigcontext *scp); } -120 STD { int|linux_sys||clone(int flags, void *stack); } +120 STD { int|linux_sys||clone(int flags, void *stack, \ + void *parent_tidptr, void *tls, void *child_tidptr); } 121 STD { int|linux_sys||setdomainname(char *domainname, \ int len); } 122 STD { int|linux_sys||uname(struct linux_utsname *up); } @@ -380,7 +381,7 @@ 221 STD { int|linux_sys||fcntl64(int fd, int cmd, void *arg); } 222 UNIMPL /* for tux */ 223 UNIMPL /* unused */ -224 UNIMPL gettid +224 NOARGS { pid_t|linux_sys||gettid(void); } 225 UNIMPL readahead 226 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } @@ -403,11 +404,15 @@ 235 STD { int|linux_sys||removexattr(char *path, char *name); } 236 STD { int|linux_sys||lremovexattr(char *path, char *name); } 237 STD { int|linux_sys||fremovexattr(int fd, char *name); } -238 UNIMPL tkill +238 STD { int|linux_sys||tkill(int tid, int sig); } 239 UNIMPL sendfile64 -240 UNIMPL futex -241 UNIMPL sched_setaffinity -242 UNIMPL sched_getaffinity +240 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ + const struct linux_timespec *timeout, int *uaddr2, \ + int val3); } +241 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +242 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } 243 UNIMPL io_setup 244 UNIMPL io_destroy 245 UNIMPL io_getevents @@ -419,9 +424,9 @@ 251 UNIMPL epoll_ctl 252 UNIMPL epoll_wait 253 UNIMPL remap_file_pages -254 UNIMPL /* for set_thread_area */ -255 UNIMPL /* for get_thread_area */ -256 UNIMPL /* for set_tid_address */ +254 UNIMPL set_thread_area +255 UNIMPL get_thread_area +256 STD { int|linux_sys||set_tid_address(int *tid); } 257 UNIMPL timer_create 258 UNIMPL timer_settime 259 UNIMPL timer_gettime @@ -440,104 +445,107 @@ size_t sz, struct linux_statfs64 *sp); } 267 STD { int|linux_sys||fstatfs64(int fd, \ size_t sz, struct linux_statfs64 *sp); } -268 UNIMPL tgkill +268 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } 269 UNIMPL utimes 270 UNIMPL fadvise64_64 271 UNIMPL pciconfig_iobase 272 UNIMPL pciconfig_read 273 UNIMPL pciconfig_write -274 UNIMPL -275 UNIMPL -276 UNIMPL -277 UNIMPL -278 UNIMPL -279 UNIMPL -280 UNIMPL -281 UNIMPL -282 UNIMPL -283 UNIMPL -284 UNIMPL -285 UNIMPL -286 UNIMPL -287 UNIMPL -288 UNIMPL -289 UNIMPL -290 UNIMPL -291 UNIMPL -292 UNIMPL -293 UNIMPL -294 UNIMPL -295 UNIMPL -296 UNIMPL -297 UNIMPL -298 UNIMPL -299 UNIMPL -300 UNIMPL -301 UNIMPL -302 UNIMPL -303 UNIMPL -304 UNIMPL -305 UNIMPL -306 UNIMPL -307 UNIMPL -308 UNIMPL -309 UNIMPL -310 UNIMPL -311 UNIMPL -312 UNIMPL -313 UNIMPL -314 UNIMPL -315 UNIMPL -316 UNIMPL -317 UNIMPL -318 UNIMPL -319 UNIMPL -320 UNIMPL -321 UNIMPL -322 UNIMPL -323 UNIMPL -324 UNIMPL -325 UNIMPL -326 UNIMPL -327 UNIMPL -328 UNIMPL -329 UNIMPL -330 UNIMPL -331 UNIMPL -332 UNIMPL -333 UNIMPL -334 UNIMPL -335 UNIMPL -336 UNIMPL -337 UNIMPL -338 UNIMPL -339 UNIMPL -340 UNIMPL -341 UNIMPL -342 UNIMPL -343 UNIMPL -344 UNIMPL -345 UNIMPL -346 UNIMPL -347 UNIMPL -348 UNIMPL -349 UNIMPL -350 UNIMPL -351 UNIMPL -352 UNIMPL -353 UNIMPL -354 UNIMPL -355 UNIMPL -356 UNIMPL -357 UNIMPL -358 UNIMPL -359 UNIMPL -360 UNIMPL -361 UNIMPL -362 UNIMPL -363 UNIMPL -364 UNIMPL -365 UNIMPL +274 UNIMPL mq_open +275 UNIMPL mq_unlink +276 UNIMPL mq_timedsend +277 UNIMPL mq_timedreceive +278 UNIMPL mq_notify +279 UNIMPL mq_getsetattr +280 UNIMPL waitid +281 UNIMPL socket +282 UNIMPL bind +283 UNIMPL connect +284 UNIMPL listen +285 UNIMPL accept +286 UNIMPL getsockname +287 UNIMPL getpeername +288 UNIMPL socketpair +289 UNIMPL send +290 UNIMPL sendto +291 UNIMPL recv +292 UNIMPL recvfrom +293 UNIMPL shutdown +294 UNIMPL setsockopt +295 UNIMPL getsockopt +296 UNIMPL sendmsg +297 UNIMPL recvmsg +298 UNIMPL semop +299 UNIMPL semget +300 UNIMPL semctl +301 UNIMPL msgsnd +302 UNIMPL msgrcv +303 UNIMPL msgget +304 UNIMPL msgctl +305 UNIMPL shmat +306 UNIMPL shmdt +307 UNIMPL shmget +308 UNIMPL shmctl +309 UNIMPL add_key +310 UNIMPL request_key +311 UNIMPL keyctl +312 UNIMPL semtimedop +313 UNIMPL vserver +314 UNIMPL ioptio_set +315 UNIMPL ioptio_get +316 UNIMPL inotify_init +317 UNIMPL inotify_add_watch +318 UNIMPL inotify_rm_watch +319 UNIMPL mbind +320 UNIMPL get_mempolicy +321 UNIMPL set_mempolicy +322 UNIMPL openat +323 UNIMPL mkdirat +324 UNIMPL mknodat +325 UNIMPL fchownat +326 UNIMPL futimesat +327 UNIMPL fstatat64 +328 UNIMPL unlinkat +329 UNIMPL renameat +330 UNIMPL linkat +331 UNIMPL symlinkat +332 UNIMPL readlinkat +333 UNIMPL fchmodat +334 UNIMPL faccessat +335 UNIMPL pselect6 +336 UNIMPL ppoll +337 UNIMPL unshare +338 STD { int|linux_sys||set_robust_list( \ + struct linux_robust_list_head *head, size_t len); } +339 STD { int|linux_sys||get_robust_list(int pid, \ + struct linux_robust_list_head **head, \ + size_t *len); } +340 UNIMPL splice +341 UNIMPL sync_file_range2 +342 UNIMPL tee +343 UNIMPL vmsplice +344 UNIMPL move_pages +345 UNIMPL getcpu +346 UNIMPL epoll_wait +347 UNIMPL kexec_load +348 UNIMPL utimensat +349 UNIMPL signalfd +350 UNIMPL timerfd_create +351 UNIMPL eventfd +352 UNIMPL fallocate +353 UNIMPL timerfd_settime +354 UNIMPL timerfd_gettime +355 UNIMPL signalfd4 +356 UNIMPL eventfd2 +357 UNIMPL epoll_create1 +358 UNIMPL dup3 +359 UNIMPL pipe2 +360 UNIMPL inotify_init1 +361 UNIMPL preadv +362 UNIMPL pwritev +363 UNIMPL rt_tgsigqueueinfo +364 UNIMPL perf_counter_open +365 UNIMPL recvmmsg 366 UNIMPL 367 UNIMPL 368 UNIMPL @@ -567,6 +575,7 @@ 384 UNIMPL /* base */ 385 STD { int|linux_sys||breakpoint(void); } 386 STD { int|linux_sys||cacheflush(uintptr_t from, \ - intptr_t to); } + intptr_t to, int flags); } 387 UNIMPL usr26 388 UNIMPL usr32 +389 STD { int|linux_sys||set_tls(void *tls); } diff --git a/sys/compat/linux/arch/i386/linux_exec_machdep.c b/sys/compat/linux/arch/i386/linux_exec_machdep.c index b58553ea395..60af419b932 100644 --- a/sys/compat/linux/arch/i386/linux_exec_machdep.c +++ b/sys/compat/linux/arch/i386/linux_exec_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_exec_machdep.c,v 1.15 2010/04/23 16:07:33 joerg Exp $ */ +/* $NetBSD: linux_exec_machdep.c,v 1.16 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 2004 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.15 2010/04/23 16:07:33 joerg Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.16 2010/07/07 01:30:34 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_vm86.h" @@ -70,7 +70,6 @@ __KERNEL_RCSID(0, "$NetBSD: linux_exec_machdep.c,v 1.15 2010/04/23 16:07:33 joer #include <compat/linux/common/linux_errno.h> #include <compat/linux//linux_syscallargs.h> - int linux_exec_setup_stack(struct lwp *l, struct exec_package *epp) { @@ -132,184 +131,25 @@ linux_exec_setup_stack(struct lwp *l, struct exec_package *epp) return 0; } - -#ifdef LINUX_NPTL -static __inline void -load_gs(u_int sel) -{ - __asm __volatile("movw %0,%%gs" : : "rm" ((unsigned short)sel)); -} - - -int -linux_init_thread_area(struct lwp *l, struct lwp *l2) -{ - struct trapframe *tf = l->l_md.md_regs, *tf2 = l2->l_md.md_regs; - struct pcb *pcb2 = lwp_getpcb(l2); - struct linux_user_desc info; - struct segment_descriptor sd; - int error, idx, a[2]; - - error = copyin((void *)tf->tf_esi, &info, sizeof(info)); - if (error) - return error; - idx = info.entry_number; - - /* - * looks like we're getting the idx we returned - * in the set_thread_area() syscall - */ - if (idx != LINUX_GLIBC_TLS_SEL && idx != GUGS_SEL) { - DPRINTF(("resetting idx %d to GUGS_SEL", idx)); - idx = GUGS_SEL; - } - - /* this doesnt happen in practice */ - if (idx == LINUX_GLIBC_TLS_SEL) { - /* we might copy out the entry_number as 3 */ - info.entry_number = GUGS_SEL; - error = copyout(&info, (void *)tf->tf_esi, sizeof(info)); - if (error) - return error; - } - - a[0] = LINUX_LDT_entry_a(&info); - a[1] = LINUX_LDT_entry_b(&info); - - (void)memcpy(&sd, &a, sizeof(a)); - KASSERT(ISMEMSDP((&sd))); - DPRINTF(("Segment created in clone with CLONE_SETTLS: lobase: %x, " - "hibase: %x, lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, " - "xx: %i, def32: %i, gran: %i\n", sd.sd_lobase, - sd.sd_hibase, sd.sd_lolimit, sd.sd_hilimit, sd.sd_type, sd.sd_dpl, - sd.sd_p, sd.sd_xx, sd.sd_def32, sd.sd_gran)); - - (void)memcpy(&pcb2->pcb_gsd, &sd, sizeof(sd)); - tf2->tf_gs = GSEL(GUGS_SEL, SEL_UPL); - - return 0; -} - - int linux_sys_set_thread_area(struct lwp *l, const struct linux_sys_set_thread_area_args *uap, register_t *retval) { - struct pcb *pcb = lwp_getpcb(l); - struct linux_user_desc info; - struct segment_descriptor sd; - int error, idx, a[2]; - - *retval = 0; - error = copyin(SCARG(uap, desc), &info, sizeof(info)); - if (error) - return error; + /* { + syscallarg(struct linux_user_desc *) desc; + } */ - DPRINTF(("set thread area: %i, %x, %x, %i, %i, %i, %i, %i, %i\n", - info.entry_number, info.base_addr, info.limit, info.seg_32bit, - info.contents, info.read_exec_only, info.limit_in_pages, - info.seg_not_present, info.useable)); - - idx = info.entry_number; - /* - * Semantics of linux version: every thread in the system has array of - * 3 tls descriptors. 1st is GLIBC TLS, 2nd is WINE, 3rd unknown. This - * syscall loads one of the selected tls decriptors with a value and - * also loads GDT descriptors 6, 7 and 8 with the content of the - * per-thread descriptors. - * - * Semantics of fbsd version: I think we can ignore that linux has 3 - * per-thread descriptors and use just the 1st one. The tls_array[] - * is used only in set/get-thread_area() syscalls and for loading the - * GDT descriptors. In fbsd we use just one GDT descriptor for TLS so - * we will load just one. - * - * XXX: this doesn't work when a user space process tries to use more - * than 1 TLS segment. Comment in the linux sources says wine might do - * this. - */ - - /* - * we support just GLIBC TLS now - * we should let 3 proceed as well because we use this segment so - * if code does two subsequent calls it should succeed - */ - if (idx != LINUX_GLIBC_TLS_SEL && idx != -1 && idx != GUGS_SEL) - return EINVAL; - - /* - * we have to copy out the GDT entry we use - * FreeBSD uses GDT entry #3 for storing %gs so load that - * - * XXX: what if a user space program doesn't check this value and tries - * to use 6, 7 or 8? - */ - idx = info.entry_number = GUGS_SEL; - error = copyout(&info, SCARG(uap, desc), sizeof(info)); - if (error) - return error; - - if (LINUX_LDT_empty(&info)) { - a[0] = 0; - a[1] = 0; - } else { - a[0] = LINUX_LDT_entry_a(&info); - a[1] = LINUX_LDT_entry_b(&info); - } - - (void)memcpy(&sd, &a, sizeof(a)); - KASSERT(ISMEMSDP((&sd))); - DPRINTF(("Segment created in set_thread_area: lobase: %x, hibase: %x, " - "lolimit: %x, hilimit: %x, type: %i, dpl: %i, p: %i, xx: %i, " - "def32: %i, gran: %i\n", sd.sd_lobase, sd.sd_hibase, sd.sd_lolimit, - sd.sd_hilimit, sd.sd_type, sd.sd_dpl, sd.sd_p, sd.sd_xx, - sd.sd_def32, sd.sd_gran)); - - kpreempt_disable(); - (void)memcpy(&pcb->pcb_gsd, &sd, sizeof(sd)); - (void)memcpy(&curcpu()->ci_gdt[GUGS_SEL], &sd, sizeof(sd)); - load_gs(GSEL(GUGS_SEL, SEL_UPL)); - kpreempt_enable(); - return 0; + return linux_lwp_setprivate(l, SCARG(uap, desc)); } int linux_sys_get_thread_area(struct lwp *l, const struct linux_sys_get_thread_area_args *uap, register_t *retval) { - struct pcb *pcb = lwp_getpcb(l); - struct linux_user_desc info; - struct linux_desc_struct desc; - struct segment_descriptor sd; - int error, idx; - - *retval = 0; - error = copyin(SCARG(uap, desc), &info, sizeof(info)); - if (error) - return error; - - idx = info.entry_number; - /* XXX: I am not sure if we want 3 to be allowed too. */ - if (idx != LINUX_GLIBC_TLS_SEL && idx != GUGS_SEL) - return EINVAL; + /* { + syscallarg(struct linux_user_desc *) desc; + } */ - idx = GUGS_SEL; - - (void)memset(&info, 0, sizeof(info)); - (void)memcpy(&sd, &pcb->pcb_gsd, sizeof(sd)); - (void)memcpy(&desc, &sd, sizeof(desc)); - - info.entry_number = idx; - info.base_addr = LINUX_GET_BASE(&desc); - info.limit = LINUX_GET_LIMIT(&desc); - info.seg_32bit = LINUX_GET_32BIT(&desc); - info.contents = LINUX_GET_CONTENTS(&desc); - info.read_exec_only = !LINUX_GET_WRITABLE(&desc); - info.limit_in_pages = LINUX_GET_LIMIT_PAGES(&desc); - info.seg_not_present = !LINUX_GET_PRESENT(&desc); - info.useable = LINUX_GET_USEABLE(&desc); - - return copyout(&info, SCARG(uap, desc), sizeof(info)); + /* glibc doesn't actually call this. */ + return ENOSYS; } - -#endif diff --git a/sys/compat/linux/arch/i386/linux_machdep.c b/sys/compat/linux/arch/i386/linux_machdep.c index a415d4d6e33..f0f8294ab4a 100644 --- a/sys/compat/linux/arch/i386/linux_machdep.c +++ b/sys/compat/linux/arch/i386/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.148 2010/02/03 13:48:53 wiz Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.149 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1995, 2000, 2008, 2009 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.148 2010/02/03 13:48:53 wiz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.149 2010/07/07 01:30:34 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_vm86.h" @@ -118,12 +118,13 @@ static void linux_rt_sendsig(const ksiginfo_t *, const sigset_t *); static void linux_old_sendsig(const ksiginfo_t *, const sigset_t *); extern char linux_sigcode[], linux_rt_sigcode[]; + /* * Deal with some i386-specific things in the Linux emulation code. */ void -linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { struct pcb *pcb = lwp_getpcb(l); struct trapframe *tf; @@ -147,7 +148,7 @@ linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) pcb->pcb_savefpu.sv_87.sv_env.en_cw = __Linux_NPXCW__; tf = l->l_md.md_regs; - tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); + tf->tf_gs = 0; tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); @@ -337,7 +338,6 @@ linux_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) /* * Build context to run handler in. */ - tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); @@ -406,7 +406,6 @@ linux_old_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) /* * Build context to run handler in. */ - tf->tf_gs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL); tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL); @@ -480,10 +479,11 @@ linux_restore_sigcontext(struct lwp *l, struct linux_sigcontext *scp, struct trapframe *tf; sigset_t mask; ssize_t ss_gap; + /* Restore register context. */ tf = l->l_md.md_regs; + DPRINTF(("sigreturn enter esp=0x%x eip=0x%x\n", tf->tf_esp, tf->tf_eip)); - DPRINTF(("sigreturn enter esp=%x eip=%x\n", tf->tf_esp, tf->tf_eip)); #ifdef VM86 if (scp->sc_eflags & PSL_VM) { void syscall_vm86(struct trapframe *); @@ -546,7 +546,7 @@ linux_restore_sigcontext(struct lwp *l, struct linux_sigcontext *scp, (void) sigprocmask1(l, SIG_SETMASK, &mask, 0); mutex_exit(p->p_lock); - DPRINTF(("sigreturn exit esp=%x eip=%x\n", tf->tf_esp, tf->tf_eip)); + DPRINTF(("sigreturn exit esp=0x%x eip=0x%x\n", tf->tf_esp, tf->tf_eip)); return EJUSTRETURN; } @@ -1109,23 +1109,3 @@ linux_get_uname_arch(void) uname_arch[1] += cpu_class; return uname_arch; } - -#ifdef LINUX_NPTL -void * -linux_get_newtls(struct lwp *l) -{ -#if 0 - struct trapframe *tf = l->l_md.md_regs; -#endif - - /* XXX: Implement me */ - return NULL; -} - -int -linux_set_newtls(struct lwp *l, void *tls) -{ - /* XXX: Implement me */ - return 0; -} -#endif diff --git a/sys/compat/linux/arch/i386/linux_machdep.h b/sys/compat/linux/arch/i386/linux_machdep.h index de0c2e98f9b..af402bac97e 100644 --- a/sys/compat/linux/arch/i386/linux_machdep.h +++ b/sys/compat/linux/arch/i386/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.36 2008/11/12 12:36:10 ad Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.37 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1995, 2000 The NetBSD Foundation, Inc. @@ -147,90 +147,6 @@ struct linux_sigframe { sig_t sf_handler; }; -struct linux_user_desc { - unsigned int entry_number; - unsigned int base_addr; - unsigned int limit; - unsigned int seg_32bit:1; - unsigned int contents:2; - unsigned int read_exec_only:1; - unsigned int limit_in_pages:1; - unsigned int seg_not_present:1; - unsigned int useable:1; -}; - -struct linux_desc_struct { - unsigned long a, b; -}; - - -#define LINUX_LOWERWORD 0x0000ffff - -#define LINUX_GLIBC_TLS_SEL 6 - -/* - * Macros which does the same thing as those in Linux include/asm-um/ldt-i386.h. - * These convert Linux user space descriptor to machine one. - */ -#define LINUX_LDT_entry_a(info) \ - ((((info)->base_addr & LINUX_LOWERWORD) << 16) | \ - ((info)->limit & LINUX_LOWERWORD)) - -#define LINUX_ENTRY_B_READ_EXEC_ONLY 9 -#define LINUX_ENTRY_B_CONTENTS 10 -#define LINUX_ENTRY_B_SEG_NOT_PRESENT 15 -#define LINUX_ENTRY_B_BASE_ADDR 16 -#define LINUX_ENTRY_B_USEABLE 20 -#define LINUX_ENTRY_B_SEG32BIT 22 -#define LINUX_ENTRY_B_LIMIT 23 - -#define LINUX_LDT_entry_b(info) \ - (((info)->base_addr & 0xff000000) | \ - ((info)->limit & 0xf0000) | \ - ((info)->contents << LINUX_ENTRY_B_CONTENTS) | \ - (((info)->seg_not_present == 0) << LINUX_ENTRY_B_SEG_NOT_PRESENT) |\ - (((info)->base_addr & 0x00ff0000) >> LINUX_ENTRY_B_BASE_ADDR) | \ - (((info)->read_exec_only == 0) << LINUX_ENTRY_B_READ_EXEC_ONLY) |\ - ((info)->seg_32bit << LINUX_ENTRY_B_SEG32BIT) | \ - ((info)->useable << LINUX_ENTRY_B_USEABLE) | \ - ((info)->limit_in_pages << LINUX_ENTRY_B_LIMIT) | 0x7000) - -#define LINUX_LDT_empty(info) \ - ((info)->base_addr == 0 && \ - (info)->limit == 0 && \ - (info)->contents == 0 && \ - (info)->seg_not_present == 1 && \ - (info)->read_exec_only == 1 && \ - (info)->seg_32bit == 0 && \ - (info)->limit_in_pages == 0 && \ - (info)->useable == 0) - -/* - * Macros for converting segments. - * They do the same as those in arch/i386/kernel/process.c in Linux. - */ -#define LINUX_GET_BASE(desc) \ - ((((desc)->a >> 16) & LINUX_LOWERWORD) | \ - (((desc)->b << 16) & 0x00ff0000) | \ - ((desc)->b & 0xff000000)) - -#define LINUX_GET_LIMIT(desc) \ - (((desc)->a & LINUX_LOWERWORD) | \ - ((desc)->b & 0xf0000)) - -#define LINUX_GET_32BIT(desc) \ - (((desc)->b >> LINUX_ENTRY_B_SEG32BIT) & 1) -#define LINUX_GET_CONTENTS(desc) \ - (((desc)->b >> LINUX_ENTRY_B_CONTENTS) & 3) -#define LINUX_GET_WRITABLE(desc) \ - (((desc)->b >> LINUX_ENTRY_B_READ_EXEC_ONLY) & 1) -#define LINUX_GET_LIMIT_PAGES(desc) \ - (((desc)->b >> LINUX_ENTRY_B_LIMIT) & 1) -#define LINUX_GET_PRESENT(desc) \ - (((desc)->b >> LINUX_ENTRY_B_SEG_NOT_PRESENT) & 1) -#define LINUX_GET_USEABLE(desc) \ - (((desc)->b >> LINUX_ENTRY_B_USEABLE) & 1) - /* * Used in ugly patch to fake device numbers. */ @@ -287,7 +203,8 @@ struct linux_desc_struct { #define LINUX_IOCTL_MAX_PASS (LINUX_VMWARE_LAST+8) #define LINUX_UNAME_ARCH linux_get_uname_arch() -#define LINUX_NPTL + +#define LINUX_LWP_SETPRIVATE linux_lwp_setprivate #ifdef _KERNEL __BEGIN_DECLS diff --git a/sys/compat/linux/arch/i386/linux_ptrace.c b/sys/compat/linux/arch/i386/linux_ptrace.c index 389109640f0..e6b6fd3b109 100644 --- a/sys/compat/linux/arch/i386/linux_ptrace.c +++ b/sys/compat/linux/arch/i386/linux_ptrace.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_ptrace.c,v 1.25 2010/07/01 02:38:28 rmind Exp $ */ +/* $NetBSD: linux_ptrace.c,v 1.26 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.25 2010/07/01 02:38:28 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_ptrace.c,v 1.26 2010/07/07 01:30:34 chs Exp $"); #include <sys/param.h> #include <sys/malloc.h> @@ -135,6 +135,7 @@ linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, struct fpreg *fpregs = NULL; struct linux_reg *linux_regs = NULL; struct linux_fpctx *linux_fpregs = NULL; + struct linux_emuldata *led; int request, error, addr; if (linux_ptrace_disabled) @@ -293,7 +294,7 @@ linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, error = 0; if (addr < LUSR_OFF(lusr_startgdb)) { /* XXX should provide appropriate register */ - error = 1; + error = ENOTSUP; } else if (addr == LUSR_OFF(u_tsize)) *retval = p->p_vmspace->vm_tsize; else if (addr == LUSR_OFF(u_dsize)) @@ -311,51 +312,51 @@ linux_sys_ptrace_arch(struct lwp *l, const struct linux_sys_ptrace_args *uap, int off = (addr - LUSR_OFF(u_debugreg)) / sizeof(int); /* only do this for Linux processes */ - if (t->p_emul != &emul_linux) - error = EINVAL; - else { - *retval = ((struct linux_emuldata *) - t->p_emuldata)->debugreg[off]; + if (t->p_emul != &emul_linux) { + mutex_exit(t->p_lock); + return EINVAL; } + + led = lt->l_emuldata; + *retval = led->led_debugreg[off]; } else if (addr == LUSR_OFF(__signal)) { - error = 1; + error = ENOTSUP; } else if (addr == LUSR_OFF(__signal)) { - error = 1; + error = ENOTSUP; } else if (addr == LUSR_OFF(u_fpstate)) { - error = 1; + error = ENOTSUP; } else if (addr == LUSR_OFF(__magic)) { - error = 1; + error = ENOTSUP; } else if (addr == LUSR_OFF(u_comm)) { - error = 1; + error = ENOTSUP; } else { #ifdef DEBUG_LINUX printf("linux_ptrace: unsupported address: %d\n", addr); #endif - error = 1; + error = ENOTSUP; } - if (error == 0) { - mutex_exit(t->p_lock); - break; - } - /* FALLTHROUGH */ + mutex_exit(t->p_lock); + break; case LINUX_PTRACE_POKEUSR: /* we only support setting debugregs for now */ addr = SCARG(uap, addr); - if (addr >= LUSR_OFF(u_debugreg) - && addr <= LUSR_OFF(u_debugreg_end)) { + if (addr >= LUSR_OFF(u_debugreg) && + addr <= LUSR_OFF(u_debugreg_end)) { int off = (addr - LUSR_OFF(u_debugreg)) / sizeof(int); int data = SCARG(uap, data); /* only do this for Linux processes */ if (t->p_emul != &emul_linux) { - error = EINVAL; - } else { - ((struct linux_emuldata *)t->p_emuldata)->debugreg[off] = data; + mutex_exit(t->p_lock); + return EINVAL; } - error = 0; + led = lt->l_emuldata; + led->led_debugreg[off] = data; } - /* FALLTHROUGH */ + mutex_exit(t->p_lock); + break; + default: mutex_exit(t->p_lock); break; diff --git a/sys/compat/linux/arch/i386/syscalls.master b/sys/compat/linux/arch/i386/syscalls.master index 692a4bee9da..c226258c18e 100644 --- a/sys/compat/linux/arch/i386/syscalls.master +++ b/sys/compat/linux/arch/i386/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.102 2010/04/23 03:02:16 chs Exp $ + $NetBSD: syscalls.master,v 1.103 2010/07/07 01:30:34 chs Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -53,7 +53,7 @@ %% 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, char *buf, u_int nbyte); } 4 NOARGS { int|sys||write(int fd, char *buf, u_int nbyte); } @@ -79,11 +79,7 @@ 18 OBSOL ostat 19 NOARGS { long|compat_43_sys||lseek(int fd, long offset, \ int whence); } -#ifdef LINUX_NPTL -20 STD { pid_t|linux_sys||getpid(void); } -#else 20 NOARGS { pid_t|sys||getpid(void); } -#endif 21 UNIMPL mount 22 UNIMPL umount 23 NOARGS linux_setuid16 { int|sys||setuid(uid_t uid); } @@ -93,7 +89,7 @@ int addr, int data); } 27 STD { int|linux_sys||alarm(unsigned int secs); } 28 OBSOL ofstat -29 STD { int|linux_sys||pause(void); } +29 NOARGS { int|linux_sys||pause(void); } 30 STD { int|linux_sys||utime(const char *path, \ struct linux_utimbuf *times); } 31 OBSOL stty @@ -133,17 +129,13 @@ 61 NOARGS { int|sys||chroot(char *path); } 62 UNIMPL ustat 63 NOARGS { int|sys||dup2(u_int from, u_int to); } -#ifdef LINUX_NPTL -64 STD { pid_t|linux_sys||getppid(void); } -#else 64 NOARGS { pid_t|sys||getppid(void); } -#endif 65 NOARGS { int|sys||getpgrp(void); } 66 NOARGS { int|sys||setsid(void); } 67 STD { int|linux_sys||sigaction(int signum, \ const struct linux_old_sigaction *nsa, \ struct linux_old_sigaction *osa); } -68 STD { int|linux_sys||siggetmask(void); } +68 NOARGS { int|linux_sys||siggetmask(void); } 69 STD { int|linux_sys||sigsetmask(linux_old_sigset_t mask); } 70 STD { int|linux_sys||setreuid16(linux_uid16_t ruid, \ linux_uid16_t euid); } @@ -386,13 +378,8 @@ 221 STD { int|linux_sys||fcntl64(int fd, int cmd, void *arg); } 222 UNIMPL /* unused */ 223 UNIMPL /* unused */ -#ifdef LINUX_NPTL -224 STD { pid_t|linux_sys||gettid(void); } -#else -224 UNIMPL gettid -#endif +224 NOARGS { pid_t|linux_sys||gettid(void); } 225 UNIMPL readahead - 226 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } 227 STD { int|linux_sys||lsetxattr(char *path, char *name, \ @@ -414,33 +401,19 @@ 235 STD { int|linux_sys||removexattr(char *path, char *name); } 236 STD { int|linux_sys||lremovexattr(char *path, char *name); } 237 STD { int|linux_sys||fremovexattr(int fd, char *name); } -#ifdef LINUX_NPTL 238 STD { int|linux_sys||tkill(int tid, int sig); } -#else -238 UNIMPL tkill -#endif 239 UNIMPL sendfile64 240 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ const struct linux_timespec *timeout, int *uaddr2, \ int val3); } -#ifdef LINUX_NPTL 241 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ unsigned int len, unsigned long *mask); } 242 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ unsigned int len, unsigned long *mask); } -#else -241 UNIMPL setaffinity -242 UNIMPL getaffinity -#endif -#ifdef LINUX_NPTL 243 STD { int|linux_sys||set_thread_area( \ struct linux_user_desc *desc); } 244 STD { int|linux_sys||get_thread_area( \ struct linux_user_desc *desc); } -#else -243 UNIMPL set_thread_area -244 UNIMPL get_thread_area -#endif 245 UNIMPL io_setup 246 UNIMPL io_destroy 247 UNIMPL io_getevents @@ -454,11 +427,7 @@ 255 UNIMPL epoll_ctl 256 UNIMPL epoll_wait 257 UNIMPL remap_file_pages -#ifdef LINUX_NPTL 258 STD { int|linux_sys||set_tid_address(int *tid); } -#else -258 UNIMPL set_tid_address -#endif 259 UNIMPL timer_create 260 UNIMPL timer_settime 261 UNIMPL timer_gettime @@ -477,11 +446,7 @@ size_t sz, struct linux_statfs64 *sp); } 269 STD { int|linux_sys||fstatfs64(int fd, \ size_t sz, struct linux_statfs64 *sp); } -#ifdef LINUX_NPTL 270 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } -#else -270 UNIMPL tgkill -#endif 271 UNIMPL utimes 272 UNIMPL fadvise64_64 273 UNIMPL vserver @@ -496,7 +461,7 @@ 282 UNIMPL mq_getsetattr 283 UNIMPL sys_kexec_load 284 UNIMPL waitid -285 OBSOL /* XXXJDM really? */ +285 UNIMPL /* unused */ 286 UNIMPL add_key 287 UNIMPL request_key 288 UNIMPL keyctl @@ -531,3 +496,24 @@ 314 UNIMPL sync_file_range 315 UNIMPL tee 316 UNIMPL vmsplice +317 UNIMPL move_pages +318 UNIMPL getcpu +319 UNIMPL epoll_wait +320 UNIMPL utimensat +321 UNIMPL signalfd +322 UNIMPL timerfd_create +323 UNIMPL eventfd +324 UNIMPL fallocate +325 UNIMPL timerfd_settime +326 UNIMPL timerfd_gettime +327 UNIMPL signalfd4 +328 UNIMPL eventfd2 +329 UNIMPL epoll_create1 +330 UNIMPL dup3 +331 UNIMPL pipe2 +332 UNIMPL inotify_init1 +333 UNIMPL preadv +334 UNIMPL pwritev +335 UNIMPL rt_tgsigqueueinfo +336 UNIMPL perf_counter_open +337 UNIMPL recvmmsg diff --git a/sys/compat/linux/arch/m68k/files.linux_m68k b/sys/compat/linux/arch/m68k/files.linux_m68k index 74057151d57..621111fae07 100644 --- a/sys/compat/linux/arch/m68k/files.linux_m68k +++ b/sys/compat/linux/arch/m68k/files.linux_m68k @@ -1,4 +1,4 @@ -# $NetBSD: files.linux_m68k,v 1.4 2008/01/15 22:38:34 njoly Exp $ +# $NetBSD: files.linux_m68k,v 1.5 2010/07/07 01:30:34 chs Exp $ # # Config file description for m68k-dependent Linux compat code. @@ -18,3 +18,4 @@ file compat/linux/common/linux_llseek.c compat_linux file compat/linux/common/linux_oldmmap.c compat_linux file compat/linux/common/linux_oldselect.c compat_linux file compat/linux/common/linux_uid16.c compat_linux +file compat/linux/common/linux_futex.c compat_linux diff --git a/sys/compat/linux/arch/m68k/linux_machdep.c b/sys/compat/linux/arch/m68k/linux_machdep.c index a81f45816e0..115f9f2e7c1 100644 --- a/sys/compat/linux/arch/m68k/linux_machdep.c +++ b/sys/compat/linux/arch/m68k/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.41 2009/04/15 20:44:26 elad Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.42 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2009/04/15 20:44:26 elad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.42 2010/07/07 01:30:34 chs Exp $"); #define COMPAT_LINUX 1 @@ -88,7 +88,7 @@ void setup_linux_rt_sigframe(struct frame *frame, int sig, * Setup registers on program execution. */ void -linux_setregs(struct lwp *l, struct exec_package *epp, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *epp, vaddr_t stack) { setregs(l, epp, stack); diff --git a/sys/compat/linux/arch/m68k/syscalls.master b/sys/compat/linux/arch/m68k/syscalls.master index 20ce17599ac..43208a62528 100644 --- a/sys/compat/linux/arch/m68k/syscalls.master +++ b/sys/compat/linux/arch/m68k/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.68 2009/11/24 10:42:44 njoly Exp $ + $NetBSD: syscalls.master,v 1.69 2010/07/07 01:30:34 chs Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -57,7 +57,7 @@ %% 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, char *buf, u_int nbyte); } 4 NOARGS { int|sys||write(int fd, char *buf, u_int nbyte); } @@ -237,7 +237,8 @@ void *ptr); } 118 NOARGS { int|sys||fsync(int fd); } 119 STD { int|linux_sys||sigreturn(void); } -120 STD { int|linux_sys||clone(int flags, void *stack); } +120 STD { int|linux_sys||clone(int flags, void *stack, \ + void *parent_tidptr, void *tls, void *child_tidptr); } 121 STD { int|linux_sys||setdomainname(char *domainname, \ int len); } 122 STD { int|linux_sys||uname(struct linux_utsname *up); } @@ -393,8 +394,8 @@ 219 UNIMPL /* unused */ 220 STD { int|linux_sys||getdents64(int fd, \ struct linux_dirent64 *dent, unsigned int count); } -221 UNIMPL gettid -222 UNIMPL tkill +221 NOARGS { pid_t|linux_sys||gettid(void); } +222 STD { int|linux_sys||tkill(int tid, int sig); } 223 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } 224 STD { int|linux_sys||lsetxattr(char *path, char *name, \ @@ -416,7 +417,9 @@ 232 STD { int|linux_sys||removexattr(char *path, char *name); } 233 STD { int|linux_sys||lremovexattr(char *path, char *name); } 234 STD { int|linux_sys||fremovexattr(int fd, char *name); } -235 UNIMPL futex +235 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ + const struct linux_timespec *timeout, int *uaddr2, \ + int val3); } 236 UNIMPL sendfile64 237 UNIMPL mincore 238 UNIMPL madvise @@ -434,12 +437,12 @@ 250 UNIMPL epoll_ctl 251 UNIMPL epoll_wait 252 UNIMPL remap_file_pages -253 UNIMPL set_tid_address +253 STD { int|linux_sys||set_tid_address(int *tid); } 254 UNIMPL timer_create 255 UNIMPL timer_settime 256 UNIMPL timer_gettime 257 UNIMPL timer_getoverrun -258 UNIMPL timer_delete +258 UNIMPL timer_ delete 259 STD { int|linux_sys||clock_settime(clockid_t which, \ struct linux_timespec *tp); } 260 STD { int|linux_sys||clock_gettime(clockid_t which, \ @@ -449,3 +452,84 @@ 262 STD { int|linux_sys||clock_nanosleep(clockid_t which, \ int flags, struct linux_timespec *rqtp, \ struct linux_timespec *rmtp); } +263 STD { int|linux_sys||statfs64(const char *path, \ + size_t sz, struct linux_statfs64 *sp); } +264 STD { int|linux_sys||fstatfs64(int fd, \ + size_t sz, struct linux_statfs64 *sp); } +265 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } +266 UNIMPL utimes +267 UNIMPL fadvise64_64 +268 UNIMPL mbind +269 UNIMPL get_mempolicy +270 UNIMPL set_mempolicy +271 UNIMPL mq_open +272 UNIMPL mq_unlink +273 UNIMPL mq_timedsend +274 UNIMPL mq_timedreceive +275 UNIMPL mq_notify +276 UNIMPL mq_getsetattr +277 UNIMPL waitid +278 UNIMPL vserver +279 UNIMPL add_key +280 UNIMPL request_key +281 UNIMPL keyctl +282 UNIMPL ioprio_set +283 UNIMPL ioprio_get +284 UNIMPL inotify_init +285 UNIMPL inotify_add_watch +286 UNIMPL inotify_rm_watch +287 UNIMPL migrate_pages +288 UNIMPL openat +289 UNIMPL mkdirat +290 UNIMPL mknodat +291 UNIMPL fchownat +292 UNIMPL futimesat +293 UNIMPL fstatat64 +294 UNIMPL unlinkat +295 UNIMPL renameat +296 UNIMPL linkat +297 UNIMPL symlinkat +298 UNIMPL readlinkat +299 UNIMPL fchmodat +300 UNIMPL faccessat +301 UNIMPL pselect6 +302 UNIMPL ppoll +303 UNIMPL unshare +304 STD { int|linux_sys||set_robust_list( \ + struct linux_robust_list_head *head, size_t len); } +305 STD { int|linux_sys||get_robust_list(int pid, \ + struct linux_robust_list_head **head, \ + size_t *len); } +306 UNIMPL splice +307 UNIMPL sync_file_range +308 UNIMPL tee +309 UNIMPL vmsplice +310 UNIMPL move_pages +311 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +312 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +313 UNIMPL kexec_load +314 UNIMPL getcpu +315 UNIMPL epoll_wait +316 UNIMPL utimensat +317 UNIMPL signalfd +318 UNIMPL timerfd_create +319 UNIMPL eventfd +320 UNIMPL fallocate +321 UNIMPL timerfd_settime +322 UNIMPL timerfd_gettime +323 UNIMPL signalfd4 +324 UNIMPL eventfd2 +325 UNIMPL epoll_create1 +326 UNIMPL dup3 +327 UNIMPL pipe2 +328 UNIMPL inotify_init1 +329 UNIMPL preadv +330 UNIMPL pwritev +331 UNIMPL rt_tgsigqueueinfo +332 UNIMPL perf_counter_open +333 UNIMPL set_thread_area +334 UNIMPL get_thread_area +335 UNIMPL atomic_cmpxchg_32 +336 UNIMPL atomic_barrier diff --git a/sys/compat/linux/arch/mips/files.linux_mips b/sys/compat/linux/arch/mips/files.linux_mips index 9c5d9fff254..2a39133fbc8 100644 --- a/sys/compat/linux/arch/mips/files.linux_mips +++ b/sys/compat/linux/arch/mips/files.linux_mips @@ -1,4 +1,4 @@ -# $NetBSD: files.linux_mips,v 1.5 2008/02/02 19:37:52 dsl Exp $ +# $NetBSD: files.linux_mips,v 1.6 2010/07/07 01:30:34 chs Exp $ # # Config file description for mips-dependent Linux compat code. @@ -17,3 +17,4 @@ file compat/linux/common/linux_llseek.c compat_linux file compat/linux/common/linux_olduname.c compat_linux file compat/linux/common/linux_file64.c compat_linux file compat/linux/common/linux_fcntl64.c compat_linux +file compat/linux/common/linux_futex.c compat_linux diff --git a/sys/compat/linux/arch/mips/linux_machdep.c b/sys/compat/linux/arch/mips/linux_machdep.c index 635a554d71e..ed304f3045c 100644 --- a/sys/compat/linux/arch/mips/linux_machdep.c +++ b/sys/compat/linux/arch/mips/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.40 2009/12/14 00:47:11 matt Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.40 2009/12/14 00:47:11 matt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2010/07/07 01:30:34 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -90,11 +90,9 @@ __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.40 2009/12/14 00:47:11 matt Exp /* * Set set up registers on exec. - * XXX not used at the moment since in sys/kern/exec_conf, LINUX_COMPAT - * entry uses NetBSD's native setregs instead of linux_setregs */ void -linux_setregs(struct lwp *l, struct exec_package *pack, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) { setregs(l, pack, stack); return; @@ -278,7 +276,7 @@ linux_sys_sigreturn(struct lwp *l, const struct linux_sys_sigreturn_args *uap, r int -linux_sys_rt_sigreturn(struct lwp *l, const void *v, register_t *retval) +linux_sys_rt_sigreturn(struct lwp *l, const struct linux_sys_rt_sigreturn_args *v, register_t *retval) { return (ENOSYS); } @@ -383,14 +381,12 @@ linux_sys_cacheflush(struct lwp *l, const struct linux_sys_cacheflush_args *uap, int linux_sys_sysmips(struct lwp *l, const struct linux_sys_sysmips_args *uap, register_t *retval) { -#if 0 - struct linux_sys_sysmips_args { + /* { syscallarg(int) cmd; syscallarg(int) arg1; syscallarg(int) arg2; syscallarg(int) arg3; - } *uap = v; -#endif + } */ int error; switch (SCARG(uap, cmd)) { @@ -456,3 +452,13 @@ linux_usertrap(struct lwp *l, vaddr_t trapaddr, void *arg) { return 0; } + +int +linux_sys_set_thread_area(struct lwp *l, const struct linux_sys_set_thread_area_args *uap, register_t *retval) +{ + /* { + syscallarg(void *) tls; + } */ + + return lwp_setprivate(l, SCARG(uap, tls)); +} diff --git a/sys/compat/linux/arch/mips/syscalls.master b/sys/compat/linux/arch/mips/syscalls.master index cc3bf2efa7e..d28a8c17166 100644 --- a/sys/compat/linux/arch/mips/syscalls.master +++ b/sys/compat/linux/arch/mips/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.37 2009/11/24 10:42:44 njoly Exp $ + $NetBSD: syscalls.master,v 1.38 2010/07/07 01:30:34 chs Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -57,7 +57,7 @@ #include <compat/linux/linux_syscallargs.h> 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, char *buf, u_int nbyte); } 4 NOARGS { int|sys||write(int fd, char *buf, u_int nbyte); } @@ -214,7 +214,8 @@ void *ptr); } 118 NOARGS { int|sys||fsync(int fd); } 119 STD { int|linux_sys||sigreturn(struct linux_sigframe *sf); } -120 STD { int|linux_sys||clone(int flags, void *stack); } +120 STD { int|linux_sys||clone(int flags, void *stack, \ + void *parent_tidptr, void *tls, void *child_tidptr); } 121 STD { int|linux_sys||setdomainname(char *domainname, \ int len); } 122 STD { int|linux_sys||new_uname(struct linux_utsname *up); } @@ -328,7 +329,7 @@ gid_t *sgid); } 192 UNIMPL prctl 193 STD { int|linux_sys||rt_sigreturn( \ - struct linux_pt_regs regs); } + struct linux_pt_regs *regs); } 194 STD { int|linux_sys||rt_sigaction(int signum, \ const struct linux_sigaction *nsa, \ struct linux_sigaction *osa, \ @@ -382,7 +383,7 @@ 220 STD { int|linux_sys||fcntl64(int fd, \ int cmd, void *arg); } 221 UNIMPL /* reserved */ -222 UNIMPL gettid +222 NOARGS { pid_t|linux_sys||gettid(void); } 223 UNIMPL readahead 224 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } @@ -405,11 +406,15 @@ 233 STD { int|linux_sys||removexattr(char *path, char *name); } 234 STD { int|linux_sys||lremovexattr(char *path, char *name); } 235 STD { int|linux_sys||fremovexattr(int fd, char *name); } -236 UNIMPL tkill +236 STD { int|linux_sys||tkill(int tid, int sig); } 237 UNIMPL sendfile64 -238 UNIMPL futex -239 UNIMPL sched_setaffinity -240 UNIMPL sched_getaffinity +238 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ + const struct linux_timespec *timeout, int *uaddr2, \ + int val3); } +239 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +240 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } 241 UNIMPL io_setup 242 UNIMPL io_destroy 243 UNIMPL io_getevents @@ -421,7 +426,7 @@ 249 UNIMPL epoll_ctl 250 UNIMPL epoll_wait 251 UNIMPL remap_file_pages -252 UNIMPL set_tid_address +252 STD { int|linux_sys||set_tid_address(int *tid); } 253 UNIMPL restart_syscall 254 UNIMPL fadvise64 255 STD { int|linux_sys||statfs64(const char *path, \ @@ -442,7 +447,7 @@ 265 STD { int|linux_sys||clock_nanosleep(clockid_t which, \ int flags, struct linux_timespec *rqtp, \ struct linux_timespec *rmtp); } -266 UNIMPL tgkill +266 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } 267 UNIMPL utimes 268 UNIMPL mbind 269 UNIMPL get_mempolicy @@ -453,3 +458,65 @@ 274 UNIMPL mq_timedreceive 275 UNIMPL mq_notify 276 UNIMPL mq_getsetattr +277 UNIMPL vserve +278 UNIMPL waitid +279 UNIMPL setaltroot +280 UNIMPL add_key +281 UNIMPL request_key +282 UNIMPL keyctl +283 STD { int|linux_sys||set_thread_area(void *tls); } +284 UNIMPL inotify_init +285 UNIMPL inotify_add_watch +286 UNIMPL inotify_rm_watch +287 UNIMPL migrate_pages +288 UNIMPL openat +289 UNIMPL mkdirat +290 UNIMPL mknodat +291 UNIMPL fchownat +292 UNIMPL futimesat +293 UNIMPL fstatat64 +294 UNIMPL unlinkat +295 UNIMPL renameat +296 UNIMPL linkat +297 UNIMPL symlinkat +298 UNIMPL readlinkat +299 UNIMPL fchmodat +300 UNIMPL faccessat +301 UNIMPL pselect6 +302 UNIMPL ppoll +303 UNIMPL unshare +304 UNIMPL splice +305 UNIMPL sync_file_range +306 UNIMPL tee +307 UNIMPL vmsplice +308 UNIMPL move_pages +309 STD { int|linux_sys||set_robust_list( \ + struct linux_robust_list_head *head, size_t len); } +310 STD { int|linux_sys||get_robust_list(int pid, \ + struct linux_robust_list_head **head, \ + size_t *len); } +311 UNIMPL kexec_load +312 UNIMPL getcpu +313 UNIMPL epoll_pwait +314 UNIMPL ioprio_set +315 UNIMPL ioprio_get +316 UNIMPL utimensat +317 UNIMPL signalfd +318 UNIMPL timerfd +319 UNIMPL eventfd +320 UNIMPL fallocate +321 UNIMPL timerfd_create +322 UNIMPL timerfd_gettime +323 UNIMPL timerfd_settime +324 UNIMPL signalfd4 +325 UNIMPL eventfd2 +326 UNIMPL epoll_create1 +327 UNIMPL dup3 +328 UNIMPL pipe2 +329 UNIMPL inotify_init1 +330 UNIMPL preadv +331 UNIMPL pwritev +332 UNIMPL rt_tgsigqueueinfo +333 UNIMPL perf_event_open +334 UNIMPL accept4 +335 UNIMPL recvmmsg diff --git a/sys/compat/linux/arch/powerpc/files.linux_powerpc b/sys/compat/linux/arch/powerpc/files.linux_powerpc index 310dcad832a..84640c7f96e 100644 --- a/sys/compat/linux/arch/powerpc/files.linux_powerpc +++ b/sys/compat/linux/arch/powerpc/files.linux_powerpc @@ -1,4 +1,4 @@ -# $NetBSD: files.linux_powerpc,v 1.9 2008/02/02 19:37:53 dsl Exp $ +# $NetBSD: files.linux_powerpc,v 1.10 2010/07/07 01:30:34 chs Exp $ # # Config file description for powerpc-dependent Linux compat code. @@ -18,3 +18,4 @@ file compat/linux/common/linux_llseek.c compat_linux file compat/linux/common/linux_olduname.c compat_linux file compat/linux/common/linux_file64.c compat_linux file compat/linux/common/linux_fcntl64.c compat_linux +file compat/linux/common/linux_futex.c compat_linux diff --git a/sys/compat/linux/arch/powerpc/linux_exec_powerpc.c b/sys/compat/linux/arch/powerpc/linux_exec_powerpc.c index 529b0e6fd2b..2d48cc067a0 100644 --- a/sys/compat/linux/arch/powerpc/linux_exec_powerpc.c +++ b/sys/compat/linux/arch/powerpc/linux_exec_powerpc.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_exec_powerpc.c,v 1.21 2008/04/28 20:23:43 martin Exp $ */ +/* $NetBSD: linux_exec_powerpc.c,v 1.22 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -41,15 +41,9 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_exec_powerpc.c,v 1.21 2008/04/28 20:23:43 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_exec_powerpc.c,v 1.22 2010/07/07 01:30:34 chs Exp $"); -#if defined (__alpha__) -#define ELFSIZE 64 -#elif defined (__powerpc__) #define ELFSIZE 32 -#else -#error Unified linux_elf_{32|64}copyargs not tested for this platform -#endif #include <sys/param.h> #include <sys/systm.h> diff --git a/sys/compat/linux/arch/powerpc/linux_machdep.c b/sys/compat/linux/arch/powerpc/linux_machdep.c index 09d7d1be9d0..7f55005e121 100644 --- a/sys/compat/linux/arch/powerpc/linux_machdep.c +++ b/sys/compat/linux/arch/powerpc/linux_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.c,v 1.41 2010/02/02 15:02:07 wiz Exp $ */ +/* $NetBSD: linux_machdep.c,v 1.42 2010/07/07 01:30:34 chs Exp $ */ /*- * Copyright (c) 1995, 2000, 2001 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2010/02/02 15:02:07 wiz Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.42 2010/07/07 01:30:34 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -85,11 +85,9 @@ __KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.41 2010/02/02 15:02:07 wiz Exp $ /* * Set set up registers on exec. - * XXX not used at the moment since in sys/kern/exec_conf, LINUX_COMPAT - * entry uses NetBSD's native setregs instead of linux_setregs */ void -linux_setregs(struct lwp *l, struct exec_package *pack, u_long stack) +linux_setregs(struct lwp *l, struct exec_package *pack, vaddr_t stack) { setregs(l, pack, stack); } @@ -441,22 +439,6 @@ linux_sys_sigreturn(struct lwp *l, const struct linux_sys_sigreturn_args *uap, r return (EJUSTRETURN); } - -#if 0 -int -linux_sys_modify_ldt(struct proc *p, void *v, register_t *retval) -{ - /* - * This syscall is not implemented in Linux/PowerPC: we should not - * be here - */ -#ifdef DEBUG_LINUX - printf("linux_sys_modify_ldt: should not be here.\n"); -#endif - return 0; -} -#endif - /* * major device numbers remapping */ @@ -494,40 +476,6 @@ linux_machdepioctl(struct lwp *l, const struct linux_sys_ioctl_args *uap, regist /* XXX NJWLWP */ return sys_ioctl(curlwp, &bia, retval); } -#if 0 -/* - * Set I/O permissions for a process. Just set the maximum level - * right away (ignoring the argument), otherwise we would have - * to rely on I/O permission maps, which are not implemented. - */ -int -linux_sys_iopl(struct lwp *l, const void *v, register_t *retval) -{ - /* - * This syscall is not implemented in Linux/PowerPC: we should not be here - */ -#ifdef DEBUG_LINUX - printf("linux_sys_iopl: should not be here.\n"); -#endif - return 0; -} -#endif - -/* - * See above. If a root process tries to set access to an I/O port, - * just let it have the whole range. - */ -int -linux_sys_ioperm(struct lwp *l, const struct linux_sys_ioperm_args *uap, register_t *retval) -{ - /* - * This syscall is not implemented in Linux/PowerPC: we should not be here - */ -#ifdef DEBUG_LINUX - printf("linux_sys_ioperm: should not be here.\n"); -#endif - return 0; -} /* * wrapper linux_sys_new_uname() -> linux_sys_uname() diff --git a/sys/compat/linux/arch/powerpc/syscalls.master b/sys/compat/linux/arch/powerpc/syscalls.master index 02a71b30aba..0f8f6e11b1a 100644 --- a/sys/compat/linux/arch/powerpc/syscalls.master +++ b/sys/compat/linux/arch/powerpc/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.44 2009/11/24 10:42:44 njoly Exp $ + $NetBSD: syscalls.master,v 1.45 2010/07/07 01:30:34 chs Exp $ ; @(#)syscalls.master 8.1 (Berkeley) 7/19/93 @@ -80,7 +80,7 @@ %% 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|sys||exit(int rval); } +1 STD { int|linux_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { int|sys||read(int fd, char *buf, u_int nbyte); } 4 NOARGS { int|sys||write(int fd, char *buf, u_int nbyte); } @@ -216,8 +216,7 @@ struct linux_statfs *sp); } 100 STD { int|linux_sys||fstatfs(int fd, \ struct linux_statfs *sp); } -101 STD { int|linux_sys||ioperm(unsigned int lo, \ - unsigned int hi, int val); } +101 UNIMPL ioperm 102 STD { int|linux_sys||socketcall(int what, void *args); } 103 UNIMPL syslog 104 NOARGS { int|compat_50_sys||setitimer(u_int which, \ @@ -243,7 +242,8 @@ void *ptr); } 118 NOARGS { int|sys||fsync(int fd); } 119 STD { int|linux_sys||sigreturn(struct linux_sigcontext *scp); } -120 STD { int|linux_sys||clone(int flags, void *stack); } +120 STD { int|linux_sys||clone(int flags, void *stack, \ + void *parent_tidptr, void *tls, void *child_tidptr); } 121 STD { int|linux_sys||setdomainname(char *domainname, \ int len); } 122 STD { int|linux_sys||new_uname(struct linux_utsname *up); } @@ -377,8 +377,8 @@ 204 STD { int|linux_sys||fcntl64(int fd, int cmd, void *arg); } 205 NOARGS { int|sys||mincore(void *addr, size_t len, char *vec); } 206 NOARGS { int|sys||madvise(void *addr, size_t len, int behav); } -207 UNIMPL gettid -208 UNIMPL tkill +207 NOARGS { pid_t|linux_sys||gettid(void); } +208 STD { int|linux_sys||tkill(int tid, int sig); } 209 STD { int|linux_sys||setxattr(char *path, char *name, \ void *value, size_t size, int flags); } 210 STD { int|linux_sys||lsetxattr(char *path, char *name, \ @@ -400,9 +400,13 @@ 218 STD { int|linux_sys||removexattr(char *path, char *name); } 219 STD { int|linux_sys||lremovexattr(char *path, char *name); } 220 STD { int|linux_sys||fremovexattr(int fd, char *name); } -221 UNIMPL futex -222 UNIMPL sched_setaffinity -223 UNIMPL sched_getaffinity +221 STD { int|linux_sys||futex(int *uaddr, int op, int val, \ + const struct linux_timespec *timeout, int *uaddr2, \ + int val3); } +222 STD { int|linux_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } +223 STD { int|linux_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, unsigned long *mask); } 224 UNIMPL /* unused */ 225 UNIMPL tuxcall 226 UNIMPL sendfile64 @@ -411,7 +415,7 @@ 229 UNIMPL io_getevents 230 UNIMPL io_submit 231 UNIMPL io_cancel -232 UNIMPL set_tid_address +232 STD { int|linux_sys||set_tid_address(int *tid); } 233 UNIMPL fadvise64 234 STD { int|linux_sys||exit_group(int error_code); } 235 UNIMPL lookup_dcookie @@ -434,7 +438,7 @@ int flags, struct linux_timespec *rqtp, \ struct linux_timespec *rmtp); } 249 UNIMPL swapcontext -250 UNIMPL tgkill +250 STD { int|linux_sys||tgkill(int tgid, int tid, int sig); } 251 UNIMPL utimes 252 STD { int|linux_sys||statfs64(const char *path, \ size_t sz, struct linux_statfs64 *sp); } @@ -455,3 +459,60 @@ 266 UNIMPL mq_notify 267 UNIMPL mq_getsetattr 268 UNIMPL kexec_load +269 UNIMPL add_key +270 UNIMPL request_key +271 UNIMPL keyctl +272 UNIMPL waitid +273 UNIMPL ioprio_set +274 UNIMPL ioprio_get +275 UNIMPL inotify_init +276 UNIMPL inotify_add_watch +277 UNIMPL inotify_rm_watch +278 UNIMPL spu_run +279 UNIMPL spu_create +280 UNIMPL pselect6 +281 UNIMPL ppoll +282 UNIMPL unshare +283 UNIMPL splice +284 UNIMPL tee +285 UNIMPL vmsplice +286 UNIMPL openat +287 UNIMPL mkdirat +288 UNIMPL mknodat +289 UNIMPL fchownat +290 UNIMPL futimesat +291 UNIMPL fstatat64 +292 UNIMPL unlinkat +293 UNIMPL renameat +294 UNIMPL linkat +295 UNIMPL symlinkat +296 UNIMPL readlinkat +297 UNIMPL fchmodat +298 UNIMPL faccessat +299 STD { int|linux_sys||set_robust_list( \ + struct linux_robust_list_head *head, size_t len); } +300 STD { int|linux_sys||get_robust_list(int pid, \ + struct linux_robust_list_head **head, \ + size_t *len); } +301 UNIMPL move_pages +302 UNIMPL getcpu +303 UNIMPL epoll_wait +304 UNIMPL utimensat +305 UNIMPL signalfd +306 UNIMPL timerfd_create +307 UNIMPL eventfd +308 UNIMPL sync_file_range2 +309 UNIMPL fallocate +310 UNIMPL subpage_prot +311 UNIMPL timerfd_settime +312 UNIMPL timerfd_gettime +313 UNIMPL signalfd4 +314 UNIMPL eventfd2 +315 UNIMPL epoll_create1 +316 UNIMPL dup3 +317 UNIMPL pipe2 +318 UNIMPL inotify_init1 +319 UNIMPL perf_event_open +320 UNIMPL preadv +321 UNIMPL pwritev +322 UNIMPL rt_tgsigqueueinfo diff --git a/sys/compat/linux/common/linux_emuldata.h b/sys/compat/linux/common/linux_emuldata.h index 5f045e69451..56289f483fb 100644 --- a/sys/compat/linux/common/linux_emuldata.h +++ b/sys/compat/linux/common/linux_emuldata.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_emuldata.h,v 1.16 2008/10/26 16:38:22 christos Exp $ */ +/* $NetBSD: linux_emuldata.h,v 1.17 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1998,2002 The NetBSD Foundation, Inc. @@ -29,7 +29,6 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ #include <compat/linux/common/linux_futex.h> #ifndef _COMMON_LINUX_EMULDATA_H @@ -41,48 +40,14 @@ * stored in the emuldata field of the proc * structure. */ -struct linux_emuldata_shared { - void * p_break; /* Processes' idea of break */ - int refs; - pid_t group_pid; /* PID of Linux process (group of threads) */ - /* List of Linux threads (NetBSD processes) in the Linux process */ - LIST_HEAD(, linux_emuldata) threads; - int flags; /* See below */ - int xstat; /* Thread group exit code, for exit_group */ -}; - -#define LINUX_LES_INEXITGROUP 0x1 /* thread group doing exit_group() */ -#define LINUX_LES_USE_NPTL 0x2 /* Need to emulate NPTL threads */ struct linux_emuldata { -#if notyet - sigset_t ps_siginfo; /* Which signals have a RT handler */ -#endif - int debugreg[8]; /* GDB information for ptrace - for use, */ + int led_debugreg[8]; /* GDB information for ptrace - for use, */ /* see ../arch/i386/linux_ptrace.c */ - struct linux_emuldata_shared *s; -#ifdef LINUX_NPTL - void *parent_tidptr; /* Used during clone() */ - void *child_tidptr; /* Used during clone() */ - int clone_flags; /* Used during clone() */ - void *clear_tid; /* Own TID to clear on exit */ - void *set_tls; /* Pointer to child TLS desc in user space */ -#if 0 - int *child_set_tid; /* in clone(): Child's TID to set on clone */ - int *child_clear_tid; /* in clone(): Child's TID to clear on exit */ - int *set_tid; /* in clone(): Own TID to set on clone */ - int flags; /* See above */ -#endif -#endif - struct linux_robust_list_head *robust_futexes; - - /* List of Linux threads (NetBSD processes) in the Linux process */ - LIST_ENTRY(linux_emuldata) threads; - struct proc *proc; /* backpointer to struct proc */ + void *led_child_tidptr; /* Used during clone() */ + void *led_clear_tid; /* Own TID to clear on exit */ + struct linux_robust_list_head *led_robust_head; }; -#define LINUX_CHILD_QUIETEXIT 0x1 /* Child will have quietexit set */ -#define LINUX_QUIETEXIT 0x2 /* Quiet exit (no zombie state) */ - #endif /* !_COMMON_LINUX_EMULDATA_H */ diff --git a/sys/compat/linux/common/linux_exec.c b/sys/compat/linux/common/linux_exec.c index 148f97fe878..afe9b3f54f3 100644 --- a/sys/compat/linux/common/linux_exec.c +++ b/sys/compat/linux/common/linux_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_exec.c,v 1.113 2009/10/25 01:14:03 rmind Exp $ */ +/* $NetBSD: linux_exec.c,v 1.114 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1994, 1995, 1998, 2000, 2007, 2008 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.113 2009/10/25 01:14:03 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.114 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -74,15 +74,6 @@ extern struct sysent linux_sysent[]; extern const char * const linux_syscallnames[]; extern char linux_sigcode[], linux_esigcode[]; -static void linux_e_proc_exec(struct proc *, struct exec_package *); -static void linux_e_proc_fork(struct proc *, struct proc *, int); -static void linux_e_proc_exit(struct proc *); -static void linux_e_proc_init(struct proc *, struct proc *, int); - -#ifdef LINUX_NPTL -void linux_userret(void); -#endif - /* * Emulation switch. */ @@ -94,7 +85,7 @@ struct emul emul_linux = { .e_path = "/emul/linux", #ifndef __HAVE_MINIMAL_EMUL .e_flags = 0, - .e_errno = (const int *)native_to_linux_errno, + .e_errno = native_to_linux_errno, .e_nosys = LINUX_SYS_syscall, .e_nsysent = LINUX_SYS_NSYSENT, #endif @@ -110,8 +101,8 @@ struct emul emul_linux = { .e_proc_exec = linux_e_proc_exec, .e_proc_fork = linux_e_proc_fork, .e_proc_exit = linux_e_proc_exit, - .e_lwp_fork = NULL, - .e_lwp_exit = NULL, + .e_lwp_fork = linux_e_lwp_fork, + .e_lwp_exit = linux_e_lwp_exit, #ifdef __HAVE_SYSCALL_INTERN .e_syscall_intern = linux_syscall_intern, #else @@ -126,293 +117,90 @@ struct emul emul_linux = { .e_startlwp = NULL }; -static void -linux_e_proc_init(struct proc *p, struct proc *parent, int forkflags) +void +linux_e_proc_exec(struct proc *p, struct exec_package *epp) { - struct linux_emuldata *e = p->p_emuldata; - struct linux_emuldata_shared *s; - struct linux_emuldata *ep = NULL; - - if (!e) { - /* allocate new Linux emuldata */ - e = malloc(sizeof(struct linux_emuldata), - M_EMULDATA, M_WAITOK); - } else { - mutex_enter(proc_lock); - e->s->refs--; - if (e->s->refs == 0) - free(e->s, M_EMULDATA); - mutex_exit(proc_lock); - } - - memset(e, '\0', sizeof(struct linux_emuldata)); - - e->proc = p; - e->robust_futexes = NULL; + struct lwp *l; - if (parent) - ep = parent->p_emuldata; - - if (forkflags & FORK_SHAREVM) { - mutex_enter(proc_lock); -#ifdef DIAGNOSTIC - if (ep == NULL) { - killproc(p, "FORK_SHAREVM while emuldata is NULL\n"); - mutex_exit(proc_lock); - free(e, M_EMULDATA); - return; - } -#endif - s = ep->s; - s->refs++; + l = LIST_FIRST(&p->p_lwps); + if (l->l_emuldata == NULL) { + l->l_emuldata = kmem_zalloc(sizeof(struct linux_emuldata), KM_SLEEP); } else { - struct vmspace *vm; - - s = malloc(sizeof(struct linux_emuldata_shared), - M_EMULDATA, M_WAITOK); - s->refs = 1; - - /* - * Set the process idea of the break to the real value. - * For fork, we use parent's vmspace since our's - * is not setup at the time of this call and is going - * to be copy of parent's anyway. For exec, just - * use our own vmspace. - */ - vm = (parent) ? parent->p_vmspace : p->p_vmspace; - s->p_break = (char *)vm->vm_daddr + ctob(vm->vm_dsize); - - /* - * Linux threads are emulated as NetBSD processes (not lwp) - * We use native PID for Linux TID. The Linux TID is the - * PID of the first process in the group. It is stored - * here - */ - s->group_pid = p->p_pid; - - /* - * Initialize the list of threads in the group - */ - LIST_INIT(&s->threads); - - s->xstat = 0; - s->flags = 0; - mutex_enter(proc_lock); + memset(l->l_emuldata, 0, sizeof (struct linux_emuldata)); } - e->s = s; - - /* - * Add this thread in the group thread list - */ - LIST_INSERT_HEAD(&s->threads, e, threads); - -#ifdef LINUX_NPTL - if (ep != NULL) { - e->parent_tidptr = ep->parent_tidptr; - e->child_tidptr = ep->child_tidptr; - e->clone_flags = ep->clone_flags; - } -#endif /* LINUX_NPTL */ - - mutex_exit(proc_lock); - p->p_emuldata = e; -} - -/* - * Allocate new per-process structures. Called when executing Linux - * process. We can reuse the old emuldata - if it's not null, - * the executed process is of same emulation as original forked one. - */ -static void -linux_e_proc_exec(struct proc *p, struct exec_package *epp) -{ - - /* exec, use our vmspace */ - linux_e_proc_init(p, NULL, 0); + KASSERT(p->p_nlwps == 1); + l = LIST_FIRST(&p->p_lwps); + mutex_enter(p->p_lock); + l->l_lid = p->p_pid; + mutex_exit(p->p_lock); } -/* - * Emulation per-process exit hook. - */ -static void +void linux_e_proc_exit(struct proc *p) { - struct linux_emuldata *e = p->p_emuldata; - -#ifdef LINUX_NPTL - linux_nptl_proc_exit(p); - release_futexes(p); -#endif - - /* Remove the thread for the group thread list */ - mutex_enter(proc_lock); - LIST_REMOVE(e, threads); + struct lwp *l; - /* free Linux emuldata and set the pointer to null */ - e->s->refs--; - if (e->s->refs == 0) - free(e->s, M_EMULDATA); - p->p_emuldata = NULL; - mutex_exit(proc_lock); - free(e, M_EMULDATA); + KASSERT(p->p_nlwps == 1); + l = LIST_FIRST(&p->p_lwps); + linux_e_lwp_exit(l); } -/* - * Emulation fork hook. - */ -static void -linux_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) +void +linux_e_proc_fork(struct proc *p2, struct lwp *l1, int flags) { - - /* - * The new process might share some vmspace-related stuff - * with parent, depending on fork flags (CLONE_VM et.al). - * Force allocation of new base emuldata, and share the - * VM-related parts only if necessary. - */ - p->p_emuldata = NULL; - linux_e_proc_init(p, parent, forkflags); - -#ifdef LINUX_NPTL - linux_nptl_proc_fork(p, parent, linux_userret); -#endif - - return; + struct linux_emuldata *led1, *led2; + struct lwp *l2; + + KASSERT(p2->p_nlwps == 1); + l2 = LIST_FIRST(&p2->p_lwps); + l2->l_lid = p2->p_pid; + led1 = l1->l_emuldata; + led2 = l2->l_emuldata; + led2->led_child_tidptr = led1->led_child_tidptr; } -#ifdef LINUX_NPTL void -linux_userret(void) +linux_e_lwp_fork(struct lwp *l1, struct lwp *l2) { - struct lwp *l = curlwp; - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - int error; - - /* LINUX_CLONE_CHILD_SETTID: copy child's TID to child's memory */ - if (led->clone_flags & LINUX_CLONE_CHILD_SETTID) { - if ((error = copyout(&l->l_proc->p_pid, - led->child_tidptr, sizeof(l->l_proc->p_pid))) != 0) - printf("linux_userret: LINUX_CLONE_CHILD_SETTID " - "failed (led->child_tidptr = %p, p->p_pid = %d)\n", - led->child_tidptr, p->p_pid); - } - - /* LINUX_CLONE_SETTLS: allocate a new TLS */ - if (led->clone_flags & LINUX_CLONE_SETTLS) { - if (linux_set_newtls(l, linux_get_newtls(l)) != 0) - printf("linux_userret: linux_set_tls failed"); - } + struct linux_emuldata *led2; - return; + led2 = kmem_zalloc(sizeof(struct linux_emuldata), KM_SLEEP); + l2->l_emuldata = led2; } void -linux_nptl_proc_exit(struct proc *p) +linux_e_lwp_exit(struct lwp *l) { - struct linux_emuldata *e = p->p_emuldata; - - mutex_enter(proc_lock); - - /* - * Check if we are a thread group leader victim of another - * thread doing exit_group(). If we are, change the exit code. - */ - if ((e->s->group_pid == p->p_pid) && - (e->s->flags & LINUX_LES_INEXITGROUP)) { - p->p_xstat = e->s->xstat; - } - - /* - * Members of the thread groups others than the leader should - * exit quietely: no zombie stage, no signal. We do that by - * reparenting to init. init will collect us and nobody will - * notice what happened. - */ -#ifdef DEBUG_LINUX - printf("%s:%d e->s->group_pid = %d, p->p_pid = %d, flags = 0x%x\n", - __func__, __LINE__, e->s->group_pid, p->p_pid, e->s->flags); -#endif - if ((e->s->group_pid != p->p_pid) && - (e->clone_flags & LINUX_CLONE_THREAD)) { - proc_reparent(p, initproc); - cv_broadcast(&initproc->p_waitcv); + struct linux_emuldata *led; + struct linux_sys_futex_args cup; + register_t retval; + int error, zero = 0; + + led = l->l_emuldata; + if (led->led_clear_tid == NULL) { + return; } - mutex_exit(proc_lock); - /* Emulate LINUX_CLONE_CHILD_CLEARTID */ - if (e->clear_tid != NULL) { - int error; - int null = 0; - struct linux_sys_futex_args cup; - register_t retval; - - error = copyout(&null, e->clear_tid, sizeof(null)); + error = copyout(&zero, led->led_clear_tid, sizeof(zero)); #ifdef DEBUG_LINUX - if (error != 0) - printf("%s: cannot clear TID\n", __func__); + if (error != 0) + printf("%s: cannot clear TID\n", __func__); #endif - SCARG(&cup, uaddr) = e->clear_tid; - SCARG(&cup, op) = LINUX_FUTEX_WAKE; - SCARG(&cup, val) = 0x7fffffff; /* Awake everyone */ - SCARG(&cup, timeout) = NULL; - SCARG(&cup, uaddr2) = NULL; - SCARG(&cup, val3) = 0; - if ((error = linux_sys_futex(curlwp, &cup, &retval)) != 0) - printf("%s: linux_sys_futex failed\n", __func__); - } - - return; -} - -void -linux_nptl_proc_fork(struct proc *p, struct proc *parent, void (*luserret)(void)) -{ - struct linux_emuldata *e = p->p_emuldata; - - /* LINUX_CLONE_CHILD_CLEARTID: clear TID in child's memory on exit() */ - if (e->clone_flags & LINUX_CLONE_CHILD_CLEARTID) - e->clear_tid = e->child_tidptr; - - /* LINUX_CLONE_PARENT_SETTID: set child's TID in parent's memory */ - if (e->clone_flags & LINUX_CLONE_PARENT_SETTID) { - if (copyout_proc(parent, &p->p_pid, - e->parent_tidptr, sizeof(p->p_pid)) != 0) - printf("%s: LINUX_CLONE_PARENT_SETTID " - "failed (e->parent_tidptr = %p, " - "parent->p_pid = %d, p->p_pid = %d)\n", - __func__, e->parent_tidptr, - parent->p_pid, p->p_pid); - } + SCARG(&cup, uaddr) = led->led_clear_tid; + SCARG(&cup, op) = LINUX_FUTEX_WAKE; + SCARG(&cup, val) = 0x7fffffff; /* Awake everyone */ + SCARG(&cup, timeout) = NULL; + SCARG(&cup, uaddr2) = NULL; + SCARG(&cup, val3) = 0; + if ((error = linux_sys_futex(curlwp, &cup, &retval)) != 0) + printf("%s: linux_sys_futex failed\n", __func__); - /* - * CLONE_CHILD_SETTID and LINUX_CLONE_SETTLS require child's VM - * setup to be completed, we postpone them until userret time. - */ - if (e->clone_flags & - (LINUX_CLONE_CHILD_CLEARTID | LINUX_CLONE_SETTLS)) - p->p_userret = luserret; - - return; -} - -void -linux_nptl_proc_init(struct proc *p, struct proc *parent) -{ - struct linux_emuldata *e = p->p_emuldata; - struct linux_emuldata *ep; - - if ((parent != NULL) && (parent->p_emuldata != NULL)) { - ep = parent->p_emuldata; - - e->parent_tidptr = ep->parent_tidptr; - e->child_tidptr = ep->child_tidptr; - e->clone_flags = ep->clone_flags; - } + release_futexes(l); - return; + led = l->l_emuldata; + l->l_emuldata = NULL; + kmem_free(led, sizeof (struct linux_emuldata)); } -#endif /* LINUX_NPTL */ diff --git a/sys/compat/linux/common/linux_exec.h b/sys/compat/linux/common/linux_exec.h index e1a7367d32a..75570e5ef26 100644 --- a/sys/compat/linux/common/linux_exec.h +++ b/sys/compat/linux/common/linux_exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_exec.h,v 1.47 2009/12/10 14:13:53 matt Exp $ */ +/* $NetBSD: linux_exec.h,v 1.48 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -136,12 +136,13 @@ int linux_aout_copyargs(struct lwp *, struct exec_package *, #endif void linux_trapsignal(struct lwp *, ksiginfo_t *); int linux_usertrap(struct lwp *, vaddr_t, void *); -#ifdef LINUX_NPTL -void linux_nptl_proc_fork(struct proc *, struct proc *, void (luserret)(void)); -void linux_nptl_proc_exit(struct proc *); -void linux_nptl_proc_init(struct proc *, struct proc *); -int linux_init_thread_area(struct lwp *, struct lwp *); -#endif +int linux_lwp_setprivate(struct lwp *, void *); + +void linux_e_proc_exec(struct proc *, struct exec_package *); +void linux_e_proc_fork(struct proc *, struct lwp *, int); +void linux_e_proc_exit(struct proc *); +void linux_e_lwp_fork(struct lwp *, struct lwp *); +void linux_e_lwp_exit(struct lwp *); #ifdef EXEC_ELF32 int linux_elf32_probe(struct lwp *, struct exec_package *, void *, diff --git a/sys/compat/linux/common/linux_futex.c b/sys/compat/linux/common/linux_futex.c index 0e2ef7ba8f5..f28d4ac31e9 100644 --- a/sys/compat/linux/common/linux_futex.c +++ b/sys/compat/linux/common/linux_futex.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_futex.c,v 1.25 2010/07/01 02:38:28 rmind Exp $ */ +/* $NetBSD: linux_futex.c,v 1.26 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.25 2010/07/01 02:38:28 rmind Exp $"); +__KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.26 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/time.h> @@ -52,9 +52,8 @@ __KERNEL_RCSID(1, "$NetBSD: linux_futex.c,v 1.25 2010/07/01 02:38:28 rmind Exp $ #include <compat/linux/common/linux_exec.h> #include <compat/linux/common/linux_signal.h> #include <compat/linux/common/linux_futex.h> -#include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sched.h> -#include <compat/linux/common/linux_sem.h> +#include <compat/linux/common/linux_machdep.h> #include <compat/linux/linux_syscallargs.h> void linux_to_native_timespec(struct timespec *, struct linux_timespec *); @@ -66,28 +65,29 @@ struct waiting_proc { struct futex *wp_new_futex; kcondvar_t wp_futex_cv; TAILQ_ENTRY(waiting_proc) wp_list; + TAILQ_ENTRY(waiting_proc) wp_rqlist; }; struct futex { void *f_uaddr; int f_refcount; LIST_ENTRY(futex) f_list; - TAILQ_HEAD(lf_waiting_proc, waiting_proc) f_waiting_proc; + TAILQ_HEAD(, waiting_proc) f_waiting_proc; + TAILQ_HEAD(, waiting_proc) f_requeue_proc; }; static LIST_HEAD(futex_list, futex) futex_list; static kmutex_t futex_lock; -#define FUTEX_LOCK mutex_enter(&futex_lock); -#define FUTEX_UNLOCK mutex_exit(&futex_lock); +#define FUTEX_LOCK mutex_enter(&futex_lock) +#define FUTEX_UNLOCK mutex_exit(&futex_lock) +#define FUTEX_LOCKASSERT KASSERT(mutex_owned(&futex_lock)) -#define FUTEX_LOCKED 1 -#define FUTEX_UNLOCKED 0 - -#define FUTEX_SYSTEM_LOCK KERNEL_LOCK(1, NULL); -#define FUTEX_SYSTEM_UNLOCK KERNEL_UNLOCK_ONE(0); +#define FUTEX_SYSTEM_LOCK KERNEL_LOCK(1, NULL) +#define FUTEX_SYSTEM_UNLOCK KERNEL_UNLOCK_ONE(0) #ifdef DEBUG_LINUX_FUTEX -#define FUTEXPRINTF(a) printf a +int debug_futex = 1; +#define FUTEXPRINTF(a) do { if (debug_futex) printf a; } while (0) #else #define FUTEXPRINTF(a) #endif @@ -102,9 +102,12 @@ futex_init(void) return 0; } -static struct futex *futex_get(void *, int); +static struct waiting_proc *futex_wp_alloc(void); +static void futex_wp_free(struct waiting_proc *); +static struct futex *futex_get(void *); +static void futex_ref(struct futex *); static void futex_put(struct futex *); -static int futex_sleep(struct futex *, lwp_t *, unsigned long); +static int futex_sleep(struct futex **, lwp_t *, int, struct waiting_proc *); static int futex_wake(struct futex *, int, struct futex *, int); static int futex_atomic_op(lwp_t *, int, void *); @@ -119,15 +122,40 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ syscallarg(int *) uaddr2; syscallarg(int) val3; } */ + struct linux_timespec lts; + struct timespec ts = { 0, 0 }; + int error; + + if ((SCARG(uap, op) & ~LINUX_FUTEX_PRIVATE_FLAG) == LINUX_FUTEX_WAIT && + SCARG(uap, timeout) != NULL) { + if ((error = copyin(SCARG(uap, timeout), + <s, sizeof(lts))) != 0) { + return error; + } + linux_to_native_timespec(&ts, <s); + } + return linux_do_futex(l, uap, retval, &ts); +} + +int +linux_do_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_t *retval, struct timespec *ts) +{ + /* { + syscallarg(int *) uaddr; + syscallarg(int) op; + syscallarg(int) val; + syscallarg(const struct linux_timespec *) timeout; + syscallarg(int *) uaddr2; + syscallarg(int) val3; + } */ int val; int ret; - struct linux_timespec timeout = { 0, 0 }; int error = 0; struct futex *f; struct futex *newf; int timeout_hz; - struct timespec ts; struct futex *f2; + struct waiting_proc *wp; int op_ret; RUN_ONCE(&futex_once, futex_init); @@ -154,26 +182,17 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return EWOULDBLOCK; } - if (SCARG(uap, timeout) != NULL) { - if ((error = copyin(SCARG(uap, timeout), - &timeout, sizeof(timeout))) != 0) { - FUTEX_SYSTEM_UNLOCK; - return error; - } - } - FUTEXPRINTF(("FUTEX_WAIT %d.%d: val = %d, uaddr = %p, " "*uaddr = %d, timeout = %lld.%09ld\n", l->l_proc->p_pid, l->l_lid, SCARG(uap, val), - SCARG(uap, uaddr), val, (long long)timeout.tv_sec, - timeout.tv_nsec)); + SCARG(uap, uaddr), val, (long long)ts->tv_sec, + ts->tv_nsec)); - linux_to_native_timespec(&ts, &timeout); - if ((error = itimespecfix(&ts)) != 0) { + if ((error = itimespecfix(ts)) != 0) { FUTEX_SYSTEM_UNLOCK; return error; } - timeout_hz = tstohz(&ts); + timeout_hz = tstohz(ts); /* * If the user process requests a non null timeout, @@ -186,9 +205,13 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ if (SCARG(uap, timeout) != NULL && timeout_hz == 0) timeout_hz = 1; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - ret = futex_sleep(f, l, timeout_hz); + wp = futex_wp_alloc(); + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + ret = futex_sleep(&f, l, timeout_hz, wp); futex_put(f); + FUTEX_UNLOCK; + futex_wp_free(wp); FUTEXPRINTF(("FUTEX_WAIT %d.%d: uaddr = %p, " "ret = %d\n", l->l_proc->p_pid, l->l_lid, @@ -216,7 +239,6 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ break; case LINUX_FUTEX_WAKE: - FUTEX_SYSTEM_LOCK; /* * XXX: Linux is able cope with different addresses * corresponding to the same mapped memory in the sleeping @@ -226,10 +248,12 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ l->l_proc->p_pid, l->l_lid, SCARG(uap, uaddr), SCARG(uap, val))); - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); + FUTEX_SYSTEM_LOCK; + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); *retval = futex_wake(f, SCARG(uap, val), NULL, 0); futex_put(f); - + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -248,12 +272,20 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return EAGAIN; } - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - newf = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + FUTEXPRINTF(("FUTEX_CMP_REQUEUE %d.%d: uaddr = %p, val = %d, " + "uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, val), SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); futex_put(newf); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -261,12 +293,20 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ case LINUX_FUTEX_REQUEUE: FUTEX_SYSTEM_LOCK; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - newf = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + FUTEXPRINTF(("FUTEX_REQUEUE %d.%d: uaddr = %p, val = %d, " + "uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, val), SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); futex_put(newf); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -277,25 +317,31 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return ENOSYS; case LINUX_FUTEX_WAKE_OP: FUTEX_SYSTEM_LOCK; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - f2 = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + + FUTEXPRINTF(("FUTEX_WAKE_OP %d.%d: uaddr = %p, op = %d, " + "val = %d, uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, op), SCARG(uap, val), + SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + f2 = futex_get(SCARG(uap, uaddr2)); + FUTEX_UNLOCK; + /* * This function returns positive number as results and * negative as errors */ op_ret = futex_atomic_op(l, SCARG(uap, val3), SCARG(uap, uaddr2)); + FUTEX_LOCK; if (op_ret < 0) { - /* XXX: We don't handle EFAULT yet */ - if (op_ret != -EFAULT) { - futex_put(f); - futex_put(f2); - FUTEX_SYSTEM_UNLOCK; - return -op_ret; - } futex_put(f); futex_put(f2); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; - return EFAULT; + return -op_ret; } ret = futex_wake(f, SCARG(uap, val), NULL, 0); @@ -311,8 +357,9 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ ret += op_ret; } futex_put(f2); - *retval = ret; + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; + *retval = ret; break; default: FUTEXPRINTF(("linux_sys_futex: unknown op %d\n", @@ -322,19 +369,34 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return 0; } +static struct waiting_proc * +futex_wp_alloc(void) +{ + struct waiting_proc *wp; + + wp = kmem_zalloc(sizeof(*wp), KM_SLEEP); + cv_init(&wp->wp_futex_cv, "futex"); + return wp; +} + +static void +futex_wp_free(struct waiting_proc *wp) +{ + + cv_destroy(&wp->wp_futex_cv); + kmem_free(wp, sizeof(*wp)); +} + static struct futex * -futex_get(void *uaddr, int locked) +futex_get(void *uaddr) { struct futex *f; - if (locked == FUTEX_UNLOCKED) - FUTEX_LOCK; + FUTEX_LOCKASSERT; LIST_FOREACH(f, &futex_list, f_list) { if (f->f_uaddr == uaddr) { f->f_refcount++; - if (locked == FUTEX_UNLOCKED) - FUTEX_UNLOCK; return f; } } @@ -344,85 +406,140 @@ futex_get(void *uaddr, int locked) f->f_uaddr = uaddr; f->f_refcount = 1; TAILQ_INIT(&f->f_waiting_proc); + TAILQ_INIT(&f->f_requeue_proc); LIST_INSERT_HEAD(&futex_list, f, f_list); - if (locked == FUTEX_UNLOCKED) - FUTEX_UNLOCK; return f; } +static void +futex_ref(struct futex *f) +{ + + FUTEX_LOCKASSERT; + + f->f_refcount++; +} + static void futex_put(struct futex *f) { - FUTEX_LOCK; + FUTEX_LOCKASSERT; + f->f_refcount--; if (f->f_refcount == 0) { KASSERT(TAILQ_EMPTY(&f->f_waiting_proc)); + KASSERT(TAILQ_EMPTY(&f->f_requeue_proc)); LIST_REMOVE(f, f_list); kmem_free(f, sizeof(*f)); } - FUTEX_UNLOCK; - - return; } static int -futex_sleep(struct futex *f, lwp_t *l, unsigned long timeout) +futex_sleep(struct futex **fp, lwp_t *l, int timeout, struct waiting_proc *wp) { - struct waiting_proc *wp; + struct futex *f, *newf; int ret; - wp = kmem_zalloc(sizeof(*wp), KM_SLEEP); + FUTEX_LOCKASSERT; + + f = *fp; wp->wp_l = l; wp->wp_new_futex = NULL; - cv_init(&wp->wp_futex_cv, "futex"); - FUTEX_LOCK; +requeue: TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list); ret = cv_timedwait_sig(&wp->wp_futex_cv, &futex_lock, timeout); TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); - FUTEX_UNLOCK; - - /* if we got woken up in futex_wake */ - if ((ret == 0) && (wp->wp_new_futex != NULL)) { - /* suspend us on the new futex */ - ret = futex_sleep(wp->wp_new_futex, l, timeout); - /* and release the old one */ - futex_put(wp->wp_new_futex); - } - cv_destroy(&wp->wp_futex_cv); - kmem_free(wp, sizeof(*wp)); + /* if futex_wake() tells us to requeue ... */ + newf = wp->wp_new_futex; + if (ret == 0 && newf != NULL) { + /* ... requeue ourselves on the new futex */ + futex_put(f); + wp->wp_new_futex = NULL; + TAILQ_REMOVE(&newf->f_requeue_proc, wp, wp_rqlist); + *fp = f = newf; + goto requeue; + } return ret; } static int futex_wake(struct futex *f, int n, struct futex *newf, int n2) { - struct waiting_proc *wp; + struct waiting_proc *wp, *wpnext; int count; + FUTEX_LOCKASSERT; + count = newf ? 0 : 1; - FUTEX_LOCK; + /* + * first, wake up any threads sleeping on this futex. + * note that sleeping threads are not in the process of requeueing. + */ + TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) { + KASSERT(wp->wp_new_futex == NULL); + + FUTEXPRINTF(("futex_wake: signal f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); + cv_signal(&wp->wp_futex_cv); if (count <= n) { - cv_signal(&wp->wp_futex_cv); count++; } else { if (newf == NULL) - continue; - /* futex_put called after tsleep */ - wp->wp_new_futex = futex_get(newf->f_uaddr, - FUTEX_LOCKED); - cv_signal(&wp->wp_futex_cv); + break; + + /* matching futex_put() is called by the other thread. */ + futex_ref(newf); + wp->wp_new_futex = newf; + TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); + FUTEXPRINTF(("futex_wake: requeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); + if (count - n >= n2) + goto out; + } + } + + /* + * next, deal with threads that are requeuing to this futex. + * we don't need to signal these threads, any thread on the + * requeue list has already been signaled but hasn't had a chance + * to run and requeue itself yet. if we would normally wake + * a thread, just remove the requeue info. if we would normally + * requeue a thread, change the requeue target. + */ + + TAILQ_FOREACH_SAFE(wp, &f->f_requeue_proc, wp_rqlist, wpnext) { + KASSERT(wp->wp_new_futex == f); + + FUTEXPRINTF(("futex_wake: unrequeue f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); + wp->wp_new_futex = NULL; + TAILQ_REMOVE(&f->f_requeue_proc, wp, wp_rqlist); + futex_put(f); + + if (count <= n) { + count++; + } else { + if (newf == NULL) + break; + + /* matching futex_put() is called by the other thread. */ + futex_ref(newf); + wp->wp_new_futex = newf; + TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); + FUTEXPRINTF(("futex_wake: rerequeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); if (count - n >= n2) break; } } - FUTEX_UNLOCK; +out: return count; } @@ -498,12 +615,16 @@ int linux_sys_set_robust_list(struct lwp *l, const struct linux_sys_set_robust_list_args *uap, register_t *retval) { - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; + /* { + syscallarg(struct linux_robust_list_head *) head; + syscallarg(size_t) len; + } */ + struct linux_emuldata *led; - if (SCARG(uap, len) != sizeof(*(led->robust_futexes))) + if (SCARG(uap, len) != sizeof(struct linux_robust_list_head)) return EINVAL; - led->robust_futexes = SCARG(uap, head); + led = l->l_emuldata; + led->led_robust_head = SCARG(uap, head); *retval = 0; return 0; } @@ -512,33 +633,51 @@ int linux_sys_get_robust_list(struct lwp *l, const struct linux_sys_get_robust_list_args *uap, register_t *retval) { + /* { + syscallarg(int) pid; + syscallarg(struct linux_robust_list_head **) head; + syscallarg(size_t *) len; + } */ + struct proc *p; struct linux_emuldata *led; - struct linux_robust_list_head **head; - size_t len = sizeof(*led->robust_futexes); + struct linux_robust_list_head *head; + size_t len; int error = 0; + p = l->l_proc; if (!SCARG(uap, pid)) { - led = l->l_proc->p_emuldata; - head = &led->robust_futexes; + led = l->l_emuldata; + head = led->led_robust_head; } else { - struct proc *p; - - mutex_enter(proc_lock); - p = proc_find(SCARG(uap, pid)); - if (p == NULL || p->p_emul != &emul_linux) { - mutex_exit(proc_lock); + mutex_enter(p->p_lock); + l = lwp_find(p, SCARG(uap, pid)); + if (l != NULL) { + led = l->l_emuldata; + head = led->led_robust_head; + } + mutex_exit(p->p_lock); + if (l == NULL) { return ESRCH; } - led = p->p_emuldata; - head = &led->robust_futexes; - mutex_exit(proc_lock); } +#ifdef __arch64__ + if (p->p_flag & PK_32) { + uint32_t u32; + + u32 = 12; + error = copyout(&u32, SCARG(uap, len), sizeof(u32)); + if (error) + return error; + u32 = (uint32_t)(uintptr_t)head; + return copyout(&u32, SCARG(uap, head), sizeof(u32)); + } +#endif - /* FIXME unlocked */ + len = sizeof(*head); error = copyout(&len, SCARG(uap, len), sizeof(len)); if (error) return error; - return copyout(head, SCARG(uap, head), sizeof(*head)); + return copyout(&head, SCARG(uap, head), sizeof(head)); } static int @@ -548,7 +687,7 @@ handle_futex_death(void *uaddr, pid_t pid, int pi) struct futex *f; retry: - if (copyin(uaddr, &uval, 4)) + if (copyin(uaddr, &uval, sizeof(uval))) return EFAULT; if ((uval & FUTEX_TID_MASK) == pid) { @@ -562,8 +701,10 @@ retry: goto retry; if (!pi && (uval & FUTEX_WAITERS)) { - f = futex_get(uaddr, FUTEX_UNLOCKED); + FUTEX_LOCK; + f = futex_get(uaddr); futex_wake(f, 1, NULL, 0); + FUTEX_UNLOCK; } } @@ -571,12 +712,23 @@ retry: } static int -fetch_robust_entry(struct linux_robust_list **entry, +fetch_robust_entry(struct lwp *l, struct linux_robust_list **entry, struct linux_robust_list **head, int *pi) { + struct linux_emuldata *led; unsigned long uentry; - if (copyin((const void *)head, &uentry, sizeof(unsigned long))) + led = l->l_emuldata; +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32; + + if (copyin(head, &u32, sizeof(u32))) + return EFAULT; + uentry = (unsigned long)u32; + } else +#endif + if (copyin(head, &uentry, sizeof(uentry))) return EFAULT; *entry = (void *)(uentry & ~1UL); @@ -587,7 +739,7 @@ fetch_robust_entry(struct linux_robust_list **entry, /* This walks the list of robust futexes, releasing them. */ void -release_futexes(struct proc *p) +release_futexes(struct lwp *l) { struct linux_robust_list_head head; struct linux_robust_list *entry, *next_entry = NULL, *pending; @@ -596,28 +748,50 @@ release_futexes(struct proc *p) unsigned long futex_offset; int rc; - led = p->p_emuldata; - if (led->robust_futexes == NULL) + led = l->l_emuldata; + if (led->led_robust_head == NULL) return; - if (copyin(led->robust_futexes, &head, sizeof(head))) +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32s[3]; + + if (copyin(led->led_robust_head, u32s, sizeof(u32s))) + return; + + head.list.next = (void *)(uintptr_t)u32s[0]; + head.futex_offset = (unsigned long)u32s[1]; + head.pending_list = (void *)(uintptr_t)u32s[2]; + } else +#endif + if (copyin(led->led_robust_head, &head, sizeof(head))) return; - if (fetch_robust_entry(&entry, &head.list.next, &pi)) + if (fetch_robust_entry(l, &entry, &head.list.next, &pi)) return; +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32; + + if (copyin(led->led_robust_head, &u32, sizeof(u32))) + return; + + head.futex_offset = (unsigned long)u32; + } else +#endif if (copyin(&head.futex_offset, &futex_offset, sizeof(unsigned long))) return; - if (fetch_robust_entry(&pending, &head.pending_list, &pip)) + if (fetch_robust_entry(l, &pending, &head.pending_list, &pip)) return; while (entry != &head.list) { - rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); + rc = fetch_robust_entry(l, &next_entry, &entry->next, &next_pi); if (entry != pending) if (handle_futex_death((char *)entry + futex_offset, - p->p_pid, pi)) + l->l_lid, pi)) return; if (rc) @@ -634,5 +808,5 @@ release_futexes(struct proc *p) if (pending) handle_futex_death((char *)pending + futex_offset, - p->p_pid, pip); + l->l_lid, pip); } diff --git a/sys/compat/linux/common/linux_futex.h b/sys/compat/linux/common/linux_futex.h index f6ef35143b2..2793a319448 100644 --- a/sys/compat/linux/common/linux_futex.h +++ b/sys/compat/linux/common/linux_futex.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_futex.h,v 1.3 2008/10/26 16:38:22 christos Exp $ */ +/* $NetBSD: linux_futex.h,v 1.4 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -72,6 +72,9 @@ struct linux_robust_list_head { #define FUTEX_OWNER_DIED 0x40000000 #define FUTEX_TID_MASK 0x3fffffff -void release_futexes(struct proc *); +void release_futexes(struct lwp *); +struct linux_sys_futex_args; +int linux_do_futex(struct lwp *, const struct linux_sys_futex_args *, + register_t *, struct timespec *); #endif /* !_LINUX_FUTEX_H */ diff --git a/sys/compat/linux/common/linux_machdep.h b/sys/compat/linux/common/linux_machdep.h index b066dcd5623..256da95873e 100644 --- a/sys/compat/linux/common/linux_machdep.h +++ b/sys/compat/linux/common/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.18 2008/04/28 20:23:43 martin Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.19 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -54,17 +54,15 @@ #define LINUX_UNAME_ARCH machine #endif +#ifndef LINUX_LWP_SETPRIVATE +#define LINUX_LWP_SETPRIVATE lwp_setprivate +#endif + #ifdef _KERNEL __BEGIN_DECLS void linux_sendsig(const ksiginfo_t *, const sigset_t *); dev_t linux_fakedev(dev_t, int); __END_DECLS -#ifdef LINUX_NPTL -__BEGIN_DECLS -void *linux_get_newtls(struct lwp *); -int linux_set_newtls(struct lwp *, void *); -__END_DECLS -#endif /* !LINUX_NPTL */ #endif /* !_KERNEL */ #endif /* !_LINUX_MACHDEP_H */ diff --git a/sys/compat/linux/common/linux_misc.c b/sys/compat/linux/common/linux_misc.c index d342c1d6f7e..9191c1692cb 100644 --- a/sys/compat/linux/common/linux_misc.c +++ b/sys/compat/linux/common/linux_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp $ */ +/* $NetBSD: linux_misc.c,v 1.216 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 1999, 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.216 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -107,8 +107,6 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> -#include <compat/linux/linux_syscallargs.h> - #include <compat/linux/common/linux_fcntl.h> #include <compat/linux/common/linux_mmap.h> #include <compat/linux/common/linux_dirent.h> @@ -122,6 +120,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp #include <compat/linux/common/linux_reboot.h> #include <compat/linux/common/linux_emuldata.h> +#include <compat/linux/linux_syscallargs.h> + #ifndef COMPAT_LINUX32 const int linux_ptrace_request_map[] = { LINUX_PTRACE_TRACEME, PT_TRACE_ME, @@ -270,8 +270,7 @@ linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_ } /* - * Linux brk(2). The check if the new address is >= the old one is - * done in the kernel in Linux. NetBSD does it in the library. + * Linux brk(2). Like native, but always return the new break value. */ int linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval) @@ -280,20 +279,13 @@ linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *r syscallarg(char *) nsize; } */ struct proc *p = l->l_proc; - char *nbrk = SCARG(uap, nsize); - struct sys_obreak_args oba; struct vmspace *vm = p->p_vmspace; - struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata; - - SCARG(&oba, nsize) = nbrk; - - if ((void *) nbrk > vm->vm_daddr && sys_obreak(l, &oba, retval) == 0) - ed->s->p_break = (char*)nbrk; - else - nbrk = ed->s->p_break; + struct sys_obreak_args oba; - retval[0] = (register_t)nbrk; + SCARG(&oba, nsize) = SCARG(uap, nsize); + (void) sys_obreak(l, &oba, retval); + retval[0] = (register_t)((char *)vm->vm_daddr + ptoa(vm->vm_dsize)); return 0; } @@ -1333,5 +1325,4 @@ linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *ua return 0; } - #endif /* !COMPAT_LINUX32 */ diff --git a/sys/compat/linux/common/linux_misc_notalpha.c b/sys/compat/linux/common/linux_misc_notalpha.c index 5291a1722be..fa3b25fc8c5 100644 --- a/sys/compat/linux/common/linux_misc_notalpha.c +++ b/sys/compat/linux/common/linux_misc_notalpha.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 njoly Exp $ */ +/* $NetBSD: linux_misc_notalpha.c,v 1.107 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.107 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -79,7 +79,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 nj #endif #ifndef COMPAT_LINUX32 -#if !defined(__m68k__) && !defined(__amd64__) +#if !defined(__amd64__) static void bsd_to_linux_statfs64(const struct statvfs *, struct linux_statfs64 *); #endif @@ -403,7 +403,7 @@ linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_ } #endif /* !amd64 */ -#if !defined(__m68k__) && !defined(__amd64__) +#if !defined(__amd64__) /* * Convert NetBSD statvfs structure to Linux statfs64 structure. * See comments in bsd_to_linux_statfs() for further background. diff --git a/sys/compat/linux/common/linux_sched.c b/sys/compat/linux/common/linux_sched.c index 630f7fb67b9..fc3a96e148e 100644 --- a/sys/compat/linux/common/linux_sched.c +++ b/sys/compat/linux/common/linux_sched.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $ */ +/* $NetBSD: linux_sched.c,v 1.63 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.63 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -47,39 +47,54 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $ #include <sys/wait.h> #include <sys/kauth.h> #include <sys/ptrace.h> -#include <sys/types.h> +#include <sys/atomic.h> #include <sys/cpu.h> #include <compat/linux/common/linux_types.h> #include <compat/linux/common/linux_signal.h> -#include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ #include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> #include <compat/linux/common/linux_exec.h> +#include <compat/linux/common/linux_machdep.h> #include <compat/linux/linux_syscallargs.h> #include <compat/linux/common/linux_sched.h> +static int linux_clone_nptl(struct lwp *, const struct linux_sys_clone_args *, register_t *); + +static void +linux_child_return(void *arg) +{ + struct lwp *l = arg; + struct proc *p = l->l_proc; + struct linux_emuldata *led = l->l_emuldata; + void *ctp = led->led_child_tidptr; + + if (ctp) { + if (copyout(&p->p_pid, ctp, sizeof(p->p_pid)) != 0) + printf("%s: LINUX_CLONE_CHILD_SETTID " + "failed (child_tidptr = %p, tid = %d)\n", + __func__, ctp, p->p_pid); + } + child_return(arg); +} + int linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_t *retval) { /* { syscallarg(int) flags; syscallarg(void *) stack; -#ifdef LINUX_NPTL syscallarg(void *) parent_tidptr; + syscallarg(void *) tls; syscallarg(void *) child_tidptr; -#endif } */ - int flags, sig; - int error; struct proc *p; -#ifdef LINUX_NPTL struct linux_emuldata *led; -#endif + int flags, sig, error; /* * We don't support the Linux CLONE_PID or CLONE_PTRACE flags. @@ -98,8 +113,14 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ && (SCARG(uap, flags) & LINUX_CLONE_VM) == 0) return (EINVAL); - flags = 0; + /* + * The thread group flavor is implemented totally differently. + */ + if (SCARG(uap, flags) & LINUX_CLONE_THREAD) { + return linux_clone_nptl(l, uap, retval); + } + flags = 0; if (SCARG(uap, flags) & LINUX_CLONE_VM) flags |= FORK_SHAREVM; if (SCARG(uap, flags) & LINUX_CLONE_FS) @@ -116,13 +137,10 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ return (EINVAL); sig = linux_to_native_signo[sig]; -#ifdef LINUX_NPTL - led = (struct linux_emuldata *)l->l_proc->p_emuldata; - - led->parent_tidptr = SCARG(uap, parent_tidptr); - led->child_tidptr = SCARG(uap, child_tidptr); - led->clone_flags = SCARG(uap, flags); -#endif /* LINUX_NPTL */ + if (SCARG(uap, flags) & LINUX_CLONE_CHILD_SETTID) { + led = l->l_emuldata; + led->led_child_tidptr = SCARG(uap, child_tidptr); + } /* * Note that Linux does not provide a portable way of specifying @@ -131,14 +149,119 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ * that makes this adjustment is a noop. */ if ((error = fork1(l, flags, sig, SCARG(uap, stack), 0, - NULL, NULL, retval, &p)) != 0) + linux_child_return, NULL, retval, &p)) != 0) return error; -#ifdef LINUX_NPTL - if ((SCARG(uap, flags) & LINUX_CLONE_SETTLS) != 0) - return linux_init_thread_area(l, LIST_FIRST(&p->p_lwps)); -#endif /* LINUX_NPTL */ + return 0; +} + +static int +linux_clone_nptl(struct lwp *l, const struct linux_sys_clone_args *uap, register_t *retval) +{ + /* { + syscallarg(int) flags; + syscallarg(void *) stack; + syscallarg(void *) parent_tidptr; + syscallarg(void *) tls; + syscallarg(void *) child_tidptr; + } */ + struct proc *p; + struct lwp *l2; + struct linux_emuldata *led; + void *parent_tidptr, *tls, *child_tidptr; + struct schedstate_percpu *spc; + vaddr_t uaddr; + lwpid_t lid; + int flags, tnprocs, error; + + p = l->l_proc; + flags = SCARG(uap, flags); + parent_tidptr = SCARG(uap, parent_tidptr); + tls = SCARG(uap, tls); + child_tidptr = SCARG(uap, child_tidptr); + + tnprocs = atomic_inc_uint_nv(&nprocs); + if (__predict_false(tnprocs >= maxproc) || + kauth_authorize_process(l->l_cred, KAUTH_PROCESS_FORK, p, + KAUTH_ARG(tnprocs), NULL, NULL) != 0) { + atomic_dec_uint(&nprocs); + return EAGAIN; + } + uaddr = uvm_uarea_alloc(); + if (__predict_false(uaddr == 0)) { + atomic_dec_uint(&nprocs); + return ENOMEM; + } + + error = lwp_create(l, p, uaddr, LWP_DETACHED | LWP_PIDLID, + SCARG(uap, stack), 0, child_return, NULL, &l2, + l->l_class); + if (__predict_false(error)) { + atomic_dec_uint(&nprocs); + uvm_uarea_free(uaddr); + return error; + } + lid = l2->l_lid; + + /* LINUX_CLONE_CHILD_CLEARTID: clear TID in child's memory on exit() */ + if (flags & LINUX_CLONE_CHILD_CLEARTID) { + led = l2->l_emuldata; + led->led_clear_tid = child_tidptr; + } + + /* LINUX_CLONE_PARENT_SETTID: store child's TID in parent's memory */ + if (flags & LINUX_CLONE_PARENT_SETTID) { + if (copyout(&lid, parent_tidptr, sizeof(lid)) != 0) + printf("%s: LINUX_CLONE_PARENT_SETTID " + "failed (parent_tidptr = %p tid = %d)\n", + __func__, parent_tidptr, lid); + } + + /* LINUX_CLONE_CHILD_SETTID: store child's TID in child's memory */ + if (flags & LINUX_CLONE_CHILD_SETTID) { + if (copyout(&lid, child_tidptr, sizeof(lid)) != 0) + printf("%s: LINUX_CLONE_CHILD_SETTID " + "failed (child_tidptr = %p, tid = %d)\n", + __func__, child_tidptr, lid); + } + + if (flags & LINUX_CLONE_SETTLS) { + error = LINUX_LWP_SETPRIVATE(l2, tls); + if (error) { + lwp_exit(l2); + return error; + } + } + + /* + * Set the new LWP running, unless the process is stopping, + * then the LWP is created stopped. + */ + mutex_enter(p->p_lock); + lwp_lock(l2); + spc = &l2->l_cpu->ci_schedstate; + if ((l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) { + if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) { + KASSERT(l2->l_wchan == NULL); + l2->l_stat = LSSTOP; + p->p_nrlwps--; + lwp_unlock_to(l2, spc->spc_lwplock); + } else { + KASSERT(lwp_locked(l2, spc->spc_mutex)); + l2->l_stat = LSRUN; + sched_enqueue(l2, false); + lwp_unlock(l2); + } + } else { + l2->l_stat = LSSUSPENDED; + p->p_nrlwps--; + lwp_unlock_to(l2, spc->spc_lwplock); + } + mutex_exit(p->p_lock); + + retval[0] = lid; + retval[1] = 0; return 0; } @@ -287,7 +410,7 @@ linux_sys_sched_setparam(struct lwp *l, const struct linux_sys_sched_setparam_ar goto out; /* We need the current policy in Linux terms. */ - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, NULL); if (error) goto out; error = sched_native2linux(policy, NULL, &policy, NULL); @@ -298,7 +421,7 @@ linux_sys_sched_setparam(struct lwp *l, const struct linux_sys_sched_setparam_ar if (error) goto out; - error = do_sched_setparam(SCARG(uap, pid), 0, policy, &sp); + error = do_sched_setparam(0, SCARG(uap, pid), policy, &sp); if (error) goto out; @@ -322,7 +445,7 @@ linux_sys_sched_getparam(struct lwp *l, const struct linux_sys_sched_getparam_ar goto out; } - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, &sp); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, &sp); if (error) goto out; #ifdef DEBUG_LINUX @@ -379,7 +502,7 @@ linux_sys_sched_setscheduler(struct lwp *l, const struct linux_sys_sched_setsche policy, sp.sched_priority); #endif - error = do_sched_setparam(SCARG(uap, pid), 0, policy, &sp); + error = do_sched_setparam(0, SCARG(uap, pid), policy, &sp); if (error) goto out; @@ -397,7 +520,7 @@ linux_sys_sched_getscheduler(struct lwp *l, const struct linux_sys_sched_getsche *retval = -1; - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, NULL); if (error) goto out; @@ -463,73 +586,24 @@ linux_sys_sched_get_priority_min(struct lwp *l, const struct linux_sys_sched_get return 0; } +int +linux_sys_exit(struct lwp *l, const struct linux_sys_exit_args *uap, register_t *retval) +{ + + lwp_exit(l); + return 0; +} + #ifndef __m68k__ /* Present on everything but m68k */ int linux_sys_exit_group(struct lwp *l, const struct linux_sys_exit_group_args *uap, register_t *retval) { -#ifdef LINUX_NPTL - /* { - syscallarg(int) error_code; - } */ - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - struct linux_emuldata *e; - - if (led->s->flags & LINUX_LES_USE_NPTL) { - -#ifdef DEBUG_LINUX - printf("%s:%d, led->s->refs = %d\n", __func__, __LINE__, - led->s->refs); -#endif - - /* - * The calling thread is supposed to kill all threads - * in the same thread group (i.e. all threads created - * via clone(2) with CLONE_THREAD flag set). - * - * If there is only one thread, things are quite simple - */ - if (led->s->refs == 1) - return sys_exit(l, (const void *)uap, retval); - -#ifdef DEBUG_LINUX - printf("%s:%d\n", __func__, __LINE__); -#endif - - mutex_enter(proc_lock); - led->s->flags |= LINUX_LES_INEXITGROUP; - led->s->xstat = W_EXITCODE(SCARG(uap, error_code), 0); - - /* - * Kill all threads in the group. The emulation exit hook takes - * care of hiding the zombies and reporting the exit code - * properly. - */ - LIST_FOREACH(e, &led->s->threads, threads) { - if (e->proc == p) - continue; - -#ifdef DEBUG_LINUX - printf("%s: kill PID %d\n", __func__, e->proc->p_pid); -#endif - psignal(e->proc, SIGKILL); - } - - /* Now, kill ourselves */ - psignal(p, SIGKILL); - mutex_exit(proc_lock); - - return 0; - - } -#endif /* LINUX_NPTL */ return sys_exit(l, (const void *)uap, retval); } #endif /* !__m68k__ */ -#ifdef LINUX_NPTL int linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_args *uap, register_t *retval) { @@ -538,12 +612,9 @@ linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_ } */ struct linux_emuldata *led; - led = (struct linux_emuldata *)l->l_proc->p_emuldata; - led->clear_tid = SCARG(uap, tid); - - led->s->flags |= LINUX_LES_USE_NPTL; - - *retval = l->l_proc->p_pid; + led = (struct linux_emuldata *)l->l_emuldata; + led->led_clear_tid = SCARG(uap, tid); + *retval = l->l_lid; return 0; } @@ -552,81 +623,22 @@ linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_ int linux_sys_gettid(struct lwp *l, const void *v, register_t *retval) { - /* The Linux kernel does it exactly that way */ - *retval = l->l_proc->p_pid; - return 0; -} - -#ifdef LINUX_NPTL -/* ARGUSED1 */ -int -linux_sys_getpid(struct lwp *l, const void *v, register_t *retval) -{ - struct linux_emuldata *led = l->l_proc->p_emuldata; - - if (led->s->flags & LINUX_LES_USE_NPTL) { - /* The Linux kernel does it exactly that way */ - *retval = led->s->group_pid; - } else { - *retval = l->l_proc->p_pid; - } - - return 0; -} - -/* ARGUSED1 */ -int -linux_sys_getppid(struct lwp *l, const void *v, register_t *retval) -{ - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - struct proc *glp; - struct proc *pp; - - mutex_enter(proc_lock); - if (led->s->flags & LINUX_LES_USE_NPTL) { - - /* Find the thread group leader's parent */ - glp = proc_find(led->s->group_pid); - if (glp == NULL) { - /* Maybe panic... */ - printf("linux_sys_getppid: missing group leader PID" - " %d\n", led->s->group_pid); - mutex_exit(proc_lock); - return -1; - } - pp = glp->p_pptr; - - /* If this is a Linux process too, return thread group PID */ - if (pp->p_emul == p->p_emul) { - struct linux_emuldata *pled; - - pled = pp->p_emuldata; - *retval = pled->s->group_pid; - } else { - *retval = pp->p_pid; - } - - } else { - *retval = p->p_pptr->p_pid; - } - mutex_exit(proc_lock); + *retval = l->l_lid; return 0; } -#endif /* LINUX_NPTL */ int linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffinity_args *uap, register_t *retval) { /* { - syscallarg(pid_t) pid; + syscallarg(linux_pid_t) pid; syscallarg(unsigned int) len; syscallarg(unsigned long *) mask; } */ - int error, size, nb = ncpu; - unsigned long *c, *data; proc_t *p; + unsigned long *lp, *data; + int error, size, nb = ncpu; /* Unlike Linux, dynamically calculate cpu mask size */ size = sizeof(long) * ((ncpu + LONG_BIT - 1) / LONG_BIT); @@ -647,27 +659,25 @@ linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffin * bit. */ data = kmem_zalloc(size, KM_SLEEP); - c = data; + lp = data; while (nb > LONG_BIT) { - *c++ = ~0UL; + *lp++ = ~0UL; nb -= LONG_BIT; } if (nb) - *c = (1 << ncpu) - 1; + *lp = (1 << ncpu) - 1; error = copyout(data, SCARG(uap, mask), size); kmem_free(data, size); - *retval = size; return error; - } int linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval) { /* { - syscallarg(pid_t) pid; + syscallarg(linux_pid_t) pid; syscallarg(unsigned int) len; syscallarg(unsigned long *) mask; } */ @@ -687,4 +697,3 @@ linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffin #endif return 0; }; -#endif /* LINUX_NPTL */ diff --git a/sys/compat/linux/common/linux_signal.c b/sys/compat/linux/common/linux_signal.c index c7243c7fa8c..ab42f9f8836 100644 --- a/sys/compat/linux/common/linux_signal.c +++ b/sys/compat/linux/common/linux_signal.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp $ */ +/* $NetBSD: linux_signal.c,v 1.71 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.71 2010/07/07 01:30:35 chs Exp $"); #define COMPAT_LINUX 1 @@ -69,9 +69,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp #include <compat/linux/common/linux_types.h> #include <compat/linux/common/linux_signal.h> -#include <compat/linux/common/linux_exec.h> /* For emul_linux */ -#include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ -#include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */ +#include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_siginfo.h> #include <compat/linux/common/linux_sigevent.h> #include <compat/linux/common/linux_util.h> @@ -609,39 +607,41 @@ linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *ua } #endif /* LINUX_SS_ONSTACK */ -#ifdef LINUX_NPTL static int linux_do_tkill(struct lwp *l, int tgid, int tid, int signum) { struct proc *p; - int error; + struct lwp *t; ksiginfo_t ksi; - struct linux_emuldata *led; + int error; if (signum < 0 || signum >= LINUX__NSIG) return EINVAL; signum = linux_to_native_signo[signum]; + if (tgid == -1) { + tgid = tid; + } + KSI_INIT(&ksi); ksi.ksi_signo = signum; ksi.ksi_code = SI_LWP; ksi.ksi_pid = l->l_proc->p_pid; ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); + ksi.ksi_lid = tid; mutex_enter(proc_lock); - if ((p = proc_find(tid)) == NULL) { - mutex_exit(proc_lock); - return ESRCH; - } - led = p->p_emuldata; - if (tgid > 0 && led->s->group_pid != tgid) { + p = proc_find(tgid); + if (p == NULL) { mutex_exit(proc_lock); return ESRCH; } mutex_enter(p->p_lock); error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL); - if (!error && signum) + if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) + error = ESRCH; + else if (signum != 0) kpsignal2(p, &ksi); mutex_exit(p->p_lock); mutex_exit(proc_lock); @@ -660,7 +660,7 @@ linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_ if (SCARG(uap, tid) <= 0) return EINVAL; - return linux_do_tkill(l, 0, SCARG(uap, tid), SCARG(uap, sig)); + return linux_do_tkill(l, -1, SCARG(uap, tid), SCARG(uap, sig)); } int @@ -672,12 +672,11 @@ linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, registe syscallarg(int) sig; } */ - if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) <= 0) + if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) < -1) return EINVAL; return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig)); } -#endif /* LINUX_NPTL */ int native_to_linux_si_code(int code) diff --git a/sys/compat/linux/common/linux_sysctl.c b/sys/compat/linux/common/linux_sysctl.c index e7b1a448956..3c9ff0dcda9 100644 --- a/sys/compat/linux/common/linux_sysctl.c +++ b/sys/compat/linux/common/linux_sysctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp $ */ +/* $NetBSD: linux_sysctl.c,v 1.40 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2003, 2008 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.40 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -57,13 +57,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp #include <compat/linux/common/linux_machdep.h> char linux_sysname[128] = "Linux"; -#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__) -char linux_release[128] = "2.4.18"; -char linux_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002"; -#else -char linux_release[128] = "2.0.38"; -char linux_version[128] = "#0 Sun Nov 11 11:11:11 MET 2000"; -#endif +char linux_release[128] = "2.6.18"; +char linux_version[128] = "#0 Wed Mar 3 03:03:03 PST 2010"; struct sysctlnode linux_sysctl_root = { .sysctl_flags = SYSCTL_VERSION| diff --git a/sys/compat/linux32/arch/amd64/linux32_exec.h b/sys/compat/linux32/arch/amd64/linux32_exec.h index 92cf9fc4cc6..ff8029b2fc0 100644 --- a/sys/compat/linux32/arch/amd64/linux32_exec.h +++ b/sys/compat/linux32/arch/amd64/linux32_exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_exec.h,v 1.3 2010/04/18 23:47:52 jym Exp $ */ +/* $NetBSD: linux32_exec.h,v 1.4 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -41,7 +41,9 @@ #define LINUX32_DEBUGLINK_SIGNATURE 1 -#define LINUX32_ELF_AUX_ENTRIES 18 +#define LINUX32_ELF_AUX_ENTRIES 14 + +#if 0 /* Hardware platform identifier string */ #define LINUX32_PLATFORM "i686" @@ -53,7 +55,7 @@ static char linux32_kernel_vsyscall[] = { 0x55, /* push %ebp */ \ 0x89, 0xcd, /* mov %ecx,%ebp */ \ 0x0f, 0x05, /* syscall */ \ - 0xb9, 0x2b, 0x00, 0x00, 0x00, /* mov $0x2b,%ecx */ \ + 0xb9, 0x7b, 0x00, 0x00, 0x00, /* mov $0x7b,%ecx */ \ 0x8e, 0xd1, /* movl %ecx,%ss */ \ 0x89, 0xe9, /* mov %ebp,%ecx */ \ 0x5d, /* pop %ebp */ \ @@ -70,6 +72,11 @@ struct linux32_extra_stack_data { }; #define LINUX32_ELF_AUX_ARGSIZ sizeof(struct linux32_extra_stack_data) +#endif + +#define LINUX32_ELF_AUX_ARGSIZ \ + (howmany(LINUX32_ELF_AUX_ENTRIES * sizeof(Aux32Info), sizeof(Elf32_Addr))) + #ifdef _KERNEL int linux32_exec_setup_stack(struct lwp *, struct exec_package *); #endif diff --git a/sys/compat/linux32/arch/amd64/linux32_machdep.c b/sys/compat/linux32/arch/amd64/linux32_machdep.c index 29b6fc7efac..d3ebe6ef8bd 100644 --- a/sys/compat/linux32/arch/amd64/linux32_machdep.c +++ b/sys/compat/linux32/arch/amd64/linux32_machdep.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_machdep.c,v 1.23 2009/11/23 00:46:07 rmind Exp $ */ +/* $NetBSD: linux32_machdep.c,v 1.24 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -31,39 +31,25 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.23 2009/11/23 00:46:07 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.24 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> -#include <sys/systm.h> -#include <sys/signalvar.h> -#include <sys/kernel.h> #include <sys/proc.h> -#include <sys/buf.h> -#include <sys/reboot.h> -#include <sys/conf.h> #include <sys/exec.h> -#include <sys/file.h> -#include <sys/callout.h> -#include <sys/malloc.h> -#include <sys/mbuf.h> -#include <sys/msgbuf.h> -#include <sys/mount.h> -#include <sys/vnode.h> -#include <sys/device.h> -#include <sys/syscallargs.h> -#include <sys/filedesc.h> -#include <sys/exec_elf.h> -#include <sys/disklabel.h> -#include <sys/ioctl.h> -#include <miscfs/specfs/specdev.h> +#include <machine/vmparam.h> +#include <machine/cpufunc.h> #include <machine/netbsd32_machdep.h> #include <compat/netbsd32/netbsd32.h> #include <compat/netbsd32/netbsd32_syscallargs.h> +#include <compat/linux/common/linux_types.h> +#include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_signal.h> #include <compat/linux/common/linux_errno.h> +#include <compat/linux/common/linux_exec.h> +#include <compat/linux/linux_syscallargs.h> #include <compat/linux32/common/linux32_types.h> #include <compat/linux32/common/linux32_errno.h> @@ -72,18 +58,15 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_machdep.c,v 1.23 2009/11/23 00:46:07 rmind E #include <compat/linux32/common/linux32_exec.h> #include <compat/linux32/linux32_syscallargs.h> -#include <sys/cpu.h> -#include <machine/cpufunc.h> -#include <machine/psl.h> -#include <machine/reg.h> -#include <machine/segments.h> -#include <machine/specialreg.h> -#include <machine/sysarch.h> -#include <machine/vmparam.h> +#ifdef DEBUG_LINUX +#define DPRINTF(a) uprintf a +#else +#define DPRINTF(a) +#endif -extern char linux32_sigcode[1]; -extern char linux32_rt_sigcode[1]; -extern char linux32_esigcode[1]; +extern char linux32_sigcode[]; +extern char linux32_rt_sigcode[]; +extern char linux32_esigcode[]; extern void (osyscall_return)(void); @@ -132,6 +115,9 @@ linux32_old_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) fp = (struct linux32_sigframe *)tf->tf_rsp; fp--; + DPRINTF(("old: onstack = %d, fp = %p sig = %d rip = 0x%lx cr2 = 0x%lx\n", + onstack, fp, sig, tf->tf_rip, lwp_getpcb(l)->pcb_cr2)); + /* Build stack frame for signal trampoline. */ NETBSD32PTR32(frame.sf_handler, catcher); frame.sf_sig = native_to_linux32_signo[sig]; @@ -155,7 +141,6 @@ linux32_old_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) /* * Build context to run handler in. */ - tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; @@ -205,6 +190,9 @@ linux32_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) NETBSD32PTR32(frame.sf_sip, &fp->sf_si); NETBSD32PTR32(frame.sf_ucp, &fp->sf_uc); + DPRINTF(("rt: onstack = %d, fp = %p sig = %d rip = 0x%lx cr2 = 0x%lx\n", + onstack, fp, sig, tf->tf_rip, lwp_getpcb(l)->pcb_cr2)); + lsi = &frame.sf_si; (void)memset(lsi, 0, sizeof(frame.sf_si)); lsi->lsi_errno = native_to_linux32_errno[ksi->ksi_errno]; @@ -259,7 +247,6 @@ linux32_rt_sendsig(const ksiginfo_t *ksi, const sigset_t *mask) /* * Build context to run handler in. */ - tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; @@ -296,13 +283,10 @@ linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) netbsd32_adjust_limits(p); l->l_md.md_flags &= ~MDP_USEDFPU; - pcb->pcb_flags = 0; + pcb->pcb_flags = PCB_COMPAT32; pcb->pcb_savefpu.fp_fxsave.fx_fcw = __Linux_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; - p->p_flag |= PK_32; @@ -325,12 +309,12 @@ linux32_setregs(struct lwp *l, struct exec_package *pack, u_long stack) tf->tf_r15 = 0; tf->tf_rip = pack->ep_entry & 0xffffffff; tf->tf_rflags = PSL_USERSET; - tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL) & 0xffffffff; - tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; - tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; - tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; - tf->tf_fs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; - tf->tf_gs = GSEL(GUDATA32_SEL, SEL_UPL) & 0xffffffff; + tf->tf_cs = GSEL(GUCODE32_SEL, SEL_UPL); + tf->tf_ss = GSEL(GUDATA32_SEL, SEL_UPL); + tf->tf_ds = GSEL(GUDATA32_SEL, SEL_UPL); + tf->tf_es = GSEL(GUDATA32_SEL, SEL_UPL); + cpu_fsgs_zero(l); + cpu_fsgs_reload(l, GSEL(GUDATA32_SEL, SEL_UPL), GSEL(GUDATA32_SEL, SEL_UPL)); /* XXX frob return address to return via old iret method, not sysret */ retaddr = (void **)tf - 1; @@ -426,42 +410,47 @@ linux32_restore_sigcontext(struct lwp *l, struct linux32_sigcontext *scp, struct trapframe *tf; struct proc *p = l->l_proc; struct sigaltstack *sas = &l->l_sigstk; + struct pcb *pcb; sigset_t mask; ssize_t ss_gap; + register_t fssel, gssel; /* Restore register context. */ tf = l->l_md.md_regs; + pcb = lwp_getpcb(l); + DPRINTF(("sigreturn enter rsp=0x%lx rip=0x%lx\n", tf->tf_rsp, + tf->tf_rip)); /* - * Check for security violations. If we're returning to - * protected mode, the CPU will validate the segment registers - * automatically and generate a trap on violations. We handle - * the trap, rather than doing all of the checking here. + * Check for security violations. */ if (((scp->sc_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 || !USERMODE(scp->sc_cs, scp->sc_eflags)) return EINVAL; - if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs)) + if (scp->sc_fs != 0 && !VALID_USER_DSEL32(scp->sc_fs) && + !(scp->sc_fs == GSEL(GUFS_SEL, SEL_UPL) && pcb->pcb_fs != 0)) return EINVAL; - if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs)) + if (scp->sc_gs != 0 && !VALID_USER_DSEL32(scp->sc_gs) && + !(scp->sc_gs == GSEL(GUGS_SEL, SEL_UPL) && pcb->pcb_gs != 0)) return EINVAL; if (scp->sc_es != 0 && !VALID_USER_DSEL32(scp->sc_es)) return EINVAL; - if (!VALID_USER_DSEL32(scp->sc_ds) || + if (!VALID_USER_DSEL32(scp->sc_ds) || !VALID_USER_DSEL32(scp->sc_ss)) return EINVAL; if (scp->sc_eip >= VM_MAXUSER_ADDRESS32) return EINVAL; - tf->tf_gs = (register_t)scp->sc_gs & 0xffffffff; - tf->tf_fs = (register_t)scp->sc_fs & 0xffffffff; - tf->tf_es = (register_t)scp->sc_es & 0xffffffff; - tf->tf_ds = (register_t)scp->sc_ds & 0xffffffff; + gssel = (register_t)scp->sc_gs & 0xffff; + fssel = (register_t)scp->sc_fs & 0xffff; + cpu_fsgs_reload(l, fssel, gssel); + tf->tf_es = (register_t)scp->sc_es & 0xffff; + tf->tf_ds = (register_t)scp->sc_ds & 0xffff; tf->tf_rflags &= ~PSL_USER; tf->tf_rflags |= ((register_t)scp->sc_eflags & PSL_USER); tf->tf_rdi = (register_t)scp->sc_edi & 0xffffffff; @@ -472,9 +461,9 @@ linux32_restore_sigcontext(struct lwp *l, struct linux32_sigcontext *scp, tf->tf_rcx = (register_t)scp->sc_ecx & 0xffffffff; tf->tf_rax = (register_t)scp->sc_eax & 0xffffffff; tf->tf_rip = (register_t)scp->sc_eip & 0xffffffff; - tf->tf_cs = (register_t)scp->sc_cs & 0xffffffff; + tf->tf_cs = (register_t)scp->sc_cs & 0xffff; tf->tf_rsp = (register_t)scp->sc_esp_at_signal & 0xffffffff; - tf->tf_ss = (register_t)scp->sc_ss & 0xffffffff; + tf->tf_ss = (register_t)scp->sc_ss & 0xffff; mutex_enter(p->p_lock); @@ -493,9 +482,30 @@ linux32_restore_sigcontext(struct lwp *l, struct linux32_sigcontext *scp, mutex_exit(p->p_lock); -#ifdef DEBUG_LINUX - printf("linux32_sigreturn: rip = 0x%lx, rsp = 0x%lx, flags = 0x%lx\n", - tf->tf_rip, tf->tf_rsp, tf->tf_rflags); -#endif + DPRINTF(("linux32_sigreturn: rip = 0x%lx, rsp = 0x%lx, flags = 0x%lx\n", + tf->tf_rip, tf->tf_rsp, tf->tf_rflags)); return EJUSTRETURN; } + +int +linux32_sys_set_thread_area(struct lwp *l, + const struct linux32_sys_set_thread_area_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_user_descp_t) desc; + } */ + + return linux_lwp_setprivate(l, SCARG_P32(uap, desc)); +} + +int +linux32_sys_get_thread_area(struct lwp *l, + const struct linux32_sys_get_thread_area_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_user_descp_t) desc; + } */ + + /* glibc doesn't actually call this. */ + return ENOSYS; +} diff --git a/sys/compat/linux32/arch/amd64/linux32_types.h b/sys/compat/linux32/arch/amd64/linux32_types.h index ca1eb7bb34c..728839cfb4a 100644 --- a/sys/compat/linux32/arch/amd64/linux32_types.h +++ b/sys/compat/linux32/arch/amd64/linux32_types.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_types.h,v 1.6 2009/06/08 14:42:10 njoly Exp $ */ +/* $NetBSD: linux32_types.h,v 1.7 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,13 +33,17 @@ #ifndef _AMD64_LINUX32_TYPES_H #define _AMD64_LINUX32_TYPES_H -typedef unsigned short linux32_uid_t; -typedef unsigned short linux32_gid_t; -typedef int linux32_pid_t; +typedef uint16_t linux32_uid_t; +typedef uint16_t linux32_gid_t; +typedef int32_t linux32_pid_t; typedef int32_t linux32_clock_t; typedef int32_t linux32_time_t; typedef int32_t linux32_off_t; typedef uint32_t linux32_ino_t; +typedef uint32_t linux32_size_t; +typedef netbsd32_pointer_t linux32_ulongp_t; + +typedef netbsd32_pointer_t linux32_user_descp_t; #define LINUX32_STAT64_HAS_NSEC 1 struct linux32_stat64 { diff --git a/sys/compat/linux32/arch/amd64/syscalls.master b/sys/compat/linux32/arch/amd64/syscalls.master index f66c5c06650..a1e254c67fb 100644 --- a/sys/compat/linux32/arch/amd64/syscalls.master +++ b/sys/compat/linux32/arch/amd64/syscalls.master @@ -1,4 +1,4 @@ - $NetBSD: syscalls.master,v 1.55 2009/11/24 10:42:44 njoly Exp $ + $NetBSD: syscalls.master,v 1.56 2010/07/07 01:30:35 chs Exp $ ; NetBSD i386 COMPAT_LINUX32 system call name/number "master" file. ; (See syscalls.conf to see what it is processed into.) @@ -60,7 +60,7 @@ %% 0 NOARGS { int|linux_sys||nosys(void); } syscall -1 NOARGS { int|netbsd32||exit(int rval); } +1 STD { int|linux32_sys||exit(int rval); } 2 NOARGS { int|sys||fork(void); } 3 NOARGS { netbsd32_ssize_t|netbsd32||read(int fd, \ netbsd32_voidp buf, netbsd32_size_t nbyte); } @@ -88,7 +88,7 @@ 18 OBSOL ostat 19 NOARGS { netbsd32_long|compat_43_netbsd32||olseek(int fd, \ netbsd32_long offset, int chence); } -20 STD { pid_t|linux_sys||getpid(void); } +20 NOARGS { pid_t|sys||getpid(void); } 21 UNIMPL mount 22 UNIMPL umount 23 NOARGS linux_setuid16 { int|netbsd32||setuid(uid_t uid); } @@ -140,7 +140,7 @@ 61 NOARGS { int|netbsd32||chroot(netbsd32_charp path); } 62 UNIMPL ustat 63 NOARGS { int|netbsd32||dup2(int from, int to); } -64 STD { pid_t|linux_sys||getppid(void); } +64 NOARGS { pid_t|sys||getppid(void); } 65 NOARGS { int|sys||getpgrp(void); } 66 NOARGS { int|sys||setsid(void); } 67 UNIMPL sigaction @@ -223,7 +223,9 @@ netbsd32_voidp ptr); } 118 NOARGS { int|netbsd32||fsync(int fd); } 119 STD { int|linux32_sys||sigreturn(linux32_sigcontextp_t scp); } -120 STD { int|linux32_sys||clone(int flags, netbsd32_voidp stack); } +120 STD { int|linux32_sys||clone(int flags, netbsd32_voidp stack, \ + netbsd32_voidp parent_tidptr, netbsd32_voidp tls, \ + netbsd32_voidp child_tidptr); } 121 UNIMPL setdomainname 122 STD { int|linux32_sys||uname(linux32_utsnamep up); } 123 UNIMPL modify_ldt @@ -269,7 +271,8 @@ netbsd32_size_t len); } 152 NOARGS { int|netbsd32||mlockall(int flags); } 153 NOARGS { int|sys||munlockall(void); } -154 UNIMPL sched_setparam +154 STD { int|linux32_sys||sched_setparam(pid_t pid, \ + const linux32_sched_paramp_t sp); } 155 STD { int|linux32_sys||sched_getparam(pid_t pid, \ linux32_sched_paramp_t sp); } 156 STD { int|linux32_sys||sched_setscheduler(pid_t pid, \ @@ -385,7 +388,7 @@ int cmd, netbsd32_voidp arg); } 222 UNIMPL /* unused */ 223 UNIMPL /* unused */ -224 STD { pid_t|linux_sys||gettid(void); } +224 NOARGS { pid_t|linux_sys||gettid(void); } 225 UNIMPL readahead 226 UNIMPL setxattr 227 UNIMPL lsetxattr @@ -399,13 +402,17 @@ 235 UNIMPL removexattr 236 UNIMPL lremovexattr 237 UNIMPL fremovexattr -238 UNIMPL tkill +238 STD { int|linux32_sys||tkill(int tid, int sig); } 239 UNIMPL sendfile64 -240 UNIMPL futex -241 UNIMPL sched_setaffinity -242 UNIMPL sched_getaffinity -243 UNIMPL set_thread_area -244 UNIMPL get_thread_area +240 STD { int|linux32_sys||futex(linux32_intp_t uaddr, int op, int val, \ + linux32_timespecp_t timeout, linux32_intp_t uaddr2, \ + int val3); } +241 STD { int|linux32_sys||sched_setaffinity(pid_t pid, \ + unsigned int len, linux32_ulongp_t mask); } +242 STD { int|linux32_sys||sched_getaffinity(pid_t pid, \ + unsigned int len, linux32_ulongp_t mask); } +243 STD { int|linux32_sys||set_thread_area(linux32_user_descp_t desc); } +244 STD { int|linux32_sys||get_thread_area(linux32_user_descp_t desc); } 245 UNIMPL io_setup 246 UNIMPL io_destroy 247 UNIMPL io_getevents @@ -419,7 +426,7 @@ 255 UNIMPL epoll_ctl 256 UNIMPL epoll_wait 257 UNIMPL remap_file_pages -258 UNIMPL set_tid_address +258 STD { int|linux32_sys||set_tid_address(linux32_intp_t tid); } 259 UNIMPL timer_create 260 UNIMPL timer_settime 261 UNIMPL timer_gettime @@ -435,7 +442,7 @@ linux32_timespecp_t rqtp, linux32_timespecp_t rmtp); } 268 UNIMPL statfs64 269 UNIMPL fstatfs64 -270 UNIMPL tgkill +270 STD { int|linux32_sys||tgkill(int tgid, int tid, int sig); } 271 UNIMPL utimes 272 UNIMPL fadvise64_64 273 UNIMPL vserver @@ -449,3 +456,59 @@ 281 UNIMPL mq_notify 282 UNIMPL mq_getsetattr 283 UNIMPL kexec_load +284 UNIMPL waitid +285 UNIMPL /* unused */ +286 UNIMPL add_key +287 UNIMPL request_key +288 UNIMPL keyctl +289 UNIMPL ioprio_set +290 UNIMPL ioprio_get +291 UNIMPL inotify_init +292 UNIMPL inotify_add_watch +293 UNIMPL inotify_rm_watch +294 UNIMPL migrate_pages +295 UNIMPL openat +296 UNIMPL mkdirat +297 UNIMPL mknodat +298 UNIMPL fchownat +299 UNIMPL futimesat +300 UNIMPL fstatat64 +301 UNIMPL unlinkat +302 UNIMPL renameat +303 UNIMPL linkat +304 UNIMPL symlinkat +305 UNIMPL readlinkat +306 UNIMPL fchmodat +307 UNIMPL faccessat +308 UNIMPL pselect6 +309 UNIMPL ppoll +310 UNIMPL unshare +311 STD { int|linux32_sys||set_robust_list( \ + linux32_robust_list_headp_t head, linux32_size_t len); } +312 STD { int|linux32_sys||get_robust_list(linux32_pid_t pid, \ + linux32_robust_list_headpp_t head, linux32_sizep_t len); } +313 UNIMPL splice +314 UNIMPL sync_file_range +315 UNIMPL tee +316 UNIMPL vmsplice +317 UNIMPL move_pages +318 UNIMPL getcpu +319 UNIMPL epoll_wait +320 UNIMPL utimensat +321 UNIMPL signalfd +322 UNIMPL timerfd_create +323 UNIMPL eventfd +324 UNIMPL fallocate +325 UNIMPL timerfd_settime +326 UNIMPL timerfd_gettime +327 UNIMPL signalfd4 +328 UNIMPL eventfd2 +329 UNIMPL epoll_create1 +330 UNIMPL dup3 +331 UNIMPL pipe2 +332 UNIMPL inotify_init1 +333 UNIMPL preadv +334 UNIMPL pwritev +335 UNIMPL rt_tgsigqueueinfo +336 UNIMPL perf_counter_open +337 UNIMPL recvmmsg diff --git a/sys/compat/linux32/common/linux32_exec.c b/sys/compat/linux32/common/linux32_exec.c index d8240e30a0c..1fcd2d6d453 100644 --- a/sys/compat/linux32/common/linux32_exec.c +++ b/sys/compat/linux32/common/linux32_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_exec.c,v 1.19 2009/10/25 01:14:03 rmind Exp $ */ +/* $NetBSD: linux32_exec.c,v 1.20 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1994-2007 The NetBSD Foundation, Inc. @@ -31,30 +31,20 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_exec.c,v 1.19 2009/10/25 01:14:03 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_exec.c,v 1.20 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> #include <sys/proc.h> -#include <sys/malloc.h> -#include <sys/namei.h> -#include <sys/vnode.h> -#include <sys/mount.h> #include <sys/exec.h> #include <sys/exec_elf.h> #include <sys/mman.h> #include <sys/syscallargs.h> -#include <sys/ptrace.h> /* For proc_reparent() */ - -#include <uvm/uvm_extern.h> - -#include <sys/cpu.h> -#include <machine/reg.h> #include <compat/linux/common/linux_types.h> -#include <compat/linux/common/linux_emuldata.h> +#include <compat/linux/common/linux_exec.h> #include <compat/linux32/common/linux32_exec.h> #include <compat/linux32/common/linux32_types.h> @@ -64,24 +54,9 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_exec.c,v 1.19 2009/10/25 01:14:03 rmind Exp #include <compat/linux32/linux32_syscallargs.h> #include <compat/linux32/linux32_syscall.h> -extern char linux32_sigcode[1]; -extern char linux32_rt_sigcode[1]; -extern char linux32_esigcode[1]; - extern struct sysent linux32_sysent[]; extern const char * const linux32_syscallnames[]; - -static void linux32_e_proc_exec(struct proc *, struct exec_package *); -static void linux32_e_proc_fork(struct proc *, struct proc *, int); -static void linux32_e_proc_exit(struct proc *); -static void linux32_e_proc_init(struct proc *, struct proc *, int); - -#ifdef LINUX32_NPTL -void linux32_userret(void); -void linux_nptl_proc_fork(struct proc *, struct proc *, void (*luserret)(void)); -void linux_nptl_proc_exit(struct proc *); -void linux_nptl_proc_init(struct proc *, struct proc *); -#endif +extern char linux32_sigcode[], linux32_esigcode[]; /* * Emulation switch. @@ -101,17 +76,17 @@ struct emul emul_linux32 = { .e_sysent = linux32_sysent, .e_syscallnames = linux32_syscallnames, .e_sendsig = linux32_sendsig, - .e_trapsignal = trapsignal, + .e_trapsignal = linux_trapsignal, .e_tracesig = NULL, .e_sigcode = linux32_sigcode, .e_esigcode = linux32_esigcode, .e_sigobject = &emul_linux32_object, .e_setregs = linux32_setregs, - .e_proc_exec = linux32_e_proc_exec, - .e_proc_fork = linux32_e_proc_fork, - .e_proc_exit = linux32_e_proc_exit, - .e_lwp_fork = NULL, - .e_lwp_exit = NULL, + .e_proc_exec = linux_e_proc_exec, + .e_proc_fork = linux_e_proc_fork, + .e_proc_exit = linux_e_proc_exit, + .e_lwp_fork = linux_e_lwp_fork, + .e_lwp_exit = linux_e_lwp_exit, .e_syscall_intern = linux32_syscall_intern, .e_sysctlovly = NULL, .e_fault = NULL, @@ -121,177 +96,3 @@ struct emul emul_linux32 = { .e_ucsize = 0, .e_startlwp = NULL }; - -static void -linux32_e_proc_init(struct proc *p, struct proc *parent, int forkflags) -{ - struct linux_emuldata *e = p->p_emuldata; - struct linux_emuldata_shared *s; - struct linux_emuldata *ep = NULL; - - if (!e) { - /* allocate new Linux emuldata */ - e = malloc(sizeof(struct linux_emuldata), - M_EMULDATA, M_WAITOK); - } else { - mutex_enter(proc_lock); - e->s->refs--; - if (e->s->refs == 0) - free(e->s, M_EMULDATA); - mutex_exit(proc_lock); - } - - memset(e, '\0', sizeof(struct linux_emuldata)); - - e->proc = p; - - if (parent) - ep = parent->p_emuldata; - - if (forkflags & FORK_SHAREVM) { - mutex_enter(proc_lock); -#ifdef DIAGNOSTIC - if (ep == NULL) { - killproc(p, "FORK_SHAREVM while emuldata is NULL\n"); - mutex_exit(proc_lock); - return; - } -#endif - s = ep->s; - s->refs++; - } else { - struct vmspace *vm; - - s = malloc(sizeof(struct linux_emuldata_shared), - M_EMULDATA, M_WAITOK); - s->refs = 1; - - /* - * Set the process idea of the break to the real value. - * For fork, we use parent's vmspace since our's - * is not setup at the time of this call and is going - * to be copy of parent's anyway. For exec, just - * use our own vmspace. - */ - vm = (parent) ? parent->p_vmspace : p->p_vmspace; - s->p_break = (char *)vm->vm_daddr + ctob(vm->vm_dsize); - - /* - * Linux threads are emulated as NetBSD processes (not lwp) - * We use native PID for Linux TID. The Linux TID is the - * PID of the first process in the group. It is stored - * here - */ - s->group_pid = p->p_pid; - - /* - * Initialize the list of threads in the group - */ - LIST_INIT(&s->threads); - - s->xstat = 0; - s->flags = 0; - mutex_enter(proc_lock); - } - - e->s = s; - - /* - * Add this thread in the group thread list - */ - LIST_INSERT_HEAD(&s->threads, e, threads); - mutex_exit(proc_lock); - -#ifdef LINUX32_NPTL - linux_nptl_proc_init(p, parent); -#endif /* LINUX32_NPTL */ - - p->p_emuldata = e; -} - -/* - * Allocate new per-process structures. Called when executing Linux - * process. We can reuse the old emuldata - if it's not null, - * the executed process is of same emulation as original forked one. - */ -static void -linux32_e_proc_exec(struct proc *p, struct exec_package *epp) -{ - /* exec, use our vmspace */ - linux32_e_proc_init(p, NULL, 0); -} - -/* - * Emulation per-process exit hook. - */ -static void -linux32_e_proc_exit(struct proc *p) -{ - struct linux_emuldata *e = p->p_emuldata; - -#ifdef LINUX32_NPTL - linux_nptl_proc_exit(p); -#endif /* LINUX32_NPTL */ - - /* Remove the thread for the group thread list */ - mutex_enter(proc_lock); - LIST_REMOVE(e, threads); - - /* free Linux emuldata and set the pointer to null */ - e->s->refs--; - if (e->s->refs == 0) - free(e->s, M_EMULDATA); - p->p_emuldata = NULL; - mutex_exit(proc_lock); - free(e, M_EMULDATA); -} - -/* - * Emulation fork hook. - */ -static void -linux32_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) -{ - /* - * The new process might share some vmspace-related stuff - * with parent, depending on fork flags (CLONE_VM et.al). - * Force allocation of new base emuldata, and share the - * VM-related parts only if necessary. - */ - p->p_emuldata = NULL; - linux32_e_proc_init(p, parent, forkflags); - -#ifdef LINUX32_NPTL - linux_nptl_proc_fork(p, parent, linux32_userret); -#endif - - return; -} - -#ifdef LINUX32_NPTL -void -linux32_userret(void) -{ - struct lwp *l = curlwp; - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - int error; - - /* LINUX_CLONE_CHILD_SETTID: copy child's TID to child's memory */ - if (led->clone_flags & LINUX_CLONE_CHILD_SETTID) { - if ((error = copyout(&l->l_proc->p_pid, - led->child_tidptr, sizeof(l->l_proc->p_pid))) != 0) - printf("linux32_userret: LINUX_CLONE_CHILD_SETTID " - "failed (led->child_tidptr = %p, p->p_pid = %d)\n", - led->child_tidptr, p->p_pid); - } - - /* LINUX_CLONE_SETTLS: allocate a new TLS */ - if (led->clone_flags & LINUX_CLONE_SETTLS) { - if (linux32_set_newtls(l, linux32_get_newtls(l)) != 0) - printf("linux32_userret: linux32_set_tls failed"); - } - - return; -} -#endif /* LINUX32_NPTL */ diff --git a/sys/compat/linux32/common/linux32_exec.h b/sys/compat/linux32/common/linux32_exec.h index 09302debe94..d0e8e567f30 100644 --- a/sys/compat/linux32/common/linux32_exec.h +++ b/sys/compat/linux32/common/linux32_exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_exec.h,v 1.6 2009/12/10 14:13:53 matt Exp $ */ +/* $NetBSD: linux32_exec.h,v 1.7 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -44,11 +44,6 @@ extern struct emul emul_linux32; /* XXXmanu Do a.out later... */ -#ifdef LINUX32_NPTL -void linux_nptl_exit_hook(struct proc *); -#endif - - #ifdef EXEC_ELF32 int linux32_elf32_probe(struct lwp *, struct exec_package *, void *, char *, vaddr_t *); diff --git a/sys/compat/linux32/common/linux32_exec_elf32.c b/sys/compat/linux32/common/linux32_exec_elf32.c index eac293415ac..9912cb22a9c 100644 --- a/sys/compat/linux32/common/linux32_exec_elf32.c +++ b/sys/compat/linux32/common/linux32_exec_elf32.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_exec_elf32.c,v 1.10 2010/04/18 23:47:52 jym Exp $ */ +/* $NetBSD: linux32_exec_elf32.c,v 1.11 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 2000, 2001,2006 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_exec_elf32.c,v 1.10 2010/04/18 23:47:52 jym Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_exec_elf32.c,v 1.11 2010/07/07 01:30:35 chs Exp $"); #define ELFSIZE 32 @@ -99,10 +99,6 @@ ELFNAME2(linux32,probe)(struct lwp *l, struct exec_package *epp, return 0; } -/* round up and down to page boundaries. */ -#define ELF_ROUND(a, b) (((a) + (b) - 1) & ~((b) - 1)) -#define ELF_TRUNC(a, b) ((a) & ~((b) - 1)) - /* * Copy arguments onto the stack in the normal way, but add some * extra information in case of dynamic binding. @@ -111,131 +107,114 @@ int linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack, struct ps_strings *arginfo, char **stackp, void *argp) { - struct linux32_extra_stack_data *esdp, esd; + Aux32Info ai[LINUX32_ELF_AUX_ENTRIES], *a; struct elf_args *ap; struct vattr *vap; - Elf_Ehdr *eh; - Elf_Phdr *ph; - Elf_Addr phdr = 0; - u_long phsize; + size_t len; int error; - int i; if ((error = netbsd32_copyargs(l, pack, arginfo, stackp, argp)) != 0) return error; + a = ai; + /* * Push extra arguments on the stack needed by dynamically * linked binaries and static binaries as well. */ - memset(&esd, 0, sizeof(esd)); - esdp = (struct linux32_extra_stack_data *)(*stackp); - ap = (struct elf_args *)pack->ep_emul_arg; - vap = pack->ep_vap; - eh = (Elf_Ehdr *)pack->ep_hdr; - /* - * We forgot this, so we ned to reload it now. XXX keep track of it? - */ - if (ap == NULL) { - phsize = eh->e_phnum * sizeof(Elf_Phdr); - ph = (Elf_Phdr *)malloc(phsize, M_TEMP, M_WAITOK); - error = exec_read_from(l, pack->ep_vp, eh->e_phoff, ph, phsize); - if (error != 0) { - for (i = 0; i < eh->e_phnum; i++) { - if (ph[i].p_type == PT_PHDR) { - phdr = ph[i].p_vaddr; - break; - } - } - } - free(ph, M_TEMP); - } + a->a_type = AT_PAGESZ; + a->a_v = PAGE_SIZE; + a++; + if ((ap = (struct elf_args *)pack->ep_emul_arg)) { - /* - * The exec_package doesn't have a proc pointer and it's not - * exactly trivial to add one since the credentials are - * changing. XXX Linux uses curlwp's credentials. - * Why can't we use them too? XXXad we do now; what's different - * about Linux's LWP creds? - */ + a->a_type = AT_PHDR; + a->a_v = ap->arg_phaddr; + a++; - i = 0; - esd.ai[i].a_type = LINUX_AT_SYSINFO; - esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]); + a->a_type = AT_PHENT; + a->a_v = ap->arg_phentsize; + a++; - esd.ai[i].a_type = LINUX_AT_SYSINFO_EHDR; - esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->elfhdr); + a->a_type = AT_PHNUM; + a->a_v = ap->arg_phnum; + a++; - esd.ai[i].a_type = LINUX_AT_HWCAP; - esd.ai[i++].a_v = LINUX32_CPUCAP; + a->a_type = AT_BASE; + a->a_v = ap->arg_interp; + a++; - esd.ai[i].a_type = AT_PAGESZ; - esd.ai[i++].a_v = PAGE_SIZE; + a->a_type = AT_FLAGS; + a->a_v = 0; + a++; - esd.ai[i].a_type = LINUX_AT_CLKTCK; - esd.ai[i++].a_v = hz; + a->a_type = AT_ENTRY; + a->a_v = ap->arg_entry; + a++; - esd.ai[i].a_type = AT_PHDR; - esd.ai[i++].a_v = (ap ? ap->arg_phaddr: phdr); + free(ap, M_TEMP); + pack->ep_emul_arg = NULL; + } - esd.ai[i].a_type = AT_PHENT; - esd.ai[i++].a_v = (ap ? ap->arg_phentsize : eh->e_phentsize); + /* Linux-specific items */ + a->a_type = LINUX_AT_CLKTCK; + a->a_v = hz; + a++; - esd.ai[i].a_type = AT_PHNUM; - esd.ai[i++].a_v = (ap ? ap->arg_phnum : eh->e_phnum); + vap = pack->ep_vap; - esd.ai[i].a_type = AT_BASE; - esd.ai[i++].a_v = (ap ? ap->arg_interp : 0); + a->a_type = LINUX_AT_UID; + a->a_v = kauth_cred_getuid(l->l_cred); + a++; - esd.ai[i].a_type = AT_FLAGS; - esd.ai[i++].a_v = 0; + a->a_type = LINUX_AT_EUID; + a->a_v = ((vap->va_mode & S_ISUID) ? + vap->va_uid : kauth_cred_geteuid(l->l_cred)); + a++; - esd.ai[i].a_type = AT_ENTRY; - esd.ai[i++].a_v = (ap ? ap->arg_entry : eh->e_entry); + a->a_type = LINUX_AT_GID; + a->a_v = kauth_cred_getgid(l->l_cred); + a++; - esd.ai[i].a_type = LINUX_AT_EGID; - esd.ai[i++].a_v = ((vap->va_mode & S_ISGID) ? + a->a_type = LINUX_AT_EGID; + a->a_v = ((vap->va_mode & S_ISGID) ? vap->va_gid : kauth_cred_getegid(l->l_cred)); + a++; - esd.ai[i].a_type = LINUX_AT_GID; - esd.ai[i++].a_v = kauth_cred_getgid(l->l_cred); + a->a_type = LINUX_AT_SECURE; + a->a_v = 0; + a++; - esd.ai[i].a_type = LINUX_AT_EUID; - esd.ai[i++].a_v = ((vap->va_mode & S_ISUID) ? - vap->va_uid : kauth_cred_geteuid(l->l_cred)); +#if 0 + a->a_type = LINUX_AT_SYSINFO; + a->a_v = NETBSD32PTR32I(&esdp->kernel_vsyscall[0]); + a++; - esd.ai[i].a_type = LINUX_AT_UID; - esd.ai[i++].a_v = kauth_cred_getuid(l->l_cred); + a->a_type = LINUX_AT_SYSINFO_EHDR; + a->a_v = NETBSD32PTR32I(&esdp->elfhdr); + a++; - esd.ai[i].a_type = LINUX_AT_SECURE; - esd.ai[i++].a_v = 0; + a->a_type = LINUX_AT_HWCAP; + a->a_v = LINUX32_CPUCAP; + a++; - esd.ai[i].a_type = LINUX_AT_PLATFORM; - esd.ai[i++].a_v = NETBSD32PTR32I(&esdp->hw_platform[0]); + a->a_type = LINUX_AT_PLATFORM; + a->a_v = NETBSD32PTR32I(&esdp->hw_platform[0]); + a++; +#endif - esd.ai[i].a_type = AT_NULL; - esd.ai[i++].a_v = 0; + a->a_type = AT_NULL; + a->a_v = 0; + a++; -#ifdef DEBUG_LINUX - if (i != LINUX32_ELF_AUX_ENTRIES) { - printf("linux32_elf32_copyargs: %d Aux entries\n", i); - return EINVAL; - } -#endif - - memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall, +#if 0 + memcpy(esd.kernel_vsyscall, linux32_kernel_vsyscall, sizeof(linux32_kernel_vsyscall)); memcpy(&esd.elfhdr, eh, sizeof(*eh)); - strcpy(esd.hw_platform, LINUX32_PLATFORM); - - if (ap) { - free((char *)ap, M_TEMP); - pack->ep_emul_arg = NULL; - } + strcpy(esd.hw_platform, LINUX32_PLATFORM); /* * Copy out the ELF auxiliary table and hw platform name @@ -243,6 +222,13 @@ linux32_elf32_copyargs(struct lwp *l, struct exec_package *pack, if ((error = copyout(&esd, esdp, sizeof(esd))) != 0) return error; *stackp += sizeof(esd); +#endif + + len = (a - ai) * sizeof(AuxInfo); + if ((error = copyout(ai, *stackp, len)) != 0) + return error; + *stackp += len; + return 0; } diff --git a/sys/compat/linux32/common/linux32_machdep.h b/sys/compat/linux32/common/linux32_machdep.h index a14b6ffcede..8f6d9991110 100644 --- a/sys/compat/linux32/common/linux32_machdep.h +++ b/sys/compat/linux32/common/linux32_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_machdep.h,v 1.2 2007/12/04 18:40:18 dsl Exp $ */ +/* $NetBSD: linux32_machdep.h,v 1.3 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -44,12 +44,6 @@ __BEGIN_DECLS void linux32_sendsig(const ksiginfo_t *, const sigset_t *); __END_DECLS -#ifdef LINUX32_NPTL -__BEGIN_DECLS -unsigned long linux32_get_newtls(struct lwp *); -int linux32_set_newtls(struct lwp *, unsigned long); -__END_DECLS -#endif /* !LINUX32_NPTL */ #endif /* !_KERNEL */ #endif /* !_LINUX32_MACHDEP_H */ diff --git a/sys/compat/linux32/common/linux32_misc.c b/sys/compat/linux32/common/linux32_misc.c index 73c82600442..805e6e26882 100644 --- a/sys/compat/linux32/common/linux32_misc.c +++ b/sys/compat/linux32/common/linux32_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_misc.c,v 1.18 2009/11/24 10:42:44 njoly Exp $ */ +/* $NetBSD: linux32_misc.c,v 1.19 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 1999 The NetBSD Foundation, Inc. @@ -32,7 +32,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_misc.c,v 1.18 2009/11/24 10:42:44 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_misc.c,v 1.19 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/proc.h> @@ -53,16 +53,19 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_misc.c,v 1.18 2009/11/24 10:42:44 njoly Exp #include <compat/linux/common/linux_ptrace.h> #include <compat/linux/common/linux_types.h> +#include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_signal.h> #include <compat/linux/common/linux_misc.h> #include <compat/linux/common/linux_statfs.h> #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> +#include <compat/linux/common/linux_futex.h> #include <compat/linux/linux_syscallargs.h> extern const struct linux_mnttypes linux_fstypes[]; extern const int linux_fstypes_cnt; +void linux32_to_native_timespec(struct timespec *, struct linux32_timespec *); /* * Implement the fs stat functions. Straightforward. @@ -189,3 +192,75 @@ linux32_sys_personality(struct lwp *l, const struct linux32_sys_personality_args retval[0] = LINUX_PER_LINUX; return 0; } + +int +linux32_sys_futex(struct lwp *l, + const struct linux32_sys_futex_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_intp_t) uaddr; + syscallarg(int) op; + syscallarg(int) val; + syscallarg(linux32_timespecp_t) timeout; + syscallarg(linux32_intp_t) uaddr2; + syscallarg(int) val3; + } */ + struct linux_sys_futex_args ua; + struct linux32_timespec lts; + struct timespec ts = { 0, 0 }; + int error; + + NETBSD32TOP_UAP(uaddr, int); + NETBSD32TO64_UAP(op); + NETBSD32TO64_UAP(val); + NETBSD32TOP_UAP(timeout, struct linux_timespec); + NETBSD32TOP_UAP(uaddr2, int); + NETBSD32TO64_UAP(val3); + if ((SCARG(uap, op) & ~LINUX_FUTEX_PRIVATE_FLAG) == LINUX_FUTEX_WAIT && + SCARG_P32(uap, timeout) != NULL) { + if ((error = copyin((void *)SCARG_P32(uap, timeout), + <s, sizeof(lts))) != 0) { + return error; + } + linux32_to_native_timespec(&ts, <s); + } + return linux_do_futex(l, &ua, retval, &ts); +} + +int +linux32_sys_set_robust_list(struct lwp *l, + const struct linux32_sys_set_robust_list_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_robust_list_headp_t) head; + syscallarg(linux32_size_t) len; + } */ + struct linux_sys_set_robust_list_args ua; + struct linux_emuldata *led; + + if (SCARG(uap, len) != 12) + return EINVAL; + + NETBSD32TOP_UAP(head, struct robust_list_head); + NETBSD32TOX64_UAP(len, size_t); + + led = l->l_emuldata; + led->led_robust_head = SCARG(&ua, head); + *retval = 0; + return 0; +} + +int +linux32_sys_get_robust_list(struct lwp *l, + const struct linux32_sys_get_robust_list_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_robust_list_headpp_t) head; + syscallarg(linux32_sizep_t) len; + } */ + struct linux_sys_get_robust_list_args ua; + + NETBSD32TOP_UAP(head, struct robust_list_head *); + NETBSD32TOP_UAP(head, size_t *); + return linux_sys_get_robust_list(l, &ua, retval); +} diff --git a/sys/compat/linux32/common/linux32_mod.c b/sys/compat/linux32/common/linux32_mod.c index 16f57ec251a..7e54cb4b520 100644 --- a/sys/compat/linux32/common/linux32_mod.c +++ b/sys/compat/linux32/common/linux32_mod.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_mod.c,v 1.2 2008/12/03 12:51:11 ad Exp $ */ +/* $NetBSD: linux32_mod.c,v 1.3 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_mod.c,v 1.2 2008/12/03 12:51:11 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_mod.c,v 1.3 2010/07/07 01:30:35 chs Exp $"); #ifdef _KERNEL_OPT #include "opt_execfmt.h" @@ -45,6 +45,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_mod.c,v 1.2 2008/12/03 12:51:11 ad Exp $"); #include <sys/exec.h> #include <sys/signalvar.h> +#include <compat/linux/common/linux_exec.h> + #include <compat/linux32/common/linux32_sysctl.h> #include <compat/linux32/common/linux32_exec.h> @@ -67,7 +69,7 @@ static struct execsw linux32_execsw[] = { linux32_elf32_copyargs, NULL, coredump_elf32, - exec_setup_stack }, + linux_exec_setup_stack }, #endif }; diff --git a/sys/compat/linux32/common/linux32_sched.c b/sys/compat/linux32/common/linux32_sched.c index e185a45ef13..207f901c2f7 100644 --- a/sys/compat/linux32/common/linux32_sched.c +++ b/sys/compat/linux32/common/linux32_sched.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_sched.c,v 1.8 2008/12/01 14:18:44 njoly Exp $ */ +/* $NetBSD: linux32_sched.c,v 1.9 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_sched.c,v 1.8 2008/12/01 14:18:44 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_sched.c,v 1.9 2010/07/07 01:30:35 chs Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -59,7 +59,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_sched.c,v 1.8 2008/12/01 14:18:44 njoly Exp #include <compat/linux/common/linux_signal.h> #include <compat/linux/common/linux_machdep.h> #include <compat/linux/common/linux_misc.h> -#include <compat/linux/common/linux_oldolduname.h> +#include <compat/linux/common/linux_sched.h> #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> #include <compat/linux/linux_syscallargs.h> @@ -77,16 +77,17 @@ linux32_sys_clone(struct lwp *l, const struct linux32_sys_clone_args *uap, regis /* { syscallarg(int) flags; syscallarg(netbsd32_voidp) stack; + syscallarg(netbsd32_voidp) parent_tidptr; + syscallarg(netbsd32_voidp) tls; + syscallarg(netbsd32_voidp) child_tidptr; } */ struct linux_sys_clone_args ua; NETBSD32TO64_UAP(flags); NETBSD32TOP_UAP(stack, void *); -#ifdef LINUX_NPTL - SCARG(&ua, parent_tidptr) = NULL; - SCARG(&ua, child_tidptr) = NULL; -#endif - + NETBSD32TOP_UAP(parent_tidptr, void *); + NETBSD32TOP_UAP(tls, void *); + NETBSD32TOP_UAP(child_tidptr, void *); return linux_sys_clone(l, &ua, retval); } @@ -99,7 +100,6 @@ linux32_sys_sched_getscheduler(struct lwp *l, const struct linux32_sys_sched_get struct linux_sys_sched_getscheduler_args ua; NETBSD32TO64_UAP(pid); - return linux_sys_sched_getscheduler(l, &ua, retval); } @@ -116,7 +116,6 @@ linux32_sys_sched_setscheduler(struct lwp *l, const struct linux32_sys_sched_set NETBSD32TO64_UAP(pid); NETBSD32TO64_UAP(policy); NETBSD32TOP_UAP(sp, const struct linux_sched_param); - return linux_sys_sched_setscheduler(l, &ua, retval); } @@ -125,17 +124,30 @@ linux32_sys_sched_getparam(struct lwp *l, const struct linux32_sys_sched_getpara { /* { syscallarg(pid_t) pid; - syscallarg(linux32_sched_paramp_t *) sp; + syscallarg(linux32_sched_paramp_t) sp; } */ struct linux_sys_sched_getparam_args ua; NETBSD32TO64_UAP(pid); NETBSD32TOP_UAP(sp, struct linux_sched_param); - return linux_sys_sched_getparam(l, &ua, retval); } int +linux32_sys_sched_setparam(struct lwp *l, const struct linux32_sys_sched_setparam_args *uap, register_t *retval) +{ + /* { + syscallarg(pid_t) pid; + syscallarg(const linux32_sched_paramp_t) sp; + } */ + struct linux_sys_sched_setparam_args ua; + + NETBSD32TO64_UAP(pid); + NETBSD32TOP_UAP(sp, const struct linux_sched_param); + return linux_sys_sched_setparam(l, &ua, retval); +} + +int linux32_sys_exit_group(struct lwp *l, const struct linux32_sys_exit_group_args *uap, register_t *retval) { /* { @@ -144,11 +156,23 @@ linux32_sys_exit_group(struct lwp *l, const struct linux32_sys_exit_group_args * struct linux_sys_exit_group_args ua; NETBSD32TO64_UAP(error_code); - return linux_sys_exit_group(l, &ua, retval); } int +linux32_sys_exit(struct lwp *l, const struct linux32_sys_exit_args *uap, register_t *retval) +{ + + /* { + syscallarg(int) rval; + } */ + struct linux_sys_exit_args ua; + + NETBSD32TO64_UAP(rval); + return linux_sys_exit(l, &ua, retval); +} + +int linux32_sys_sched_get_priority_max(struct lwp *l, const struct linux32_sys_sched_get_priority_max_args *uap, register_t *retval) { /* { @@ -158,7 +182,6 @@ linux32_sys_sched_get_priority_max(struct lwp *l, const struct linux32_sys_sched struct linux_sys_sched_get_priority_max_args ua; NETBSD32TO64_UAP(policy); - return linux_sys_sched_get_priority_max(l, &ua, retval); } @@ -172,6 +195,80 @@ linux32_sys_sched_get_priority_min(struct lwp *l, const struct linux32_sys_sched struct linux_sys_sched_get_priority_min_args ua; NETBSD32TO64_UAP(policy); - return linux_sys_sched_get_priority_min(l, &ua, retval); } + + +int +linux32_sys_set_tid_address(struct lwp *l, const struct linux32_sys_set_tid_address_args *uap, register_t *retval) +{ + /* { + syscallarg(linux32_intp_t) tid; + } */ + struct linux_sys_set_tid_address_args ua; + + NETBSD32TOP_UAP(tid, int); + return linux_sys_set_tid_address(l, &ua, retval); +} + +int +linux32_sys_sched_getaffinity(struct lwp *l, const struct linux32_sys_sched_getaffinity_args *uap, register_t *retval) +{ + /* { + syscallarg(linux_pid_t) pid; + syscallarg(unsigned int) len; + syscallarg(linux32_longp_t) mask; + } */ + struct linux_sys_sched_getaffinity_args ua; + + NETBSD32TO64_UAP(pid); + NETBSD32TO64_UAP(len); + NETBSD32TOP_UAP(mask, long); + return linux_sys_sched_getaffinity(l, &ua, retval); +} + +int +linux32_sys_sched_setaffinity(struct lwp *l, const struct linux32_sys_sched_setaffinity_args *uap, register_t *retval) +{ + /* { + syscallarg(linux_pid_t) pid; + syscallarg(unsigned int) len; + syscallarg(linux32_longp_t) mask; + } */ + struct linux_sys_sched_setaffinity_args ua; + + NETBSD32TO64_UAP(pid); + NETBSD32TO64_UAP(len); + NETBSD32TOP_UAP(mask, long); + return linux_sys_sched_setaffinity(l, &ua, retval); +} + +int +linux32_sys_tkill(struct lwp *l, const struct linux32_sys_tkill_args *uap, register_t *retval) +{ + /* { + syscallarg(int) tid; + syscallarg(int) sig; + } */ + struct linux_sys_tkill_args ua; + + NETBSD32TO64_UAP(tid); + NETBSD32TO64_UAP(sig); + return linux_sys_tkill(l, &ua, retval); +} + +int +linux32_sys_tgkill(struct lwp *l, const struct linux32_sys_tgkill_args *uap, register_t *retval) +{ + /* { + syscallarg(int) tgid; + syscallarg(int) tid; + syscallarg(int) sig; + } */ + struct linux_sys_tgkill_args ua; + + NETBSD32TO64_UAP(tgid); + NETBSD32TO64_UAP(tid); + NETBSD32TO64_UAP(sig); + return linux_sys_tgkill(l, &ua, retval); +} diff --git a/sys/compat/linux32/common/linux32_sysctl.c b/sys/compat/linux32/common/linux32_sysctl.c index 27934d8c04f..3e1419d76f6 100644 --- a/sys/compat/linux32/common/linux32_sysctl.c +++ b/sys/compat/linux32/common/linux32_sysctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_sysctl.c,v 1.12 2009/01/05 09:33:19 njoly Exp $ */ +/* $NetBSD: linux32_sysctl.c,v 1.13 2010/07/07 01:30:36 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -31,7 +31,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_sysctl.c,v 1.12 2009/01/05 09:33:19 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_sysctl.c,v 1.13 2010/07/07 01:30:36 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -57,8 +57,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_sysctl.c,v 1.12 2009/01/05 09:33:19 njoly Ex #include <compat/linux32/linux32_syscallargs.h> char linux32_sysname[128] = "Linux"; -char linux32_release[128] = "2.4.18"; -char linux32_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002"; +char linux32_release[128] = "2.6.18"; +char linux32_version[128] = "#0 Wed Mar 3 03:03:03 PST 2010"; struct sysctlnode linux32_sysctl_root = { .sysctl_flags = SYSCTL_VERSION| diff --git a/sys/compat/linux32/common/linux32_time.c b/sys/compat/linux32/common/linux32_time.c index 9c9466df983..25f820e118b 100644 --- a/sys/compat/linux32/common/linux32_time.c +++ b/sys/compat/linux32/common/linux32_time.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_time.c,v 1.33 2010/04/08 15:59:37 njoly Exp $ */ +/* $NetBSD: linux32_time.c,v 1.34 2010/07/07 01:30:36 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -33,7 +33,7 @@ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.33 2010/04/08 15:59:37 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.34 2010/07/07 01:30:36 chs Exp $"); #include <sys/types.h> #include <sys/param.h> @@ -78,10 +78,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux32_time.c,v 1.33 2010/04/08 15:59:37 njoly Exp extern struct timezone linux_sys_tz; -static __inline void -native_to_linux32_timespec(struct linux32_timespec *, struct timespec *); -static __inline void -linux32_to_native_timespec(struct timespec *, struct linux32_timespec *); +void native_to_linux32_timespec(struct linux32_timespec *, struct timespec *); +void linux32_to_native_timespec(struct timespec *, struct linux32_timespec *); int linux32_sys_gettimeofday(struct lwp *l, const struct linux32_sys_gettimeofday_args *uap, register_t *retval) @@ -235,14 +233,14 @@ linux32_sys_utime(struct lwp *l, const struct linux32_sys_utime_args *uap, regis tvp, UIO_SYSSPACE); } -static __inline void +void native_to_linux32_timespec(struct linux32_timespec *ltp, struct timespec *ntp) { ltp->tv_sec = ntp->tv_sec; ltp->tv_nsec = ntp->tv_nsec; } -static __inline void +void linux32_to_native_timespec(struct timespec *ntp, struct linux32_timespec *ltp) { ntp->tv_sec = ltp->tv_sec; diff --git a/sys/compat/linux32/common/linux32_types.h b/sys/compat/linux32/common/linux32_types.h index 1cc8220aeee..72f6e2da7c8 100644 --- a/sys/compat/linux32/common/linux32_types.h +++ b/sys/compat/linux32/common/linux32_types.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux32_types.h,v 1.11 2009/01/16 13:10:47 njoly Exp $ */ +/* $NetBSD: linux32_types.h,v 1.12 2010/07/07 01:30:36 chs Exp $ */ /*- * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. @@ -38,8 +38,8 @@ #include <compat/linux32/arch/amd64/linux32_types.h> #endif -typedef unsigned short linux32_gid16_t; -typedef unsigned short linux32_uid16_t; +typedef uint16_t linux32_gid16_t; +typedef uint16_t linux32_uid16_t; typedef netbsd32_pointer_t linux32_oldmmapp; typedef netbsd32_pointer_t linux32_utsnamep; @@ -64,6 +64,10 @@ typedef netbsd32_pointer_t linux32_oldselectp_t; typedef netbsd32_pointer_t linux32_sysinfop_t; typedef netbsd32_pointer_t linux32_oldutsnamep_t; typedef netbsd32_pointer_t linux32_timespecp_t; +typedef netbsd32_pointer_t linux32_robust_list_headp_t; +typedef netbsd32_pointer_t linux32_robust_list_headpp_t; +typedef netbsd32_pointer_t linux32_sizep_t; +typedef netbsd32_pointer_t linux32_intp_t; struct linux32_sysctl { netbsd32_intp name; diff --git a/sys/compat/mach/mach_exec.c b/sys/compat/mach/mach_exec.c index e2fce571618..730b57a2ff0 100644 --- a/sys/compat/mach/mach_exec.c +++ b/sys/compat/mach/mach_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: mach_exec.c,v 1.72 2009/06/02 23:21:38 pooka Exp $ */ +/* $NetBSD: mach_exec.c,v 1.73 2010/07/07 01:30:36 chs Exp $ */ /*- * Copyright (c) 2001-2003 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.72 2009/06/02 23:21:38 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.73 2010/07/07 01:30:36 chs Exp $"); #include "opt_syscall_debug.h" @@ -71,51 +71,50 @@ struct uvm_object *emul_mach_object; #endif struct emul emul_mach = { - "mach", - "/emul/mach", + .e_name = "mach", + .e_path = "/emul/mach", #ifndef __HAVE_MINIMAL_EMUL - 0, - 0, - SYS_syscall, - SYS_NSYSENT, + .e_flags = 0, + .e_errno = NULL, + .e_nosys = SYS_syscall, + .e_nsysent = SYS_NSYSENT, #endif - sysent, + .e_sysent = sysent, #ifdef SYSCALL_DEBUG - syscallnames, + .e_syscallnames = mach_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - sendsig, - mach_trapsignal, - NULL, + .e_sendsig = sendsig, + .e_trapsignal = mach_trapsignal, + .e_tracesig = NULL, #ifdef COMPAT_16 - sigcode, - esigcode, - &emul_mach_object, + .e_sigcode = sigcode, + .e_esigcode = esigcode, + .e_sigobject = &emul_mach_object, #else - NULL, - NULL, - NULL, + .e_sigcode = NULL, + .e_esigcode = NULL, + .e_sigobject = NULL, #endif - setregs, - mach_e_proc_exec, - mach_e_proc_fork, - mach_e_proc_exit, - mach_e_lwp_fork, - mach_e_lwp_exit, + .e_setregs = setregs, + .e_proc_exec = mach_e_proc_exec, + .e_proc_fork = mach_e_proc_fork, + .e_proc_exit = mach_e_proc_exit, + .e_lwp_fork = mach_e_lwp_fork, + .e_lwp_exit = mach_e_lwp_exit, #ifdef __HAVE_SYSCALL_INTERN - mach_syscall_intern, + .e_syscall_intern = mach_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, /* e_fault */ - NULL, /* e_vm_default_addr */ - - uvm_default_mapaddr, - NULL, /* e_usertrap */ - NULL, /* e_sa */ - 0, /* e_ucsize */ - NULL, /* e_startlwp */ + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; /* @@ -186,7 +185,7 @@ exec_mach_probe(const char **path) void mach_e_proc_exec(struct proc *p, struct exec_package *epp) { - mach_e_proc_init(p, p->p_vmspace); + mach_e_proc_init(p); if (p->p_emul != epp->ep_esch->es_emul) { struct lwp *l = LIST_FIRST(&p->p_lwps); @@ -198,31 +197,30 @@ mach_e_proc_exec(struct proc *p, struct exec_package *epp) } void -mach_e_proc_fork(struct proc *p, struct proc *parent, int forkflags) +mach_e_proc_fork(struct proc *p2, struct lwp *l1, int forkflags) { - mach_e_proc_fork1(p, parent, 1); + mach_e_proc_fork1(p2, l1, 1); return; } void -mach_e_proc_fork1(struct proc *p, struct proc *parent, int allocate) +mach_e_proc_fork1(struct proc *p2, struct lwp *l1, int allocate) { struct mach_emuldata *med1; struct mach_emuldata *med2; int i; /* - * For Darwin binaries, p->p_emuldata has already been + * For Darwin binaries, p2->p_emuldata has already been * allocated, no need to throw it away and allocate it again. */ if (allocate) - p->p_emuldata = NULL; + p2->p_emuldata = NULL; - /* Use parent's vmspace because our vmspace may not be set up yet */ - mach_e_proc_init(p, parent->p_vmspace); + mach_e_proc_init(p2); - med1 = p->p_emuldata; - med2 = parent->p_emuldata; + med1 = p2->p_emuldata; + med2 = l1->l_proc->p_emuldata; /* * Exception ports are inherited between forks, @@ -244,7 +242,7 @@ mach_e_proc_fork1(struct proc *p, struct proc *parent, int allocate) } void -mach_e_proc_init(struct proc *p, struct vmspace *vmspace) +mach_e_proc_init(struct proc *p) { struct mach_emuldata *med; struct mach_right *mr; diff --git a/sys/compat/mach/mach_exec.h b/sys/compat/mach/mach_exec.h index 97cfd7fa6aa..85ec032f9b0 100644 --- a/sys/compat/mach/mach_exec.h +++ b/sys/compat/mach/mach_exec.h @@ -1,4 +1,4 @@ -/* $NetBSD: mach_exec.h,v 1.33 2008/11/19 18:36:05 ad Exp $ */ +/* $NetBSD: mach_exec.h,v 1.34 2010/07/07 01:30:36 chs Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -64,11 +64,11 @@ struct mach_lwp_emuldata { int exec_mach_copyargs(struct lwp *, struct exec_package *, struct ps_strings *, char **, void *); int exec_mach_probe(const char **); -void mach_e_proc_init(struct proc *, struct vmspace *); +void mach_e_proc_init(struct proc *); void mach_e_proc_exit(struct proc *); void mach_e_proc_exec(struct proc *, struct exec_package *); -void mach_e_proc_fork(struct proc *, struct proc *, int); -void mach_e_proc_fork1(struct proc *, struct proc *, int); +void mach_e_proc_fork(struct proc *, struct lwp *, int); +void mach_e_proc_fork1(struct proc *, struct lwp *, int); void mach_e_lwp_fork(struct lwp *, struct lwp *); void mach_e_lwp_exit(struct lwp *); diff --git a/sys/compat/osf1/osf1_exec.c b/sys/compat/osf1/osf1_exec.c index f7d34173020..5ec584ae504 100644 --- a/sys/compat/osf1/osf1_exec.c +++ b/sys/compat/osf1/osf1_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: osf1_exec.c,v 1.42 2008/11/19 18:36:05 ad Exp $ */ +/* $NetBSD: osf1_exec.c,v 1.43 2010/07/07 01:30:36 chs Exp $ */ /* * Copyright (c) 1999 Christopher G. Demetriou. All rights reserved. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: osf1_exec.c,v 1.42 2008/11/19 18:36:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: osf1_exec.c,v 1.43 2010/07/07 01:30:36 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -61,39 +61,42 @@ void syscall(void); struct uvm_object *emul_osf1_object; struct emul emul_osf1 = { - "osf1", - "/emul/osf1", + .e_name = "osf1", + .e_path = "/emul/osf1", #ifndef __HAVE_MINIMAL_EMUL - 0, - (int *)native_to_osf1_errno, - OSF1_SYS_syscall, - OSF1_SYS_NSYSENT, + .e_flags = 0, + .e_errno = native_to_osf1_errno, + .e_nosys = OSF1_SYS_syscall, + .e_nsysent = OSF1_SYS_NSYSENT, #endif - osf1_sysent, + .e_sysent = osf1_sysent, #ifdef SYSCALL_DEBUG - osf1_syscallnames, + .e_syscallnames = osf1_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - sendsig_sigcontext, - trapsignal, - NULL, - osf1_sigcode, - osf1_esigcode, - &emul_osf1_object, - setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = sendsig_sigcontext, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = osf1_sigcode, + .e_esigcode = osf1_esigcode, + .e_sigobject = &emul_osf1_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - osf1_syscall_intern, + .e_syscall_intern = osf1_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/pecoff/pecoff_emul.c b/sys/compat/pecoff/pecoff_emul.c index 2eedbbbea55..8d56eaf27dd 100644 --- a/sys/compat/pecoff/pecoff_emul.c +++ b/sys/compat/pecoff/pecoff_emul.c @@ -1,4 +1,4 @@ -/* $NetBSD: pecoff_emul.c,v 1.23 2009/06/02 23:21:38 pooka Exp $ */ +/* $NetBSD: pecoff_emul.c,v 1.24 2010/07/07 01:30:36 chs Exp $ */ /* * Copyright (c) 2000 Masaru OKI @@ -37,7 +37,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: pecoff_emul.c,v 1.23 2009/06/02 23:21:38 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: pecoff_emul.c,v 1.24 2010/07/07 01:30:36 chs Exp $"); /*#define DEBUG_PECOFF*/ @@ -78,49 +78,42 @@ void syscall(void); #endif struct emul emul_pecoff = { - "pecoff", - "/emul/pecoff", + .e_name = "pecoff", + .e_path = "/emul/pecoff", #ifndef __HAVE_MINIMAL_EMUL - EMUL_HAS_SYS___syscall, - 0, - SYS_syscall, - SYS_NSYSENT, + .e_flags = EMUL_HAS_SYS___syscall, + .e_errno = NULL + .e_nosys = SYS_syscall, + .e_nsysent = SYS_NSYSENT, #endif - sysent, + .e_sysent = sysent, #ifdef SYSCALL_DEBUG - syscallnames, -#else - NULL, + .e_syscallnames = syscallnames, #endif - sendsig, - trapsignal, - NULL, + .e_sendsig = sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, #ifdef COMPAT_16 - sigcode, - esigcode, - &emul_pecoff_object, -#else - NULL, - NULL, - NULL, + .e_sigcode = sigcode, + .e_esigcode = esigcode, + .e_sigobject = &emul_pecoff_object, #endif - setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - syscall_intern, + .e_syscall_intern = syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, - NULL, - NULL, - sizeof(ucontext_t), - NULL, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = sizeof(ucontext_t), + .e_startlwp = NULL }; diff --git a/sys/compat/sunos/sunos_exec.c b/sys/compat/sunos/sunos_exec.c index b65b4e56fd5..57946e9b201 100644 --- a/sys/compat/sunos/sunos_exec.c +++ b/sys/compat/sunos/sunos_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: sunos_exec.c,v 1.52 2008/11/19 18:36:05 ad Exp $ */ +/* $NetBSD: sunos_exec.c,v 1.53 2010/07/07 01:30:36 chs Exp $ */ /* * Copyright (c) 1993 Theo de Raadt @@ -28,7 +28,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunos_exec.c,v 1.52 2008/11/19 18:36:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunos_exec.c,v 1.53 2010/07/07 01:30:36 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -63,39 +63,42 @@ void syscall(void); struct uvm_object *emul_sunos_object; struct emul emul_sunos = { - "sunos", - "/emul/sunos", + .e_name = "sunos", + .e_path = "/emul/sunos", #ifndef __HAVE_MINIMAL_EMUL - 0, - NULL, - SUNOS_SYS_syscall, - SUNOS_SYS_NSYSENT, + .e_flags = 0, + .e_errno = NULL, + .e_nosys = SUNOS_SYS_syscall, + .e_nsysent = SUNOS_SYS_NSYSENT, #endif - sunos_sysent, + .e_sysent = sunos_sysent, #ifdef SYSCALL_DEBUG - sunos_syscallnames, + .e_syscallnames = sunos_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - sunos_sendsig, - trapsignal, - NULL, - sunos_sigcode, - sunos_esigcode, - &emul_sunos_object, - setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = sunos_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = sunos_sigcode, + .e_esigcode = sunos_esigcode, + .e_sigobject = &emul_sunos_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - sunos_syscall_intern, + .e_syscall_intern = sunos_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/sunos32/sunos32_exec.c b/sys/compat/sunos32/sunos32_exec.c index bbcb0e62527..be5a3e8d427 100644 --- a/sys/compat/sunos32/sunos32_exec.c +++ b/sys/compat/sunos32/sunos32_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: sunos32_exec.c,v 1.31 2008/11/19 18:36:05 ad Exp $ */ +/* $NetBSD: sunos32_exec.c,v 1.32 2010/07/07 01:30:37 chs Exp $ */ /* * Copyright (c) 2001 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sunos32_exec.c,v 1.31 2008/11/19 18:36:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sunos32_exec.c,v 1.32 2010/07/07 01:30:37 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -36,6 +36,7 @@ __KERNEL_RCSID(0, "$NetBSD: sunos32_exec.c,v 1.31 2008/11/19 18:36:05 ad Exp $") #include <sys/param.h> #include <sys/proc.h> #include <sys/mount.h> +#include <sys/exec.h> #include <uvm/uvm_extern.h> @@ -61,42 +62,42 @@ void syscall(void); struct uvm_object *emul_sunos32_object; struct emul emul_sunos = { - "sunos32", - "/emul/sunos", + .e_name = "sunos32", + .e_path = "/emul/sunos32", #ifndef __HAVE_MINIMAL_EMUL - 0, - NULL, - SUNOS32_SYS_syscall, - SUNOS32_SYS_NSYSENT, + .e_flags = 0, + .e_errno = NULL, + .e_nosys = SUNOS32_SYS_syscall, + .e_nsysent = SUNOS32_SYS_NSYSENT, #endif - sunos32_sysent, + .e_sysent = sunos32_sysent, #ifdef SYSCALL_DEBUG - sunos32_syscallnames, + .e_syscallnames = sunos32_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - sunos32_sendsig, - trapsignal, - NULL, - sunos_sigcode, - sunos_esigcode, - &emul_sunos32_object, - sunos32_setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = sunos32_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = sunos_sigcode, + .e_esigcode = sunos_esigcode, + .e_sigobject = &emul_sunos32_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - sunos_syscall_intern, + .e_syscall_intern = sunos_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - uvm_default_mapaddr, - NULL, - NULL, - 0, - NULL, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/svr4/svr4_exec.c b/sys/compat/svr4/svr4_exec.c index 8ee9d15b843..b50b626ca19 100644 --- a/sys/compat/svr4/svr4_exec.c +++ b/sys/compat/svr4/svr4_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_exec.c,v 1.64 2008/11/19 18:36:05 ad Exp $ */ +/* $NetBSD: svr4_exec.c,v 1.65 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 1994, 2000 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svr4_exec.c,v 1.64 2008/11/19 18:36:05 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_exec.c,v 1.65 2010/07/07 01:30:37 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: svr4_exec.c,v 1.64 2008/11/19 18:36:05 ad Exp $"); #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/exec.h> #include <uvm/uvm_extern.h> @@ -60,43 +61,42 @@ void syscall(void); struct uvm_object *emul_svr4_object; struct emul emul_svr4 = { - "svr4", - "/emul/svr4", + .e_name = "svr4", + .e_path = "/emul/svr4", #ifndef __HAVE_MINIMAL_EMUL - 0, - native_to_svr4_errno, - SVR4_SYS_syscall, - SVR4_SYS_NSYSENT, + .e_flags = 0, + .e_errno = native_to_svr4_errno, + .e_nosys = SVR4_SYS_syscall, + .e_nsysent = SVR4_SYS_NSYSENT, #endif - svr4_sysent, + .e_sysent = svr4_sysent, #ifdef SYSCALL_DEBUG - svr4_syscallnames, + .e_syscallnames = svr4_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - svr4_sendsig, - trapsignal, - NULL, - svr4_sigcode, - svr4_esigcode, - &emul_svr4_object, - svr4_setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = svr4_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = svr4_sigcode, + .e_esigcode = svr4_esigcode, + .e_sigobject = &emul_svr4_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - svr4_syscall_intern, + .e_syscall_intern = svr4_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, - NULL, /* e_usertrap */ - NULL, /* e_sa */ - 0, /* e_ucsize */ - NULL, /* e_startlwp */ + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/svr4_32/svr4_32_exec.c b/sys/compat/svr4_32/svr4_32_exec.c index 1c2ba2d42f1..92158d0fa35 100644 --- a/sys/compat/svr4_32/svr4_32_exec.c +++ b/sys/compat/svr4_32/svr4_32_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: svr4_32_exec.c,v 1.25 2008/11/19 18:36:06 ad Exp $ */ +/* $NetBSD: svr4_32_exec.c,v 1.26 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 1994, 2000 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec.c,v 1.25 2008/11/19 18:36:06 ad Exp $"); +__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec.c,v 1.26 2010/07/07 01:30:37 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_syscall_debug.h" @@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: svr4_32_exec.c,v 1.25 2008/11/19 18:36:06 ad Exp $") #include <sys/param.h> #include <sys/systm.h> #include <sys/proc.h> +#include <sys/exec.h> #include <uvm/uvm_extern.h> @@ -63,43 +64,42 @@ void syscall(void); struct uvm_object *emul_svr4_32_object; struct emul emul_svr4_32 = { - "svr4_32", - "/emul/svr4_32", + .e_name = "svr4_32", + .e_path = "/emul/svr4_32", #ifndef __HAVE_MINIMAL_EMUL - 0, - native_to_svr4_errno, - SVR4_32_SYS_syscall, - SVR4_32_SYS_NSYSENT, + .e_flags = 0, + .e_errno = native_to_svr4_errno, + .e_nosys = SVR4_32_SYS_syscall, + .e_nsysent = SVR4_32_SYS_NSYSENT, #endif - svr4_32_sysent, + .e_sysent = svr4_32_sysent, #ifdef SYSCALL_DEBUG - svr4_32_syscallnames, + .e_syscallnames = svr4_32_syscallnames, #else - NULL, + .e_syscallnames = NULL, #endif - svr4_32_sendsig, - trapsignal, - NULL, - svr4_32_sigcode, - svr4_32_esigcode, - &emul_svr4_32_object, - svr4_32_setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_sendsig = svr4_32_sendsig, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = svr4_32_sigcode, + .e_esigcode = svr4_32_esigcode, + .e_sigobject = &emul_svr4_32_object, + .e_setregs = svr4_32_setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - svr4_32_syscall_intern, + .e_syscall_intern = svr4_32_syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - svr4_32_vm_default_addr, - NULL, - NULL, - 0, - NULL, + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = svr4_32_vm_default_addr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; diff --git a/sys/compat/ultrix/ultrix_misc.c b/sys/compat/ultrix/ultrix_misc.c index c7c71a0aa59..ca827048c42 100644 --- a/sys/compat/ultrix/ultrix_misc.c +++ b/sys/compat/ultrix/ultrix_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: ultrix_misc.c,v 1.120 2010/03/03 11:02:34 pooka Exp $ */ +/* $NetBSD: ultrix_misc.c,v 1.121 2010/07/07 01:30:37 chs Exp $ */ /* * Copyright (c) 1995, 1997 Jonathan Stone (hereinafter referred to as the author) @@ -76,7 +76,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: ultrix_misc.c,v 1.120 2010/03/03 11:02:34 pooka Exp $"); +__KERNEL_RCSID(0, "$NetBSD: ultrix_misc.c,v 1.121 2010/07/07 01:30:37 chs Exp $"); #if defined(_KERNEL_OPT) #include "opt_sysv.h" @@ -159,45 +159,48 @@ void syscall(void); #endif struct emul emul_ultrix = { - "ultrix", - "/emul/ultrix", + .e_name = "ultrix", + .e_path = "/emul/ultrix", #ifndef __HAVE_MINIMAL_EMUL - 0, - NULL, - ULTRIX_SYS_syscall, - ULTRIX_SYS_NSYSENT, + .e_flags = 0, + .e_errno = NULL, + .e_nosys = ULTRIX_SYS_syscall, + .e_nsysent = ULTRIX_SYS_NSYSENT, +#endif + .e_sysent = ultrix_sysent, +#ifdef SYSCALL_DEBUG + .e_syscallnames = ultrix_syscallnames, +#else + .e_syscallnames = NULL, #endif - ultrix_sysent, - ultrix_syscallnames, #ifdef __mips - sendsig_sigcontext, + .e_sendsig = sendsig_sigcontext, #else /* vax */ - sendsig, + .e_sendsig = sendsig, #endif - trapsignal, - NULL, - ultrix_sigcode, - ultrix_esigcode, - &emul_ultrix_object, - setregs, - NULL, - NULL, - NULL, - NULL, - NULL, + .e_trapsignal = trapsignal, + .e_tracesig = NULL, + .e_sigcode = ultrix_sigcode, + .e_esigcode = ultrix_esigcode, + .e_sigobject = &emul_ultrix_object, + .e_setregs = setregs, + .e_proc_exec = NULL, + .e_proc_fork = NULL, + .e_proc_exit = NULL, + .e_lwp_fork = NULL, + .e_lwp_exit = NULL, #ifdef __HAVE_SYSCALL_INTERN - syscall_intern, + .e_syscall_intern = syscall_intern, #else - syscall, + .e_syscall_intern = syscall, #endif - NULL, - NULL, - - uvm_default_mapaddr, - NULL, - NULL, - 0, - NULL + .e_sysctlovly = NULL, + .e_fault = NULL, + .e_vm_default_addr = uvm_default_mapaddr, + .e_usertrap = NULL, + .e_sa = NULL, + .e_ucsize = 0, + .e_startlwp = NULL }; #define GSI_PROG_ENV 1 diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index 6e70785cb3e..916c8d17573 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exec.c,v 1.298 2010/06/24 13:03:11 hannken Exp $ */ +/* $NetBSD: kern_exec.c,v 1.299 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 2008 The NetBSD Foundation, Inc. @@ -59,7 +59,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.298 2010/06/24 13:03:11 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.299 2010/07/07 01:30:37 chs Exp $"); #include "opt_ktrace.h" #include "opt_modular.h" @@ -766,10 +766,6 @@ execve1(struct lwp *l, const char *path, char * const *args, if (p->p_lwpctl != NULL) lwp_ctl_exit(); - /* This is now LWP 1 */ - l->l_lid = 1; - p->p_nlwpid = 1; - #ifdef KERN_SA /* Release any SA state. */ if (p->p_sa) @@ -1126,6 +1122,14 @@ execve1(struct lwp *l, const char *path, char * const *args, (*p->p_emul->e_proc_exit)(p); /* + * This is now LWP 1. + */ + mutex_enter(p->p_lock); + p->p_nlwpid = 1; + l->l_lid = 1; + mutex_exit(p->p_lock); + + /* * Call exec hook. Emulation code may NOT store reference to anything * from &pack. */ diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index bd794a2b580..60667e71c41 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_exit.c,v 1.229 2010/07/01 02:38:30 rmind Exp $ */ +/* $NetBSD: kern_exit.c,v 1.230 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 1998, 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.229 2010/07/01 02:38:30 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_exit.c,v 1.230 2010/07/07 01:30:37 chs Exp $"); #include "opt_ktrace.h" #include "opt_perfctrs.h" @@ -932,7 +932,7 @@ proc_free(struct proc *p, struct rusage *ru) /* * Let pid be reallocated. */ - proc_free_pid(p); + proc_free_pid(p->p_pid); /* * Unlink process from its process group. diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 70cda4828ff..4d6c99d962e 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_fork.c,v 1.177 2010/06/13 04:13:31 yamt Exp $ */ +/* $NetBSD: kern_fork.c,v 1.178 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 1999, 2001, 2004, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -67,7 +67,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.177 2010/06/13 04:13:31 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_fork.c,v 1.178 2010/07/07 01:30:37 chs Exp $"); #include "opt_ktrace.h" @@ -217,7 +217,6 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, struct lwp *l2; int count; vaddr_t uaddr; - int tmp; int tnprocs; int error = 0; @@ -413,21 +412,10 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, p2->p_stats = pstatscopy(p1->p_stats); /* - * If emulation has process fork hook, call it now. + * Set up the new process address space. */ - if (p2->p_emul->e_proc_fork) - (*p2->p_emul->e_proc_fork)(p2, p1, flags); - - /* - * ...and finally, any other random fork hooks that subsystems - * might have registered. - */ - doforkhooks(p2, p1); - uvm_proc_fork(p1, p2, (flags & FORK_SHAREVM) ? true : false); - SDT_PROBE(proc,,,create, p2, p1, flags, 0, 0); - /* * Finish creating the child process. * It will return through a different path later. @@ -437,6 +425,20 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, l1->l_class); /* + * If emulation has a process fork hook, call it now. + */ + if (p2->p_emul->e_proc_fork) + (*p2->p_emul->e_proc_fork)(p2, l1, flags); + + /* + * ...and finally, any other random fork hooks that subsystems + * might have registered. + */ + doforkhooks(p2, p1); + + SDT_PROBE(proc,,,create, p2, p1, flags, 0, 0); + + /* * It's now safe for the scheduler and other processes to see the * child process. */ @@ -487,7 +489,6 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, * Make child runnable, set start time, and add to run queue except * if the parent requested the child to start in SSTOP state. */ - tmp = (p2->p_userret != NULL ? LW_WUSERRET : 0); mutex_enter(p2->p_lock); /* @@ -509,13 +510,11 @@ fork1(struct lwp *l1, int flags, int exitsig, void *stack, size_t stacksize, p2->p_waited = 0; p1->p_nstopchild++; l2->l_stat = LSSTOP; - l2->l_flag |= tmp; lwp_unlock(l2); } else { p2->p_nrlwps = 1; p2->p_stat = SACTIVE; l2->l_stat = LSRUN; - l2->l_flag |= tmp; sched_enqueue(l2, false); lwp_unlock(l2); } diff --git a/sys/kern/kern_lwp.c b/sys/kern/kern_lwp.c index 6a60daec958..505c65ad4f4 100644 --- a/sys/kern/kern_lwp.c +++ b/sys/kern/kern_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_lwp.c,v 1.150 2010/07/01 02:38:30 rmind Exp $ */ +/* $NetBSD: kern_lwp.c,v 1.151 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 2001, 2006, 2007, 2008, 2009 The NetBSD Foundation, Inc. @@ -209,7 +209,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.150 2010/07/01 02:38:30 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_lwp.c,v 1.151 2010/07/07 01:30:37 chs Exp $"); #include "opt_ddb.h" #include "opt_lockdebug.h" @@ -641,6 +641,7 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, int flags, { struct lwp *l2, *isfree; turnstile_t *ts; + lwpid_t lid; KASSERT(l1 == curlwp || l1->l_proc == &proc0); @@ -727,6 +728,13 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, int flags, uvm_lwp_fork(l1, l2, stack, stacksize, func, (arg != NULL) ? arg : l2); + if ((flags & LWP_PIDLID) != 0) { + lid = proc_alloc_pid(p2); + l2->l_pflag |= LP_PIDLID; + } else { + lid = 0; + } + mutex_enter(p2->p_lock); if ((flags & LWP_DETACHED) != 0) { @@ -739,10 +747,13 @@ lwp_create(lwp_t *l1, proc_t *p2, vaddr_t uaddr, int flags, CIRCLEQ_INIT(&l2->l_sigpend.sp_info); sigemptyset(&l2->l_sigpend.sp_set); - p2->p_nlwpid++; - if (p2->p_nlwpid == 0) + if (lid == 0) { p2->p_nlwpid++; - l2->l_lid = p2->p_nlwpid; + if (p2->p_nlwpid == 0) + p2->p_nlwpid++; + lid = p2->p_nlwpid; + } + l2->l_lid = lid; LIST_INSERT_HEAD(&p2->p_lwps, l2, l_sibling); p2->p_nlwps++; p2->p_nrlwps++; @@ -876,9 +887,13 @@ lwp_exit(struct lwp *l) /* * Remove the LWP from the global list. + * Free its LID from the PID namespace if needed. */ mutex_enter(proc_lock); LIST_REMOVE(l, l_list); + if ((l->l_pflag & LP_PIDLID) != 0 && l->l_lid != p->p_pid) { + proc_free_pid(l->l_lid); + } mutex_exit(proc_lock); /* @@ -904,7 +919,7 @@ lwp_exit(struct lwp *l) /* * If we find a pending signal for the process and we have been - * asked to check for signals, then we loose: arrange to have + * asked to check for signals, then we lose: arrange to have * all other LWPs in the process check for signals. */ if ((l->l_flag & LW_PENDSIG) != 0 && @@ -1162,12 +1177,12 @@ lwp_find2(pid_t pid, lwpid_t lid) } /* - * Look up a live LWP within the speicifed process, and return it locked. + * Look up a live LWP within the specified process, and return it locked. * * Must be called with p->p_lock held. */ struct lwp * -lwp_find(struct proc *p, int id) +lwp_find(struct proc *p, lwpid_t id) { struct lwp *l; @@ -1340,7 +1355,6 @@ void lwp_userret(struct lwp *l) { struct proc *p; - void (*hook)(void); int sig; KASSERT(l == curlwp); @@ -1410,16 +1424,6 @@ lwp_userret(struct lwp *l) KASSERT(0); /* NOTREACHED */ } - - /* Call userret hook; used by Linux emulation. */ - if ((l->l_flag & LW_WUSERRET) != 0) { - lwp_lock(l); - l->l_flag &= ~LW_WUSERRET; - lwp_unlock(l); - hook = p->p_userret; - p->p_userret = NULL; - (*hook)(); - } } #ifdef KERN_SA @@ -1771,6 +1775,21 @@ lwp_pctr(void) return curlwp->l_ncsw; } +/* + * Set an LWP's private data pointer. + */ +int +lwp_setprivate(struct lwp *l, void *ptr) +{ + int error = 0; + + l->l_private = ptr; +#ifdef __HAVE_CPU_LWP_SETPRIVATE + error = cpu_lwp_setprivate(l, ptr); +#endif + return error; +} + #if defined(DDB) void lwp_whatis(uintptr_t addr, void (*pr)(const char *, ...)) diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index 52e048a82ad..0dde0caf2b1 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.167 2010/07/01 02:38:30 rmind Exp $ */ +/* $NetBSD: kern_proc.c,v 1.168 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -62,7 +62,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.167 2010/07/01 02:38:30 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.168 2010/07/07 01:30:37 chs Exp $"); #ifdef _KERNEL_OPT #include "opt_kstack.h" @@ -125,6 +125,7 @@ kmutex_t *proc_lock; struct pid_table { struct proc *pt_proc; struct pgrp *pt_pgrp; + pid_t pt_pid; }; #if 1 /* strongly typed cast - should be a noop */ static inline uint p2u(struct proc *p) { return (uint)(uintptr_t)p; } @@ -313,6 +314,7 @@ procinit(void) for (i = 0; i <= pid_tbl_mask; i++) { pid_table[i].pt_proc = P_FREE(LINK_EMPTY + i + 1); pid_table[i].pt_pgrp = 0; + pid_table[i].pt_pid = 0; } /* slot 0 is just grabbed */ next_free_pt = 1; @@ -511,9 +513,13 @@ p_inferior(struct proc *p, struct proc *q) proc_t * proc_find_raw(pid_t pid) { - proc_t *p = pid_table[pid & pid_tbl_mask].pt_proc; + struct pid_table *pt; + proc_t *p; - if (__predict_false(!P_VALID(p) || p->p_pid != pid)) { + KASSERT(mutex_owned(proc_lock)); + pt = &pid_table[pid & pid_tbl_mask]; + p = pt->pt_proc; + if (__predict_false(!P_VALID(p) || pt->pt_pid != pid)) { return NULL; } return p; @@ -524,12 +530,11 @@ proc_find(pid_t pid) { proc_t *p; - KASSERT(mutex_owned(proc_lock)); - p = proc_find_raw(pid); if (__predict_false(p == NULL)) { return NULL; } + /* * Only allow live processes to be found by PID. * XXX: p_stat might change, since unlocked. @@ -553,6 +558,7 @@ pgrp_find(pid_t pgid) KASSERT(mutex_owned(proc_lock)); pg = pid_table[pgid & pid_tbl_mask].pt_pgrp; + /* * Cannot look up a process group that only exists because the * session has not died yet (traditional). @@ -570,12 +576,14 @@ expand_pid_table(void) struct pid_table *n_pt, *new_pt; struct proc *proc; struct pgrp *pgrp; - pid_t pid; + pid_t pid, rpid; u_int i; + uint new_pt_mask; pt_size = pid_tbl_mask + 1; tsz = pt_size * 2 * sizeof(struct pid_table); new_pt = kmem_alloc(tsz, KM_SLEEP); + new_pt_mask = pt_size * 2 - 1; mutex_enter(proc_lock); if (pt_size != pid_tbl_mask + 1) { @@ -594,7 +602,7 @@ expand_pid_table(void) * We stuff free items on the front of the freelist * because we can't write to unmodified entries. * Processing the table backwards maintains a semblance - * of issueing pid numbers that increase with time. + * of issuing pid numbers that increase with time. */ i = pt_size - 1; n_pt = new_pt + i; @@ -604,21 +612,27 @@ expand_pid_table(void) if (!P_VALID(proc)) { /* Up 'use count' so that link is valid */ pid = (P_NEXT(proc) + pt_size) & ~pt_size; + rpid = 0; proc = P_FREE(pid); if (pgrp) pid = pgrp->pg_id; - } else - pid = proc->p_pid; + } else { + pid = pid_table[i].pt_pid; + rpid = pid; + } /* Save entry in appropriate half of table */ n_pt[pid & pt_size].pt_proc = proc; n_pt[pid & pt_size].pt_pgrp = pgrp; + n_pt[pid & pt_size].pt_pid = rpid; /* Put other piece on start of free list */ pid = (pid ^ pt_size) & ~pid_tbl_mask; n_pt[pid & pt_size].pt_proc = - P_FREE((pid & ~pt_size) | next_free_pt); + P_FREE((pid & ~pt_size) | next_free_pt); n_pt[pid & pt_size].pt_pgrp = 0; + n_pt[pid & pt_size].pt_pid = 0; + next_free_pt = i | (pid & pt_size); if (i == 0) break; @@ -628,7 +642,7 @@ expand_pid_table(void) tsz = pt_size * sizeof(struct pid_table); n_pt = pid_table; pid_table = new_pt; - pid_tbl_mask = pt_size * 2 - 1; + pid_tbl_mask = new_pt_mask; /* * pid_max starts as PID_MAX (= 30000), once we have 16384 @@ -648,15 +662,22 @@ struct proc * proc_alloc(void) { struct proc *p; - int nxt; - pid_t pid; - struct pid_table *pt; p = pool_cache_get(proc_cache, PR_WAITOK); p->p_stat = SIDL; /* protect against others */ - proc_initspecific(p); kdtrace_proc_ctor(NULL, p); + p->p_pid = -1; + proc_alloc_pid(p); + return p; +} + +pid_t +proc_alloc_pid(struct proc *p) +{ + struct pid_table *pt; + pid_t pid; + int nxt; for (;;expand_pid_table()) { if (__predict_false(pid_alloc_cnt >= pid_alloc_lim)) @@ -679,15 +700,20 @@ proc_alloc(void) pid = (nxt & ~pid_tbl_mask) + pid_tbl_mask + 1 + next_free_pt; if ((uint)pid > (uint)pid_max) pid &= pid_tbl_mask; - p->p_pid = pid; next_free_pt = nxt & pid_tbl_mask; /* Grab table slot */ pt->pt_proc = p; + + KASSERT(pt->pt_pid == 0); + pt->pt_pid = pid; + if (p->p_pid == -1) { + p->p_pid = pid; + } pid_alloc_cnt++; mutex_exit(proc_lock); - return p; + return pid; } /* @@ -696,27 +722,25 @@ proc_alloc(void) * Called with the proc_lock held. */ void -proc_free_pid(struct proc *p) +proc_free_pid(pid_t pid) { - pid_t pid = p->p_pid; struct pid_table *pt; KASSERT(mutex_owned(proc_lock)); pt = &pid_table[pid & pid_tbl_mask]; -#ifdef DIAGNOSTIC - if (__predict_false(pt->pt_proc != p)) - panic("proc_free: pid_table mismatch, pid %x, proc %p", - pid, p); -#endif + /* save pid use count in slot */ pt->pt_proc = P_FREE(pid & ~pid_tbl_mask); + KASSERT(pt->pt_pid == pid); + pt->pt_pid = 0; if (pt->pt_pgrp == NULL) { /* link last freed entry onto ours */ pid &= pid_tbl_mask; pt = &pid_table[last_free_pt]; pt->pt_proc = P_FREE(P_NEXT(pt->pt_proc) | pid); + pt->pt_pid = 0; last_free_pt = pid; pid_alloc_cnt--; } @@ -957,6 +981,7 @@ pg_remove(pid_t pg_id) pg_id &= pid_tbl_mask; pt = &pid_table[last_free_pt]; pt->pt_proc = P_FREE(P_NEXT(pt->pt_proc) | pg_id); + KASSERT(pt->pt_pid == 0); last_free_pt = pg_id; pid_alloc_cnt--; } @@ -1101,8 +1126,8 @@ pidtbl_dump(void) continue; db_printf(" id %x: ", id); if (P_VALID(p)) - db_printf("proc %p id %d (0x%x) %s\n", - p, p->p_pid, p->p_pid, p->p_comm); + db_printf("slotpid %d proc %p id %d (0x%x) %s\n", + pt->pt_pid, p, p->p_pid, p->p_pid, p->p_comm); else db_printf("next %x use %x\n", P_NEXT(p) & pid_tbl_mask, @@ -1431,4 +1456,3 @@ proc_uidmatch(kauth_cred_t cred, kauth_cred_t target) return (r); } - diff --git a/sys/kern/sys_lwp.c b/sys/kern/sys_lwp.c index 268e3a748e1..04198049256 100644 --- a/sys/kern/sys_lwp.c +++ b/sys/kern/sys_lwp.c @@ -1,4 +1,4 @@ -/* $NetBSD: sys_lwp.c,v 1.51 2010/06/13 04:13:32 yamt Exp $ */ +/* $NetBSD: sys_lwp.c,v 1.52 2010/07/07 01:30:37 chs Exp $ */ /*- * Copyright (c) 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.51 2010/06/13 04:13:32 yamt Exp $"); +__KERNEL_RCSID(0, "$NetBSD: sys_lwp.c,v 1.52 2010/07/07 01:30:37 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -190,12 +190,7 @@ sys__lwp_setprivate(struct lwp *l, const struct sys__lwp_setprivate_args *uap, syscallarg(void *) ptr; } */ - l->l_private = SCARG(uap, ptr); -#ifdef __HAVE_CPU_LWP_SETPRIVATE - cpu_lwp_setprivate(l, SCARG(uap, ptr)); -#endif - - return 0; + return lwp_setprivate(l, SCARG(uap, ptr)); } int diff --git a/sys/sys/lwp.h b/sys/sys/lwp.h index 8ab43886050..973ec3af9a9 100644 --- a/sys/sys/lwp.h +++ b/sys/sys/lwp.h @@ -1,4 +1,4 @@ -/* $NetBSD: lwp.h,v 1.135 2010/06/13 03:31:28 yamt Exp $ */ +/* $NetBSD: lwp.h,v 1.136 2010/07/07 01:30:38 chs Exp $ */ /*- * Copyright (c) 2001, 2006, 2007, 2008, 2009, 2010 @@ -230,7 +230,6 @@ extern lwp_t lwp0; /* LWP for proc0 */ #define LW_SA_BLOCKING 0x00800000 /* Blocking in tsleep() */ #define LW_PENDSIG 0x01000000 /* Pending signal for us */ #define LW_CANCELLED 0x02000000 /* tsleep should not sleep */ -#define LW_WUSERRET 0x04000000 /* Call proc::p_userret on return to user */ #define LW_WREBOOT 0x08000000 /* System is rebooting, please suspend */ #define LW_UNPARKED 0x10000000 /* Unpark op pending */ #define LW_SA_YIELD 0x40000000 /* LWP on VP is yielding */ @@ -240,6 +239,7 @@ extern lwp_t lwp0; /* LWP for proc0 */ #define LP_KTRACTIVE 0x00000001 /* Executing ktrace operation */ #define LP_KTRCSW 0x00000002 /* ktrace context switch marker */ #define LP_KTRCSWUSER 0x00000004 /* ktrace context switch marker */ +#define LP_PIDLID 0x00000008 /* free LID from PID space on exit */ #define LP_OWEUPC 0x00000010 /* Owe user profiling tick */ #define LP_MPSAFE 0x00000020 /* Starts life without kernel_lock */ #define LP_INTR 0x00000040 /* Soft interrupt handler */ @@ -259,7 +259,7 @@ extern lwp_t lwp0; /* LWP for proc0 */ * user. */ #define LW_USERRET (LW_WEXIT|LW_PENDSIG|LW_WREBOOT|LW_WSUSPEND|LW_WCORE|\ - LW_WUSERRET|LW_SA_BLOCKING|LW_SA_UPCALL) + LW_SA_BLOCKING|LW_SA_UPCALL) /* * Status values. @@ -326,6 +326,7 @@ void lwp_free(lwp_t *, bool, bool); void lwp_sys_init(void); void lwp_unsleep(lwp_t *, bool); uint64_t lwp_pctr(void); +int lwp_setprivate(lwp_t *, void *); void lwpinit_specificdata(void); int lwp_specific_key_create(specificdata_key_t *, specificdata_dtor_t); @@ -498,6 +499,9 @@ KPREEMPT_ENABLE(lwp_t *l) /* Flags for _lwp_create(), as per Solaris. */ #define LWP_DETACHED 0x00000040 #define LWP_SUSPENDED 0x00000080 + +/* Kernel-internal flags for LWP creation. */ +#define LWP_PIDLID 0x40000000 #define LWP_VFORK 0x80000000 #endif /* !_SYS_LWP_H_ */ diff --git a/sys/sys/proc.h b/sys/sys/proc.h index 8d6a47277b5..4639d2b2264 100644 --- a/sys/sys/proc.h +++ b/sys/sys/proc.h @@ -1,4 +1,4 @@ -/* $NetBSD: proc.h,v 1.297 2010/07/01 02:38:31 rmind Exp $ */ +/* $NetBSD: proc.h,v 1.298 2010/07/07 01:30:38 chs Exp $ */ /*- * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc. @@ -153,7 +153,7 @@ struct emul { /* Per-process hooks */ void (*e_proc_exec)(struct proc *, struct exec_package *); - void (*e_proc_fork)(struct proc *, struct proc *, int); + void (*e_proc_fork)(struct proc *, struct lwp *, int); void (*e_proc_exit)(struct proc *); void (*e_lwp_fork)(struct lwp *, struct lwp *); void (*e_lwp_exit)(struct lwp *); @@ -281,14 +281,12 @@ struct proc { void *p_tracep; /* k: Trace private data */ struct vnode *p_textvp; /* :: Vnode of executable */ - void (*p_userret)(void);/* p: return-to-user hook */ struct emul *p_emul; /* :: emulation information */ void *p_emuldata; /* :: per-proc emul data, or NULL */ const struct execsw *p_execsw; /* :: exec package information */ struct klist p_klist; /* p: knotes attached to proc */ LIST_HEAD(, lwp) p_sigwaiters; /* p: LWPs waiting for signals */ - sigstore_t p_sigstore; /* p: process-wide signal state */ sigpend_t p_sigpend; /* p: pending signals */ struct lcproc *p_lwpctl; /* p, a: _lwp_ctl() information */ pid_t p_ppid; /* :: cached parent pid */ @@ -480,7 +478,8 @@ void exit1(struct lwp *, int) __dead; int do_sys_wait(int *, int *, int, struct rusage *); struct proc *proc_alloc(void); void proc0_init(void); -void proc_free_pid(struct proc *); +pid_t proc_alloc_pid(struct proc *); +void proc_free_pid(pid_t); void proc_free_mem(struct proc *); void exit_lwps(struct lwp *l); int fork1(struct lwp *, int, int, void *, size_t, |
