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