From f4a80449ce4a08aa63cfceb50dab983bc589eeab Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Thu, 29 Nov 2018 03:39:11 +0000 Subject: [PATCH] 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 --- sys/powerpc/powerpc/exec_machdep.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sys/powerpc/powerpc/exec_machdep.c b/sys/powerpc/powerpc/exec_machdep.c index 58373509934..c506373ed5b 100644 --- a/sys/powerpc/powerpc/exec_machdep.c +++ b/sys/powerpc/powerpc/exec_machdep.c @@ -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 }