Fix thread creation in PowerPC64 ELFv2 processes.

Summary:
Currently, the upcall used to create threads assumes ELFv1.

Instead, we should check which sysentvec is in use on the process and act
accordingly.

This makes ELFv2 threaded processes work.

Submitted by:	git_bdragon.rtk0.net
Differential Revision: https://reviews.freebsd.org/D18330
This commit is contained in:
Justin Hibbits 2018-11-29 03:39:11 +00:00
parent 1e9a1bf589
commit f4a80449ce

View File

@ -124,6 +124,10 @@ static int grab_mcontext32(struct thread *td, mcontext32_t *, int flags);
static int grab_mcontext(struct thread *, mcontext_t *, int);
#ifdef __powerpc64__
extern struct sysentvec elf64_freebsd_sysvec_v2;
#endif
void
sendsig(sig_t catcher, ksiginfo_t *ksi, sigset_t *mask)
{
@ -1014,11 +1018,18 @@ cpu_set_upcall(struct thread *td, void (*entry)(void *), void *arg,
#endif
} else {
#ifdef __powerpc64__
register_t entry_desc[3];
(void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
tf->srr0 = entry_desc[0];
tf->fixreg[2] = entry_desc[1];
tf->fixreg[11] = entry_desc[2];
if (td->td_proc->p_sysent == &elf64_freebsd_sysvec_v2) {
tf->srr0 = (register_t)entry;
/* ELFv2 ABI requires that the global entry point be in r12. */
tf->fixreg[12] = (register_t)entry;
}
else {
register_t entry_desc[3];
(void)copyin((void *)entry, entry_desc, sizeof(entry_desc));
tf->srr0 = entry_desc[0];
tf->fixreg[2] = entry_desc[1];
tf->fixreg[11] = entry_desc[2];
}
tf->srr1 = psl_userset | PSL_FE_DFLT;
#endif
}