[OpenBIOS] r462 - in openbios-devel: arch/ppc/qemu include/ppc

svn at openbios.org svn at openbios.org
Sat Feb 28 19:38:55 CET 2009


Author: blueswirl
Date: 2009-02-28 19:38:55 +0100 (Sat, 28 Feb 2009)
New Revision: 462

Modified:
   openbios-devel/arch/ppc/qemu/init.c
   openbios-devel/arch/ppc/qemu/start.S
   openbios-devel/include/ppc/processor.h
Log:
Make OpenBIOS interrupt handlers 64bit aware v2

While booting a 64bit kernel, there is a small timeframe where OF and the kernel communicate with each other. Within that timeframe, DSI/ISI interrupts may occur, because some memory is not mapped yet.

Right now in case that happens, we jump into the DSI/ISI interrupt handler which clobbers the high 32 bits of the kernel's registers. In order to circumvent that, let's save/restore all 64 bits of all kernel registers when we get a DSI/ISI interrupt.

This patch enables a PPC64 Linux kernel to boot up to the point where it tries to set up the SLB entries (slbmte), which is not yet implemented in qemu.

v2 implements handling for the HIOR register, bringing interrupt handlers to RAM.

Signed-off-by: Alexander Graf <alex at csgraf.de>


Modified: openbios-devel/arch/ppc/qemu/init.c
===================================================================
--- openbios-devel/arch/ppc/qemu/init.c	2009-02-27 22:13:34 UTC (rev 461)
+++ openbios-devel/arch/ppc/qemu/init.c	2009-02-28 18:38:55 UTC (rev 462)
@@ -32,6 +32,7 @@
 #include "libc/vsprintf.h"
 #define NO_QEMU_PROTOS
 #include "openbios/fw_cfg.h"
+#include "ppc/processor.h"
 
 #define UUID_FMT "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x"
 
@@ -238,7 +239,27 @@
     fword("finish-device");
 }
 
+/* In order to get 64 bit aware handlers that rescue all our
+   GPRs from getting truncated to 32 bits, we need to patch the
+   existing handlers so they jump to our 64 bit aware ones. */
 static void
+ppc64_patch_handlers(void)
+{
+    uint32_t *dsi = (uint32_t *)0x300UL;
+    uint32_t *isi = (uint32_t *)0x400UL;
+
+    // Patch the first DSI handler instruction to: ba 0x2000
+    *dsi = 0x48002002;
+
+    // Patch the first ISI handler instruction to: ba 0x2200
+    *isi = 0x48002202;
+
+    // Invalidate the cache lines
+    asm ( "icbi 0, %0" : : "r"(dsi) );
+    asm ( "icbi 0, %0" : : "r"(isi) );
+}
+
+static void
 cpu_970_init(const struct cpudef *cpu)
 {
     cpu_generic_init(cpu);
@@ -249,6 +270,15 @@
     fword("property");
 
     fword("finish-device");
+
+    /* The 970 is a PPC64 CPU, so we need to activate
+     * 64bit aware interrupt handlers */
+
+    ppc64_patch_handlers();
+
+    /* The 970 also implements the HIOR which we need to set to 0 */
+
+    mtspr(S_HIOR, 0);
 }
 
 static const struct cpudef ppc_defs[] = {

Modified: openbios-devel/arch/ppc/qemu/start.S
===================================================================
--- openbios-devel/arch/ppc/qemu/start.S	2009-02-27 22:13:34 UTC (rev 461)
+++ openbios-devel/arch/ppc/qemu/start.S	2009-02-28 18:38:55 UTC (rev 462)
@@ -24,39 +24,155 @@
 #define ILLEGAL_VECTOR( v )	.org __vectors + v ; bl trap_error ;
 #define VECTOR( v, dummystr )	.org __vectors + v ; vector__##v
 
-#define EXCEPTION_PREAMBLE \
-	mtsprg1	r1 ;		/* scratch */ \
-	mfsprg0	r1 ;		/* exception stack in sprg0 */ \
-	addi	r1,r1,-80 ;	/* push exception frame */ \
+/* We're trying to use the same code for the ppc32 and ppc64 handlers here.
+ * On ppc32 we only save/restore the registers, C considers volatile.
+ *
+ * On ppc64 on the other hand, we have to save/restore all registers, because
+ * all OF code is 32 bits, which only saves/restores the low 32 bits of the
+ * registers it clobbers.
+ */
+
+#define EXCEPTION_PREAMBLE_TEMPLATE \
+	mtsprg1	r1 ;				/* scratch */ \
+	mfsprg0	r1 ;				/* exception stack in sprg0 */ \
+.ifc ULONG_SIZE, 8 ; \
+	addi	r1,r1,-(40 * ULONG_SIZE) ;	/* push exception frame */ \
+.else ; \
+	addi	r1,r1,-(20 * ULONG_SIZE) ;	/* push exception frame */ \
+.endif ; \
  \
-	stw	r0,0(r1) ;	/* save r0 */ \
+	stl	r0,(0 * ULONG_SIZE)(r1) ;	/* save r0 */ \
 	mfsprg1	r0 ; \
-	stw	r0,4(r1) ;	/* save r1 */ \
-	stw	r2,8(r1) ;	/* save r2 */ \
-	stw	r3,12(r1) ;	/* save r3 */ \
-	stw	r4,16(r1) ; \
-	stw	r5,20(r1) ; \
-	stw	r6,24(r1) ; \
-	stw	r7,28(r1) ; \
-	stw	r8,32(r1) ; \
-	stw	r9,36(r1) ; \
-	stw	r10,40(r1) ; \
-	stw	r11,44(r1) ; \
-	stw	r12,48(r1) ; \
+	stl	r0,(1 * ULONG_SIZE)(r1) ;	/* save r1 */ \
+	stl	r2,(2 * ULONG_SIZE)(r1) ;	/* save r2 */ \
+	stl	r3,(3 * ULONG_SIZE)(r1) ;	/* save r3 */ \
+	stl	r4,(4 * ULONG_SIZE)(r1) ; \
+	stl	r5,(5 * ULONG_SIZE)(r1) ; \
+	stl	r6,(6 * ULONG_SIZE)(r1) ; \
+	stl	r7,(7 * ULONG_SIZE)(r1) ; \
+	stl	r8,(8 * ULONG_SIZE)(r1) ; \
+	stl	r9,(9 * ULONG_SIZE)(r1) ; \
+	stl	r10,(10 * ULONG_SIZE)(r1) ; \
+	stl	r11,(11 * ULONG_SIZE)(r1) ; \
+	stl	r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+	stl	r13,(17 * ULONG_SIZE)(r1) ; \
+	stl	r14,(18 * ULONG_SIZE)(r1) ; \
+	stl	r15,(19 * ULONG_SIZE)(r1) ; \
+	stl	r16,(20 * ULONG_SIZE)(r1) ; \
+	stl	r17,(21 * ULONG_SIZE)(r1) ; \
+	stl	r18,(22 * ULONG_SIZE)(r1) ; \
+	stl	r19,(23 * ULONG_SIZE)(r1) ; \
+	stl	r20,(24 * ULONG_SIZE)(r1) ; \
+	stl	r21,(25 * ULONG_SIZE)(r1) ; \
+	stl	r22,(26 * ULONG_SIZE)(r1) ; \
+	stl	r23,(27 * ULONG_SIZE)(r1) ; \
+	stl	r24,(28 * ULONG_SIZE)(r1) ; \
+	stl	r25,(29 * ULONG_SIZE)(r1) ; \
+	stl	r26,(30 * ULONG_SIZE)(r1) ; \
+	stl	r27,(31 * ULONG_SIZE)(r1) ; \
+	stl	r28,(32 * ULONG_SIZE)(r1) ; \
+	stl	r29,(33 * ULONG_SIZE)(r1) ; \
+	stl	r30,(34 * ULONG_SIZE)(r1) ; \
+	stl	r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
  \
 	mflr	r0 ; \
-	stw	r0,52(r1) ; \
+	stl	r0,(13 * ULONG_SIZE)(r1) ; \
 	mfcr	r0 ; \
-	stw	r0,56(r1) ; \
+	stl	r0,(14 * ULONG_SIZE)(r1) ; \
 	mfctr	r0 ; \
-	stw	r0,60(r1) ; \
+	stl	r0,(15 * ULONG_SIZE)(r1) ; \
 	mfxer	r0 ; \
-	stw	r0,64(r1) ; \
+	stl	r0,(16 * ULONG_SIZE)(r1) ; \
  \
 	/* 76(r1) unused */ \
-	addi	r1,r1,-16 ;	/* call conventions uses 0(r1) and 4(r1)... */
+	addi	r1,r1,-16 ;	/* C ABI uses 0(r1) and 4(r1)... */
 
+#define EXCEPTION_EPILOGUE_TEMPLATE \
+	addi	r1,r1,16 ;			/* pop ABI frame */ \
+\
+	ll	r0,(13 * ULONG_SIZE)(r1) ; \
+	mtlr	r0 ; \
+	ll	r0,(14 * ULONG_SIZE)(r1) ; \
+	mtcr	r0 ; \
+	ll	r0,(15 * ULONG_SIZE)(r1) ; \
+	mtctr	r0 ; \
+	ll	r0,(16 * ULONG_SIZE)(r1) ; \
+	mtxer	r0 ; \
+\
+	ll	r0,(0 * ULONG_SIZE)(r1) ; \
+	ll	r2,(2 * ULONG_SIZE)(r1) ; \
+	ll	r3,(3 * ULONG_SIZE)(r1) ; \
+	ll	r4,(4 * ULONG_SIZE)(r1) ; \
+	ll	r5,(5 * ULONG_SIZE)(r1) ; \
+	ll	r6,(6 * ULONG_SIZE)(r1) ; \
+	ll	r7,(7 * ULONG_SIZE)(r1) ; \
+	ll	r8,(8 * ULONG_SIZE)(r1) ; \
+	ll	r9,(9 * ULONG_SIZE)(r1) ; \
+	ll	r10,(10 * ULONG_SIZE)(r1) ; \
+	ll	r11,(11 * ULONG_SIZE)(r1) ; \
+	ll	r12,(12 * ULONG_SIZE)(r1) ; \
+.ifc ULONG_SIZE, 8 ; \
+	ll	r13,(17 * ULONG_SIZE)(r1) ; \
+	ll	r14,(18 * ULONG_SIZE)(r1) ; \
+	ll	r15,(19 * ULONG_SIZE)(r1) ; \
+	ll	r16,(20 * ULONG_SIZE)(r1) ; \
+	ll	r17,(21 * ULONG_SIZE)(r1) ; \
+	ll	r18,(22 * ULONG_SIZE)(r1) ; \
+	ll	r19,(23 * ULONG_SIZE)(r1) ; \
+	ll	r20,(24 * ULONG_SIZE)(r1) ; \
+	ll	r21,(25 * ULONG_SIZE)(r1) ; \
+	ll	r22,(26 * ULONG_SIZE)(r1) ; \
+	ll	r23,(27 * ULONG_SIZE)(r1) ; \
+	ll	r24,(28 * ULONG_SIZE)(r1) ; \
+	ll	r25,(29 * ULONG_SIZE)(r1) ; \
+	ll	r26,(30 * ULONG_SIZE)(r1) ; \
+	ll	r27,(31 * ULONG_SIZE)(r1) ; \
+	ll	r28,(32 * ULONG_SIZE)(r1) ; \
+	ll	r29,(33 * ULONG_SIZE)(r1) ; \
+	ll	r30,(34 * ULONG_SIZE)(r1) ; \
+	ll	r31,(35 * ULONG_SIZE)(r1) ; \
+.endif ; \
+	ll	r1,(1 * ULONG_SIZE)(r1) ;	/* restore stack at last */ \
+	rfi
 
+// PPC32
+
+#define ULONG_SIZE		4
+#define stl			stw
+#define ll			lwz
+
+.macro EXCEPTION_PREAMBLE
+	EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE
+	EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
+// PPC64
+
+#define ULONG_SIZE		8
+#define stl			std
+#define ll			ld
+
+.macro EXCEPTION_PREAMBLE_64
+	EXCEPTION_PREAMBLE_TEMPLATE
+.endm
+
+.macro EXCEPTION_EPILOGUE_64
+	EXCEPTION_EPILOGUE_TEMPLATE
+.endm
+
+#undef ULONG_SIZE
+#undef stl
+#undef ll
+
 /************************************************************************/
 /*	vectors								*/
 /************************************************************************/
@@ -68,32 +184,8 @@
 	b	1b
 
 exception_return:
-	addi	r1,r1,16	// pop ABI frame
+	EXCEPTION_EPILOGUE
 
-	lwz	r0,52(r1)
-	mtlr	r0
-	lwz	r0,56(r1)
-	mtcr	r0
-	lwz	r0,60(r1)
-	mtctr	r0
-	lwz	r0,64(r1)
-	mtxer	r0
-
-	lwz	r0,0(r1)	// restore r0
-	lwz	r2,8(r1)	// restore r2
-	lwz	r3,12(r1)	// restore r3
-	lwz	r4,16(r1)
-	lwz	r5,20(r1)
-	lwz	r6,24(r1)
-	lwz	r7,28(r1)
-	lwz	r8,32(r1)
-	lwz	r9,36(r1)
-	lwz	r10,40(r1)
-	lwz	r11,44(r1)
-	lwz	r12,48(r1)
-	lwz	r1,4(r1)	// restore r1
-	rfi
-
 	.globl	__divide_error
 __divide_error:
 trap_error:
@@ -150,6 +242,22 @@
 ILLEGAL_VECTOR( 0x1600 )
 ILLEGAL_VECTOR( 0x1700 )
 
+VECTOR( 0x2000, "DSI_64" ):
+	EXCEPTION_PREAMBLE_64
+	lis	r3,HA(dsi_exception)
+	addi	r3,r3,LO(dsi_exception)
+	mtctr	r3
+	bctrl
+	EXCEPTION_EPILOGUE_64
+
+VECTOR( 0x2200, "ISI_64" ):
+	EXCEPTION_PREAMBLE_64
+	lis	r3,HA(isi_exception)
+	addi	r3,r3,LO(isi_exception)
+	mtctr	r3
+	bctrl
+	EXCEPTION_EPILOGUE_64
+
 GLOBL(__vectors_end):
 
 /************************************************************************/

Modified: openbios-devel/include/ppc/processor.h
===================================================================
--- openbios-devel/include/ppc/processor.h	2009-02-27 22:13:34 UTC (rev 461)
+++ openbios-devel/include/ppc/processor.h	2009-02-28 18:38:55 UTC (rev 462)
@@ -92,6 +92,7 @@
 #define S_TBWL		284	/* Time base Upper/Lower (Writing) */
 #define S_TBWU		285
 #define S_PVR		287	/* Processor Version Register */
+#define S_HIOR		311	/* Hardware Interrupt Offset Register */
 #define S_IBAT0U	528
 #define S_IBAT0L	529
 #define S_IBAT1U	530
@@ -400,4 +401,10 @@
 
 #define SPRNUM_FLIP( v )	( (((v)>>5) & 0x1f) | (((v)<<5) & 0x3e0) )
 
+/* C helpers */
+
+#define __stringify_1(x)	#x
+#define __stringify(x)		__stringify_1(x)
+#define mtspr(rn, v)		asm volatile("mtspr " __stringify(rn) ",%0" : : "r" (v))
+
 #endif   /* _H_PROCESSOR */




More information about the OpenBIOS mailing list