diff options
| author | chs <chs@NetBSD.org> | 2010-07-07 01:30:32 +0000 |
|---|---|---|
| committer | chs <chs@NetBSD.org> | 2010-07-07 01:30:32 +0000 |
| commit | 33fa5ccbbf17bc2390e2d136c34926c6f93ac5d1 (patch) | |
| tree | c52fdcf81396fba59fce0a9c410d0dcc8c104091 /sys/compat/linux | |
| parent | 56acc98394a822ba38a843f6385171e0b1aa5e9a (diff) | |
many changes for COMPAT_LINUX:
- update the linux syscall table for each platform.
- support new-style (NPTL) linux pthreads on all platforms.
clone() with CLONE_THREAD uses 1 process with many LWPs
instead of separate processes.
- move the contents of sys__lwp_setprivate() into a new
lwp_setprivate() and use that everywhere.
- update linux_release[] and linux32_release[] to "2.6.18".
- adjust placement of emul fork/exec/exit hooks as needed
and adjust other emul code to match.
- convert all struct emul definitions to use named initializers.
- change the pid allocator to allow multiple pids to refer to the same proc.
- remove a few fields from struct proc that are no longer needed.
- disable the non-functional "vdso" code in linux32/amd64,
glibc works fine without it.
- fix a race in the futex code where we could miss a wakeup after
a requeue operation.
- redo futex locking to be a little more efficient.
Diffstat (limited to 'sys/compat/linux')
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), + <s, sizeof(lts))) != 0) { + return error; + } + linux_to_native_timespec(&ts, <s); + } + return linux_do_futex(l, uap, retval, &ts); +} + +int +linux_do_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_t *retval, struct timespec *ts) +{ + /* { + syscallarg(int *) uaddr; + syscallarg(int) op; + syscallarg(int) val; + syscallarg(const struct linux_timespec *) timeout; + syscallarg(int *) uaddr2; + syscallarg(int) val3; + } */ int val; int ret; - struct linux_timespec timeout = { 0, 0 }; int error = 0; struct futex *f; struct futex *newf; int timeout_hz; - struct timespec ts; struct futex *f2; + struct waiting_proc *wp; int op_ret; RUN_ONCE(&futex_once, futex_init); @@ -154,26 +182,17 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return EWOULDBLOCK; } - if (SCARG(uap, timeout) != NULL) { - if ((error = copyin(SCARG(uap, timeout), - &timeout, sizeof(timeout))) != 0) { - FUTEX_SYSTEM_UNLOCK; - return error; - } - } - FUTEXPRINTF(("FUTEX_WAIT %d.%d: val = %d, uaddr = %p, " "*uaddr = %d, timeout = %lld.%09ld\n", l->l_proc->p_pid, l->l_lid, SCARG(uap, val), - SCARG(uap, uaddr), val, (long long)timeout.tv_sec, - timeout.tv_nsec)); + SCARG(uap, uaddr), val, (long long)ts->tv_sec, + ts->tv_nsec)); - linux_to_native_timespec(&ts, &timeout); - if ((error = itimespecfix(&ts)) != 0) { + if ((error = itimespecfix(ts)) != 0) { FUTEX_SYSTEM_UNLOCK; return error; } - timeout_hz = tstohz(&ts); + timeout_hz = tstohz(ts); /* * If the user process requests a non null timeout, @@ -186,9 +205,13 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ if (SCARG(uap, timeout) != NULL && timeout_hz == 0) timeout_hz = 1; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - ret = futex_sleep(f, l, timeout_hz); + wp = futex_wp_alloc(); + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + ret = futex_sleep(&f, l, timeout_hz, wp); futex_put(f); + FUTEX_UNLOCK; + futex_wp_free(wp); FUTEXPRINTF(("FUTEX_WAIT %d.%d: uaddr = %p, " "ret = %d\n", l->l_proc->p_pid, l->l_lid, @@ -216,7 +239,6 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ break; case LINUX_FUTEX_WAKE: - FUTEX_SYSTEM_LOCK; /* * XXX: Linux is able cope with different addresses * corresponding to the same mapped memory in the sleeping @@ -226,10 +248,12 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ l->l_proc->p_pid, l->l_lid, SCARG(uap, uaddr), SCARG(uap, val))); - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); + FUTEX_SYSTEM_LOCK; + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); *retval = futex_wake(f, SCARG(uap, val), NULL, 0); futex_put(f); - + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -248,12 +272,20 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return EAGAIN; } - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - newf = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + FUTEXPRINTF(("FUTEX_CMP_REQUEUE %d.%d: uaddr = %p, val = %d, " + "uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, val), SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); futex_put(newf); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -261,12 +293,20 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ case LINUX_FUTEX_REQUEUE: FUTEX_SYSTEM_LOCK; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - newf = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + FUTEXPRINTF(("FUTEX_REQUEUE %d.%d: uaddr = %p, val = %d, " + "uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, val), SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + newf = futex_get(SCARG(uap, uaddr2)); *retval = futex_wake(f, SCARG(uap, val), newf, (int)(unsigned long)SCARG(uap, timeout)); futex_put(f); futex_put(newf); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; break; @@ -277,25 +317,31 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return ENOSYS; case LINUX_FUTEX_WAKE_OP: FUTEX_SYSTEM_LOCK; - f = futex_get(SCARG(uap, uaddr), FUTEX_UNLOCKED); - f2 = futex_get(SCARG(uap, uaddr2), FUTEX_UNLOCKED); + + FUTEXPRINTF(("FUTEX_WAKE_OP %d.%d: uaddr = %p, op = %d, " + "val = %d, uaddr2 = %p, val2 = %d\n", + l->l_proc->p_pid, l->l_lid, + SCARG(uap, uaddr), SCARG(uap, op), SCARG(uap, val), + SCARG(uap, uaddr2), + (int)(unsigned long)SCARG(uap, timeout))); + + FUTEX_LOCK; + f = futex_get(SCARG(uap, uaddr)); + f2 = futex_get(SCARG(uap, uaddr2)); + FUTEX_UNLOCK; + /* * This function returns positive number as results and * negative as errors */ op_ret = futex_atomic_op(l, SCARG(uap, val3), SCARG(uap, uaddr2)); + FUTEX_LOCK; if (op_ret < 0) { - /* XXX: We don't handle EFAULT yet */ - if (op_ret != -EFAULT) { - futex_put(f); - futex_put(f2); - FUTEX_SYSTEM_UNLOCK; - return -op_ret; - } futex_put(f); futex_put(f2); + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; - return EFAULT; + return -op_ret; } ret = futex_wake(f, SCARG(uap, val), NULL, 0); @@ -311,8 +357,9 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ ret += op_ret; } futex_put(f2); - *retval = ret; + FUTEX_UNLOCK; FUTEX_SYSTEM_UNLOCK; + *retval = ret; break; default: FUTEXPRINTF(("linux_sys_futex: unknown op %d\n", @@ -322,19 +369,34 @@ linux_sys_futex(struct lwp *l, const struct linux_sys_futex_args *uap, register_ return 0; } +static struct waiting_proc * +futex_wp_alloc(void) +{ + struct waiting_proc *wp; + + wp = kmem_zalloc(sizeof(*wp), KM_SLEEP); + cv_init(&wp->wp_futex_cv, "futex"); + return wp; +} + +static void +futex_wp_free(struct waiting_proc *wp) +{ + + cv_destroy(&wp->wp_futex_cv); + kmem_free(wp, sizeof(*wp)); +} + static struct futex * -futex_get(void *uaddr, int locked) +futex_get(void *uaddr) { struct futex *f; - if (locked == FUTEX_UNLOCKED) - FUTEX_LOCK; + FUTEX_LOCKASSERT; LIST_FOREACH(f, &futex_list, f_list) { if (f->f_uaddr == uaddr) { f->f_refcount++; - if (locked == FUTEX_UNLOCKED) - FUTEX_UNLOCK; return f; } } @@ -344,85 +406,140 @@ futex_get(void *uaddr, int locked) f->f_uaddr = uaddr; f->f_refcount = 1; TAILQ_INIT(&f->f_waiting_proc); + TAILQ_INIT(&f->f_requeue_proc); LIST_INSERT_HEAD(&futex_list, f, f_list); - if (locked == FUTEX_UNLOCKED) - FUTEX_UNLOCK; return f; } +static void +futex_ref(struct futex *f) +{ + + FUTEX_LOCKASSERT; + + f->f_refcount++; +} + static void futex_put(struct futex *f) { - FUTEX_LOCK; + FUTEX_LOCKASSERT; + f->f_refcount--; if (f->f_refcount == 0) { KASSERT(TAILQ_EMPTY(&f->f_waiting_proc)); + KASSERT(TAILQ_EMPTY(&f->f_requeue_proc)); LIST_REMOVE(f, f_list); kmem_free(f, sizeof(*f)); } - FUTEX_UNLOCK; - - return; } static int -futex_sleep(struct futex *f, lwp_t *l, unsigned long timeout) +futex_sleep(struct futex **fp, lwp_t *l, int timeout, struct waiting_proc *wp) { - struct waiting_proc *wp; + struct futex *f, *newf; int ret; - wp = kmem_zalloc(sizeof(*wp), KM_SLEEP); + FUTEX_LOCKASSERT; + + f = *fp; wp->wp_l = l; wp->wp_new_futex = NULL; - cv_init(&wp->wp_futex_cv, "futex"); - FUTEX_LOCK; +requeue: TAILQ_INSERT_TAIL(&f->f_waiting_proc, wp, wp_list); ret = cv_timedwait_sig(&wp->wp_futex_cv, &futex_lock, timeout); TAILQ_REMOVE(&f->f_waiting_proc, wp, wp_list); - FUTEX_UNLOCK; - - /* if we got woken up in futex_wake */ - if ((ret == 0) && (wp->wp_new_futex != NULL)) { - /* suspend us on the new futex */ - ret = futex_sleep(wp->wp_new_futex, l, timeout); - /* and release the old one */ - futex_put(wp->wp_new_futex); - } - cv_destroy(&wp->wp_futex_cv); - kmem_free(wp, sizeof(*wp)); + /* if futex_wake() tells us to requeue ... */ + newf = wp->wp_new_futex; + if (ret == 0 && newf != NULL) { + /* ... requeue ourselves on the new futex */ + futex_put(f); + wp->wp_new_futex = NULL; + TAILQ_REMOVE(&newf->f_requeue_proc, wp, wp_rqlist); + *fp = f = newf; + goto requeue; + } return ret; } static int futex_wake(struct futex *f, int n, struct futex *newf, int n2) { - struct waiting_proc *wp; + struct waiting_proc *wp, *wpnext; int count; + FUTEX_LOCKASSERT; + count = newf ? 0 : 1; - FUTEX_LOCK; + /* + * first, wake up any threads sleeping on this futex. + * note that sleeping threads are not in the process of requeueing. + */ + TAILQ_FOREACH(wp, &f->f_waiting_proc, wp_list) { + KASSERT(wp->wp_new_futex == NULL); + + FUTEXPRINTF(("futex_wake: signal f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); + cv_signal(&wp->wp_futex_cv); if (count <= n) { - cv_signal(&wp->wp_futex_cv); count++; } else { if (newf == NULL) - continue; - /* futex_put called after tsleep */ - wp->wp_new_futex = futex_get(newf->f_uaddr, - FUTEX_LOCKED); - cv_signal(&wp->wp_futex_cv); + break; + + /* matching futex_put() is called by the other thread. */ + futex_ref(newf); + wp->wp_new_futex = newf; + TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); + FUTEXPRINTF(("futex_wake: requeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); + if (count - n >= n2) + goto out; + } + } + + /* + * next, deal with threads that are requeuing to this futex. + * we don't need to signal these threads, any thread on the + * requeue list has already been signaled but hasn't had a chance + * to run and requeue itself yet. if we would normally wake + * a thread, just remove the requeue info. if we would normally + * requeue a thread, change the requeue target. + */ + + TAILQ_FOREACH_SAFE(wp, &f->f_requeue_proc, wp_rqlist, wpnext) { + KASSERT(wp->wp_new_futex == f); + + FUTEXPRINTF(("futex_wake: unrequeue f %p l %p ref %d\n", + f, wp->wp_l, f->f_refcount)); + wp->wp_new_futex = NULL; + TAILQ_REMOVE(&f->f_requeue_proc, wp, wp_rqlist); + futex_put(f); + + if (count <= n) { + count++; + } else { + if (newf == NULL) + break; + + /* matching futex_put() is called by the other thread. */ + futex_ref(newf); + wp->wp_new_futex = newf; + TAILQ_INSERT_TAIL(&newf->f_requeue_proc, wp, wp_rqlist); + FUTEXPRINTF(("futex_wake: rerequeue newf %p l %p ref %d\n", + newf, wp->wp_l, newf->f_refcount)); if (count - n >= n2) break; } } - FUTEX_UNLOCK; +out: return count; } @@ -498,12 +615,16 @@ int linux_sys_set_robust_list(struct lwp *l, const struct linux_sys_set_robust_list_args *uap, register_t *retval) { - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; + /* { + syscallarg(struct linux_robust_list_head *) head; + syscallarg(size_t) len; + } */ + struct linux_emuldata *led; - if (SCARG(uap, len) != sizeof(*(led->robust_futexes))) + if (SCARG(uap, len) != sizeof(struct linux_robust_list_head)) return EINVAL; - led->robust_futexes = SCARG(uap, head); + led = l->l_emuldata; + led->led_robust_head = SCARG(uap, head); *retval = 0; return 0; } @@ -512,33 +633,51 @@ int linux_sys_get_robust_list(struct lwp *l, const struct linux_sys_get_robust_list_args *uap, register_t *retval) { + /* { + syscallarg(int) pid; + syscallarg(struct linux_robust_list_head **) head; + syscallarg(size_t *) len; + } */ + struct proc *p; struct linux_emuldata *led; - struct linux_robust_list_head **head; - size_t len = sizeof(*led->robust_futexes); + struct linux_robust_list_head *head; + size_t len; int error = 0; + p = l->l_proc; if (!SCARG(uap, pid)) { - led = l->l_proc->p_emuldata; - head = &led->robust_futexes; + led = l->l_emuldata; + head = led->led_robust_head; } else { - struct proc *p; - - mutex_enter(proc_lock); - p = proc_find(SCARG(uap, pid)); - if (p == NULL || p->p_emul != &emul_linux) { - mutex_exit(proc_lock); + mutex_enter(p->p_lock); + l = lwp_find(p, SCARG(uap, pid)); + if (l != NULL) { + led = l->l_emuldata; + head = led->led_robust_head; + } + mutex_exit(p->p_lock); + if (l == NULL) { return ESRCH; } - led = p->p_emuldata; - head = &led->robust_futexes; - mutex_exit(proc_lock); } +#ifdef __arch64__ + if (p->p_flag & PK_32) { + uint32_t u32; + + u32 = 12; + error = copyout(&u32, SCARG(uap, len), sizeof(u32)); + if (error) + return error; + u32 = (uint32_t)(uintptr_t)head; + return copyout(&u32, SCARG(uap, head), sizeof(u32)); + } +#endif - /* FIXME unlocked */ + len = sizeof(*head); error = copyout(&len, SCARG(uap, len), sizeof(len)); if (error) return error; - return copyout(head, SCARG(uap, head), sizeof(*head)); + return copyout(&head, SCARG(uap, head), sizeof(head)); } static int @@ -548,7 +687,7 @@ handle_futex_death(void *uaddr, pid_t pid, int pi) struct futex *f; retry: - if (copyin(uaddr, &uval, 4)) + if (copyin(uaddr, &uval, sizeof(uval))) return EFAULT; if ((uval & FUTEX_TID_MASK) == pid) { @@ -562,8 +701,10 @@ retry: goto retry; if (!pi && (uval & FUTEX_WAITERS)) { - f = futex_get(uaddr, FUTEX_UNLOCKED); + FUTEX_LOCK; + f = futex_get(uaddr); futex_wake(f, 1, NULL, 0); + FUTEX_UNLOCK; } } @@ -571,12 +712,23 @@ retry: } static int -fetch_robust_entry(struct linux_robust_list **entry, +fetch_robust_entry(struct lwp *l, struct linux_robust_list **entry, struct linux_robust_list **head, int *pi) { + struct linux_emuldata *led; unsigned long uentry; - if (copyin((const void *)head, &uentry, sizeof(unsigned long))) + led = l->l_emuldata; +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32; + + if (copyin(head, &u32, sizeof(u32))) + return EFAULT; + uentry = (unsigned long)u32; + } else +#endif + if (copyin(head, &uentry, sizeof(uentry))) return EFAULT; *entry = (void *)(uentry & ~1UL); @@ -587,7 +739,7 @@ fetch_robust_entry(struct linux_robust_list **entry, /* This walks the list of robust futexes, releasing them. */ void -release_futexes(struct proc *p) +release_futexes(struct lwp *l) { struct linux_robust_list_head head; struct linux_robust_list *entry, *next_entry = NULL, *pending; @@ -596,28 +748,50 @@ release_futexes(struct proc *p) unsigned long futex_offset; int rc; - led = p->p_emuldata; - if (led->robust_futexes == NULL) + led = l->l_emuldata; + if (led->led_robust_head == NULL) return; - if (copyin(led->robust_futexes, &head, sizeof(head))) +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32s[3]; + + if (copyin(led->led_robust_head, u32s, sizeof(u32s))) + return; + + head.list.next = (void *)(uintptr_t)u32s[0]; + head.futex_offset = (unsigned long)u32s[1]; + head.pending_list = (void *)(uintptr_t)u32s[2]; + } else +#endif + if (copyin(led->led_robust_head, &head, sizeof(head))) return; - if (fetch_robust_entry(&entry, &head.list.next, &pi)) + if (fetch_robust_entry(l, &entry, &head.list.next, &pi)) return; +#ifdef __arch64__ + if (l->l_proc->p_flag & PK_32) { + uint32_t u32; + + if (copyin(led->led_robust_head, &u32, sizeof(u32))) + return; + + head.futex_offset = (unsigned long)u32; + } else +#endif if (copyin(&head.futex_offset, &futex_offset, sizeof(unsigned long))) return; - if (fetch_robust_entry(&pending, &head.pending_list, &pip)) + if (fetch_robust_entry(l, &pending, &head.pending_list, &pip)) return; while (entry != &head.list) { - rc = fetch_robust_entry(&next_entry, &entry->next, &next_pi); + rc = fetch_robust_entry(l, &next_entry, &entry->next, &next_pi); if (entry != pending) if (handle_futex_death((char *)entry + futex_offset, - p->p_pid, pi)) + l->l_lid, pi)) return; if (rc) @@ -634,5 +808,5 @@ release_futexes(struct proc *p) if (pending) handle_futex_death((char *)pending + futex_offset, - p->p_pid, pip); + l->l_lid, pip); } diff --git a/sys/compat/linux/common/linux_futex.h b/sys/compat/linux/common/linux_futex.h index f6ef35143b2..2793a319448 100644 --- a/sys/compat/linux/common/linux_futex.h +++ b/sys/compat/linux/common/linux_futex.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_futex.h,v 1.3 2008/10/26 16:38:22 christos Exp $ */ +/* $NetBSD: linux_futex.h,v 1.4 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2005 Emmanuel Dreyfus, all rights reserved. @@ -72,6 +72,9 @@ struct linux_robust_list_head { #define FUTEX_OWNER_DIED 0x40000000 #define FUTEX_TID_MASK 0x3fffffff -void release_futexes(struct proc *); +void release_futexes(struct lwp *); +struct linux_sys_futex_args; +int linux_do_futex(struct lwp *, const struct linux_sys_futex_args *, + register_t *, struct timespec *); #endif /* !_LINUX_FUTEX_H */ diff --git a/sys/compat/linux/common/linux_machdep.h b/sys/compat/linux/common/linux_machdep.h index b066dcd5623..256da95873e 100644 --- a/sys/compat/linux/common/linux_machdep.h +++ b/sys/compat/linux/common/linux_machdep.h @@ -1,4 +1,4 @@ -/* $NetBSD: linux_machdep.h,v 1.18 2008/04/28 20:23:43 martin Exp $ */ +/* $NetBSD: linux_machdep.h,v 1.19 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -54,17 +54,15 @@ #define LINUX_UNAME_ARCH machine #endif +#ifndef LINUX_LWP_SETPRIVATE +#define LINUX_LWP_SETPRIVATE lwp_setprivate +#endif + #ifdef _KERNEL __BEGIN_DECLS void linux_sendsig(const ksiginfo_t *, const sigset_t *); dev_t linux_fakedev(dev_t, int); __END_DECLS -#ifdef LINUX_NPTL -__BEGIN_DECLS -void *linux_get_newtls(struct lwp *); -int linux_set_newtls(struct lwp *, void *); -__END_DECLS -#endif /* !LINUX_NPTL */ #endif /* !_KERNEL */ #endif /* !_LINUX_MACHDEP_H */ diff --git a/sys/compat/linux/common/linux_misc.c b/sys/compat/linux/common/linux_misc.c index d342c1d6f7e..9191c1692cb 100644 --- a/sys/compat/linux/common/linux_misc.c +++ b/sys/compat/linux/common/linux_misc.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp $ */ +/* $NetBSD: linux_misc.c,v 1.216 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 1999, 2008 The NetBSD Foundation, Inc. @@ -57,7 +57,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.216 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -107,8 +107,6 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> -#include <compat/linux/linux_syscallargs.h> - #include <compat/linux/common/linux_fcntl.h> #include <compat/linux/common/linux_mmap.h> #include <compat/linux/common/linux_dirent.h> @@ -122,6 +120,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc.c,v 1.215 2010/06/24 13:03:07 hannken Exp #include <compat/linux/common/linux_reboot.h> #include <compat/linux/common/linux_emuldata.h> +#include <compat/linux/linux_syscallargs.h> + #ifndef COMPAT_LINUX32 const int linux_ptrace_request_map[] = { LINUX_PTRACE_TRACEME, PT_TRACE_ME, @@ -270,8 +270,7 @@ linux_sys_wait4(struct lwp *l, const struct linux_sys_wait4_args *uap, register_ } /* - * Linux brk(2). The check if the new address is >= the old one is - * done in the kernel in Linux. NetBSD does it in the library. + * Linux brk(2). Like native, but always return the new break value. */ int linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *retval) @@ -280,20 +279,13 @@ linux_sys_brk(struct lwp *l, const struct linux_sys_brk_args *uap, register_t *r syscallarg(char *) nsize; } */ struct proc *p = l->l_proc; - char *nbrk = SCARG(uap, nsize); - struct sys_obreak_args oba; struct vmspace *vm = p->p_vmspace; - struct linux_emuldata *ed = (struct linux_emuldata*)p->p_emuldata; - - SCARG(&oba, nsize) = nbrk; - - if ((void *) nbrk > vm->vm_daddr && sys_obreak(l, &oba, retval) == 0) - ed->s->p_break = (char*)nbrk; - else - nbrk = ed->s->p_break; + struct sys_obreak_args oba; - retval[0] = (register_t)nbrk; + SCARG(&oba, nsize) = SCARG(uap, nsize); + (void) sys_obreak(l, &oba, retval); + retval[0] = (register_t)((char *)vm->vm_daddr + ptoa(vm->vm_dsize)); return 0; } @@ -1333,5 +1325,4 @@ linux_sys_getpriority(struct lwp *l, const struct linux_sys_getpriority_args *ua return 0; } - #endif /* !COMPAT_LINUX32 */ diff --git a/sys/compat/linux/common/linux_misc_notalpha.c b/sys/compat/linux/common/linux_misc_notalpha.c index 5291a1722be..fa3b25fc8c5 100644 --- a/sys/compat/linux/common/linux_misc_notalpha.c +++ b/sys/compat/linux/common/linux_misc_notalpha.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 njoly Exp $ */ +/* $NetBSD: linux_misc_notalpha.c,v 1.107 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998, 2008 The NetBSD Foundation, Inc. @@ -31,7 +31,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.107 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -79,7 +79,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_misc_notalpha.c,v 1.106 2009/06/02 13:00:23 nj #endif #ifndef COMPAT_LINUX32 -#if !defined(__m68k__) && !defined(__amd64__) +#if !defined(__amd64__) static void bsd_to_linux_statfs64(const struct statvfs *, struct linux_statfs64 *); #endif @@ -403,7 +403,7 @@ linux_sys_stime(struct lwp *l, const struct linux_sys_stime_args *uap, register_ } #endif /* !amd64 */ -#if !defined(__m68k__) && !defined(__amd64__) +#if !defined(__amd64__) /* * Convert NetBSD statvfs structure to Linux statfs64 structure. * See comments in bsd_to_linux_statfs() for further background. diff --git a/sys/compat/linux/common/linux_sched.c b/sys/compat/linux/common/linux_sched.c index 630f7fb67b9..fc3a96e148e 100644 --- a/sys/compat/linux/common/linux_sched.c +++ b/sys/compat/linux/common/linux_sched.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $ */ +/* $NetBSD: linux_sched.c,v 1.63 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1999 The NetBSD Foundation, Inc. @@ -35,7 +35,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.63 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/mount.h> @@ -47,39 +47,54 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sched.c,v 1.62 2010/07/01 02:38:29 rmind Exp $ #include <sys/wait.h> #include <sys/kauth.h> #include <sys/ptrace.h> -#include <sys/types.h> +#include <sys/atomic.h> #include <sys/cpu.h> #include <compat/linux/common/linux_types.h> #include <compat/linux/common/linux_signal.h> -#include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ #include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_ipc.h> #include <compat/linux/common/linux_sem.h> #include <compat/linux/common/linux_exec.h> +#include <compat/linux/common/linux_machdep.h> #include <compat/linux/linux_syscallargs.h> #include <compat/linux/common/linux_sched.h> +static int linux_clone_nptl(struct lwp *, const struct linux_sys_clone_args *, register_t *); + +static void +linux_child_return(void *arg) +{ + struct lwp *l = arg; + struct proc *p = l->l_proc; + struct linux_emuldata *led = l->l_emuldata; + void *ctp = led->led_child_tidptr; + + if (ctp) { + if (copyout(&p->p_pid, ctp, sizeof(p->p_pid)) != 0) + printf("%s: LINUX_CLONE_CHILD_SETTID " + "failed (child_tidptr = %p, tid = %d)\n", + __func__, ctp, p->p_pid); + } + child_return(arg); +} + int linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_t *retval) { /* { syscallarg(int) flags; syscallarg(void *) stack; -#ifdef LINUX_NPTL syscallarg(void *) parent_tidptr; + syscallarg(void *) tls; syscallarg(void *) child_tidptr; -#endif } */ - int flags, sig; - int error; struct proc *p; -#ifdef LINUX_NPTL struct linux_emuldata *led; -#endif + int flags, sig, error; /* * We don't support the Linux CLONE_PID or CLONE_PTRACE flags. @@ -98,8 +113,14 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ && (SCARG(uap, flags) & LINUX_CLONE_VM) == 0) return (EINVAL); - flags = 0; + /* + * The thread group flavor is implemented totally differently. + */ + if (SCARG(uap, flags) & LINUX_CLONE_THREAD) { + return linux_clone_nptl(l, uap, retval); + } + flags = 0; if (SCARG(uap, flags) & LINUX_CLONE_VM) flags |= FORK_SHAREVM; if (SCARG(uap, flags) & LINUX_CLONE_FS) @@ -116,13 +137,10 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ return (EINVAL); sig = linux_to_native_signo[sig]; -#ifdef LINUX_NPTL - led = (struct linux_emuldata *)l->l_proc->p_emuldata; - - led->parent_tidptr = SCARG(uap, parent_tidptr); - led->child_tidptr = SCARG(uap, child_tidptr); - led->clone_flags = SCARG(uap, flags); -#endif /* LINUX_NPTL */ + if (SCARG(uap, flags) & LINUX_CLONE_CHILD_SETTID) { + led = l->l_emuldata; + led->led_child_tidptr = SCARG(uap, child_tidptr); + } /* * Note that Linux does not provide a portable way of specifying @@ -131,14 +149,119 @@ linux_sys_clone(struct lwp *l, const struct linux_sys_clone_args *uap, register_ * that makes this adjustment is a noop. */ if ((error = fork1(l, flags, sig, SCARG(uap, stack), 0, - NULL, NULL, retval, &p)) != 0) + linux_child_return, NULL, retval, &p)) != 0) return error; -#ifdef LINUX_NPTL - if ((SCARG(uap, flags) & LINUX_CLONE_SETTLS) != 0) - return linux_init_thread_area(l, LIST_FIRST(&p->p_lwps)); -#endif /* LINUX_NPTL */ + return 0; +} + +static int +linux_clone_nptl(struct lwp *l, const struct linux_sys_clone_args *uap, register_t *retval) +{ + /* { + syscallarg(int) flags; + syscallarg(void *) stack; + syscallarg(void *) parent_tidptr; + syscallarg(void *) tls; + syscallarg(void *) child_tidptr; + } */ + struct proc *p; + struct lwp *l2; + struct linux_emuldata *led; + void *parent_tidptr, *tls, *child_tidptr; + struct schedstate_percpu *spc; + vaddr_t uaddr; + lwpid_t lid; + int flags, tnprocs, error; + + p = l->l_proc; + flags = SCARG(uap, flags); + parent_tidptr = SCARG(uap, parent_tidptr); + tls = SCARG(uap, tls); + child_tidptr = SCARG(uap, child_tidptr); + + tnprocs = atomic_inc_uint_nv(&nprocs); + if (__predict_false(tnprocs >= maxproc) || + kauth_authorize_process(l->l_cred, KAUTH_PROCESS_FORK, p, + KAUTH_ARG(tnprocs), NULL, NULL) != 0) { + atomic_dec_uint(&nprocs); + return EAGAIN; + } + uaddr = uvm_uarea_alloc(); + if (__predict_false(uaddr == 0)) { + atomic_dec_uint(&nprocs); + return ENOMEM; + } + + error = lwp_create(l, p, uaddr, LWP_DETACHED | LWP_PIDLID, + SCARG(uap, stack), 0, child_return, NULL, &l2, + l->l_class); + if (__predict_false(error)) { + atomic_dec_uint(&nprocs); + uvm_uarea_free(uaddr); + return error; + } + lid = l2->l_lid; + + /* LINUX_CLONE_CHILD_CLEARTID: clear TID in child's memory on exit() */ + if (flags & LINUX_CLONE_CHILD_CLEARTID) { + led = l2->l_emuldata; + led->led_clear_tid = child_tidptr; + } + + /* LINUX_CLONE_PARENT_SETTID: store child's TID in parent's memory */ + if (flags & LINUX_CLONE_PARENT_SETTID) { + if (copyout(&lid, parent_tidptr, sizeof(lid)) != 0) + printf("%s: LINUX_CLONE_PARENT_SETTID " + "failed (parent_tidptr = %p tid = %d)\n", + __func__, parent_tidptr, lid); + } + + /* LINUX_CLONE_CHILD_SETTID: store child's TID in child's memory */ + if (flags & LINUX_CLONE_CHILD_SETTID) { + if (copyout(&lid, child_tidptr, sizeof(lid)) != 0) + printf("%s: LINUX_CLONE_CHILD_SETTID " + "failed (child_tidptr = %p, tid = %d)\n", + __func__, child_tidptr, lid); + } + + if (flags & LINUX_CLONE_SETTLS) { + error = LINUX_LWP_SETPRIVATE(l2, tls); + if (error) { + lwp_exit(l2); + return error; + } + } + + /* + * Set the new LWP running, unless the process is stopping, + * then the LWP is created stopped. + */ + mutex_enter(p->p_lock); + lwp_lock(l2); + spc = &l2->l_cpu->ci_schedstate; + if ((l->l_flag & (LW_WREBOOT | LW_WSUSPEND | LW_WEXIT)) == 0) { + if (p->p_stat == SSTOP || (p->p_sflag & PS_STOPPING) != 0) { + KASSERT(l2->l_wchan == NULL); + l2->l_stat = LSSTOP; + p->p_nrlwps--; + lwp_unlock_to(l2, spc->spc_lwplock); + } else { + KASSERT(lwp_locked(l2, spc->spc_mutex)); + l2->l_stat = LSRUN; + sched_enqueue(l2, false); + lwp_unlock(l2); + } + } else { + l2->l_stat = LSSUSPENDED; + p->p_nrlwps--; + lwp_unlock_to(l2, spc->spc_lwplock); + } + mutex_exit(p->p_lock); + + retval[0] = lid; + retval[1] = 0; return 0; } @@ -287,7 +410,7 @@ linux_sys_sched_setparam(struct lwp *l, const struct linux_sys_sched_setparam_ar goto out; /* We need the current policy in Linux terms. */ - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, NULL); if (error) goto out; error = sched_native2linux(policy, NULL, &policy, NULL); @@ -298,7 +421,7 @@ linux_sys_sched_setparam(struct lwp *l, const struct linux_sys_sched_setparam_ar if (error) goto out; - error = do_sched_setparam(SCARG(uap, pid), 0, policy, &sp); + error = do_sched_setparam(0, SCARG(uap, pid), policy, &sp); if (error) goto out; @@ -322,7 +445,7 @@ linux_sys_sched_getparam(struct lwp *l, const struct linux_sys_sched_getparam_ar goto out; } - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, &sp); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, &sp); if (error) goto out; #ifdef DEBUG_LINUX @@ -379,7 +502,7 @@ linux_sys_sched_setscheduler(struct lwp *l, const struct linux_sys_sched_setsche policy, sp.sched_priority); #endif - error = do_sched_setparam(SCARG(uap, pid), 0, policy, &sp); + error = do_sched_setparam(0, SCARG(uap, pid), policy, &sp); if (error) goto out; @@ -397,7 +520,7 @@ linux_sys_sched_getscheduler(struct lwp *l, const struct linux_sys_sched_getsche *retval = -1; - error = do_sched_getparam(SCARG(uap, pid), 0, &policy, NULL); + error = do_sched_getparam(0, SCARG(uap, pid), &policy, NULL); if (error) goto out; @@ -463,73 +586,24 @@ linux_sys_sched_get_priority_min(struct lwp *l, const struct linux_sys_sched_get return 0; } +int +linux_sys_exit(struct lwp *l, const struct linux_sys_exit_args *uap, register_t *retval) +{ + + lwp_exit(l); + return 0; +} + #ifndef __m68k__ /* Present on everything but m68k */ int linux_sys_exit_group(struct lwp *l, const struct linux_sys_exit_group_args *uap, register_t *retval) { -#ifdef LINUX_NPTL - /* { - syscallarg(int) error_code; - } */ - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - struct linux_emuldata *e; - - if (led->s->flags & LINUX_LES_USE_NPTL) { - -#ifdef DEBUG_LINUX - printf("%s:%d, led->s->refs = %d\n", __func__, __LINE__, - led->s->refs); -#endif - - /* - * The calling thread is supposed to kill all threads - * in the same thread group (i.e. all threads created - * via clone(2) with CLONE_THREAD flag set). - * - * If there is only one thread, things are quite simple - */ - if (led->s->refs == 1) - return sys_exit(l, (const void *)uap, retval); - -#ifdef DEBUG_LINUX - printf("%s:%d\n", __func__, __LINE__); -#endif - - mutex_enter(proc_lock); - led->s->flags |= LINUX_LES_INEXITGROUP; - led->s->xstat = W_EXITCODE(SCARG(uap, error_code), 0); - - /* - * Kill all threads in the group. The emulation exit hook takes - * care of hiding the zombies and reporting the exit code - * properly. - */ - LIST_FOREACH(e, &led->s->threads, threads) { - if (e->proc == p) - continue; - -#ifdef DEBUG_LINUX - printf("%s: kill PID %d\n", __func__, e->proc->p_pid); -#endif - psignal(e->proc, SIGKILL); - } - - /* Now, kill ourselves */ - psignal(p, SIGKILL); - mutex_exit(proc_lock); - - return 0; - - } -#endif /* LINUX_NPTL */ return sys_exit(l, (const void *)uap, retval); } #endif /* !__m68k__ */ -#ifdef LINUX_NPTL int linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_args *uap, register_t *retval) { @@ -538,12 +612,9 @@ linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_ } */ struct linux_emuldata *led; - led = (struct linux_emuldata *)l->l_proc->p_emuldata; - led->clear_tid = SCARG(uap, tid); - - led->s->flags |= LINUX_LES_USE_NPTL; - - *retval = l->l_proc->p_pid; + led = (struct linux_emuldata *)l->l_emuldata; + led->led_clear_tid = SCARG(uap, tid); + *retval = l->l_lid; return 0; } @@ -552,81 +623,22 @@ linux_sys_set_tid_address(struct lwp *l, const struct linux_sys_set_tid_address_ int linux_sys_gettid(struct lwp *l, const void *v, register_t *retval) { - /* The Linux kernel does it exactly that way */ - *retval = l->l_proc->p_pid; - return 0; -} - -#ifdef LINUX_NPTL -/* ARGUSED1 */ -int -linux_sys_getpid(struct lwp *l, const void *v, register_t *retval) -{ - struct linux_emuldata *led = l->l_proc->p_emuldata; - - if (led->s->flags & LINUX_LES_USE_NPTL) { - /* The Linux kernel does it exactly that way */ - *retval = led->s->group_pid; - } else { - *retval = l->l_proc->p_pid; - } - - return 0; -} - -/* ARGUSED1 */ -int -linux_sys_getppid(struct lwp *l, const void *v, register_t *retval) -{ - struct proc *p = l->l_proc; - struct linux_emuldata *led = p->p_emuldata; - struct proc *glp; - struct proc *pp; - - mutex_enter(proc_lock); - if (led->s->flags & LINUX_LES_USE_NPTL) { - - /* Find the thread group leader's parent */ - glp = proc_find(led->s->group_pid); - if (glp == NULL) { - /* Maybe panic... */ - printf("linux_sys_getppid: missing group leader PID" - " %d\n", led->s->group_pid); - mutex_exit(proc_lock); - return -1; - } - pp = glp->p_pptr; - - /* If this is a Linux process too, return thread group PID */ - if (pp->p_emul == p->p_emul) { - struct linux_emuldata *pled; - - pled = pp->p_emuldata; - *retval = pled->s->group_pid; - } else { - *retval = pp->p_pid; - } - - } else { - *retval = p->p_pptr->p_pid; - } - mutex_exit(proc_lock); + *retval = l->l_lid; return 0; } -#endif /* LINUX_NPTL */ int linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffinity_args *uap, register_t *retval) { /* { - syscallarg(pid_t) pid; + syscallarg(linux_pid_t) pid; syscallarg(unsigned int) len; syscallarg(unsigned long *) mask; } */ - int error, size, nb = ncpu; - unsigned long *c, *data; proc_t *p; + unsigned long *lp, *data; + int error, size, nb = ncpu; /* Unlike Linux, dynamically calculate cpu mask size */ size = sizeof(long) * ((ncpu + LONG_BIT - 1) / LONG_BIT); @@ -647,27 +659,25 @@ linux_sys_sched_getaffinity(struct lwp *l, const struct linux_sys_sched_getaffin * bit. */ data = kmem_zalloc(size, KM_SLEEP); - c = data; + lp = data; while (nb > LONG_BIT) { - *c++ = ~0UL; + *lp++ = ~0UL; nb -= LONG_BIT; } if (nb) - *c = (1 << ncpu) - 1; + *lp = (1 << ncpu) - 1; error = copyout(data, SCARG(uap, mask), size); kmem_free(data, size); - *retval = size; return error; - } int linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffinity_args *uap, register_t *retval) { /* { - syscallarg(pid_t) pid; + syscallarg(linux_pid_t) pid; syscallarg(unsigned int) len; syscallarg(unsigned long *) mask; } */ @@ -687,4 +697,3 @@ linux_sys_sched_setaffinity(struct lwp *l, const struct linux_sys_sched_setaffin #endif return 0; }; -#endif /* LINUX_NPTL */ diff --git a/sys/compat/linux/common/linux_signal.c b/sys/compat/linux/common/linux_signal.c index c7243c7fa8c..ab42f9f8836 100644 --- a/sys/compat/linux/common/linux_signal.c +++ b/sys/compat/linux/common/linux_signal.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp $ */ +/* $NetBSD: linux_signal.c,v 1.71 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. @@ -48,7 +48,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.71 2010/07/07 01:30:35 chs Exp $"); #define COMPAT_LINUX 1 @@ -69,9 +69,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.70 2010/07/01 02:38:29 rmind Exp #include <compat/linux/common/linux_types.h> #include <compat/linux/common/linux_signal.h> -#include <compat/linux/common/linux_exec.h> /* For emul_linux */ -#include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ -#include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */ +#include <compat/linux/common/linux_emuldata.h> #include <compat/linux/common/linux_siginfo.h> #include <compat/linux/common/linux_sigevent.h> #include <compat/linux/common/linux_util.h> @@ -609,39 +607,41 @@ linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *ua } #endif /* LINUX_SS_ONSTACK */ -#ifdef LINUX_NPTL static int linux_do_tkill(struct lwp *l, int tgid, int tid, int signum) { struct proc *p; - int error; + struct lwp *t; ksiginfo_t ksi; - struct linux_emuldata *led; + int error; if (signum < 0 || signum >= LINUX__NSIG) return EINVAL; signum = linux_to_native_signo[signum]; + if (tgid == -1) { + tgid = tid; + } + KSI_INIT(&ksi); ksi.ksi_signo = signum; ksi.ksi_code = SI_LWP; ksi.ksi_pid = l->l_proc->p_pid; ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); + ksi.ksi_lid = tid; mutex_enter(proc_lock); - if ((p = proc_find(tid)) == NULL) { - mutex_exit(proc_lock); - return ESRCH; - } - led = p->p_emuldata; - if (tgid > 0 && led->s->group_pid != tgid) { + p = proc_find(tgid); + if (p == NULL) { mutex_exit(proc_lock); return ESRCH; } mutex_enter(p->p_lock); error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL); - if (!error && signum) + if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) + error = ESRCH; + else if (signum != 0) kpsignal2(p, &ksi); mutex_exit(p->p_lock); mutex_exit(proc_lock); @@ -660,7 +660,7 @@ linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_ if (SCARG(uap, tid) <= 0) return EINVAL; - return linux_do_tkill(l, 0, SCARG(uap, tid), SCARG(uap, sig)); + return linux_do_tkill(l, -1, SCARG(uap, tid), SCARG(uap, sig)); } int @@ -672,12 +672,11 @@ linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, registe syscallarg(int) sig; } */ - if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) <= 0) + if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) < -1) return EINVAL; return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig)); } -#endif /* LINUX_NPTL */ int native_to_linux_si_code(int code) diff --git a/sys/compat/linux/common/linux_sysctl.c b/sys/compat/linux/common/linux_sysctl.c index e7b1a448956..3c9ff0dcda9 100644 --- a/sys/compat/linux/common/linux_sysctl.c +++ b/sys/compat/linux/common/linux_sysctl.c @@ -1,4 +1,4 @@ -/* $NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp $ */ +/* $NetBSD: linux_sysctl.c,v 1.40 2010/07/07 01:30:35 chs Exp $ */ /*- * Copyright (c) 2003, 2008 The NetBSD Foundation, Inc. @@ -34,7 +34,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.40 2010/07/07 01:30:35 chs Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -57,13 +57,8 @@ __KERNEL_RCSID(0, "$NetBSD: linux_sysctl.c,v 1.39 2009/01/05 09:33:19 njoly Exp #include <compat/linux/common/linux_machdep.h> char linux_sysname[128] = "Linux"; -#if defined(__amd64__) || defined(__i386__) || defined(__powerpc__) -char linux_release[128] = "2.4.18"; -char linux_version[128] = "#0 Wed Feb 20 20:00:02 CET 2002"; -#else -char linux_release[128] = "2.0.38"; -char linux_version[128] = "#0 Sun Nov 11 11:11:11 MET 2000"; -#endif +char linux_release[128] = "2.6.18"; +char linux_version[128] = "#0 Wed Mar 3 03:03:03 PST 2010"; struct sysctlnode linux_sysctl_root = { .sysctl_flags = SYSCTL_VERSION| |
