]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc64: Fix occasional crash at boot in OF interface
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Tue, 9 Mar 2004 12:14:38 +0000 (04:14 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 9 Mar 2004 12:14:38 +0000 (04:14 -0800)
The assembly code used to callback into Open Firmware client
interface in 32 bits mode used to backup the stack pointer in
the SPRG2 register.

That upsets Apple's implementation of Open Firmware significantly
and maybe others, causing them to crash in _some_ operations,
apparently the trigger is to cause a segment or hash table
fault, typically happens when letting that code initialize the
second display.

This patch fixes it, along with other cleanups of that asm code,
it did unnecessary register restores and backing up the stack
pointer is actually useless anyway.

arch/ppc64/kernel/entry.S

index 84f41f686d6edd406cde88d5bbd86558aaa87f92..756bf61fcb2664e4a9fd985600d19ec5ab399cc9 100644 (file)
@@ -570,11 +570,10 @@ _GLOBAL(enter_prom)
         * of all registers that it saves.  We therefore save those registers
         * PROM might touch to the stack.  (r0, r3-r13 are caller saved)
         */
-       SAVE_8GPRS(2, r1)               /* Save the TOC & incoming param(s) */
-       SAVE_GPR(13, r1)                /* Save paca */
-       SAVE_8GPRS(14, r1)              /* Save the non-volatiles */
-       SAVE_10GPRS(22, r1)             /* ditto */
-
+       SAVE_8GPRS(2, r1)
+       SAVE_GPR(13, r1)
+       SAVE_8GPRS(14, r1)
+       SAVE_10GPRS(22, r1)
        mfcr    r4
        std     r4,_CCR(r1)
        mfctr   r5
@@ -592,20 +591,16 @@ _GLOBAL(enter_prom)
        mfmsr   r11
        std     r11,_MSR(r1)
 
-       /* Unfortunatly, the stack pointer is also clobbered, so it is saved
-        * in the SPRG2 which allows us to restore our original state after
-        * PROM returns.
-         */
-       mtspr   SPRG2,r1
-
-        /* put a relocation offset into r3 */
+       /* Get the PROM entrypoint */
         bl      .reloc_offset
        LOADADDR(r12,prom)
        sub     r12,r12,r3
-       ld      r12,PROMENTRY(r12)      /* get the prom->entry value */
+       ld      r12,PROMENTRY(r12)
        mtlr    r12
 
-        mfmsr   r11                    /* grab the current MSR */
+       /* Switch MSR to 32 bits mode
+        */
+        mfmsr   r11
         li      r12,1
         rldicr  r12,r12,MSR_SF_LG,(63-MSR_SF_LG)
         andc    r11,r11,r12
@@ -615,22 +610,25 @@ _GLOBAL(enter_prom)
         mtmsrd  r11
         isync
 
-       REST_8GPRS(2, r1)               /* Restore the TOC & param(s) */
-       REST_GPR(13, r1)                /* Restore paca */
-       REST_8GPRS(14, r1)              /* Restore the non-volatiles */
-       REST_10GPRS(22, r1)             /* ditto */
-       blrl                            /* Entering PROM here... */
+       /* Restore arguments & enter PROM here... */
+       ld      r3,GPR3(r1)
+       blrl
 
-       mfspr   r1,SPRG2                /* Restore the stack pointer */
-       ld      r6,_MSR(r1)             /* Restore the MSR */
-       mtmsrd  r6
-        isync
+       /* Just make sure that r1 top 32 bits didn't get
+        * corrupt by OF
+        */
+       rldicl  r1,r1,0,32
 
-       REST_GPR(2, r1)                 /* Restore the TOC */
-       REST_GPR(13, r1)                /* Restore paca */
-       REST_8GPRS(14, r1)              /* Restore the non-volatiles */
-       REST_10GPRS(22, r1)             /* ditto */
+       /* Restore the MSR (back to 64 bits) */
+       ld      r0,_MSR(r1)
+       mtmsrd  r0
+        isync
 
+       /* Restore other registers */
+       REST_GPR(2, r1)
+       REST_GPR(13, r1)
+       REST_8GPRS(14, r1)
+       REST_10GPRS(22, r1)
        ld      r4,_CCR(r1)
        mtcr    r4
        ld      r5,_CTR(r1)
@@ -645,9 +643,10 @@ _GLOBAL(enter_prom)
        mtsrr0  r9
        ld      r10,_SRR1(r1)
        mtsrr1  r10
+       
         addi   r1,r1,PROM_FRAME_SIZE
-       ld      r0,16(r1)               /* get return address */
-
+       ld      r0,16(r1)
        mtlr    r0
-        blr                            /* return to caller */
+        blr
+       
 #endif /* defined(CONFIG_PPC_PSERIES) */