svn commit: r279496 - head/sys/powerpc/powerpc

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sun Mar 1 21:20:19 UTC 2015


Author: nwhitehorn
Date: Sun Mar  1 21:20:18 2015
New Revision: 279496
URL: https://svnweb.freebsd.org/changeset/base/279496

Log:
  Merge r278429 from ppc64:
  
  Fix an extremely subtle concurrency bug triggered by running on 32-thread
  POWER8 systems. During thread switch, there was a very small window when
  the stack pointer was set to the stack pointer of the outgoing thread, but
  after the lock on that thread had already been released.
  
  If, during that window, the outgoing thread were rescheduled on another CPU
  and begin execution and an exception were taken on the original CPU, the
  trap handler and the outgoing thread would simultaneously execute on the same
  stack, causing memory corruption. Fix this by making sure to release the
  old thread only after cpu_switch() is done with its stack.
  
  MFC after:	2 weeks

Modified:
  head/sys/powerpc/powerpc/swtch32.S

Modified: head/sys/powerpc/powerpc/swtch32.S
==============================================================================
--- head/sys/powerpc/powerpc/swtch32.S	Sun Mar  1 21:03:34 2015	(r279495)
+++ head/sys/powerpc/powerpc/swtch32.S	Sun Mar  1 21:20:18 2015	(r279496)
@@ -71,6 +71,8 @@
  */
 ENTRY(cpu_throw)
 	mr	%r2, %r4
+	li	%r14,0	/* Tell cpu_switchin not to release a thread */
+
 	b	cpu_switchin
 
 /*
@@ -119,7 +121,6 @@ ENTRY(cpu_switch)
 	bl	pmap_deactivate		/* Deactivate the current pmap */
 
 	sync				/* Make sure all of that finished */
-	stw	%r16,TD_LOCK(%r14)	/* ULE:	update old thread's lock */
 
 cpu_switchin:
 #if defined(SMP) && defined(SCHED_ULE)
@@ -133,7 +134,15 @@ blocked_loop:
 	isync
 #endif
 
-	mfsprg	%r7,0			/* Get the pcpu pointer */
+	lwz	%r17,TD_PCB(%r2)	/* Get new current PCB */
+	lwz	%r1,PCB_SP(%r17)	/* Load new stack pointer */
+
+	/* Release old thread now that we have a stack pointer set up */
+	cmpwi	%r14,0
+	beq-	1f
+	stw	%r16,TD_LOCK(%r14)	/* ULE:	update old thread's lock */
+
+1:	mfsprg	%r7,0			/* Get the pcpu pointer */
 	stw	%r2,PC_CURTHREAD(%r7)	/* Store new current thread */
 	lwz	%r17,TD_PCB(%r2)	/* Store new current PCB */
 	stw	%r17,PC_CURPCB(%r7)


More information about the svn-src-head mailing list