1ad2056f2SAlexander Leidinger /*- 2ad2056f2SAlexander Leidinger * Copyright (c) 2006 Roman Divacky 3ad2056f2SAlexander Leidinger * All rights reserved. 4ad2056f2SAlexander Leidinger * 5ad2056f2SAlexander Leidinger * Redistribution and use in source and binary forms, with or without 6ad2056f2SAlexander Leidinger * modification, are permitted provided that the following conditions 7ad2056f2SAlexander Leidinger * are met: 8ad2056f2SAlexander Leidinger * 1. Redistributions of source code must retain the above copyright 9ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer 10ad2056f2SAlexander Leidinger * in this position and unchanged. 11ad2056f2SAlexander Leidinger * 2. Redistributions in binary form must reproduce the above copyright 12ad2056f2SAlexander Leidinger * notice, this list of conditions and the following disclaimer in the 13ad2056f2SAlexander Leidinger * documentation and/or other materials provided with the distribution. 14ad2056f2SAlexander Leidinger * 3. The name of the author may not be used to endorse or promote products 15ad2056f2SAlexander Leidinger * derived from this software without specific prior written permission 16ad2056f2SAlexander Leidinger * 17ad2056f2SAlexander Leidinger * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18ad2056f2SAlexander Leidinger * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19ad2056f2SAlexander Leidinger * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20ad2056f2SAlexander Leidinger * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21ad2056f2SAlexander Leidinger * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22ad2056f2SAlexander Leidinger * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23ad2056f2SAlexander Leidinger * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24ad2056f2SAlexander Leidinger * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25ad2056f2SAlexander Leidinger * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26ad2056f2SAlexander Leidinger * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27ad2056f2SAlexander Leidinger */ 28ad2056f2SAlexander Leidinger 29ad2056f2SAlexander Leidinger #include <sys/cdefs.h> 30ad2056f2SAlexander Leidinger __FBSDID("$FreeBSD$"); 31ad2056f2SAlexander Leidinger 32ad2056f2SAlexander Leidinger #include "opt_compat.h" 33*19e252baSAlexander Leidinger #include "opt_kdtrace.h" 34ad2056f2SAlexander Leidinger 35ad2056f2SAlexander Leidinger #include <sys/param.h> 36ad2056f2SAlexander Leidinger #include <sys/systm.h> 37ad2056f2SAlexander Leidinger #include <sys/imgact.h> 38b4bb5154SKonstantin Belousov #include <sys/kernel.h> 39ad2056f2SAlexander Leidinger #include <sys/lock.h> 40ad2056f2SAlexander Leidinger #include <sys/malloc.h> 41ad2056f2SAlexander Leidinger #include <sys/mutex.h> 42*19e252baSAlexander Leidinger #include <sys/sdt.h> 43ad2056f2SAlexander Leidinger #include <sys/sx.h> 44ad2056f2SAlexander Leidinger #include <sys/proc.h> 45ad2056f2SAlexander Leidinger #include <sys/syscallsubr.h> 4695353459SDimitry Andric #include <sys/sysent.h> 47ad2056f2SAlexander Leidinger #include <sys/sysproto.h> 48ad2056f2SAlexander Leidinger #include <sys/unistd.h> 49ad2056f2SAlexander Leidinger 50ad2056f2SAlexander Leidinger #ifdef COMPAT_LINUX32 51ad2056f2SAlexander Leidinger #include <machine/../linux32/linux.h> 52ad2056f2SAlexander Leidinger #include <machine/../linux32/linux32_proto.h> 53ad2056f2SAlexander Leidinger #else 54ad2056f2SAlexander Leidinger #include <machine/../linux/linux.h> 55ad2056f2SAlexander Leidinger #include <machine/../linux/linux_proto.h> 56ad2056f2SAlexander Leidinger #endif 57ad2056f2SAlexander Leidinger 58*19e252baSAlexander Leidinger #include <compat/linux/linux_dtrace.h> 594732e446SRoman Divacky #include <compat/linux/linux_emul.h> 604732e446SRoman Divacky #include <compat/linux/linux_futex.h> 614732e446SRoman Divacky 62*19e252baSAlexander Leidinger /** 63*19e252baSAlexander Leidinger * Special DTrace provider for the linuxulator. 64*19e252baSAlexander Leidinger * 65*19e252baSAlexander Leidinger * In this file we define the provider for the entire linuxulator. All 66*19e252baSAlexander Leidinger * modules (= files of the linuxulator) use it. 67*19e252baSAlexander Leidinger * 68*19e252baSAlexander Leidinger * We define a different name depending on the emulated bitsize, see 69*19e252baSAlexander Leidinger * ../../<ARCH>/linux{,32}/linux.h, e.g.: 70*19e252baSAlexander Leidinger * native bitsize = linuxulator 71*19e252baSAlexander Leidinger * amd64, 32bit emulation = linuxulator32 72*19e252baSAlexander Leidinger */ 73*19e252baSAlexander Leidinger LIN_SDT_PROVIDER_DEFINE(LINUX_DTRACE); 74*19e252baSAlexander Leidinger 75*19e252baSAlexander Leidinger /** 76*19e252baSAlexander Leidinger * Special DTrace module "locks", it covers some linuxulator internal 77*19e252baSAlexander Leidinger * locks. 78*19e252baSAlexander Leidinger */ 79*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_lock, locked, "struct mtx *"); 80*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_lock, unlock, "struct mtx *"); 81*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, locked, "struct sx *"); 82*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_shared_rlock, unlock, "struct sx *"); 83*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, locked, "struct sx *"); 84*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(locks, emul_shared_wlock, unlock, "struct sx *"); 85*19e252baSAlexander Leidinger 86*19e252baSAlexander Leidinger /** 87*19e252baSAlexander Leidinger * DTrace probes in this module. 88*19e252baSAlexander Leidinger */ 89*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(emul, em_find, entry, "struct proc *", "int"); 90*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, em_find, return); 91*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE3(emul, proc_init, entry, "struct thread *", "pid_t", 92*19e252baSAlexander Leidinger "int"); 93*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, create_thread); 94*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, fork); 95*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, exec); 96*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_init, return); 97*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, proc_exit, entry, "struct proc *"); 98*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_exit, futex_failed); 99*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE3(emul, proc_exit, reparent, "pid_t", "pid_t", 100*19e252baSAlexander Leidinger "struct proc *"); 101*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, proc_exit, child_clear_tid_error, "int"); 102*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_exit, return); 103*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(emul, proc_exec, entry, "struct proc *", 104*19e252baSAlexander Leidinger "struct image_params *"); 105*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, proc_exec, return); 106*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, entry); 107*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, linux_schedtail, copyout_error, "int"); 108*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_schedtail, return); 109*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, linux_set_tid_address, entry, "int *"); 110*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_set_tid_address, return); 111*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE2(emul, linux_kill_threads, entry, "struct thread *", 112*19e252baSAlexander Leidinger "int"); 113*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE1(emul, linux_kill_threads, kill, "pid_t"); 114*19e252baSAlexander Leidinger LIN_SDT_PROBE_DEFINE0(emul, linux_kill_threads, return); 115*19e252baSAlexander Leidinger 116ad2056f2SAlexander Leidinger struct sx emul_shared_lock; 117357afa71SJung-uk Kim struct mtx emul_lock; 118ad2056f2SAlexander Leidinger 119ad2056f2SAlexander Leidinger /* this returns locked reference to the emuldata entry (if found) */ 120ad2056f2SAlexander Leidinger struct linux_emuldata * 121ad2056f2SAlexander Leidinger em_find(struct proc *p, int locked) 122ad2056f2SAlexander Leidinger { 123ad2056f2SAlexander Leidinger struct linux_emuldata *em; 124ad2056f2SAlexander Leidinger 125*19e252baSAlexander Leidinger LIN_SDT_PROBE2(emul, em_find, entry, p, locked); 126*19e252baSAlexander Leidinger 1271c65504cSAlexander Leidinger if (locked == EMUL_DOLOCK) 128ad2056f2SAlexander Leidinger EMUL_LOCK(&emul_lock); 129ad2056f2SAlexander Leidinger 130ad2056f2SAlexander Leidinger em = p->p_emuldata; 131ad2056f2SAlexander Leidinger 1321c65504cSAlexander Leidinger if (em == NULL && locked == EMUL_DOLOCK) 133ad2056f2SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 134ad2056f2SAlexander Leidinger 135*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, em_find, return, em); 136ad2056f2SAlexander Leidinger return (em); 137ad2056f2SAlexander Leidinger } 138ad2056f2SAlexander Leidinger 139ad2056f2SAlexander Leidinger int 140ad2056f2SAlexander Leidinger linux_proc_init(struct thread *td, pid_t child, int flags) 141ad2056f2SAlexander Leidinger { 142ad2056f2SAlexander Leidinger struct linux_emuldata *em, *p_em; 143ad2056f2SAlexander Leidinger struct proc *p; 144ad2056f2SAlexander Leidinger 145*19e252baSAlexander Leidinger LIN_SDT_PROBE3(emul, proc_init, entry, td, child, flags); 146*19e252baSAlexander Leidinger 147ad2056f2SAlexander Leidinger if (child != 0) { 148*19e252baSAlexander Leidinger /* fork or create a thread */ 1495342db08SSuleiman Souhlal em = malloc(sizeof *em, M_LINUX, M_WAITOK | M_ZERO); 150ad2056f2SAlexander Leidinger em->pid = child; 151955d762aSAlexander Leidinger em->pdeath_signal = 0; 152d14cc07dSDmitry Chagin em->flags = 0; 1534732e446SRoman Divacky em->robust_futexes = NULL; 154a4e3bad7SJung-uk Kim if (flags & LINUX_CLONE_THREAD) { 155ad2056f2SAlexander Leidinger /* handled later in the code */ 156*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_init, create_thread); 157ad2056f2SAlexander Leidinger } else { 158ad2056f2SAlexander Leidinger struct linux_emuldata_shared *s; 159ad2056f2SAlexander Leidinger 160*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_init, fork); 161*19e252baSAlexander Leidinger 1625342db08SSuleiman Souhlal s = malloc(sizeof *s, M_LINUX, M_WAITOK | M_ZERO); 163ad2056f2SAlexander Leidinger s->refs = 1; 164ad2056f2SAlexander Leidinger s->group_pid = child; 165ad2056f2SAlexander Leidinger 166ad2056f2SAlexander Leidinger LIST_INIT(&s->threads); 167d071f504SAlexander Leidinger em->shared = s; 168ad2056f2SAlexander Leidinger } 169ad2056f2SAlexander Leidinger } else { 170*19e252baSAlexander Leidinger /* exec */ 171*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_init, exec); 172*19e252baSAlexander Leidinger 173ad2056f2SAlexander Leidinger /* lookup the old one */ 1741c65504cSAlexander Leidinger em = em_find(td->td_proc, EMUL_DOLOCK); 175ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_init: emuldata not found in exec case.\n")); 176ad2056f2SAlexander Leidinger } 177ad2056f2SAlexander Leidinger 178ad2056f2SAlexander Leidinger em->child_clear_tid = NULL; 179ad2056f2SAlexander Leidinger em->child_set_tid = NULL; 180ad2056f2SAlexander Leidinger 1810eef2f8aSAlexander Leidinger /* 182a628609eSAlexander Leidinger * allocate the shared struct only in clone()/fork cases in the case 183a628609eSAlexander Leidinger * of clone() td = calling proc and child = pid of the newly created 184a628609eSAlexander Leidinger * proc 185ad2056f2SAlexander Leidinger */ 186ad2056f2SAlexander Leidinger if (child != 0) { 187a4e3bad7SJung-uk Kim if (flags & LINUX_CLONE_THREAD) { 188ad2056f2SAlexander Leidinger /* lookup the parent */ 18925954d74SKonstantin Belousov /* 19025954d74SKonstantin Belousov * we dont have to lock the p_em because 19125954d74SKonstantin Belousov * its waiting for us in linux_clone so 19225954d74SKonstantin Belousov * there is no chance of it changing the 19325954d74SKonstantin Belousov * p_em->shared address 19425954d74SKonstantin Belousov */ 19525954d74SKonstantin Belousov p_em = em_find(td->td_proc, EMUL_DONTLOCK); 196292a85f4SKonstantin Belousov KASSERT(p_em != NULL, ("proc_init: parent emuldata not found for CLONE_THREAD\n")); 197ad2056f2SAlexander Leidinger em->shared = p_em->shared; 19825954d74SKonstantin Belousov EMUL_SHARED_WLOCK(&emul_shared_lock); 199ad2056f2SAlexander Leidinger em->shared->refs++; 200291081ceSAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 201ad2056f2SAlexander Leidinger } else { 202a628609eSAlexander Leidinger /* 203a628609eSAlexander Leidinger * handled earlier to avoid malloc(M_WAITOK) with 204a628609eSAlexander Leidinger * rwlock held 205a628609eSAlexander Leidinger */ 206ad2056f2SAlexander Leidinger } 207*19e252baSAlexander Leidinger 208ad2056f2SAlexander Leidinger EMUL_SHARED_WLOCK(&emul_shared_lock); 209ad2056f2SAlexander Leidinger LIST_INSERT_HEAD(&em->shared->threads, em, threads); 210ad2056f2SAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 211ad2056f2SAlexander Leidinger 212ad2056f2SAlexander Leidinger p = pfind(child); 213d071f504SAlexander Leidinger KASSERT(p != NULL, ("process not found in proc_init\n")); 214d071f504SAlexander Leidinger p->p_emuldata = em; 2158618fd85SAlexander Leidinger PROC_UNLOCK(p); 216ad2056f2SAlexander Leidinger } else 217ad2056f2SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 218ad2056f2SAlexander Leidinger 219*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_init, return); 220ad2056f2SAlexander Leidinger return (0); 221ad2056f2SAlexander Leidinger } 222ad2056f2SAlexander Leidinger 223ad2056f2SAlexander Leidinger void 224ad2056f2SAlexander Leidinger linux_proc_exit(void *arg __unused, struct proc *p) 225ad2056f2SAlexander Leidinger { 226ad2056f2SAlexander Leidinger struct linux_emuldata *em; 227bb63fddeSAlexander Leidinger int error, shared_flags, shared_xstat; 228ad2056f2SAlexander Leidinger struct thread *td = FIRST_THREAD_IN_PROC(p); 229ad2056f2SAlexander Leidinger int *child_clear_tid; 230955d762aSAlexander Leidinger struct proc *q, *nq; 231ad2056f2SAlexander Leidinger 232ad2056f2SAlexander Leidinger if (__predict_true(p->p_sysent != &elf_linux_sysvec)) 233ad2056f2SAlexander Leidinger return; 234ad2056f2SAlexander Leidinger 235*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, proc_exit, entry, p); 236*19e252baSAlexander Leidinger 2374732e446SRoman Divacky release_futexes(p); 2384732e446SRoman Divacky 239ad2056f2SAlexander Leidinger /* find the emuldata */ 2401c65504cSAlexander Leidinger em = em_find(p, EMUL_DOLOCK); 241ad2056f2SAlexander Leidinger 242ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_exit: emuldata not found.\n")); 243ad2056f2SAlexander Leidinger 24425954d74SKonstantin Belousov /* reparent all procs that are not a thread leader to initproc */ 24525954d74SKonstantin Belousov if (em->shared->group_pid != p->p_pid) { 246*19e252baSAlexander Leidinger LIN_SDT_PROBE3(emul, proc_exit, reparent, 247*19e252baSAlexander Leidinger em->shared->group_pid, p->p_pid, p); 248*19e252baSAlexander Leidinger 249e8b8b834SAlexander Leidinger child_clear_tid = em->child_clear_tid; 250e8b8b834SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 25125954d74SKonstantin Belousov sx_xlock(&proctree_lock); 25225954d74SKonstantin Belousov wakeup(initproc); 25325954d74SKonstantin Belousov PROC_LOCK(p); 25425954d74SKonstantin Belousov proc_reparent(p, initproc); 25525954d74SKonstantin Belousov p->p_sigparent = SIGCHLD; 25625954d74SKonstantin Belousov PROC_UNLOCK(p); 25725954d74SKonstantin Belousov sx_xunlock(&proctree_lock); 258e8b8b834SAlexander Leidinger } else { 259ad2056f2SAlexander Leidinger child_clear_tid = em->child_clear_tid; 260ad2056f2SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 261e8b8b834SAlexander Leidinger } 262ad2056f2SAlexander Leidinger 263ad2056f2SAlexander Leidinger EMUL_SHARED_WLOCK(&emul_shared_lock); 264bb63fddeSAlexander Leidinger shared_flags = em->shared->flags; 265bb63fddeSAlexander Leidinger shared_xstat = em->shared->xstat; 266ad2056f2SAlexander Leidinger LIST_REMOVE(em, threads); 267ad2056f2SAlexander Leidinger 268ad2056f2SAlexander Leidinger em->shared->refs--; 2691a26db0aSAlexander Leidinger if (em->shared->refs == 0) { 2701a26db0aSAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 2715342db08SSuleiman Souhlal free(em->shared, M_LINUX); 2721a26db0aSAlexander Leidinger } else 273ad2056f2SAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 274ad2056f2SAlexander Leidinger 275526384ecSAlexander Leidinger if ((shared_flags & EMUL_SHARED_HASXSTAT) != 0) 276bb63fddeSAlexander Leidinger p->p_xstat = shared_xstat; 277bb63fddeSAlexander Leidinger 278ad2056f2SAlexander Leidinger if (child_clear_tid != NULL) { 279ad2056f2SAlexander Leidinger struct linux_sys_futex_args cup; 280ad2056f2SAlexander Leidinger int null = 0; 281ad2056f2SAlexander Leidinger 282ad2056f2SAlexander Leidinger error = copyout(&null, child_clear_tid, sizeof(null)); 28328638377SAlexander Leidinger if (error) { 284*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, proc_exit, 285*19e252baSAlexander Leidinger child_clear_tid_error, error); 286*19e252baSAlexander Leidinger 28728638377SAlexander Leidinger free(em, M_LINUX); 288*19e252baSAlexander Leidinger 289*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_exit, return); 290ad2056f2SAlexander Leidinger return; 29128638377SAlexander Leidinger } 292ad2056f2SAlexander Leidinger 293ad2056f2SAlexander Leidinger /* futexes stuff */ 294ad2056f2SAlexander Leidinger cup.uaddr = child_clear_tid; 295ad2056f2SAlexander Leidinger cup.op = LINUX_FUTEX_WAKE; 296ad2056f2SAlexander Leidinger cup.val = 0x7fffffff; /* Awake everyone */ 297ad2056f2SAlexander Leidinger cup.timeout = NULL; 298ad2056f2SAlexander Leidinger cup.uaddr2 = NULL; 299ad2056f2SAlexander Leidinger cup.val3 = 0; 300ad2056f2SAlexander Leidinger error = linux_sys_futex(FIRST_THREAD_IN_PROC(p), &cup); 3010eef2f8aSAlexander Leidinger /* 302a628609eSAlexander Leidinger * this cannot happen at the moment and if this happens it 303802e08a3SAlexander Leidinger * probably means there is a user space bug 304ad2056f2SAlexander Leidinger */ 305*19e252baSAlexander Leidinger if (error) { 306*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_exit, futex_failed); 307ad2056f2SAlexander Leidinger printf(LMSG("futex stuff in proc_exit failed.\n")); 308ad2056f2SAlexander Leidinger } 309*19e252baSAlexander Leidinger } 310ad2056f2SAlexander Leidinger 311ad2056f2SAlexander Leidinger /* clean the stuff up */ 3125342db08SSuleiman Souhlal free(em, M_LINUX); 313955d762aSAlexander Leidinger 314955d762aSAlexander Leidinger /* this is a little weird but rewritten from exit1() */ 315955d762aSAlexander Leidinger sx_xlock(&proctree_lock); 316955d762aSAlexander Leidinger q = LIST_FIRST(&p->p_children); 317955d762aSAlexander Leidinger for (; q != NULL; q = nq) { 318955d762aSAlexander Leidinger nq = LIST_NEXT(q, p_sibling); 319955d762aSAlexander Leidinger if (q->p_flag & P_WEXIT) 320955d762aSAlexander Leidinger continue; 321955d762aSAlexander Leidinger if (__predict_false(q->p_sysent != &elf_linux_sysvec)) 322955d762aSAlexander Leidinger continue; 3231c65504cSAlexander Leidinger em = em_find(q, EMUL_DOLOCK); 324955d762aSAlexander Leidinger KASSERT(em != NULL, ("linux_reparent: emuldata not found: %i\n", q->p_pid)); 325955d762aSAlexander Leidinger PROC_LOCK(q); 32617b9edd3SKonstantin Belousov if ((q->p_flag & P_WEXIT) == 0 && em->pdeath_signal != 0) { 3278451d0ddSKip Macy kern_psignal(q, em->pdeath_signal); 328955d762aSAlexander Leidinger } 32917b9edd3SKonstantin Belousov PROC_UNLOCK(q); 330955d762aSAlexander Leidinger EMUL_UNLOCK(&emul_lock); 331955d762aSAlexander Leidinger } 332955d762aSAlexander Leidinger sx_xunlock(&proctree_lock); 333*19e252baSAlexander Leidinger 334*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_exit, return); 335ad2056f2SAlexander Leidinger } 336ad2056f2SAlexander Leidinger 3370eef2f8aSAlexander Leidinger /* 3380eef2f8aSAlexander Leidinger * This is used in a case of transition from FreeBSD binary execing to linux binary 339ad2056f2SAlexander Leidinger * in this case we create linux emuldata proc entry with the pid of the currently running 340ad2056f2SAlexander Leidinger * process. 341ad2056f2SAlexander Leidinger */ 342a628609eSAlexander Leidinger void 343a628609eSAlexander Leidinger linux_proc_exec(void *arg __unused, struct proc *p, struct image_params *imgp) 344ad2056f2SAlexander Leidinger { 345*19e252baSAlexander Leidinger if (__predict_false(imgp->sysent == &elf_linux_sysvec)) { 346*19e252baSAlexander Leidinger LIN_SDT_PROBE2(emul, proc_exec, entry, p, imgp); 347*19e252baSAlexander Leidinger } 348ad2056f2SAlexander Leidinger if (__predict_false(imgp->sysent == &elf_linux_sysvec 349ad2056f2SAlexander Leidinger && p->p_sysent != &elf_linux_sysvec)) 350ad2056f2SAlexander Leidinger linux_proc_init(FIRST_THREAD_IN_PROC(p), p->p_pid, 0); 351526384ecSAlexander Leidinger if (__predict_false((p->p_sysent->sv_flags & SV_ABI_MASK) == 352526384ecSAlexander Leidinger SV_ABI_LINUX)) 353bb63fddeSAlexander Leidinger /* Kill threads regardless of imgp->sysent value */ 354bb63fddeSAlexander Leidinger linux_kill_threads(FIRST_THREAD_IN_PROC(p), SIGKILL); 355ad2056f2SAlexander Leidinger if (__predict_false(imgp->sysent != &elf_linux_sysvec 356ad2056f2SAlexander Leidinger && p->p_sysent == &elf_linux_sysvec)) { 357ad2056f2SAlexander Leidinger struct linux_emuldata *em; 358ad2056f2SAlexander Leidinger 35925954d74SKonstantin Belousov /* 36025954d74SKonstantin Belousov * XXX:There's a race because here we assign p->p_emuldata NULL 36125954d74SKonstantin Belousov * but the process is still counted as linux one for a short 36225954d74SKonstantin Belousov * time so some other process might reference it and try to 36325954d74SKonstantin Belousov * access its p->p_emuldata and panicing on a NULL reference. 36425954d74SKonstantin Belousov */ 36525954d74SKonstantin Belousov em = em_find(p, EMUL_DONTLOCK); 366ad2056f2SAlexander Leidinger 367ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("proc_exec: emuldata not found.\n")); 368ad2056f2SAlexander Leidinger 369ad2056f2SAlexander Leidinger EMUL_SHARED_WLOCK(&emul_shared_lock); 370ad2056f2SAlexander Leidinger LIST_REMOVE(em, threads); 371ad2056f2SAlexander Leidinger 372ad2056f2SAlexander Leidinger PROC_LOCK(p); 373ad2056f2SAlexander Leidinger p->p_emuldata = NULL; 374ad2056f2SAlexander Leidinger PROC_UNLOCK(p); 375ad2056f2SAlexander Leidinger 376ad2056f2SAlexander Leidinger em->shared->refs--; 3771a26db0aSAlexander Leidinger if (em->shared->refs == 0) { 3781a26db0aSAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 379c67e0cc9SSuleiman Souhlal free(em->shared, M_LINUX); 3801a26db0aSAlexander Leidinger } else 381ad2056f2SAlexander Leidinger EMUL_SHARED_WUNLOCK(&emul_shared_lock); 382ad2056f2SAlexander Leidinger 383c67e0cc9SSuleiman Souhlal free(em, M_LINUX); 384ad2056f2SAlexander Leidinger } 385*19e252baSAlexander Leidinger 386*19e252baSAlexander Leidinger if (__predict_false(imgp->sysent == &elf_linux_sysvec)) { 387*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, proc_exec, return); 388*19e252baSAlexander Leidinger } 389ad2056f2SAlexander Leidinger } 390ad2056f2SAlexander Leidinger 391ad2056f2SAlexander Leidinger void 392e5d81ef1SDmitry Chagin linux_schedtail(struct thread *td) 393ad2056f2SAlexander Leidinger { 394ad2056f2SAlexander Leidinger struct linux_emuldata *em; 395e5d81ef1SDmitry Chagin struct proc *p; 396ad2056f2SAlexander Leidinger int error = 0; 397ad2056f2SAlexander Leidinger int *child_set_tid; 398ad2056f2SAlexander Leidinger 399e5d81ef1SDmitry Chagin p = td->td_proc; 400e5d81ef1SDmitry Chagin 401*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, linux_schedtail, entry, p); 402*19e252baSAlexander Leidinger 403ad2056f2SAlexander Leidinger /* find the emuldata */ 4041c65504cSAlexander Leidinger em = em_find(p, EMUL_DOLOCK); 405ad2056f2SAlexander Leidinger 40625954d74SKonstantin Belousov KASSERT(em != NULL, ("linux_schedtail: emuldata not found.\n")); 407ad2056f2SAlexander Leidinger child_set_tid = em->child_set_tid; 408ad2056f2SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 409ad2056f2SAlexander Leidinger 410*19e252baSAlexander Leidinger if (child_set_tid != NULL) { 411a628609eSAlexander Leidinger error = copyout(&p->p_pid, (int *)child_set_tid, 412a628609eSAlexander Leidinger sizeof(p->p_pid)); 413ad2056f2SAlexander Leidinger 414*19e252baSAlexander Leidinger if (error != 0) { 415*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, linux_schedtail, copyout_error, 416*19e252baSAlexander Leidinger error); 417*19e252baSAlexander Leidinger } 418*19e252baSAlexander Leidinger } 419*19e252baSAlexander Leidinger 420*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, linux_schedtail, return); 421*19e252baSAlexander Leidinger 422ad2056f2SAlexander Leidinger return; 423ad2056f2SAlexander Leidinger } 424ad2056f2SAlexander Leidinger 425ad2056f2SAlexander Leidinger int 426ad2056f2SAlexander Leidinger linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args) 427ad2056f2SAlexander Leidinger { 428ad2056f2SAlexander Leidinger struct linux_emuldata *em; 429ad2056f2SAlexander Leidinger 430*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, linux_set_tid_address, entry, args->tidptr); 431ad2056f2SAlexander Leidinger 432ad2056f2SAlexander Leidinger /* find the emuldata */ 4331c65504cSAlexander Leidinger em = em_find(td->td_proc, EMUL_DOLOCK); 434ad2056f2SAlexander Leidinger 435ad2056f2SAlexander Leidinger KASSERT(em != NULL, ("set_tid_address: emuldata not found.\n")); 436ad2056f2SAlexander Leidinger 437ad2056f2SAlexander Leidinger em->child_clear_tid = args->tidptr; 438ad2056f2SAlexander Leidinger td->td_retval[0] = td->td_proc->p_pid; 439ad2056f2SAlexander Leidinger 440ad2056f2SAlexander Leidinger EMUL_UNLOCK(&emul_lock); 441*19e252baSAlexander Leidinger 442*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, linux_set_tid_address, return); 443ad2056f2SAlexander Leidinger return 0; 444ad2056f2SAlexander Leidinger } 445bb63fddeSAlexander Leidinger 446bb63fddeSAlexander Leidinger void 447bb63fddeSAlexander Leidinger linux_kill_threads(struct thread *td, int sig) 448bb63fddeSAlexander Leidinger { 449bb63fddeSAlexander Leidinger struct linux_emuldata *em, *td_em, *tmp_em; 450bb63fddeSAlexander Leidinger struct proc *sp; 451bb63fddeSAlexander Leidinger 452*19e252baSAlexander Leidinger LIN_SDT_PROBE2(emul, linux_kill_threads, entry, td, sig); 453*19e252baSAlexander Leidinger 454bb63fddeSAlexander Leidinger td_em = em_find(td->td_proc, EMUL_DONTLOCK); 455bb63fddeSAlexander Leidinger 456bb63fddeSAlexander Leidinger KASSERT(td_em != NULL, ("linux_kill_threads: emuldata not found.\n")); 457bb63fddeSAlexander Leidinger 458bb63fddeSAlexander Leidinger EMUL_SHARED_RLOCK(&emul_shared_lock); 459bb63fddeSAlexander Leidinger LIST_FOREACH_SAFE(em, &td_em->shared->threads, threads, tmp_em) { 460bb63fddeSAlexander Leidinger if (em->pid == td_em->pid) 461bb63fddeSAlexander Leidinger continue; 462bb63fddeSAlexander Leidinger 463bb63fddeSAlexander Leidinger sp = pfind(em->pid); 464bb63fddeSAlexander Leidinger if ((sp->p_flag & P_WEXIT) == 0) 4658451d0ddSKip Macy kern_psignal(sp, sig); 466bb63fddeSAlexander Leidinger PROC_UNLOCK(sp); 467*19e252baSAlexander Leidinger 468*19e252baSAlexander Leidinger LIN_SDT_PROBE1(emul, linux_kill_threads, kill, em->pid); 469bb63fddeSAlexander Leidinger } 470bb63fddeSAlexander Leidinger EMUL_SHARED_RUNLOCK(&emul_shared_lock); 471*19e252baSAlexander Leidinger 472*19e252baSAlexander Leidinger LIN_SDT_PROBE0(emul, linux_kill_threads, return); 473bb63fddeSAlexander Leidinger } 474