]> git.neil.brown.name Git - history.git/commitdiff
ppc64: Add the head.S changes to boot a PowerMac G5.
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 13 Feb 2004 02:03:58 +0000 (13:03 +1100)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Fri, 13 Feb 2004 02:03:58 +0000 (13:03 +1100)
Apple's OF boots us with translation enabled. Also move the
copy_and_flush of the CPU holding loop to prom.c as it mustn't
be called on platforms that don't boot in real mode (that space
isn't always mapped)

arch/ppc64/kernel/head.S
arch/ppc64/kernel/prom.c

index 893e254b117cef41f7d366b5e85350b03b4e9206..e4d46294d2671017666823e8a0910a9023080a17 100644 (file)
@@ -1320,6 +1320,16 @@ _GLOBAL(__start_initialization_iSeries)
 #endif
 
 #ifdef CONFIG_PPC_PSERIES
+
+_STATIC(mmu_off)
+       mfmsr   r3
+       andi.   r0,r3,MSR_IR|MSR_DR
+       beqlr
+       andc    r3,r3,r0
+       mtspr   SRR0,r4
+       mtspr   SRR1,r3
+       sync
+       rfid
 _GLOBAL(__start_initialization_pSeries)
        mr      r31,r3                  /* save parameters */
        mr      r30,r4
@@ -1339,33 +1349,27 @@ _GLOBAL(__start_initialization_pSeries)
        /* Relocate the TOC from a virt addr to a real addr */
        sub     r2,r2,r3
 
-       /* DRENG / PPPBBB Fix the following comment!!! -Peter */
-       /* The following copies the first 0x100 bytes of code from the    */
-       /* load addr to physical addr 0x0.  This code causes secondary    */
-       /* processors to spin until a flag in the PACA is set.  This      */
-       /* is done at this time rather than with the entire kernel        */
-       /* relocation which is done below because we need to cause the    */
-       /* processors to spin on code that is not going to move while OF  */
-       /* is still alive. Although the spin code is not actually run on  */
-       /* a uniprocessor, we always do this copy.                        */
-       SET_REG_TO_CONST(r4, KERNELBASE)/* Src addr                       */
-       sub     r4,r4,r3                /* current address of __start     */
-                                       /*        the source addr         */
-       li      r3,0                    /* Dest addr                      */
-       li      r5,0x100                /* # bytes of memory to copy      */
-       li      r6,0                    /* Destination offset             */
-       bl      .copy_and_flush         /* copy the first 0x100 bytes     */
-
+       /* Save parameters */
        mr      r3,r31
        mr      r4,r30
        mr      r5,r29
        mr      r6,r28
        mr      r7,r27
 
+       /* Do all of the interaction with OF client interface */
        bl      .prom_init
+       mr      r23,r3                  /* Save phys address we are running at */
+
+       /* Setup some critical 970 SPRs before switching MMU off */
+       bl      .__power4_cpu_preinit
 
        li      r24,0                   /* cpu # */
 
+       /* Switch off MMU if not already */
+       LOADADDR(r4, .__after_prom_start - KERNELBASE)
+       add     r4,r4,r23
+       bl      .mmu_off        
+
 /*
  * At this point, r3 contains the physical address we are running at,
  * returned by prom_init()
@@ -1390,6 +1394,7 @@ _STATIC(__after_prom_start)
 
        li      r3,0                    /* target addr */
 
+       // XXX FIXME: Use phys returned by OF (r23)
        sub     r4,r27,r26              /* source addr */
                                        /* current address of _start   */
                                        /*   i.e. where we are running */
@@ -1425,7 +1430,7 @@ _STATIC(__after_prom_start)
  *
  * Note: this routine *only* clobbers r0, r6 and lr
  */
-_STATIC(copy_and_flush)
+_GLOBAL(copy_and_flush)
        addi    r5,r5,-8
        addi    r6,r6,-8
 4:     li      r0,16                   /* Use the least common      */
@@ -1675,6 +1680,58 @@ _GLOBAL(giveup_altivec)
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_SMP
+#ifdef CONFIG_PPC_PMAC
+/*
+ * On PowerMac, secondary processors starts from the reset vector, which
+ * is temporarily turned into a call to one of the functions below.
+ */
+       .section ".text";
+       .align 2 ;
+
+       .globl  pmac_secondary_start_1  
+pmac_secondary_start_1:        
+       li      r24, 1
+       b       .pmac_secondary_start
+       
+       .globl pmac_secondary_start_2
+pmac_secondary_start_2:        
+       li      r24, 2
+       b       .pmac_secondary_start
+       
+       .globl pmac_secondary_start_3
+pmac_secondary_start_3:
+       li      r24, 3
+       b       .pmac_secondary_start
+       
+_GLOBAL(pmac_secondary_start)
+       /* turn on 64-bit mode */
+       bl      .enable_64b_mode
+       isync
+
+       /* Copy some CPU settings from CPU 0 */
+       bl      .__restore_cpu_setup
+
+       /* pSeries do that early though I don't think we really need it */
+       mfmsr   r3
+       ori     r3,r3,MSR_RI
+       mtmsrd  r3                      /* RI on */
+
+       /* Set up a paca value for this processor. */
+       LOADADDR(r4, paca)               /* Get base vaddr of paca array  */
+       mulli   r13,r24,PACA_SIZE        /* Calculate vaddr of right paca */
+       add     r13,r13,r4               /* for this processor.           */
+       mtspr   SPRG3,r13                /* Save vaddr of paca in SPRG3   */
+
+        /* Create a temp kernel stack for use before relocation is on.    */
+        mr      r1,r13
+        addi    r1,r1,PACAGUARD
+        addi    r1,r1,0x1000
+        subi    r1,r1,STACK_FRAME_OVERHEAD
+
+       b       .__secondary_start
+
+#endif /* CONFIG_PPC_PMAC */
+
 /*
  * This function is called after the master CPU has released the
  * secondary processors.  The execution environment is relocation off.
@@ -1870,6 +1927,12 @@ _STATIC(start_here_pSeries)
        li      r0,0
        stdu    r0,-STACK_FRAME_OVERHEAD(r1)
 
+               /* set up the TOC (physical address) */
+       LOADADDR(r2,__toc_start)
+       addi    r2,r2,0x4000
+       addi    r2,r2,0x4000
+       sub     r2,r2,r26
+
        LOADADDR(r3,cpu_specs)
        sub     r3,r3,r26
        LOADADDR(r4,cur_cpu_spec)
@@ -1877,12 +1940,6 @@ _STATIC(start_here_pSeries)
        mr      r5,r26
        bl      .identify_cpu
 
-       /* set up the TOC (physical address) */
-       LOADADDR(r2,__toc_start)
-       addi    r2,r2,0x4000
-       addi    r2,r2,0x4000
-       sub     r2,r2,r26
-
        /* Get the pointer to the segment table which is used by           */
        /* stab_initialize                                                 */
        LOADADDR(r27, boot_cpuid)
@@ -1926,7 +1983,8 @@ _STATIC(start_here_pSeries)
 
        li      r3,SYSTEMCFG_PHYS_ADDR  /* r3 = ptr to systemcfg */
        lwz     r3,PLATFORM(r3)         /* r3 = platform flags */
-       cmpldi r3,PLATFORM_PSERIES
+       /* Test if bit 0 is set (LPAR bit) */
+       andi.   r3,r3,0x1
        bne    98f
        LOADADDR(r6,_SDR1)              /* Only if NOT LPAR */
        sub     r6,r6,r26
@@ -1938,11 +1996,12 @@ _STATIC(start_here_pSeries)
        mtspr   SRR0,r3
        mtspr   SRR1,r4
        rfid
-#endif /* CONFIG_PPC_PSERIES */
-
+#endif /* CONFIG_PPC_PSERIES */
+       
        /* This is where all platforms converge execution */
 _STATIC(start_here_common)
-       
+       /* relocation is on at this point */
+
        /* The following code sets up the SP and TOC now that we are */
        /* running with translation enabled. */
 
@@ -2013,8 +2072,6 @@ _STATIC(start_here_common)
 
 _GLOBAL(__setup_cpu_power3)
        blr
-_GLOBAL(__setup_cpu_power4)
-       blr
 
 _GLOBAL(hmt_init)
 #ifdef CONFIG_HMT
index 30796300f974ae4c615da0b7ba4e87de712563b0..8c68908d97e2ebcfeaf4eb72471d72c8540d4dff 100644 (file)
@@ -189,6 +189,8 @@ void prom_dump_lmb(void);
 extern unsigned long reloc_offset(void);
 
 extern void enter_prom(void *dummy,...);
+extern void copy_and_flush(unsigned long dest, unsigned long src,
+                          unsigned long size, unsigned long offset);
 
 extern char cmd_line[512];     /* XXX */
 unsigned long dev_tree_size;
@@ -1262,6 +1264,9 @@ prom_init(unsigned long r3, unsigned long r4, unsigned long pp,
        if ((long)_prom->chosen <= 0)
                prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */
 
+       /* On pSeries, copy the CPU hold code */
+       if (_systemcfg->platform == PLATFORM_PSERIES)
+               copy_and_flush(0, KERNELBASE - offset, 0x100, 0);
         if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen,
                            RELOC("stdout"), &getprop_rval,
                            sizeof(getprop_rval)) <= 0)