diff --git a/arch/ppc/qemu/init.c b/arch/ppc/qemu/init.c index b733737..9b7bdab 100644 --- a/arch/ppc/qemu/init.c +++ b/arch/ppc/qemu/init.c @@ -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,6 +239,26 @@ cpu_g4_init(const struct cpudef *cpu) 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) { @@ -249,6 +270,15 @@ cpu_970_init(const struct cpudef *cpu) 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[] = { diff --git a/arch/ppc/qemu/start.S b/arch/ppc/qemu/start.S index 196eddf..857885a 100644 --- a/arch/ppc/qemu/start.S +++ b/arch/ppc/qemu/start.S @@ -24,38 +24,154 @@ #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,31 +184,7 @@ GLOBL(__vectors): b 1b exception_return: - addi r1,r1,16 // pop ABI frame - - 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 + EXCEPTION_EPILOGUE .globl __divide_error __divide_error: @@ -150,6 +242,22 @@ ILLEGAL_VECTOR( 0x1500 ) 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): /************************************************************************/ diff --git a/include/ppc/processor.h b/include/ppc/processor.h index 4c979d4..87e3693 100644 --- a/include/ppc/processor.h +++ b/include/ppc/processor.h @@ -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 */