From owner-p4-projects@FreeBSD.ORG Thu Jul 6 11:05:20 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 7883916A4E1; Thu, 6 Jul 2006 11:05:20 +0000 (UTC) X-Original-To: perforce@FreeBSD.org Delivered-To: perforce@FreeBSD.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 5267916A4DA for ; Thu, 6 Jul 2006 11:05:20 +0000 (UTC) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id EE01043D4C for ; Thu, 6 Jul 2006 11:05:19 +0000 (GMT) (envelope-from rdivacky@FreeBSD.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.6/8.13.6) with ESMTP id k66B5JiJ065289 for ; Thu, 6 Jul 2006 11:05:19 GMT (envelope-from rdivacky@FreeBSD.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.6/8.13.4/Submit) id k66B5JKG065286 for perforce@freebsd.org; Thu, 6 Jul 2006 11:05:19 GMT (envelope-from rdivacky@FreeBSD.org) Date: Thu, 6 Jul 2006 11:05:19 GMT Message-Id: <200607061105.k66B5JKG065286@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to rdivacky@FreeBSD.org using -f From: Roman Divacky To: Perforce Change Reviews Cc: Subject: PERFORCE change 100719 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Jul 2006 11:05:20 -0000 http://perforce.freebsd.org/chv.cgi?CH=100719 Change 100719 by rdivacky@rdivacky_witten on 2006/07/06 11:04:26 TID handling o introduction of P_LINUX proc flag o introduction of linux hooks into exit1() and userret() o TID handling in i386 version of linuxolator this has not been tested much. More testing will come once the futexes are finished. Affected files ... .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_dummy.c#5 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#7 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_proto.h#8 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_syscall.h#8 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysent.c#8 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#5 edit .. //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/syscalls.master#8 edit .. //depot/projects/soc2006/rdivacky_linuxolator/kern/kern_exit.c#3 edit .. //depot/projects/soc2006/rdivacky_linuxolator/kern/subr_trap.c#2 edit .. //depot/projects/soc2006/rdivacky_linuxolator/sys/proc.h#2 edit Differences ... ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_dummy.c#5 (text+ko) ==== @@ -73,7 +73,6 @@ DUMMY(epoll_ctl); DUMMY(epoll_wait); DUMMY(remap_file_pages); -DUMMY(set_tid_address); DUMMY(timer_create); DUMMY(timer_settime); DUMMY(timer_gettime); ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_machdep.c#7 (text+ko) ==== @@ -37,6 +37,7 @@ #include #include #include +#include #include #include #include @@ -61,6 +62,14 @@ #include /* needed for pcb definition in linux_set_thread_area */ +SLIST_HEAD(emuldata_head, linux_emuldata) emuldata_head = + SLIST_HEAD_INITIALIZER(emuldata_head); +struct linux_emuldata *emuldata_headp; /* where we store the emulation data */ + +static int linux_proc_init(struct thread *, pid_t); +int linux_proc_exit(struct thread *); +int linux_userret(struct thread *); + struct l_descriptor { l_uint entry_number; l_ulong base_addr; @@ -124,6 +133,8 @@ free(newpath, M_TEMP); if (error == 0) error = kern_execve(td, &eargs, NULL); + if (error == 0) + error = linux_proc_init(td, 0); return (error); } @@ -278,6 +289,9 @@ linux_fork(struct thread *td, struct linux_fork_args *args) { int error; +#if 0 + struct linux_emuldata *em; +#endif #ifdef DEBUG if (ldebug(fork)) @@ -289,6 +303,16 @@ if (td->td_retval[1] == 1) td->td_retval[0] = 0; + error = linux_proc_init(td, td->td_retval[0]); + if (error) + return (error); + +#if 0 + /* impossible to not find it */ + SLIST_FOREACH(em, &emuldata_head, emuldatas) + if (em->pid == td->td_retval[0]) + break; +#endif return (0); } @@ -307,6 +331,9 @@ /* Are we the child? */ if (td->td_retval[1] == 1) td->td_retval[0] = 0; + error = linux_proc_init(td, td->td_retval[0]); + if (error) + return (error); return (0); } @@ -316,6 +343,9 @@ #define CLONE_SIGHAND 0x800 #define CLONE_PID 0x1000 #define CLONE_THREAD 0x10000 +#define CLONE_CHILD_CLEARTID 0x00200000 +#define CLONE_CHILD_SETTID 0x01000000 +#define CLONE_PARENT_SETTID 0x00100000 #define THREADING_FLAGS (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) @@ -326,11 +356,14 @@ struct proc *p2; struct thread *td2; int exit_signal; + struct linux_emuldata *em; #ifdef DEBUG if (ldebug(clone)) { - printf(ARGS(clone, "flags %x, stack %x"), - (unsigned int)args->flags, (unsigned int)args->stack); + printf(ARGS(clone, "flags %x, stack %x, parent tid: %x, + child tid: %x"), + (unsigned int)args->flags, (unsigned int)args->stack, + (unsigned int) args->parent_tidptr, (unsigned int)args->child_tidptr); if (args->flags & CLONE_PID) printf(LMSG("CLONE_PID not yet supported")); } @@ -350,6 +383,7 @@ if (!(args->flags & CLONE_FILES)) ff |= RFFDG; + /* * Attempt to detect when linux_clone(2) is used for creating * kernel threads. Unfortunately despite the existence of the @@ -370,6 +404,29 @@ if (error) return (error); + /* create the emuldata */ + linux_proc_init(td, td->td_retval[0]); + SLIST_FOREACH(em, &emuldata_head, emuldatas) + if (em->pid == td->td_retval[0]) + break; + /* and adjust it */ + if (args->flags & CLONE_PARENT_SETTID) { + if (args->parent_tidptr == NULL) + return (EINVAL); + error = copyout(&td->td_proc->p_pid, args->parent_tidptr, sizeof(td->td_proc->p_pid)); + if (error) + return (error); + } + + if (args->flags & CLONE_CHILD_CLEARTID) + em->child_clear_tid = args->child_tidptr; + else + em->child_clear_tid = NULL; + + if (args->flags & CLONE_CHILD_SETTID) + em->child_set_tid = args->child_tidptr; + else + em->child_set_tid = NULL; PROC_LOCK(p2); p2->p_sigparent = exit_signal; @@ -961,3 +1018,110 @@ return (linux_kill(td, (struct linux_kill_args *) args)); } +static int +linux_proc_init(struct thread *td, pid_t child) +{ + struct linux_emuldata *em, *p_em; + int found = 0; + + /* XXX: locking? */ + MALLOC(em, struct linux_emuldata *, sizeof *em, M_LINUX, M_WAITOK | M_ZERO); + + /* exec call */ + if (child != 0) + em->pid = child; + em->child_clear_tid = NULL; + em->child_set_tid = NULL; + + /* SLIST is inefficient - use hash instead */ + /* find the emuldata for the parent process */ + SLIST_FOREACH(p_em, &emuldata_head, emuldatas) + if (p_em->pid == td->td_proc->p_pid) { + found = 1; + break; + } + + if (found) { + em->clear_tid = p_em->clear_tid; + em->set_tid = p_em->set_tid; + } + + /* we have to free the old emuldata */ + if (child == 0) { + found = 0; + /* lookup the old one */ + SLIST_FOREACH(p_em, &emuldata_head, emuldatas) + if (em->pid == td->td_proc->p_pid) { + found = 1; + break; + } + if (found) + FREE(em, M_LINUX); + } + + SLIST_INSERT_HEAD(&emuldata_head, em, emuldatas); + + /* XXX: sched_lock locking? */ + + return (0); +} + +int +linux_proc_exit(struct thread *td) +{ + struct linux_emuldata *em; + int error; + + /* find the emuldata */ + SLIST_FOREACH(em, &emuldata_head, emuldatas) + if (em->pid == td->td_proc->p_pid) + break; + + if (em->clear_tid != NULL) { + int null = 0; + + error = copyout(&null, em->clear_tid, sizeof(null)); + if (error) + return (error); + + /* TODO: futexes stuff */ + } + + /* clean the stuff up */ + FREE(em, M_LINUX); + + return (0); +} + +int +linux_userret(struct thread *td) +{ + struct linux_emuldata *em; + int error = 0; + + /* find the emuldata */ + SLIST_FOREACH(em, &emuldata_head, emuldatas) + if (em->pid == td->td_proc->p_pid) + break; + + if (em->set_tid != NULL) + error = copyout(&td->td_proc->p_pid, em->set_tid, sizeof(td->td_proc->p_pid)); + + return (error); +} + +int +linux_set_tid_address(struct thread *td, struct linux_set_tid_address_args *args) +{ + struct linux_emuldata *em; + + /* find the emuldata */ + SLIST_FOREACH(em, &emuldata_head, emuldatas) + if (em->pid == td->td_proc->p_pid) + break; + + em->clear_tid = args->tidptr; + td->td_retval[0] = td->td_proc->p_pid; + + return 0; +} ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_proto.h#8 (text+ko) ==== @@ -2,7 +2,7 @@ * System call prototypes. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_proto.h,v 1.72 2006/06/26 18:37:36 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp */ @@ -374,6 +374,8 @@ struct linux_clone_args { char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)]; char stack_l_[PADL_(void *)]; void * stack; char stack_r_[PADR_(void *)]; + char parent_tidptr_l_[PADL_(void *)]; void * parent_tidptr; char parent_tidptr_r_[PADR_(void *)]; + char child_tidptr_l_[PADL_(void *)]; void * child_tidptr; char child_tidptr_r_[PADR_(void *)]; }; struct linux_newuname_args { char buf_l_[PADL_(struct l_new_utsname *)]; struct l_new_utsname * buf; char buf_r_[PADR_(struct l_new_utsname *)]; @@ -724,7 +726,7 @@ register_t dummy; }; struct linux_set_tid_address_args { - register_t dummy; + char tidptr_l_[PADL_(int *)]; int * tidptr; char tidptr_r_[PADR_(int *)]; }; struct linux_timer_create_args { register_t dummy; ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_syscall.h#8 (text+ko) ==== @@ -2,7 +2,7 @@ * System call numbers. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_syscall.h,v 1.66 2006/06/26 18:37:36 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp */ ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysent.c#8 (text+ko) ==== @@ -2,7 +2,7 @@ * System call switch table. * * DO NOT EDIT-- this file is automatically generated. - * $FreeBSD: src/sys/i386/linux/linux_sysent.c,v 1.73 2006/06/26 18:37:36 jhb Exp $ + * $FreeBSD$ * created from FreeBSD: src/sys/i386/linux/syscalls.master,v 1.69 2006/06/26 18:36:16 jhb Exp */ @@ -277,7 +277,7 @@ { SYF_MPSAFE | 0, (sy_call_t *)linux_epoll_ctl, AUE_NULL }, /* 255 = linux_epoll_ctl */ { SYF_MPSAFE | 0, (sy_call_t *)linux_epoll_wait, AUE_NULL }, /* 256 = linux_epoll_wait */ { SYF_MPSAFE | 0, (sy_call_t *)linux_remap_file_pages, AUE_NULL }, /* 257 = linux_remap_file_pages */ - { SYF_MPSAFE | 0, (sy_call_t *)linux_set_tid_address, AUE_NULL }, /* 258 = linux_set_tid_address */ + { SYF_MPSAFE | AS(linux_set_tid_address_args), (sy_call_t *)linux_set_tid_address, AUE_NULL }, /* 258 = linux_set_tid_address */ { SYF_MPSAFE | 0, (sy_call_t *)linux_timer_create, AUE_NULL }, /* 259 = linux_timer_create */ { SYF_MPSAFE | 0, (sy_call_t *)linux_timer_settime, AUE_NULL }, /* 260 = linux_timer_settime */ { SYF_MPSAFE | 0, (sy_call_t *)linux_timer_gettime, AUE_NULL }, /* 261 = linux_timer_gettime */ ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/linux_sysvec.c#5 (text+ko) ==== @@ -91,6 +91,7 @@ extern int linux_szsigcode; extern struct sysent linux_sysent[LINUX_SYS_MAXSYSCALL]; +extern SLIST_HEAD(emuldata_head, linux_emuldata) emuldata_head; SET_DECLARE(linux_ioctl_handler_set, struct linux_ioctl_handler); SET_DECLARE(linux_device_handler_set, struct linux_device_handler); @@ -105,6 +106,12 @@ static void exec_linux_setregs(struct thread *td, u_long entry, u_long stack, u_long ps_strings); +extern int (*linux_proc_exit_p)(struct thread *); +extern int (*linux_userret_p)(struct thread *); + +extern int linux_userret(struct thread *); +extern int linux_proc_exit(struct thread *); + /* * Linux syscalls return negative errno's, we do positive and map them */ @@ -907,6 +914,9 @@ printf("Linux ELF exec handler installed\n"); } else printf("cannot insert Linux ELF brand handler\n"); + SLIST_INIT(&emuldata_head); + linux_proc_exit_p = linux_proc_exit; + linux_userret_p = linux_userret; break; case MOD_UNLOAD: for (brandinfo = &linux_brandlist[0]; *brandinfo != NULL; @@ -928,6 +938,8 @@ printf("Linux ELF exec handler removed\n"); } else printf("Could not deinstall ELF interpreter entry\n"); + linux_proc_exit_p = NULL; + linux_userret_p = NULL; break; default: return EOPNOTSUPP; ==== //depot/projects/soc2006/rdivacky_linuxolator/i386/linux/syscalls.master#8 (text+ko) ==== @@ -219,7 +219,8 @@ 118 AUE_FSYNC MNOPROTO { int fsync(int fd); } 119 AUE_SIGRETURN MSTD { int linux_sigreturn( \ struct l_sigframe *sfp); } -120 AUE_RFORK MSTD { int linux_clone(l_int flags, void *stack); } +120 AUE_RFORK MSTD { int linux_clone(l_int flags, void *stack, \ + void *parent_tidptr, void * child_tidptr); } 121 AUE_SYSCTL MNOPROTO { int setdomainname(char *name, \ int len); } 122 AUE_NULL MSTD { int linux_newuname( \ @@ -424,7 +425,7 @@ 255 AUE_NULL MSTD { int linux_epoll_ctl(void); } 256 AUE_NULL MSTD { int linux_epoll_wait(void); } 257 AUE_NULL MSTD { int linux_remap_file_pages(void); } -258 AUE_NULL MSTD { int linux_set_tid_address(void); } +258 AUE_NULL MSTD { int linux_set_tid_address(int *tidptr); } 259 AUE_NULL MSTD { int linux_timer_create(void); } 260 AUE_NULL MSTD { int linux_timer_settime(void); } 261 AUE_NULL MSTD { int linux_timer_gettime(void); } ==== //depot/projects/soc2006/rdivacky_linuxolator/kern/kern_exit.c#3 (text+ko) ==== @@ -87,6 +87,7 @@ /* Hook for NFS teardown procedure. */ void (*nlminfo_release_p)(struct proc *p); +int (*linux_proc_exit_p)(struct thread *) = NULL; /* necessary for linuxolator */ /* * exit -- @@ -236,6 +237,9 @@ */ EVENTHANDLER_INVOKE(process_exit, p); + /* we have to call linux exit hook */ + if (p->p_flag & P_LINUX && linux_proc_exit_p != NULL) + (linux_proc_exit_p)(td); MALLOC(p->p_ru, struct rusage *, sizeof(struct rusage), M_ZOMBIE, M_WAITOK); /* ==== //depot/projects/soc2006/rdivacky_linuxolator/kern/subr_trap.c#2 (text+ko) ==== @@ -67,6 +67,8 @@ #include #include +int (*linux_userret_p)(struct thread *) = NULL; /* for linuxolator */ + /* * Define the code needed before returning to user mode, for * trap and syscall. @@ -128,6 +130,10 @@ addupc_task(td, TRAPF_PC(frame), td->td_pticks * psratio); } + /* linux userret */ + if (p->p_flag & P_LINUX && linux_userret_p != NULL) + (linux_userret_p)(td); + /* * Let the scheduler adjust our priority etc. */ ==== //depot/projects/soc2006/rdivacky_linuxolator/sys/proc.h#2 (text+ko) ==== @@ -655,6 +655,7 @@ #define P_HWPMC 0x800000 /* Process is using HWPMCs */ #define P_JAILED 0x1000000 /* Process is in jail. */ +#define P_LINUX 0x2000000 /* linux binary */ #define P_INEXEC 0x4000000 /* Process is in execve(). */ #define P_STATCHILD 0x8000000 /* Child process stopped or exited. */