blob: a3550e8f1a77b6ee291efe9b767c8cdced8c2ddc [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * Copyright (C) Paul Mackerras 1997.
3 *
Cédric Le Goaterf16e9682014-04-24 09:23:37 +02004 * Adapted for 64 bit LE PowerPC by Andrew Tauferner
5 *
Linus Torvalds1da177e2005-04-16 15:20:36 -07006 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070011 */
12
Olaf Heringdecd3002005-08-08 13:24:38 +100013#include "ppc_asm.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070014
Cédric Le Goaterf16e9682014-04-24 09:23:37 +020015RELA = 7
16RELACOUNT = 0x6ffffff9
17
Paul Mackerras1837a062018-11-27 09:01:54 +110018 .data
Michael Ellerman6975a782011-04-12 20:38:55 +000019 /* A procedure descriptor used when booting this as a COFF file.
20 * When making COFF, this comes first in the link and we're
21 * linked at 0x500000.
22 */
Paul Mackerrasf40e5242007-06-07 22:21:31 +100023 .globl _zimage_start_opd
Paul Mackerras66a45dd2006-01-14 15:04:06 +110024_zimage_start_opd:
Michael Ellerman6975a782011-04-12 20:38:55 +000025 .long 0x500000, 0, 0, 0
Paul Mackerras1837a062018-11-27 09:01:54 +110026 .text
27 b _zimage_start
Michael Ellerman6975a782011-04-12 20:38:55 +000028
Cédric Le Goaterf16e9682014-04-24 09:23:37 +020029#ifdef __powerpc64__
30.balign 8
31p_start: .llong _start
32p_etext: .llong _etext
33p_bss_start: .llong __bss_start
34p_end: .llong _end
35
36p_toc: .llong __toc_start + 0x8000 - p_base
37p_dyn: .llong __dynamic_start - p_base
38p_rela: .llong __rela_dyn_start - p_base
39p_prom: .llong 0
40 .weak _platform_stack_top
41p_pstack: .llong _platform_stack_top
42#else
Michael Ellerman6975a782011-04-12 20:38:55 +000043p_start: .long _start
44p_etext: .long _etext
45p_bss_start: .long __bss_start
46p_end: .long _end
47
48 .weak _platform_stack_top
49p_pstack: .long _platform_stack_top
Cédric Le Goaterf16e9682014-04-24 09:23:37 +020050#endif
Paul Mackerras66a45dd2006-01-14 15:04:06 +110051
Olaf Hering67a1b682005-10-28 17:46:49 -070052 .globl _zimage_start
Joel Stanley76c386b2018-09-14 13:36:47 +093053 /* Clang appears to require the .weak directive to be after the symbol
54 * is defined. See https://bugs.llvm.org/show_bug.cgi?id=38921 */
55 .weak _zimage_start
Olaf Hering67a1b682005-10-28 17:46:49 -070056_zimage_start:
Milton Miller160cc3e2007-03-21 09:02:53 -060057 .globl _zimage_start_lib
58_zimage_start_lib:
Paul Mackerras66a45dd2006-01-14 15:04:06 +110059 /* Work out the offset between the address we were linked at
60 and the address where we're running. */
Michael Ellerman6975a782011-04-12 20:38:55 +000061 bl .+4
62p_base: mflr r10 /* r10 now points to runtime addr of p_base */
Cédric Le Goaterf16e9682014-04-24 09:23:37 +020063#ifndef __powerpc64__
Michael Ellerman6975a782011-04-12 20:38:55 +000064 /* grab the link address of the dynamic section in r11 */
65 addis r11,r10,(_GLOBAL_OFFSET_TABLE_-p_base)@ha
66 lwz r11,(_GLOBAL_OFFSET_TABLE_-p_base)@l(r11)
67 cmpwi r11,0
68 beq 3f /* if not linked -pie */
69 /* get the runtime address of the dynamic section in r12 */
70 .weak __dynamic_start
71 addis r12,r10,(__dynamic_start-p_base)@ha
72 addi r12,r12,(__dynamic_start-p_base)@l
73 subf r11,r11,r12 /* runtime - linktime offset */
Olaf Heringa4497232005-10-28 17:46:48 -070074
Michael Ellerman6975a782011-04-12 20:38:55 +000075 /* The dynamic section contains a series of tagged entries.
76 * We need the RELA and RELACOUNT entries. */
Michael Ellerman6975a782011-04-12 20:38:55 +000077 li r9,0
78 li r0,0
799: lwz r8,0(r12) /* get tag */
80 cmpwi r8,0
81 beq 10f /* end of list */
82 cmpwi r8,RELA
83 bne 11f
84 lwz r9,4(r12) /* get RELA pointer in r9 */
85 b 12f
8611: addis r8,r8,(-RELACOUNT)@ha
87 cmpwi r8,RELACOUNT@l
88 bne 12f
89 lwz r0,4(r12) /* get RELACOUNT value in r0 */
9012: addi r12,r12,8
91 b 9b
92
93 /* The relocation section contains a list of relocations.
94 * We now do the R_PPC_RELATIVE ones, which point to words
95 * which need to be initialized with addend + offset.
96 * The R_PPC_RELATIVE ones come first and there are RELACOUNT
97 * of them. */
9810: /* skip relocation if we don't have both */
99 cmpwi r0,0
Olaf Hering68643cf2005-11-17 22:09:02 +0100100 beq 3f
Michael Ellerman6975a782011-04-12 20:38:55 +0000101 cmpwi r9,0
102 beq 3f
103
104 add r9,r9,r11 /* Relocate RELA pointer */
105 mtctr r0
1062: lbz r0,4+3(r9) /* ELF32_R_INFO(reloc->r_info) */
107 cmpwi r0,22 /* R_PPC_RELATIVE */
108 bne 3f
109 lwz r12,0(r9) /* reloc->r_offset */
110 lwz r0,8(r9) /* reloc->r_addend */
111 add r0,r0,r11
112 stwx r0,r11,r12
113 addi r9,r9,12
Olaf Hering68643cf2005-11-17 22:09:02 +0100114 bdnz 2b
Olaf Heringa4497232005-10-28 17:46:48 -0700115
David Gibsoncd197ff2007-03-05 14:24:52 +1100116 /* Do a cache flush for our text, in case the loader didn't */
Michael Ellerman6975a782011-04-12 20:38:55 +00001173: lwz r9,p_start-p_base(r10) /* note: these are relocated now */
118 lwz r8,p_etext-p_base(r10)
Olaf Hering68643cf2005-11-17 22:09:02 +01001194: dcbf r0,r9
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 icbi r0,r9
121 addi r9,r9,0x20
Olaf Heringeacb1962006-03-04 13:15:40 +0100122 cmplw cr0,r9,r8
Olaf Hering68643cf2005-11-17 22:09:02 +0100123 blt 4b
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 sync
125 isync
126
David Gibsoncd197ff2007-03-05 14:24:52 +1100127 /* Clear the BSS */
Michael Ellerman6975a782011-04-12 20:38:55 +0000128 lwz r9,p_bss_start-p_base(r10)
129 lwz r8,p_end-p_base(r10)
130 li r0,0
1315: stw r0,0(r9)
David Gibsoncd197ff2007-03-05 14:24:52 +1100132 addi r9,r9,4
133 cmplw cr0,r9,r8
134 blt 5b
Linus Torvalds1da177e2005-04-16 15:20:36 -0700135
David Gibsoncd197ff2007-03-05 14:24:52 +1100136 /* Possibly set up a custom stack */
Michael Ellerman6975a782011-04-12 20:38:55 +0000137 lwz r8,p_pstack-p_base(r10)
David Gibsoncd197ff2007-03-05 14:24:52 +1100138 cmpwi r8,0
139 beq 6f
140 lwz r1,0(r8)
141 li r0,0
142 stwu r0,-16(r1) /* establish a stack frame */
1436:
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200144#else /* __powerpc64__ */
145 /* Save the prom pointer at p_prom. */
146 std r5,(p_prom-p_base)(r10)
David Gibsoncd197ff2007-03-05 14:24:52 +1100147
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200148 /* Set r2 to the TOC. */
149 ld r2,(p_toc-p_base)(r10)
150 add r2,r2,r10
151
152 /* Grab the link address of the dynamic section in r11. */
153 ld r11,-32768(r2)
154 cmpwi r11,0
155 beq 3f /* if not linked -pie then no dynamic section */
156
157 ld r11,(p_dyn-p_base)(r10)
158 add r11,r11,r10
159 ld r9,(p_rela-p_base)(r10)
160 add r9,r9,r10
161
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800162 li r13,0
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200163 li r8,0
Jeremy Kerr7f664cf2015-02-11 12:55:44 +08001649: ld r12,0(r11) /* get tag */
165 cmpdi r12,0
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200166 beq 12f /* end of list */
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800167 cmpdi r12,RELA
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200168 bne 10f
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800169 ld r13,8(r11) /* get RELA pointer in r13 */
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200170 b 11f
Jeremy Kerr7f664cf2015-02-11 12:55:44 +080017110: addis r12,r12,(-RELACOUNT)@ha
172 cmpdi r12,RELACOUNT@l
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200173 bne 11f
174 ld r8,8(r11) /* get RELACOUNT value in r8 */
17511: addi r11,r11,16
176 b 9b
17712:
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800178 cmpdi r13,0 /* check we have both RELA and RELACOUNT */
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200179 cmpdi cr1,r8,0
180 beq 3f
181 beq cr1,3f
182
183 /* Calcuate the runtime offset. */
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800184 subf r13,r13,r9
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200185
186 /* Run through the list of relocations and process the
187 * R_PPC64_RELATIVE ones. */
188 mtctr r8
18913: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */
190 cmpdi r0,22 /* R_PPC64_RELATIVE */
191 bne 3f
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800192 ld r12,0(r9) /* reloc->r_offset */
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200193 ld r0,16(r9) /* reloc->r_addend */
Jeremy Kerr7f664cf2015-02-11 12:55:44 +0800194 add r0,r0,r13
195 stdx r0,r13,r12
Cédric Le Goaterf16e9682014-04-24 09:23:37 +0200196 addi r9,r9,24
197 bdnz 13b
198
199 /* Do a cache flush for our text, in case the loader didn't */
2003: ld r9,p_start-p_base(r10) /* note: these are relocated now */
201 ld r8,p_etext-p_base(r10)
2024: dcbf r0,r9
203 icbi r0,r9
204 addi r9,r9,0x20
205 cmpld cr0,r9,r8
206 blt 4b
207 sync
208 isync
209
210 /* Clear the BSS */
211 ld r9,p_bss_start-p_base(r10)
212 ld r8,p_end-p_base(r10)
213 li r0,0
2145: std r0,0(r9)
215 addi r9,r9,8
216 cmpld cr0,r9,r8
217 blt 5b
218
219 /* Possibly set up a custom stack */
220 ld r8,p_pstack-p_base(r10)
221 cmpdi r8,0
222 beq 6f
223 ld r1,0(r8)
224 li r0,0
Jeremy Kerr8c06f0d2015-02-11 12:55:44 +0800225 stdu r0,-112(r1) /* establish a stack frame */
Cédric Le Goaterf16e9682014-04-24 09:23:37 +02002266:
227#endif /* __powerpc64__ */
David Gibsoncd197ff2007-03-05 14:24:52 +1100228 /* Call platform_init() */
229 bl platform_init
230
231 /* Call start */
David Gibsoncd197ff2007-03-05 14:24:52 +1100232 b start
Cédric Le Goater93d39212014-04-24 09:23:36 +0200233
234#ifdef __powerpc64__
235
236#define PROM_FRAME_SIZE 512
237#define SAVE_GPR(n, base) std n,8*(n)(base)
238#define REST_GPR(n, base) ld n,8*(n)(base)
239#define SAVE_2GPRS(n, base) SAVE_GPR(n, base); SAVE_GPR(n+1, base)
240#define SAVE_4GPRS(n, base) SAVE_2GPRS(n, base); SAVE_2GPRS(n+2, base)
241#define SAVE_8GPRS(n, base) SAVE_4GPRS(n, base); SAVE_4GPRS(n+4, base)
242#define SAVE_10GPRS(n, base) SAVE_8GPRS(n, base); SAVE_2GPRS(n+8, base)
243#define REST_2GPRS(n, base) REST_GPR(n, base); REST_GPR(n+1, base)
244#define REST_4GPRS(n, base) REST_2GPRS(n, base); REST_2GPRS(n+2, base)
245#define REST_8GPRS(n, base) REST_4GPRS(n, base); REST_4GPRS(n+4, base)
246#define REST_10GPRS(n, base) REST_8GPRS(n, base); REST_2GPRS(n+8, base)
247
248/* prom handles the jump into and return from firmware. The prom args pointer
249 is loaded in r3. */
250.globl prom
251prom:
252 mflr r0
253 std r0,16(r1)
254 stdu r1,-PROM_FRAME_SIZE(r1) /* Save SP and create stack space */
255
256 SAVE_GPR(2, r1)
257 SAVE_GPR(13, r1)
258 SAVE_8GPRS(14, r1)
259 SAVE_10GPRS(22, r1)
260 mfcr r10
261 std r10,8*32(r1)
262 mfmsr r10
263 std r10,8*33(r1)
264
265 /* remove MSR_LE from msr but keep MSR_SF */
266 mfmsr r10
267 rldicr r10,r10,0,62
268 mtsrr1 r10
269
270 /* Load FW address, set LR to label 1, and jump to FW */
271 bl 0f
2720: mflr r10
273 addi r11,r10,(1f-0b)
274 mtlr r11
275
276 ld r10,(p_prom-0b)(r10)
277 mtsrr0 r10
278
279 rfid
280
2811: /* Return from OF */
Cédric Le Goater147c0512014-04-24 09:23:39 +0200282 FIXUP_ENDIAN
Cédric Le Goater93d39212014-04-24 09:23:36 +0200283
284 /* Restore registers and return. */
285 rldicl r1,r1,0,32
286
287 /* Restore the MSR (back to 64 bits) */
288 ld r10,8*(33)(r1)
289 mtmsr r10
290 isync
291
292 /* Restore other registers */
293 REST_GPR(2, r1)
294 REST_GPR(13, r1)
295 REST_8GPRS(14, r1)
296 REST_10GPRS(22, r1)
297 ld r10,8*32(r1)
298 mtcr r10
299
300 addi r1,r1,PROM_FRAME_SIZE
301 ld r0,16(r1)
302 mtlr r0
303 blr
304#endif