Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 29 Nov 2018 03:39:11 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r341177 - head/sys/powerpc/powerpc
Message-ID:  <201811290339.wAT3dBqf027972@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Thu Nov 29 03:39:11 2018
New Revision: 341177
URL: https://svnweb.freebsd.org/changeset/base/341177

Log:
  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

Modified:
  head/sys/powerpc/powerpc/exec_machdep.c

Modified: head/sys/powerpc/powerpc/exec_machdep.c
==============================================================================
--- head/sys/powerpc/powerpc/exec_machdep.c	Thu Nov 29 02:52:08 2018	(r341176)
+++ head/sys/powerpc/powerpc/exec_machdep.c	Thu Nov 29 03:39:11 2018	(r341177)
@@ -124,6 +124,10 @@ static int	grab_mcontext32(struct thread *td, mcontext
 
 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 *
 		#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
 	}



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