svn commit: r214835 - in head/sys: amd64/amd64 arm/arm i386/i386 ia64/ia64 mips/mips pc98/pc98 powerpc/aim powerpc/booke sparc64/sparc64 sun4v/sun4v

John Baldwin jhb at FreeBSD.org
Fri Nov 5 13:42:59 UTC 2010


Author: jhb
Date: Fri Nov  5 13:42:58 2010
New Revision: 214835
URL: http://svn.freebsd.org/changeset/base/214835

Log:
  Adjust the order of operations in spinlock_enter() and spinlock_exit() to
  work properly with single-stepping in a kernel debugger.  Specifically,
  these routines have always disabled interrupts before increasing the nesting
  count and restored the prior state of interrupts after decreasing the nesting
  count to avoid problems with a nested interrupt not disabling interrupts
  when acquiring a spin lock.  However, trap interrupts for single-stepping
  can still occur even when interrupts are disabled.  Now the saved state of
  interrupts is not saved in the thread until after interrupts have been
  disabled and the nesting count has been increased.  Similarly, the saved
  state from the thread cannot be read once the nesting count has been
  decreased to zero.  To fix this, use temporary variables to store interrupt
  state and shuffle it between the thread's MD area and the appropriate
  registers.
  
  In cooperation with:	bde
  MFC after:     1 month

Modified:
  head/sys/amd64/amd64/machdep.c
  head/sys/arm/arm/machdep.c
  head/sys/i386/i386/machdep.c
  head/sys/ia64/ia64/machdep.c
  head/sys/mips/mips/machdep.c
  head/sys/pc98/pc98/machdep.c
  head/sys/powerpc/aim/machdep.c
  head/sys/powerpc/booke/machdep.c
  head/sys/sparc64/sparc64/machdep.c
  head/sys/sun4v/sun4v/machdep.c

Modified: head/sys/amd64/amd64/machdep.c
==============================================================================
--- head/sys/amd64/amd64/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/amd64/amd64/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -1762,11 +1762,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_flags = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		flags = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_flags = flags;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -1774,12 +1778,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
 	critical_exit();
+	flags = td->td_md.md_saved_flags;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_flags);
+		intr_restore(flags);
 }
 
 /*

Modified: head/sys/arm/arm/machdep.c
==============================================================================
--- head/sys/arm/arm/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/arm/arm/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -493,11 +493,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t cspr;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_cspr = disable_interrupts(I32_bit | F32_bit);
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		cspr = disable_interrupts(I32_bit | F32_bit);
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_cspr = cspr;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -505,12 +509,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t cspr;
 
 	td = curthread;
 	critical_exit();
+	cspr = td->td_md.md_saved_cspr;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		restore_interrupts(td->td_md.md_saved_cspr);
+		restore_interrupts(cspr);
 }
 
 /*

Modified: head/sys/i386/i386/machdep.c
==============================================================================
--- head/sys/i386/i386/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/i386/i386/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -2997,11 +2997,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_flags = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		flags = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_flags = flags;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -3009,12 +3013,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
 	critical_exit();
+	flags = td->td_md.md_saved_flags;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_flags);
+		intr_restore(flags);
 }
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)

Modified: head/sys/ia64/ia64/machdep.c
==============================================================================
--- head/sys/ia64/ia64/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/ia64/ia64/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -513,11 +513,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	int intr;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_intr = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		intr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_intr = intr;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -525,12 +529,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	int intr;
 
 	td = curthread;
 	critical_exit();
+	intr = td->td_md.md_saved_intr;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_intr);
+		intr_restore(intr);
 }
 
 void

Modified: head/sys/mips/mips/machdep.c
==============================================================================
--- head/sys/mips/mips/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/mips/mips/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -450,11 +450,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t intr;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_intr = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		intr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_intr = intr;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -462,12 +466,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t intr;
 
 	td = curthread;
 	critical_exit();
+	intr = td->td_md.md_saved_intr;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_intr);
+		intr_restore(intr);
 }
 
 /*

Modified: head/sys/pc98/pc98/machdep.c
==============================================================================
--- head/sys/pc98/pc98/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/pc98/pc98/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -2340,11 +2340,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_flags = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		flags = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_flags = flags;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -2352,12 +2356,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t flags;
 
 	td = curthread;
 	critical_exit();
+	flags = td->td_md.md_saved_flags;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_flags);
+		intr_restore(flags);
 }
 
 #if defined(I586_CPU) && !defined(NO_F00F_HACK)

Modified: head/sys/powerpc/aim/machdep.c
==============================================================================
--- head/sys/powerpc/aim/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/powerpc/aim/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -751,11 +751,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t msr;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_msr = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		msr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_msr = msr;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -763,12 +767,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t msr;
 
 	td = curthread;
 	critical_exit();
+	msr = td->td_md.md_saved_msr;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_msr);
+		intr_restore(msr);
 }
 
 /*

Modified: head/sys/powerpc/booke/machdep.c
==============================================================================
--- head/sys/powerpc/booke/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/powerpc/booke/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -516,11 +516,15 @@ void
 spinlock_enter(void)
 {
 	struct thread *td;
+	register_t msr;
 
 	td = curthread;
-	if (td->td_md.md_spinlock_count == 0)
-		td->td_md.md_saved_msr = intr_disable();
-	td->td_md.md_spinlock_count++;
+	if (td->td_md.md_spinlock_count == 0) {
+		msr = intr_disable();
+		td->td_md.md_spinlock_count = 1;
+		td->td_md.md_saved_msr = msr;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -528,12 +532,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t msr;
 
 	td = curthread;
 	critical_exit();
+	msr = td->td_md.md_saved_msr;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		intr_restore(td->td_md.md_saved_msr);
+		intr_restore(msr);
 }
 
 /* Shutdown the CPU as much as possible. */

Modified: head/sys/sparc64/sparc64/machdep.c
==============================================================================
--- head/sys/sparc64/sparc64/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/sparc64/sparc64/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -224,9 +224,10 @@ spinlock_enter(void)
 	if (td->td_md.md_spinlock_count == 0) {
 		pil = rdpr(pil);
 		wrpr(pil, 0, PIL_TICK);
+		td->td_md.md_spinlock_count = 1;
 		td->td_md.md_saved_pil = pil;
-	}
-	td->td_md.md_spinlock_count++;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -234,12 +235,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t pil;
 
 	td = curthread;
 	critical_exit();
+	pil = td->td_md.md_saved_pil;
 	td->td_md.md_spinlock_count--;
 	if (td->td_md.md_spinlock_count == 0)
-		wrpr(pil, td->td_md.md_saved_pil, 0);
+		wrpr(pil, pil, 0);
 }
 
 static phandle_t

Modified: head/sys/sun4v/sun4v/machdep.c
==============================================================================
--- head/sys/sun4v/sun4v/machdep.c	Fri Nov  5 11:31:39 2010	(r214834)
+++ head/sys/sun4v/sun4v/machdep.c	Fri Nov  5 13:42:58 2010	(r214835)
@@ -269,9 +269,10 @@ spinlock_enter(void)
 	td = curthread;
 	if (td->td_md.md_spinlock_count == 0) {
 		pil = intr_disable();
+		td->td_md.md_spinlock_count = 1;
 		td->td_md.md_saved_pil = pil;
-	}
-	td->td_md.md_spinlock_count++;
+	} else
+		td->td_md.md_spinlock_count++;
 	critical_enter();
 }
 
@@ -279,14 +280,14 @@ void
 spinlock_exit(void)
 {
 	struct thread *td;
+	register_t pil;
 
 	td = curthread;
 	critical_exit();
+	pil = td->td_md.md_saved_pil;
 	td->td_md.md_spinlock_count--;
-	if (td->td_md.md_spinlock_count == 0) {
-		intr_restore(td->td_md.md_saved_pil);
-	}
-
+	if (td->td_md.md_spinlock_count == 0)
+		intr_restore(pil);
 }
 
 unsigned


More information about the svn-src-head mailing list