From owner-svn-src-projects@FreeBSD.ORG Fri Sep 11 15:38:28 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 062061065670; Fri, 11 Sep 2009 15:38:28 +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 E91628FC1B; Fri, 11 Sep 2009 15:38:27 +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 n8BFcR6i056128; Fri, 11 Sep 2009 15:38:27 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n8BFcR7x056124; Fri, 11 Sep 2009 15:38:27 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <200909111538.n8BFcR7x056124@svn.freebsd.org> From: Nathan Whitehorn Date: Fri, 11 Sep 2009 15:38:27 +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: r197092 - in projects/ppc64/sys/powerpc: aim aim64 ofw 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: Fri, 11 Sep 2009 15:38:28 -0000 Author: nwhitehorn Date: Fri Sep 11 15:38:27 2009 New Revision: 197092 URL: http://svn.freebsd.org/changeset/base/197092 Log: Fix a number of problems related to calling into a 32-bit OFW implementation. OFW cannot save the non-volatile registers properly, since it stores them as 32-bit quantities, so we have to do that, and also properly sign-extend its output, and take care that type promotion maintains sign info when passing things from firmware back to 64-bit C code. This brings the boot much further on real hardware. Modified: projects/ppc64/sys/powerpc/aim/ofw_machdep.c projects/ppc64/sys/powerpc/aim64/locore.S projects/ppc64/sys/powerpc/ofw/ofw_real.c Modified: projects/ppc64/sys/powerpc/aim/ofw_machdep.c ============================================================================== --- projects/ppc64/sys/powerpc/aim/ofw_machdep.c Fri Sep 11 15:35:28 2009 (r197091) +++ projects/ppc64/sys/powerpc/aim/ofw_machdep.c Fri Sep 11 15:38:27 2009 (r197092) @@ -68,7 +68,6 @@ static int (*ofwcall)(void *); static void *fdt; int ofw_real_mode; -int ofw_real_mode_entry(void *); int ofw_32bit_mode_entry(void *); static int openfirmware(void *args); @@ -323,9 +322,7 @@ OF_initial_setup(void *fdt_ptr, void *ju * For PPC64, we need to use some hand-written * asm trampolines to get to OF. */ - if (ofw_real_mode && openfirm != NULL) - ofwcall = ofw_real_mode_entry; - else + if (openfirm != NULL) ofwcall = ofw_32bit_mode_entry; #else ofwcall = openfirm; @@ -369,9 +366,9 @@ OF_bootstrap() static int openfirmware(void *args) { - long oldmsr; int result; #ifndef __powerpc64__ + long oldmsr; register_t srsave[16]; u_int i; #endif @@ -401,7 +398,6 @@ openfirmware(void *args) } isync(); } - #endif __asm __volatile( "\t" "sync\n\t" @@ -411,16 +407,17 @@ openfirmware(void *args) : "=r" (oldmsr) : "r" (ofmsr[0]) ); + #endif result = ofwcall(args); + #ifndef __powerpc64__ __asm( "\t" "mtmsr %0\n\t" "isync\n" : : "r" (oldmsr) ); - #ifndef __powerpc64__ if (pmap_bootstrapped && !ofw_real_mode) { /* * Restore the kernel's addr space. The isync() doesn;t Modified: projects/ppc64/sys/powerpc/aim64/locore.S ============================================================================== --- projects/ppc64/sys/powerpc/aim64/locore.S Fri Sep 11 15:35:28 2009 (r197091) +++ projects/ppc64/sys/powerpc/aim64/locore.S Fri Sep 11 15:38:27 2009 (r197092) @@ -154,12 +154,6 @@ ASENTRY(__start) lis 2,tocbase@ha ld 2,tocbase@l(2) - /* Switch to 64-bit mode */ - mfmsr 9 - li 8,1 - insrdi 9,8,1,0 - mtmsrd 9 - mfmsr 0 lis 9,ofmsr@ha stdu 0,ofmsr@l(9) @@ -172,6 +166,12 @@ ASENTRY(__start) std 0,24(9) /* ofmsr[3] = sprg2 */ mfsprg3 0 std 0,32(9) /* ofmsr[4] = sprg3 */ + + /* Switch to 64-bit mode */ + mfmsr 9 + li 8,1 + insrdi 9,8,1,0 + mtmsrd 9 bl .OF_initial_setup nop @@ -210,47 +210,97 @@ tocbase: * Open Firmware Real-mode Entry Point. This is a huge pain. */ -ASENTRY(ofw_real_mode_entry) - mflr 0 - lis 4,openfirmware_entry@ha - ld 4,openfirmware_entry@l(4) /* read client interface handler */ - - mfmsr 5 - mtsprg3 5 - andi. 5, 5, ~(PSL_DR | PSL_IR | PSL_EE)@l - mtmsrd 5 - - mtctr 4 - bctrl - - mfsprg3 5 - mtmsrd 5 - mtlr 0 - blr - ASENTRY(ofw_32bit_mode_entry) - mflr 4 - mtsprg1 4 - - lis 4,openfirmware_entry@ha - ld 4,openfirmware_entry@l(4) /* read client interface handler */ + mflr %r0 + std %r0,16(%r1) + stdu %r1,-224(%r1) + + /* + * We need to save the following, because OF's register save/ + * restore code assumes that the contents of registers are + * at most 32 bits wide: lr, cr, r2, r13-r31, the old MSR. These + * get placed in that order in the stack. + */ + + mfcr %r4 + std %r4,48(%r1) + std %r13,56(%r1) + std %r14,64(%r1) + std %r15,72(%r1) + std %r16,80(%r1) + std %r17,88(%r1) + std %r18,96(%r1) + std %r19,104(%r1) + std %r20,112(%r1) + std %r21,120(%r1) + std %r22,128(%r1) + std %r23,136(%r1) + std %r24,144(%r1) + std %r25,152(%r1) + std %r26,160(%r1) + std %r27,168(%r1) + std %r28,176(%r1) + 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 */ - /* Set up a 32-bit MSR in r5 */ - mfmsr 5 - mtsprg2 5 - clrldi 5,5,1 + lis %r4,openfirmware_entry@ha + ld %r4,openfirmware_entry@l(%r4) /* read client interface handler */ /* Set MSR, branch to OF, and come back */ - mtmsrd 5 + lis %r5,ofmsr@ha + ld %r5,ofmsr@l(%r5) + mtmsrd %r5 isync - mtctr 4 + mtctr %r4 bctrl - mfsprg2 5 - mtmsrd 5 + + /* Turn translation back on to get to the stack */ + mtmsr %r14 isync - mfsprg1 4 - mtlr 4 + /* Now we can use the stack again, so get the real MSR */ + ld %r5,216(%r1) + mtmsrd %r5 + isync + + /* Sign-extend the return value from OF */ + extsw %r3,%r3 + + /* Restore all the non-volatile registers */ + ld %r5,48(%r1) + mtcr %r5 + ld %r13,56(%r1) + ld %r14,64(%r1) + ld %r15,72(%r1) + ld %r16,80(%r1) + ld %r17,88(%r1) + ld %r18,96(%r1) + ld %r19,104(%r1) + ld %r20,112(%r1) + ld %r21,120(%r1) + ld %r22,128(%r1) + ld %r23,136(%r1) + ld %r24,144(%r1) + ld %r25,152(%r1) + ld %r26,160(%r1) + ld %r27,168(%r1) + ld %r28,176(%r1) + 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) + ld %r0,16(%r1) + mtlr %r0 blr /* Modified: projects/ppc64/sys/powerpc/ofw/ofw_real.c ============================================================================== --- projects/ppc64/sys/powerpc/ofw/ofw_real.c Fri Sep 11 15:35:28 2009 (r197091) +++ projects/ppc64/sys/powerpc/ofw/ofw_real.c Fri Sep 11 15:38:27 2009 (r197092) @@ -423,7 +423,7 @@ ofw_real_getproplen(ofw_t ofw, phandle_t cell_t nreturns; cell_t package; cell_t propname; - cell_t proplen; + int32_t proplen; } args; args.name = (cell_t)(uintptr_t)"getproplen"; @@ -455,7 +455,7 @@ ofw_real_getprop(ofw_t ofw, phandle_t pa cell_t propname; cell_t buf; cell_t buflen; - cell_t size; + int32_t size; } args; args.name = (cell_t)(uintptr_t)"getprop"; @@ -558,7 +558,7 @@ ofw_real_canon(ofw_t ofw, const char *de cell_t device; cell_t buf; cell_t len; - cell_t size; + int32_t size; } args; args.name = (cell_t)(uintptr_t)"canon"; @@ -618,7 +618,7 @@ ofw_real_instance_to_path(ofw_t ofw, iha cell_t instance; cell_t buf; cell_t len; - cell_t size; + int32_t size; } args; args.name = (cell_t)(uintptr_t)"instance-to-path"; @@ -651,7 +651,7 @@ ofw_real_package_to_path(ofw_t ofw, phan cell_t package; cell_t buf; cell_t len; - cell_t size; + int32_t size; } args; args.name = (cell_t)(uintptr_t)"package-to-path"; @@ -779,7 +779,7 @@ ofw_real_read(ofw_t ofw, ihandle_t insta cell_t instance; cell_t addr; cell_t len; - cell_t actual; + int32_t actual; } args; args.name = (cell_t)(uintptr_t)"read"; @@ -812,7 +812,7 @@ ofw_real_write(ofw_t ofw, ihandle_t inst cell_t instance; cell_t addr; cell_t len; - cell_t actual; + int32_t actual; } args; args.name = (cell_t)(uintptr_t)"write";