Date: Tue, 6 Oct 2009 15:44:08 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r197805 - in projects/ppc64/sys/powerpc: aim aim64 Message-ID: <200910061544.n96Fi9e3051175@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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@ha - ld %r4,openfirmware_entry@l(%r4) /* read client interface handler */ + ld %r4,openfirmware_entry@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@ha + ld %r5,ofmsr@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@ha - ld %r5,ofmsr@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)
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200910061544.n96Fi9e3051175>