Subject: [rfc][patch] handling of firmware calls (Efika boots)
To: None <port-powerpc@netbsd.org>
From: Aymeric Vincent <vincent@labri.fr>
List: port-powerpc
Date: 01/07/2007 20:58:40
       Hi,

while investigating how to make the Efika boot, I had to dig a bit
into how open firmware calls are handled in NetBSD and I'd like to
gather a few comments before committing.

Jorge Acereda's patch for the Pegasos contains a line to save in ofmsr
a msr that disables the MMU and is enough to make the Efika boot. It
was the starting point of this patch.

Basically, in the case where FIRMWORKSBUGS is used and the kernel is
started with the MMU enabled, the openfirmware entry point is faked to
point to a trampoline in arch/powerpc/powerpc/ofwreal.S. The role of
this trampoline is to save and restore everything MMU-related before
and after calls to the openfirmware.

The first thing is to patch ofwreal.S to disable the MMU while
restoring the MMU registers. This is really needed and I will commit
this soon without doubt. (This is the reason why Jorge's patch worked:
it led to the MMU being disabled in restoremmu)

The second thing is that the "straight" path to call the open firmware
(in powerpc/oea/ofw_subr.S) has grown similar activities as the
trampoline: it saves and restores things among which the msr.
So the role of the second patch is to jump as straightly into the
trampoline as possible if it is activated and not save and restore
several registers several times uselessly.

All this leads IMHO to the fact that we should discuss a modular way
to tell (based on the detection of the platform) which registers
should be saved/restored before/after calling to the openfirmware and
getting rid of the FIRMWORKSBUGS #define whose name doesn't reflect
reality: we have to save and restore stuff on all our powerpc
platforms, so let's not have code that does this in two places.
But I'm not familiar with many of the powerpc platforms we support, so
I would prefer if others could say what they think about this.

Regards,
 Aymeric

Index: powerpc/ofwreal.S
===================================================================
RCS file: /usr/local/cvsroot/src/sys/arch/powerpc/powerpc/ofwreal.S,v
retrieving revision 1.8
diff -u -u -r1.8 ofwreal.S
--- powerpc/ofwreal.S	25 Sep 2006 01:45:27 -0000	1.8
+++ powerpc/ofwreal.S	6 Jan 2007 23:58:16 -0000
@@ -246,6 +246,10 @@
  * Restore everyting related to the mmu from the saveare pointed to by r3.
  */
 restoremmu:
+	mfmsr	%r12
+	andi.	%r4,%r12,~(PSL_IR|PSL_DR)@l
+	mtmsr	%r4			/* Disable MMU */
+	isync
 
 	li	%r4,0			/* first, invalidate BATs */
 	mtibatu	0,%r4
@@ -346,5 +350,6 @@
 	tlbsync
 	sync
 
+	mtmsr	%r12			/* restore MMU */
 	mtlr	%r11
 	blr
Index: oea/ofw_subr.S
===================================================================
RCS file: /usr/local/cvsroot/src/sys/arch/powerpc/oea/ofw_subr.S,v
retrieving revision 1.3
diff -u -u -r1.3 ofw_subr.S
--- oea/ofw_subr.S	5 Aug 2006 21:26:49 -0000	1.3
+++ oea/ofw_subr.S	7 Jan 2007 19:31:27 -0000
@@ -44,6 +44,9 @@
 GLOBAL(ofwsprg0save)
 	.long	0
 
+GLOBAL(ofwreal_incharge)
+	.long	0
+
 	.comm	firmstk,NBPG,8
 	.comm	OF_buffer,NBPG,4
 	.comm	openfirmware_entry,4,4	/* openfirmware entry point */
@@ -59,6 +62,10 @@
 	andi.	0,0,PSL_IR|PSL_DR
 	beq	1f
 
+	li	8,1
+	lis	9,ofwreal_incharge@ha
+	stw	8,ofwreal_incharge@l(9)
+
 	mflr	30
 	bl	_C_LABEL(ofwr_init)
 	mtlr	30
@@ -96,13 +103,26 @@
 	stw	0,4(1)
 	stwu	1,-16(1)		/* setup stack frame */
 
-	mfmsr	4			/* save msr */
-	stw	4,8(1)
-
 	lis	4,openfirmware_entry@ha	/* get firmware entry point */
 	lwz	4,openfirmware_entry@l(4)
 	mtlr	4
 
+	mfsprg	5,0			/* save current sprg0 (curcpu) */
+	lis	4,ofwsprg0save@ha
+	addi	4,4,ofwsprg0save@l
+	stw	5,0(4)
+
+#ifdef FIRMWORKSBUGS
+	lis	4,ofwreal_incharge@ha
+	lwz	4,ofwreal_incharge@l(4)
+	cmpwi	4,1
+	bne	1f
+	blrl
+1:
+#else
+	mfmsr	4			/* save msr */
+	stw	4,8(1)
+
 	li	0,0			/* clear battable translations */
 #if defined (PPC_OEA) && !defined (PPC_OEA64) && !defined (PPC_OEA64_BRIDGE)
 	mtdbatu	2,0
@@ -121,11 +141,6 @@
 	cmpwi	5,0
 	bne	1b
 
-	mfsprg	5,0			/* save current sprg0 (curcpu) */
-	lis	4,ofwsprg0save@ha
-	addi	4,4,ofwsprg0save@l
-	stw	5,0(4)
-
 	lis	4,_C_LABEL(ofw_pmap)@ha	/* load OFW SR */
 	addi	4,4,_C_LABEL(ofw_pmap)@l
 	lwz	0,PM_KERNELSR(4)
@@ -154,11 +169,6 @@
 
 	blrl				/* call Open Firmware */
 
-	lis	4,ofwsprg0save@ha	/* restore saved sprg0 (curcpu) */
-	addi	4,4,ofwsprg0save@l
-	lwz	5,0(4)
-	mtsprg	0,5
-
 	lis	4,ofwsrsave@ha		/* restore saved SRs */
 	addi	4,4,ofwsrsave@l
 	li	5,0
@@ -172,6 +182,12 @@
 	lwz	4,8(1)			/* restore msr */
 	mtmsr	4
 	isync
+#endif /* FIRMWORKSBUGS */
+
+	lis	4,ofwsprg0save@ha	/* restore saved sprg0 (curcpu) */
+	addi	4,4,ofwsprg0save@l
+	lwz	5,0(4)
+	mtsprg	0,5
 
 	lwz	1,0(1)			/* and return */
 	lwz	0,4(1)