svn commit: r197805 - in projects/ppc64/sys/powerpc: aim aim64

Nathan Whitehorn nwhitehorn at FreeBSD.org
Tue Oct 6 15:44:09 UTC 2009


Author: nwhitehorn
Date: Tue Oct  6 15:44:08 2009
New Revision: 197805
URL: http://svn.freebsd.org/changeset/base/197805

Log:
  Add even more paranoia to the 32-bit OF thunk, and also sprinkle some
  in ofw_machdep.c. This fixes a problem where the system could take
  an interrupt in the middle of a firmware call, and then end in the trap
  handler with a trashed PCPU pointer and a wrong stack pointer, with the
  expected ensuing hilarity.
  
  This fixes the last known problem on hardware -- both my XServe and the
  Cell simulator successfully mount root and then complain that the userland
  does not exist yet.

Modified:
  projects/ppc64/sys/powerpc/aim/ofw_machdep.c
  projects/ppc64/sys/powerpc/aim64/locore.S

Modified: projects/ppc64/sys/powerpc/aim/ofw_machdep.c
==============================================================================
--- projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Tue Oct  6 14:05:57 2009	(r197804)
+++ projects/ppc64/sys/powerpc/aim/ofw_machdep.c	Tue Oct  6 15:44:08 2009	(r197805)
@@ -367,12 +367,19 @@ static int
 openfirmware(void *args)
 {
 	int		result;
+	register_t	oldmsr;
 	#ifndef __powerpc64__
-	long		oldmsr;
 	register_t	srsave[16];
 	u_int		i;
 	#endif
 
+	/*
+	 * Turn off exceptions - we really don't want to end up
+	 * anywhere unexpected with PCPU set to something strange,
+	 * the stack pointer wrong, or the OFW mapping enabled.
+	 */
+	oldmsr = intr_disable();
+
 	if (pmap_bootstrapped && ofw_real_mode)
 		args = (void *)pmap_kextract((vm_offset_t)args);
 
@@ -398,26 +405,11 @@ openfirmware(void *args)
 		}
 		isync();
 	}
-
-	__asm __volatile(	"\t"
-		"sync\n\t"
-		"mfmsr  %0\n\t"
-		"mtmsr  %1\n\t"
-		"isync\n"
-		: "=r" (oldmsr)
-		: "r" (ofmsr[0])
-	);
       #endif
 
        	result = ofwcall(args);
 
       #ifndef __powerpc64__
-	__asm(	"\t"
-		"mtmsr  %0\n\t"
-		"isync\n"
-		: : "r" (oldmsr)
-	);
-
 	if (pmap_bootstrapped && !ofw_real_mode) {
 		/*
 		 * Restore the kernel's addr space. The isync() doesn;t
@@ -434,6 +426,8 @@ openfirmware(void *args)
 
 	ofw_sprg_restore();
 
+	intr_restore(oldmsr);
+
 	return (result);
 }
 

Modified: projects/ppc64/sys/powerpc/aim64/locore.S
==============================================================================
--- projects/ppc64/sys/powerpc/aim64/locore.S	Tue Oct  6 14:05:57 2009	(r197804)
+++ projects/ppc64/sys/powerpc/aim64/locore.S	Tue Oct  6 15:44:08 2009	(r197805)
@@ -216,7 +216,7 @@ tocbase:
 ASENTRY(ofw_32bit_mode_entry)
 	mflr	%r0
 	std	%r0,16(%r1)
-	stdu	%r1,-224(%r1)
+	stdu	%r1,-208(%r1)
 
 	/*
 	 * We need to save the following, because OF's register save/
@@ -246,47 +246,51 @@ ASENTRY(ofw_32bit_mode_entry)
 	std	%r29,184(%r1)
 	std	%r30,192(%r1)
 	std	%r31,200(%r1)
-	std	%r2,208(%r1)
 
-	/* Save the old MSR */
-	mfmsr	%r4
-	std	%r4,216(%r1)
-	mr	%r14,%r4	/* Save in a non-volatile reg */
+	/* Record the old MSR */
+	mfmsr	%r6
 
+	/* read client interface handler */
 	lis	%r4,openfirmware_entry at ha
-	ld	%r4,openfirmware_entry at l(%r4) /* read client interface handler */
+	ld	%r4,openfirmware_entry at l(%r4)
+
+	/*
+	 * Set the MSR to the OF value. This has the side effect of disabling
+	 * exceptions, which is important for the next few steps.
+	 */
+
+	lis	%r5,ofmsr at ha
+	ld	%r5,ofmsr at l(%r5)
+	mtmsrd	%r5
+	isync
 
 	/*
 	 * Set up OF stack. This needs to be accessible in real mode and
 	 * use the 32-bit ABI stack frame format. The pointer to the current
-	 * kernel stack is placed at the very top of the stack so we
-	 * can get it back later.
+	 * kernel stack is placed at the very top of the stack along with
+	 * the old MSR so we can get them back later.
 	 */
 	mr	%r5,%r1
-	lis	%r1,(ofwstk+OFWSTKSZ-16)@ha
-	addi	%r1,%r1,(ofwstk+OFWSTKSZ-16)@l
+	lis	%r1,(ofwstk+OFWSTKSZ-32)@ha
+	addi	%r1,%r1,(ofwstk+OFWSTKSZ-32)@l
 	std	%r5,8(%r1)	/* Save real stack pointer */
+	std	%r2,16(%r1)	/* Save old TOC */
+	std	%r6,24(%r1)	/* Save old MSR */
 	li	%r5,0
 	stw	%r5,4(%r1)
 	stw	%r5,0(%r1)
 
-	/* Set MSR, branch to OF, and come back */
-	lis	%r5,ofmsr at ha
-	ld	%r5,ofmsr at l(%r5)
-	mtmsrd	%r5
-	isync
+	/* Finally, branch to OF */
 	mtctr	%r4
 	bctrl
 
-	/* Turn translation back on to get to the stack */
-	mtmsr	%r14
-	isync
-
-	ld	%r1,8(%r1)	/* Load real stack pointer */
+	/* Reload stack pointer and MSR from the OFW stack */
+	ld	%r6,24(%r1)
+	ld	%r2,16(%r1)
+	ld	%r1,8(%r1)
 
-	/* Now we can use the stack again, so get the real MSR */
-	ld	%r5,216(%r1)
-	mtmsrd	%r5
+	/* Now set the real MSR */
+	mtmsrd	%r6
 	isync
 
 	/* Sign-extend the return value from OF */
@@ -314,7 +318,6 @@ ASENTRY(ofw_32bit_mode_entry)
 	ld	%r29,184(%r1)
 	ld	%r30,192(%r1)
 	ld	%r31,200(%r1)
-	ld	%r2,208(%r1)
 
 	/* Restore the stack and link register */
 	ld	%r1,0(%r1)


More information about the svn-src-projects mailing list