svn commit: r197092 - in projects/ppc64/sys/powerpc: aim aim64 ofw
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Fri Sep 11 15:38:28 UTC 2009
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 at ha
ld 2,tocbase at l(2)
- /* Switch to 64-bit mode */
- mfmsr 9
- li 8,1
- insrdi 9,8,1,0
- mtmsrd 9
-
mfmsr 0
lis 9,ofmsr at ha
stdu 0,ofmsr at 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 at ha
- ld 4,openfirmware_entry at 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 at ha
- ld 4,openfirmware_entry at 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 at ha
+ ld %r4,openfirmware_entry at l(%r4) /* read client interface handler */
/* Set MSR, branch to OF, and come back */
- mtmsrd 5
+ lis %r5,ofmsr at ha
+ ld %r5,ofmsr at 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";
More information about the svn-src-projects
mailing list