Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 11 Sep 2009 15:38:27 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r197092 - in projects/ppc64/sys/powerpc: aim aim64 ofw
Message-ID:  <200909111538.n8BFcR7x056124@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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";



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909111538.n8BFcR7x056124>