* [Qemu-devel] [PATCH] PPC64: Make OpenBIOS interrupt handlers 64bit aware v2
@ 2009-02-28 16:45 Alexander Graf
2009-02-28 18:41 ` [Qemu-devel] " Blue Swirl
0 siblings, 1 reply; 2+ messages in thread
From: Alexander Graf @ 2009-02-28 16:45 UTC (permalink / raw)
To: openbios; +Cc: Blue Swirl, qemu-devel, Laurent Vivier
[-- Attachment #1: Type: text/plain, Size: 756 bytes --]
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@csgraf.de>
[-- Attachment #2.1: Type: text/html, Size: 972 bytes --]
[-- Attachment #2.2: ppc64-interrupt-handlers.patch --]
[-- Type: application/octet-stream, Size: 8545 bytes --]
Index: include/ppc/processor.h
===================================================================
--- include/ppc/processor.h (revision 461)
+++ include/ppc/processor.h (working copy)
@@ -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 */
Index: arch/ppc/qemu/init.c
===================================================================
--- arch/ppc/qemu/init.c (revision 461)
+++ arch/ppc/qemu/init.c (working copy)
@@ -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[] = {
Index: arch/ppc/qemu/start.S
===================================================================
--- arch/ppc/qemu/start.S (revision 461)
+++ arch/ppc/qemu/start.S (working copy)
@@ -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):
/************************************************************************/
[-- Attachment #2.3: Type: text/html, Size: 134 bytes --]
^ permalink raw reply [flat|nested] 2+ messages in thread* [Qemu-devel] Re: [PATCH] PPC64: Make OpenBIOS interrupt handlers 64bit aware v2
2009-02-28 16:45 [Qemu-devel] [PATCH] PPC64: Make OpenBIOS interrupt handlers 64bit aware v2 Alexander Graf
@ 2009-02-28 18:41 ` Blue Swirl
0 siblings, 0 replies; 2+ messages in thread
From: Blue Swirl @ 2009-02-28 18:41 UTC (permalink / raw)
To: Alexander Graf; +Cc: openbios, qemu-devel, Laurent Vivier
On 2/28/09, Alexander Graf <alex@csgraf.de> wrote:
> 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@csgraf.de>
Thanks, applied.
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2009-02-28 18:41 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-02-28 16:45 [Qemu-devel] [PATCH] PPC64: Make OpenBIOS interrupt handlers 64bit aware v2 Alexander Graf
2009-02-28 18:41 ` [Qemu-devel] " Blue Swirl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).