Sync the MI parts for amd64 with i386 and remove the corresponding special

handling for amd64 in the common code. The MD parts for amd64 are still
outstanding, but at least this fixes some panics on amd64.

Sponsored by:	Google SoC 2006
Submitted by:	rdivacky
Tested by:	bsam
This commit is contained in:
Alexander Leidinger 2006-08-20 13:50:27 +00:00
parent f4cc92c97c
commit 1a28c0df09
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=161474
2 changed files with 90 additions and 16 deletions

View File

@ -60,6 +60,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_ipc.h>
#include <compat/linux/linux_signal.h>
#include <compat/linux/linux_util.h>
#include <compat/linux/linux_emul.h>
struct l_old_select_argv {
l_int nfds;
@ -211,6 +212,14 @@ linux_execve(struct thread *td, struct linux_execve_args *args)
free(path, M_TEMP);
if (error == 0)
error = kern_execve(td, &eargs, NULL);
if (error == 0)
/* linux process can exec fbsd one, dont attempt
* to create emuldata for such process using
* linux_proc_init, this leads to a panic on KASSERT
* because such process has p->p_emuldata == NULL
*/
if (td->td_proc->p_sysent == &elf_linux_sysvec)
error = linux_proc_init(td, 0, 0);
return (error);
}
@ -452,6 +461,10 @@ linux_fork(struct thread *td, struct linux_fork_args *args)
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
error = linux_proc_init(td, td->td_retval[0], 0);
if (error)
return (error);
return (0);
}
@ -470,6 +483,9 @@ linux_vfork(struct thread *td, struct linux_vfork_args *args)
/* Are we the child? */
if (td->td_retval[1] == 1)
td->td_retval[0] = 0;
error = linux_proc_init(td, td->td_retval[0], 0);
if (error)
return (error);
return (0);
}
@ -480,12 +496,14 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
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)(uintptr_t)args->flags,
(unsigned int)(uintptr_t)args->stack);
printf(ARGS(clone, "flags %x, stack %x, parent tid: %x, child tid: %x"),
(unsigned int)args->flags, (unsigned int)(uintptr_t)args->stack,
(unsigned int)(uintptr_t)args->parent_tidptr,
(unsigned int)(uintptr_t)args->child_tidptr);
}
#endif
@ -503,10 +521,74 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
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
* CLONE_THREAD flag, version of linuxthreads package used in
* most popular distros as of beginning of 2005 doesn't make
* any use of it. Therefore, this detection relay fully on
* empirical observation that linuxthreads sets certain
* combination of flags, so that we can make more or less
* precise detection and notify the FreeBSD kernel that several
* processes are in fact part of the same threading group, so
* that special treatment is necessary for signal delivery
* between those processes and fd locking.
*/
if ((args->flags & 0xffffff00) == THREADING_FLAGS)
ff |= RFTHREAD;
error = fork1(td, ff, 0, &p2);
if (error)
return (error);
/* create the emuldata */
error = linux_proc_init(td, p2->p_pid, args->flags);
/* reference it - no need to check this */
em = em_find(p2, EMUL_UNLOCKED);
KASSERT(em != NULL, ("clone: emuldata not found.\n"));
/* and adjust it */
if (args->flags & CLONE_PARENT_SETTID) {
if (args->parent_tidptr == NULL) {
EMUL_UNLOCK(&emul_lock);
return (EINVAL);
}
error = copyout(&p2->p_pid, args->parent_tidptr, sizeof(p2->p_pid));
if (error) {
EMUL_UNLOCK(&emul_lock);
return (error);
}
}
if (args->flags & CLONE_PARENT) {
#ifdef DEBUG
printf("linux_clone: CLONE_PARENT\n");
#endif
}
if (args->flags & CLONE_THREAD) {
/* XXX: linux mangles pgrp and pptr somehow
* I think it might be this but I am not sure.
*/
#ifdef notyet
p2->p_pgrp = td->td_proc->p_pgrp;
p2->p_pptr = td->td_proc->p_pptr;
#endif
exit_signal = 0;
#ifdef DEBUG
printf("linux_clone: CLONE_THREADS\n");
#endif
}
if (args->flags & CLONE_CHILD_SETTID)
em->child_set_tid = args->child_tidptr;
else
em->child_set_tid = NULL;
if (args->flags & CLONE_CHILD_CLEARTID)
em->child_clear_tid = args->child_tidptr;
else
em->child_clear_tid = NULL;
EMUL_UNLOCK(&emul_lock);
PROC_LOCK(p2);
p2->p_sigparent = exit_signal;
@ -519,6 +601,10 @@ linux_clone(struct thread *td, struct linux_clone_args *args)
if (args->stack)
td2->td_frame->tf_rsp = PTROUT(args->stack);
if (args->flags & CLONE_SETTLS) {
/* XXX: todo */
}
#ifdef DEBUG
if (ldebug(clone))
printf(LMSG("clone: successful rfork to %ld, stack %p sig = %d"),

View File

@ -1331,7 +1331,6 @@ linux_reboot(struct thread *td, struct linux_reboot_args *args)
int
linux_getpid(struct thread *td, struct linux_getpid_args *args)
{
#ifdef __i386__
struct linux_emuldata *em;
char osrel[LINUX_MAX_UTSNAME];
@ -1346,11 +1345,7 @@ linux_getpid(struct thread *td, struct linux_getpid_args *args)
td->td_retval[0] = td->td_proc->p_pid;
PROC_UNLOCK(td->td_proc);
}
#else
PROC_LOCK(td->td_proc);
td->td_retval[0] = td->td_proc->p_pid;
PROC_UNLOCK(td->td_proc);
#endif
return (0);
}
@ -1370,7 +1365,6 @@ linux_gettid(struct thread *td, struct linux_gettid_args *args)
int
linux_getppid(struct thread *td, struct linux_getppid_args *args)
{
#ifdef __i386__
struct linux_emuldata *em;
struct proc *p, *pp;
char osrel[LINUX_MAX_UTSNAME];
@ -1412,9 +1406,6 @@ linux_getppid(struct thread *td, struct linux_getppid_args *args)
EMUL_UNLOCK(&emul_lock);
PROC_UNLOCK(pp);
#else
return getppid(td, (struct getppid_args *) args);
#endif
return (0);
}
@ -1481,7 +1472,6 @@ linux_sethostname(struct thread *td, struct linux_sethostname_args *args)
int
linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
{
#ifdef __i386__
struct linux_emuldata *em, *td_em, *tmp_em;
struct proc *sp;
char osrel[LINUX_MAX_UTSNAME];
@ -1513,10 +1503,8 @@ linux_exit_group(struct thread *td, struct linux_exit_group_args *args)
EMUL_SHARED_RUNLOCK(&emul_shared_lock);
EMUL_UNLOCK(&emul_lock);
}
#endif
exit1(td, W_EXITCODE(args->error_code,0));
return (0);
}