diff options
author | Cédric Le Goater <clg@fr.ibm.com> | 2014-04-24 03:23:37 -0400 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2014-04-28 03:36:12 -0400 |
commit | f16e9684996188c12e1f460589003e99086ce36e (patch) | |
tree | 2072c5c57b07305fd06d2723ee41c2a4b46fea20 /arch/powerpc/boot | |
parent | 93d3921042988317e94b1bcc2e19844efe0b7356 (diff) |
powerpc/boot: Modify entry point for 64bit
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>
Diffstat (limited to 'arch/powerpc/boot')
-rw-r--r-- | arch/powerpc/boot/crt0.S | 108 |
1 files changed, 104 insertions, 4 deletions
diff --git a/arch/powerpc/boot/crt0.S b/arch/powerpc/boot/crt0.S index dbd99d064828..689290561e69 100644 --- a/arch/powerpc/boot/crt0.S +++ b/arch/powerpc/boot/crt0.S | |||
@@ -1,17 +1,20 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) Paul Mackerras 1997. | 2 | * Copyright (C) Paul Mackerras 1997. |
3 | * | 3 | * |
4 | * Adapted for 64 bit LE PowerPC by Andrew Tauferner | ||
5 | * | ||
4 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
5 | * modify it under the terms of the GNU General Public License | 7 | * modify it under the terms of the GNU General Public License |
6 | * as published by the Free Software Foundation; either version | 8 | * as published by the Free Software Foundation; either version |
7 | * 2 of the License, or (at your option) any later version. | 9 | * 2 of the License, or (at your option) any later version. |
8 | * | 10 | * |
9 | * NOTE: this code runs in 32 bit mode, is position-independent, | ||
10 | * and is packaged as ELF32. | ||
11 | */ | 11 | */ |
12 | 12 | ||
13 | #include "ppc_asm.h" | 13 | #include "ppc_asm.h" |
14 | 14 | ||
15 | RELA = 7 | ||
16 | RELACOUNT = 0x6ffffff9 | ||
17 | |||
15 | .text | 18 | .text |
16 | /* A procedure descriptor used when booting this as a COFF file. | 19 | /* A procedure descriptor used when booting this as a COFF file. |
17 | * When making COFF, this comes first in the link and we're | 20 | * When making COFF, this comes first in the link and we're |
@@ -21,6 +24,20 @@ | |||
21 | _zimage_start_opd: | 24 | _zimage_start_opd: |
22 | .long 0x500000, 0, 0, 0 | 25 | .long 0x500000, 0, 0, 0 |
23 | 26 | ||
27 | #ifdef __powerpc64__ | ||
28 | .balign 8 | ||
29 | p_start: .llong _start | ||
30 | p_etext: .llong _etext | ||
31 | p_bss_start: .llong __bss_start | ||
32 | p_end: .llong _end | ||
33 | |||
34 | p_toc: .llong __toc_start + 0x8000 - p_base | ||
35 | p_dyn: .llong __dynamic_start - p_base | ||
36 | p_rela: .llong __rela_dyn_start - p_base | ||
37 | p_prom: .llong 0 | ||
38 | .weak _platform_stack_top | ||
39 | p_pstack: .llong _platform_stack_top | ||
40 | #else | ||
24 | p_start: .long _start | 41 | p_start: .long _start |
25 | p_etext: .long _etext | 42 | p_etext: .long _etext |
26 | p_bss_start: .long __bss_start | 43 | p_bss_start: .long __bss_start |
@@ -28,6 +45,7 @@ p_end: .long _end | |||
28 | 45 | ||
29 | .weak _platform_stack_top | 46 | .weak _platform_stack_top |
30 | p_pstack: .long _platform_stack_top | 47 | p_pstack: .long _platform_stack_top |
48 | #endif | ||
31 | 49 | ||
32 | .weak _zimage_start | 50 | .weak _zimage_start |
33 | .globl _zimage_start | 51 | .globl _zimage_start |
@@ -38,6 +56,7 @@ _zimage_start_lib: | |||
38 | and the address where we're running. */ | 56 | and the address where we're running. */ |
39 | bl .+4 | 57 | bl .+4 |
40 | p_base: mflr r10 /* r10 now points to runtime addr of p_base */ | 58 | p_base: mflr r10 /* r10 now points to runtime addr of p_base */ |
59 | #ifndef __powerpc64__ | ||
41 | /* grab the link address of the dynamic section in r11 */ | 60 | /* grab the link address of the dynamic section in r11 */ |
42 | addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha | 61 | addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha |
43 | lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11) | 62 | 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 */ | |||
51 | 70 | ||
52 | /* The dynamic section contains a series of tagged entries. | 71 | /* The dynamic section contains a series of tagged entries. |
53 | * We need the RELA and RELACOUNT entries. */ | 72 | * We need the RELA and RELACOUNT entries. */ |
54 | RELA = 7 | ||
55 | RELACOUNT = 0x6ffffff9 | ||
56 | li r9,0 | 73 | li r9,0 |
57 | li r0,0 | 74 | li r0,0 |
58 | 9: lwz r8,0(r12) /* get tag */ | 75 | 9: lwz r8,0(r12) /* get tag */ |
@@ -120,7 +137,90 @@ RELACOUNT = 0x6ffffff9 | |||
120 | li r0,0 | 137 | li r0,0 |
121 | stwu r0,-16(r1) /* establish a stack frame */ | 138 | stwu r0,-16(r1) /* establish a stack frame */ |
122 | 6: | 139 | 6: |
140 | #else /* __powerpc64__ */ | ||
141 | /* Save the prom pointer at p_prom. */ | ||
142 | std r5,(p_prom-p_base)(r10) | ||
143 | |||
144 | /* Set r2 to the TOC. */ | ||
145 | ld r2,(p_toc-p_base)(r10) | ||
146 | add r2,r2,r10 | ||
147 | |||
148 | /* Grab the link address of the dynamic section in r11. */ | ||
149 | ld r11,-32768(r2) | ||
150 | cmpwi r11,0 | ||
151 | beq 3f /* if not linked -pie then no dynamic section */ | ||
152 | |||
153 | ld r11,(p_dyn-p_base)(r10) | ||
154 | add r11,r11,r10 | ||
155 | ld r9,(p_rela-p_base)(r10) | ||
156 | add r9,r9,r10 | ||
157 | |||
158 | li r7,0 | ||
159 | li r8,0 | ||
160 | 9: ld r6,0(r11) /* get tag */ | ||
161 | cmpdi r6,0 | ||
162 | beq 12f /* end of list */ | ||
163 | cmpdi r6,RELA | ||
164 | bne 10f | ||
165 | ld r7,8(r11) /* get RELA pointer in r7 */ | ||
166 | b 11f | ||
167 | 10: addis r6,r6,(-RELACOUNT)@ha | ||
168 | cmpdi r6,RELACOUNT@l | ||
169 | bne 11f | ||
170 | ld r8,8(r11) /* get RELACOUNT value in r8 */ | ||
171 | 11: addi r11,r11,16 | ||
172 | b 9b | ||
173 | 12: | ||
174 | cmpdi r7,0 /* check we have both RELA and RELACOUNT */ | ||
175 | cmpdi cr1,r8,0 | ||
176 | beq 3f | ||
177 | beq cr1,3f | ||
178 | |||
179 | /* Calcuate the runtime offset. */ | ||
180 | subf r7,r7,r9 | ||
123 | 181 | ||
182 | /* Run through the list of relocations and process the | ||
183 | * R_PPC64_RELATIVE ones. */ | ||
184 | mtctr r8 | ||
185 | 13: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */ | ||
186 | cmpdi r0,22 /* R_PPC64_RELATIVE */ | ||
187 | bne 3f | ||
188 | ld r6,0(r9) /* reloc->r_offset */ | ||
189 | ld r0,16(r9) /* reloc->r_addend */ | ||
190 | add r0,r0,r7 | ||
191 | stdx r0,r7,r6 | ||
192 | addi r9,r9,24 | ||
193 | bdnz 13b | ||
194 | |||
195 | /* Do a cache flush for our text, in case the loader didn't */ | ||
196 | 3: ld r9,p_start-p_base(r10) /* note: these are relocated now */ | ||
197 | ld r8,p_etext-p_base(r10) | ||
198 | 4: dcbf r0,r9 | ||
199 | icbi r0,r9 | ||
200 | addi r9,r9,0x20 | ||
201 | cmpld cr0,r9,r8 | ||
202 | blt 4b | ||
203 | sync | ||
204 | isync | ||
205 | |||
206 | /* Clear the BSS */ | ||
207 | ld r9,p_bss_start-p_base(r10) | ||
208 | ld r8,p_end-p_base(r10) | ||
209 | li r0,0 | ||
210 | 5: std r0,0(r9) | ||
211 | addi r9,r9,8 | ||
212 | cmpld cr0,r9,r8 | ||
213 | blt 5b | ||
214 | |||
215 | /* Possibly set up a custom stack */ | ||
216 | ld r8,p_pstack-p_base(r10) | ||
217 | cmpdi r8,0 | ||
218 | beq 6f | ||
219 | ld r1,0(r8) | ||
220 | li r0,0 | ||
221 | stdu r0,-16(r1) /* establish a stack frame */ | ||
222 | 6: | ||
223 | #endif /* __powerpc64__ */ | ||
124 | /* Call platform_init() */ | 224 | /* Call platform_init() */ |
125 | bl platform_init | 225 | bl platform_init |
126 | 226 | ||