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@csgraf.de>


git-svn-id: svn://coreboot.org/openbios/openbios-devel@462 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Alexander Graf
2009-02-28 18:38:55 +00:00
committed by Blue Swirl
parent 189c9077a1
commit d257db6033
3 changed files with 192 additions and 47 deletions

View File

@@ -32,6 +32,7 @@
#include "libc/vsprintf.h" #include "libc/vsprintf.h"
#define NO_QEMU_PROTOS #define NO_QEMU_PROTOS
#include "openbios/fw_cfg.h" #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" #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"); 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 static void
cpu_970_init(const struct cpudef *cpu) cpu_970_init(const struct cpudef *cpu)
{ {
@@ -249,6 +270,15 @@ cpu_970_init(const struct cpudef *cpu)
fword("property"); fword("property");
fword("finish-device"); 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[] = { static const struct cpudef ppc_defs[] = {

View File

@@ -24,38 +24,154 @@
#define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ; #define ILLEGAL_VECTOR( v ) .org __vectors + v ; bl trap_error ;
#define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v #define VECTOR( v, dummystr ) .org __vectors + v ; vector__##v
#define EXCEPTION_PREAMBLE \ /* We're trying to use the same code for the ppc32 and ppc64 handlers here.
mtsprg1 r1 ; /* scratch */ \ * On ppc32 we only save/restore the registers, C considers volatile.
mfsprg0 r1 ; /* exception stack in sprg0 */ \ *
addi r1,r1,-80 ; /* push exception frame */ \ * 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 ; \ mfsprg1 r0 ; \
stw r0,4(r1) ; /* save r1 */ \ stl r0,(1 * ULONG_SIZE)(r1) ; /* save r1 */ \
stw r2,8(r1) ; /* save r2 */ \ stl r2,(2 * ULONG_SIZE)(r1) ; /* save r2 */ \
stw r3,12(r1) ; /* save r3 */ \ stl r3,(3 * ULONG_SIZE)(r1) ; /* save r3 */ \
stw r4,16(r1) ; \ stl r4,(4 * ULONG_SIZE)(r1) ; \
stw r5,20(r1) ; \ stl r5,(5 * ULONG_SIZE)(r1) ; \
stw r6,24(r1) ; \ stl r6,(6 * ULONG_SIZE)(r1) ; \
stw r7,28(r1) ; \ stl r7,(7 * ULONG_SIZE)(r1) ; \
stw r8,32(r1) ; \ stl r8,(8 * ULONG_SIZE)(r1) ; \
stw r9,36(r1) ; \ stl r9,(9 * ULONG_SIZE)(r1) ; \
stw r10,40(r1) ; \ stl r10,(10 * ULONG_SIZE)(r1) ; \
stw r11,44(r1) ; \ stl r11,(11 * ULONG_SIZE)(r1) ; \
stw r12,48(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 ; \ mflr r0 ; \
stw r0,52(r1) ; \ stl r0,(13 * ULONG_SIZE)(r1) ; \
mfcr r0 ; \ mfcr r0 ; \
stw r0,56(r1) ; \ stl r0,(14 * ULONG_SIZE)(r1) ; \
mfctr r0 ; \ mfctr r0 ; \
stw r0,60(r1) ; \ stl r0,(15 * ULONG_SIZE)(r1) ; \
mfxer r0 ; \ mfxer r0 ; \
stw r0,64(r1) ; \ stl r0,(16 * ULONG_SIZE)(r1) ; \
\ \
/* 76(r1) unused */ \ /* 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 */ /* vectors */
@@ -68,31 +184,7 @@ GLOBL(__vectors):
b 1b b 1b
exception_return: 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 .globl __divide_error
__divide_error: __divide_error:
@@ -150,6 +242,22 @@ ILLEGAL_VECTOR( 0x1500 )
ILLEGAL_VECTOR( 0x1600 ) ILLEGAL_VECTOR( 0x1600 )
ILLEGAL_VECTOR( 0x1700 ) 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): GLOBL(__vectors_end):
/************************************************************************/ /************************************************************************/

View File

@@ -92,6 +92,7 @@
#define S_TBWL 284 /* Time base Upper/Lower (Writing) */ #define S_TBWL 284 /* Time base Upper/Lower (Writing) */
#define S_TBWU 285 #define S_TBWU 285
#define S_PVR 287 /* Processor Version Register */ #define S_PVR 287 /* Processor Version Register */
#define S_HIOR 311 /* Hardware Interrupt Offset Register */
#define S_IBAT0U 528 #define S_IBAT0U 528
#define S_IBAT0L 529 #define S_IBAT0L 529
#define S_IBAT1U 530 #define S_IBAT1U 530
@@ -400,4 +401,10 @@
#define SPRNUM_FLIP( v ) ( (((v)>>5) & 0x1f) | (((v)<<5) & 0x3e0) ) #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 */ #endif /* _H_PROCESSOR */