svn commit: r258811 - head/sys/powerpc/ofw

Nathan Whitehorn nwhitehorn at FreeBSD.org
Sun Dec 1 19:59:37 UTC 2013


Author: nwhitehorn
Date: Sun Dec  1 19:59:36 2013
New Revision: 258811
URL: http://svnweb.freebsd.org/changeset/base/258811

Log:
  Revert last few revisions; apologies for the noise. There are very rare,
  broken systems that require SPRG state to be preserved.

Modified:
  head/sys/powerpc/ofw/ofw_machdep.c

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c	Sun Dec  1 19:56:30 2013	(r258810)
+++ head/sys/powerpc/ofw/ofw_machdep.c	Sun Dec  1 19:59:36 2013	(r258811)
@@ -90,6 +90,49 @@ ofw_restore_trap_vec(char *restore_trap_
 	bcopy(restore_trap_vec, (void *)EXC_RST, EXC_LAST - EXC_RST);
 	__syncicache(EXC_RSVD, EXC_LAST - EXC_RSVD);
 }
+
+/*
+ * Saved SPRG0-3 from OpenFirmware. Will be restored prior to the callback.
+ */
+register_t	ofw_sprg0_save;
+
+static __inline void
+ofw_sprg_prepare(void)
+{
+	if (ofw_real_mode)
+		return;
+	
+	/*
+	 * Assume that interrupt are disabled at this point, or
+	 * SPRG1-3 could be trashed
+	 */
+	__asm __volatile("mfsprg0 %0\n\t"
+			 "mtsprg0 %1\n\t"
+	    		 "mtsprg1 %2\n\t"
+	    		 "mtsprg2 %3\n\t"
+			 "mtsprg3 %4\n\t"
+			 : "=&r"(ofw_sprg0_save)
+			 : "r"(ofmsr[1]),
+			 "r"(ofmsr[2]),
+			 "r"(ofmsr[3]),
+			 "r"(ofmsr[4]));
+}
+
+static __inline void
+ofw_sprg_restore(void)
+{
+	if (ofw_real_mode)
+		return;
+	
+	/*
+	 * Note that SPRG1-3 contents are irrelevant. They are scratch
+	 * registers used in the early portion of trap handling when
+	 * interrupts are disabled.
+	 *
+	 * PCPU data cannot be used until this routine is called !
+	 */
+	__asm __volatile("mtsprg0 %0" :: "r"(ofw_sprg0_save));
+}
 #endif
 
 static int
@@ -287,10 +330,13 @@ openfirmware_core(void *args)
 
 	/*
 	 * Turn off exceptions - we really don't want to end up
-	 * anywhere in the kernel while in OF state.
+	 * anywhere unexpected with PCPU set to something strange
+	 * or the stack pointer wrong.
 	 */
 	oldmsr = intr_disable();
 
+	ofw_sprg_prepare();
+
 	/* Save trap vectors */
 	ofw_save_trap_vec(save_trap_of);
 
@@ -312,6 +358,8 @@ openfirmware_core(void *args)
 	/* Restore trap vecotrs */
 	ofw_restore_trap_vec(save_trap_of);
 
+	ofw_sprg_restore();
+
 	intr_restore(oldmsr);
 
 	return (result);


More information about the svn-src-head mailing list