Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 6 Jul 2006 11:05:19 GMT
From:      Roman Divacky <rdivacky@FreeBSD.org>
To:        Perforce Change Reviews <perforce@FreeBSD.org>
Subject:   PERFORCE change 100719 for review
Message-ID:  <200607061105.k66B5JKG065286@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <sys/mman.h>
 #include <sys/mutex.h>
 #include <sys/proc.h>
+#include <sys/queue.h>
 #include <sys/resource.h>
 #include <sys/resourcevar.h>
 #include <sys/signalvar.h>
@@ -61,6 +62,14 @@
 
 #include <i386/include/pcb.h>			/* 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 <machine/cpu.h>
 #include <machine/pcb.h>
 
+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. */
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200607061105.k66B5JKG065286>