svn commit: r199442 - head/sys/sparc64/sparc64

Marius Strobl marius at FreeBSD.org
Tue Nov 17 21:08:11 UTC 2009


Author: marius
Date: Tue Nov 17 21:08:10 2009
New Revision: 199442
URL: http://svn.freebsd.org/changeset/base/199442

Log:
  Unroll copying of the registers in {g,s}et_mcontext() and limit it
  to the set actually restored by tl0_ret() instead of using the whole
  trapframe. Additionally skip %g7 as that register is used as the
  userland TLS pointer.
  
  PR:		140523
  MFC after:	1 week

Modified:
  head/sys/sparc64/sparc64/machdep.c

Modified: head/sys/sparc64/sparc64/machdep.c
==============================================================================
--- head/sys/sparc64/sparc64/machdep.c	Tue Nov 17 21:00:02 2009	(r199441)
+++ head/sys/sparc64/sparc64/machdep.c	Tue Nov 17 21:08:10 2009	(r199442)
@@ -692,12 +692,39 @@ get_mcontext(struct thread *td, mcontext
 
 	tf = td->td_frame;
 	pcb = td->td_pcb;
-	bcopy(tf, mc, sizeof(*tf));
+	/*
+	 * Copy the registers which will be restored by tl0_ret() from the
+	 * trapframe.
+	 * Note that we skip %g7 which is used as the userland TLS register
+	 * and %wstate.
+	 */
+	mc->mc_flags = _MC_VERSION;
+	mc->mc_global[1] = tf->tf_global[1];
+	mc->mc_global[2] = tf->tf_global[2];
+	mc->mc_global[3] = tf->tf_global[3];
+	mc->mc_global[4] = tf->tf_global[4];
+	mc->mc_global[5] = tf->tf_global[5];
+	mc->mc_global[6] = tf->tf_global[6];
 	if (flags & GET_MC_CLEAR_RET) {
 		mc->mc_out[0] = 0;
 		mc->mc_out[1] = 0;
+	} else {
+		mc->mc_out[0] = tf->tf_out[0];
+		mc->mc_out[1] = tf->tf_out[1];
 	}
-	mc->mc_flags = _MC_VERSION;
+	mc->mc_out[2] = tf->tf_out[2];
+	mc->mc_out[3] = tf->tf_out[3];
+	mc->mc_out[4] = tf->tf_out[4];
+	mc->mc_out[5] = tf->tf_out[5];
+	mc->mc_out[6] = tf->tf_out[6];
+	mc->mc_out[7] = tf->tf_out[7];
+	mc->mc_fprs = tf->tf_fprs;
+	mc->mc_fsr = tf->tf_fsr;
+	mc->mc_gsr = tf->tf_gsr;
+	mc->mc_tnpc = tf->tf_tnpc;
+	mc->mc_tpc = tf->tf_tpc;
+	mc->mc_tstate = tf->tf_tstate;
+	mc->mc_y = tf->tf_y;
 	critical_enter();
 	if ((tf->tf_fprs & FPRS_FEF) != 0) {
 		savefpctx(pcb->pcb_ufp);
@@ -717,7 +744,6 @@ set_mcontext(struct thread *td, const mc
 {
 	struct trapframe *tf;
 	struct pcb *pcb;
-	uint64_t wstate;
 
 	if (!TSTATE_SECURE(mc->mc_tstate) ||
 	    (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION)
@@ -726,9 +752,33 @@ set_mcontext(struct thread *td, const mc
 	pcb = td->td_pcb;
 	/* Make sure the windows are spilled first. */
 	flushw();
-	wstate = tf->tf_wstate;
-	bcopy(mc, tf, sizeof(*tf));
-	tf->tf_wstate = wstate;
+	/*
+	 * Copy the registers which will be restored by tl0_ret() to the
+	 * trapframe.
+	 * Note that we skip %g7 which is used as the userland TLS register
+	 * and %wstate.
+	 */
+	tf->tf_global[1] = mc->mc_global[1];
+	tf->tf_global[2] = mc->mc_global[2];
+	tf->tf_global[3] = mc->mc_global[3];
+	tf->tf_global[4] = mc->mc_global[4];
+	tf->tf_global[5] = mc->mc_global[5];
+	tf->tf_global[6] = mc->mc_global[6];
+	tf->tf_out[0] = mc->mc_out[0];
+	tf->tf_out[1] = mc->mc_out[1];
+	tf->tf_out[2] = mc->mc_out[2];
+	tf->tf_out[3] = mc->mc_out[3];
+	tf->tf_out[4] = mc->mc_out[4];
+	tf->tf_out[5] = mc->mc_out[5];
+	tf->tf_out[6] = mc->mc_out[6];
+	tf->tf_out[7] = mc->mc_out[7];
+	tf->tf_fprs = mc->mc_fprs;
+	tf->tf_fsr = mc->mc_fsr;
+	tf->tf_gsr = mc->mc_gsr;
+	tf->tf_tnpc = mc->mc_tnpc;
+	tf->tf_tpc = mc->mc_tpc;
+	tf->tf_tstate = mc->mc_tstate;
+	tf->tf_y = mc->mc_y;
 	if ((mc->mc_fprs & FPRS_FEF) != 0) {
 		tf->tf_fprs = 0;
 		bcopy(mc->mc_fp, pcb->pcb_ufp, sizeof(pcb->pcb_ufp));


More information about the svn-src-head mailing list