]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/kernel/head_64.S
Merge git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / head_64.S
index 6cdfd44d8efe6eeb5371c75fee7392b3515aa04f..69489bd3210c03ecf9c6d5e36fe5bee1c23e8871 100644 (file)
@@ -97,6 +97,12 @@ __secondary_hold_spinloop:
 __secondary_hold_acknowledge:
        .llong  0x0
 
+       /* This flag is set by purgatory if we should be a kdump kernel. */
+       /* Do not move this variable as purgatory knows about it. */
+       .globl  __kdump_flag
+__kdump_flag:
+       .llong  0x0
+
 #ifdef CONFIG_PPC_ISERIES
        /*
         * At offset 0x20, there is a pointer to iSeries LPAR data.
@@ -1360,6 +1366,12 @@ _INIT_STATIC(__boot_from_prom)
         */
        rldicr  r1,r1,0,59
 
+#ifdef CONFIG_RELOCATABLE
+       /* Relocate code for where we are now */
+       mr      r3,r26
+       bl      .relocate
+#endif
+
        /* Restore parameters */
        mr      r3,r31
        mr      r4,r30
@@ -1368,11 +1380,25 @@ _INIT_STATIC(__boot_from_prom)
        mr      r7,r27
 
        /* Do all of the interaction with OF client interface */
+       mr      r8,r26
        bl      .prom_init
        /* We never return */
        trap
 
 _STATIC(__after_prom_start)
+#ifdef CONFIG_RELOCATABLE
+       /* process relocations for the final address of the kernel */
+       lis     r25,PAGE_OFFSET@highest /* compute virtual base of kernel */
+       sldi    r25,r25,32
+#ifdef CONFIG_CRASH_DUMP
+       ld      r7,__kdump_flag-_stext(r26)
+       cmpldi  cr0,r7,1        /* kdump kernel ? - stay where we are */
+       bne     1f
+       add     r25,r25,r26
+#endif
+1:     mr      r3,r25
+       bl      .relocate
+#endif
 
 /*
  * We need to run with _stext at physical address PHYSICAL_START.
@@ -1381,15 +1407,29 @@ _STATIC(__after_prom_start)
  *
  * Note: This process overwrites the OF exception vectors.
  */
-       LOAD_REG_IMMEDIATE(r3, PHYSICAL_START)  /* target addr */
-       cmpd    r3,r26                  /* In some cases the loader may  */
+       li      r3,0                    /* target addr */
+       mr.     r4,r26                  /* In some cases the loader may  */
        beq     9f                      /* have already put us at zero */
-       mr      r4,r26                  /* source address */
-       lis     r5,(copy_to_here - _stext)@ha
-       addi    r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
        li      r6,0x100                /* Start offset, the first 0x100 */
                                        /* bytes were copied earlier.    */
 
+#ifdef CONFIG_CRASH_DUMP
+/*
+ * Check if the kernel has to be running as relocatable kernel based on the
+ * variable __kdump_flag, if it is set the kernel is treated as relocatable
+ * kernel, otherwise it will be moved to PHYSICAL_START
+ */
+       ld      r7,__kdump_flag-_stext(r26)
+       cmpldi  cr0,r7,1
+       bne     3f
+
+       li      r5,__end_interrupts - _stext    /* just copy interrupts */
+       b       5f
+3:
+#endif
+       lis     r5,(copy_to_here - _stext)@ha
+       addi    r5,r5,(copy_to_here - _stext)@l /* # bytes of memory to copy */
+
        bl      .copy_and_flush         /* copy the first n bytes        */
                                        /* this includes the code being  */
                                        /* executed here.                */
@@ -1398,15 +1438,15 @@ _STATIC(__after_prom_start)
        mtctr   r8
        bctr
 
+p_end: .llong  _end - _stext
+
 4:     /* Now copy the rest of the kernel up to _end */
        addis   r5,r26,(p_end - _stext)@ha
        ld      r5,(p_end - _stext)@l(r5)       /* get _end */
-       bl      .copy_and_flush         /* copy the rest */
+5:     bl      .copy_and_flush         /* copy the rest */
 
 9:     b       .start_here_multiplatform
 
-p_end: .llong  _end - _stext
-
 /*
  * Copy routine used to copy the kernel to start at physical address 0
  * and flush and invalidate the caches as needed.
@@ -1617,6 +1657,13 @@ _INIT_STATIC(start_here_multiplatform)
        ori     r6,r6,MSR_RI
        mtmsrd  r6                      /* RI on */
 
+#ifdef CONFIG_RELOCATABLE
+       /* Save the physical address we're running at in kernstart_addr */
+       LOAD_REG_ADDR(r4, kernstart_addr)
+       clrldi  r0,r25,2
+       std     r0,0(r4)
+#endif
+
        /* The following gets the stack set up with the regs */
        /* pointing to the real addr of the kernel stack.  This is   */
        /* all done to support the C function call below which sets  */