From owner-svn-src-projects@FreeBSD.ORG Tue Oct 6 15:44:09 2009 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 69EAB1065692; Tue, 6 Oct 2009 15:44:09 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 58CBB8FC12; Tue, 6 Oct 2009 15:44:09 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n96Fi9P2051178; Tue, 6 Oct 2009 15:44:09 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n96Fi9e3051175; Tue, 6 Oct 2009 15:44:09 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <200910061544.n96Fi9e3051175@svn.freebsd.org> From: Nathan Whitehorn Date: Tue, 6 Oct 2009 15:44:08 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r197805 - in projects/ppc64/sys/powerpc: aim aim64 X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 06 Oct 2009 15:44:09 -0000 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)