summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorchs <chs@NetBSD.org>2010-07-07 01:30:32 +0000
committerchs <chs@NetBSD.org>2010-07-07 01:30:32 +0000
commit33fa5ccbbf17bc2390e2d136c34926c6f93ac5d1 (patch)
treec52fdcf81396fba59fce0a9c410d0dcc8c104091 /sys
parent56acc98394a822ba38a843f6385171e0b1aa5e9a (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')
-rw-r--r--sys/arch/x86/x86/linux_trap.c57
-rw-r--r--sys/compat/aoutm68k/aoutm68k_exec.c58
-rw-r--r--sys/compat/darwin/darwin_exec.c91
-rw-r--r--sys/compat/freebsd/freebsd_exec.c65
-rw-r--r--sys/compat/ibcs2/ibcs2_exec.c65
-rw-r--r--sys/compat/irix/irix_exec.c75
-rw-r--r--sys/compat/linux/arch/alpha/files.linux_alpha3
-rw-r--r--sys/compat/linux/arch/alpha/linux_machdep.c6
-rw-r--r--sys/compat/linux/arch/alpha/syscalls.master84
-rw-r--r--sys/compat/linux/arch/amd64/linux_exec_machdep.c20
-rw-r--r--sys/compat/linux/arch/amd64/linux_machdep.c81
-rw-r--r--sys/compat/linux/arch/amd64/linux_machdep.h5
-rw-r--r--sys/compat/linux/arch/amd64/syscalls.master28
-rw-r--r--sys/compat/linux/arch/arm/linux_commons.c5
-rw-r--r--sys/compat/linux/arch/arm/linux_machdep.c6
-rw-r--r--sys/compat/linux/arch/arm/linux_ptrace.c22
-rw-r--r--sys/compat/linux/arch/arm/linux_sys_machdep.c14
-rw-r--r--sys/compat/linux/arch/arm/syscalls.master219
-rw-r--r--sys/compat/linux/arch/i386/linux_exec_machdep.c182
-rw-r--r--sys/compat/linux/arch/i386/linux_machdep.c36
-rw-r--r--sys/compat/linux/arch/i386/linux_machdep.h89
-rw-r--r--sys/compat/linux/arch/i386/linux_ptrace.c53
-rw-r--r--sys/compat/linux/arch/i386/syscalls.master68
-rw-r--r--sys/compat/linux/arch/m68k/files.linux_m68k3
-rw-r--r--sys/compat/linux/arch/m68k/linux_machdep.c6
-rw-r--r--sys/compat/linux/arch/m68k/syscalls.master100
-rw-r--r--sys/compat/linux/arch/mips/files.linux_mips3
-rw-r--r--sys/compat/linux/arch/mips/linux_machdep.c26
-rw-r--r--sys/compat/linux/arch/mips/syscalls.master89
-rw-r--r--sys/compat/linux/arch/powerpc/files.linux_powerpc3
-rw-r--r--sys/compat/linux/arch/powerpc/linux_exec_powerpc.c10
-rw-r--r--sys/compat/linux/arch/powerpc/linux_machdep.c58
-rw-r--r--sys/compat/linux/arch/powerpc/syscalls.master85
-rw-r--r--sys/compat/linux/common/linux_emuldata.h45
-rw-r--r--sys/compat/linux/common/linux_exec.c334
-rw-r--r--sys/compat/linux/common/linux_exec.h15
-rw-r--r--sys/compat/linux/common/linux_futex.c410
-rw-r--r--sys/compat/linux/common/linux_futex.h7
-rw-r--r--sys/compat/linux/common/linux_machdep.h12
-rw-r--r--sys/compat/linux/common/linux_misc.c27
-rw-r--r--sys/compat/linux/common/linux_misc_notalpha.c8
-rw-r--r--sys/compat/linux/common/linux_sched.c331
-rw-r--r--sys/compat/linux/common/linux_signal.c35
-rw-r--r--sys/compat/linux/common/linux_sysctl.c13
-rw-r--r--sys/compat/linux32/arch/amd64/linux32_exec.h13
-rw-r--r--sys/compat/linux32/arch/amd64/linux32_machdep.c134
-rw-r--r--sys/compat/linux32/arch/amd64/linux32_types.h12
-rw-r--r--sys/compat/linux32/arch/amd64/syscalls.master93
-rw-r--r--sys/compat/linux32/common/linux32_exec.c219
-rw-r--r--sys/compat/linux32/common/linux32_exec.h7
-rw-r--r--sys/compat/linux32/common/linux32_exec_elf32.c172
-rw-r--r--sys/compat/linux32/common/linux32_machdep.h8
-rw-r--r--sys/compat/linux32/common/linux32_misc.c79
-rw-r--r--sys/compat/linux32/common/linux32_mod.c8
-rw-r--r--sys/compat/linux32/common/linux32_sched.c127
-rw-r--r--sys/compat/linux32/common/linux32_sysctl.c8
-rw-r--r--sys/compat/linux32/common/linux32_time.c14
-rw-r--r--sys/compat/linux32/common/linux32_types.h10
-rw-r--r--sys/compat/mach/mach_exec.c92
-rw-r--r--sys/compat/mach/mach_exec.h8
-rw-r--r--sys/compat/osf1/osf1_exec.c61
-rw-r--r--sys/compat/pecoff/pecoff_emul.c69
-rw-r--r--sys/compat/sunos/sunos_exec.c61
-rw-r--r--sys/compat/sunos32/sunos32_exec.c65
-rw-r--r--sys/compat/svr4/svr4_exec.c66
-rw-r--r--sys/compat/svr4_32/svr4_32_exec.c66
-rw-r--r--sys/compat/ultrix/ultrix_misc.c69
-rw-r--r--sys/kern/kern_exec.c16
-rw-r--r--sys/kern/kern_exit.c6
-rw-r--r--sys/kern/kern_fork.c35
-rw-r--r--sys/kern/kern_lwp.c57
-rw-r--r--sys/kern/kern_proc.c80
-rw-r--r--sys/kern/sys_lwp.c11
-rw-r--r--sys/sys/lwp.h10
-rw-r--r--sys/sys/proc.h9
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),
+ &lts, sizeof(lts))) != 0) {
+ return error;
+ }
+ linux_to_native_timespec(&ts, &lts);
+ }
+ 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),
+ &lts, sizeof(lts))) != 0) {
+ return error;
+ }
+ linux32_to_native_timespec(&ts, &lts);
+ }
+ 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,