powerpc/boot: Modify entry point for 64bit
authorCédric Le Goater <clg@fr.ibm.com>
Thu, 24 Apr 2014 07:23:37 +0000 (09:23 +0200)
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>
Mon, 28 Apr 2014 07:36:12 +0000 (17:36 +1000)
This patch adds support a 64bit wrapper entry point. As in 32bit, the
entry point does its own relocation and can be loaded at any address
by the firmware.

Signed-off-by: Cédric Le Goater <clg@fr.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
arch/powerpc/boot/crt0.S

index dbd99d0648287e96e18280ae253866b8d1a91fe7..689290561e6902f218d0ac11ea86bf1b580dcd6a 100644 (file)
@@ -1,17 +1,20 @@
 /*
  * Copyright (C) Paul Mackerras 1997.
  *
+ * Adapted for 64 bit LE PowerPC by Andrew Tauferner
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
  * as published by the Free Software Foundation; either version
  * 2 of the License, or (at your option) any later version.
  *
- * NOTE: this code runs in 32 bit mode, is position-independent,
- * and is packaged as ELF32.
  */
 
 #include "ppc_asm.h"
 
+RELA = 7
+RELACOUNT = 0x6ffffff9
+
        .text
        /* A procedure descriptor used when booting this as a COFF file.
         * When making COFF, this comes first in the link and we're
 _zimage_start_opd:
        .long   0x500000, 0, 0, 0
 
+#ifdef __powerpc64__
+.balign 8
+p_start:       .llong  _start
+p_etext:       .llong  _etext
+p_bss_start:   .llong  __bss_start
+p_end:         .llong  _end
+
+p_toc:         .llong  __toc_start + 0x8000 - p_base
+p_dyn:         .llong  __dynamic_start - p_base
+p_rela:                .llong  __rela_dyn_start - p_base
+p_prom:                .llong  0
+       .weak   _platform_stack_top
+p_pstack:      .llong  _platform_stack_top
+#else
 p_start:       .long   _start
 p_etext:       .long   _etext
 p_bss_start:   .long   __bss_start
@@ -28,6 +45,7 @@ p_end:                .long   _end
 
        .weak   _platform_stack_top
 p_pstack:      .long   _platform_stack_top
+#endif
 
        .weak   _zimage_start
        .globl  _zimage_start
@@ -38,6 +56,7 @@ _zimage_start_lib:
           and the address where we're running. */
        bl      .+4
 p_base:        mflr    r10             /* r10 now points to runtime addr of p_base */
+#ifndef __powerpc64__
        /* grab the link address of the dynamic section in r11 */
        addis   r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
        lwz     r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
@@ -51,8 +70,6 @@ p_base:       mflr    r10             /* r10 now points to runtime addr of p_base */
 
        /* The dynamic section contains a series of tagged entries.
         * We need the RELA and RELACOUNT entries. */
-RELA = 7
-RELACOUNT = 0x6ffffff9
        li      r9,0
        li      r0,0
 9:     lwz     r8,0(r12)       /* get tag */
@@ -120,7 +137,90 @@ RELACOUNT = 0x6ffffff9
        li      r0,0
        stwu    r0,-16(r1)      /* establish a stack frame */
 6:
+#else /* __powerpc64__ */
+       /* Save the prom pointer at p_prom. */
+       std     r5,(p_prom-p_base)(r10)
+
+       /* Set r2 to the TOC. */
+       ld      r2,(p_toc-p_base)(r10)
+       add     r2,r2,r10
+
+       /* Grab the link address of the dynamic section in r11. */
+       ld      r11,-32768(r2)
+       cmpwi   r11,0
+       beq     3f              /* if not linked -pie then no dynamic section */
+
+       ld      r11,(p_dyn-p_base)(r10)
+       add     r11,r11,r10
+       ld      r9,(p_rela-p_base)(r10)
+       add     r9,r9,r10
+
+       li      r7,0
+       li      r8,0
+9:     ld      r6,0(r11)       /* get tag */
+       cmpdi   r6,0
+       beq     12f              /* end of list */
+       cmpdi   r6,RELA
+       bne     10f
+       ld      r7,8(r11)       /* get RELA pointer in r7 */
+       b       11f
+10:    addis   r6,r6,(-RELACOUNT)@ha
+       cmpdi   r6,RELACOUNT@l
+       bne     11f
+       ld      r8,8(r11)       /* get RELACOUNT value in r8 */
+11:    addi    r11,r11,16
+       b       9b
+12:
+       cmpdi   r7,0            /* check we have both RELA and RELACOUNT */
+       cmpdi   cr1,r8,0
+       beq     3f
+       beq     cr1,3f
+
+       /* Calcuate the runtime offset. */
+       subf    r7,r7,r9
 
+       /* Run through the list of relocations and process the
+        * R_PPC64_RELATIVE ones. */
+       mtctr   r8
+13:    ld      r0,8(r9)        /* ELF64_R_TYPE(reloc->r_info) */
+       cmpdi   r0,22           /* R_PPC64_RELATIVE */
+       bne     3f
+       ld      r6,0(r9)        /* reloc->r_offset */
+       ld      r0,16(r9)       /* reloc->r_addend */
+       add     r0,r0,r7
+       stdx    r0,r7,r6
+       addi    r9,r9,24
+       bdnz    13b
+
+       /* Do a cache flush for our text, in case the loader didn't */
+3:     ld      r9,p_start-p_base(r10)  /* note: these are relocated now */
+       ld      r8,p_etext-p_base(r10)
+4:     dcbf    r0,r9
+       icbi    r0,r9
+       addi    r9,r9,0x20
+       cmpld   cr0,r9,r8
+       blt     4b
+       sync
+       isync
+
+       /* Clear the BSS */
+       ld      r9,p_bss_start-p_base(r10)
+       ld      r8,p_end-p_base(r10)
+       li      r0,0
+5:     std     r0,0(r9)
+       addi    r9,r9,8
+       cmpld   cr0,r9,r8
+       blt     5b
+
+       /* Possibly set up a custom stack */
+       ld      r8,p_pstack-p_base(r10)
+       cmpdi   r8,0
+       beq     6f
+       ld      r1,0(r8)
+       li      r0,0
+       stdu    r0,-16(r1)      /* establish a stack frame */
+6:
+#endif  /* __powerpc64__ */
        /* Call platform_init() */
        bl      platform_init