summaryrefslogtreecommitdiff
path: root/sys/compat/linux
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/compat/linux
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/compat/linux')
-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
38 files changed, 1196 insertions, 1345 deletions
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|