1/* SPDX-License-Identifier: GPL-2.0-or-later */ 2/* 3 * Code to process dynamic relocations in the kernel. 4 * 5 * Copyright 2008 Paul Mackerras, IBM Corp. 6 */ 7 8#include <asm/ppc_asm.h> 9 10RELA = 7 11RELASZ = 8 12RELAENT = 9 13R_PPC64_RELATIVE = 22 14R_PPC64_UADDR64 = 43 15 16/* 17 * r3 = desired final address of kernel 18 */ 19_GLOBAL(relocate) 20 mflr r0 21 bcl 20,31,$+4 220: mflr r12 /* r12 has runtime addr of label 0 */ 23 mtlr r0 24 ld r11,(p_dyn - 0b)(r12) 25 add r11,r11,r12 /* r11 has runtime addr of .dynamic section */ 26 ld r9,(p_rela - 0b)(r12) 27 add r9,r9,r12 /* r9 has runtime addr of .rela.dyn section */ 28 ld r10,(p_st - 0b)(r12) 29 add r10,r10,r12 /* r10 has runtime addr of _stext */ 30 ld r13,(p_sym - 0b)(r12) 31 add r13,r13,r12 /* r13 has runtime addr of .dynsym */ 32 33 /* 34 * Scan the dynamic section for the RELA, RELASZ and RELAENT entries. 35 */ 36 li r7,0 37 li r8,0 38.Ltags: 39 ld r6,0(r11) /* get tag */ 40 cmpdi r6,0 41 beq .Lend_of_list /* end of list */ 42 cmpdi r6,RELA 43 bne 2f 44 ld r7,8(r11) /* get RELA pointer in r7 */ 45 b 4f 462: cmpdi r6,RELASZ 47 bne 3f 48 ld r8,8(r11) /* get RELASZ value in r8 */ 49 b 4f 503: cmpdi r6,RELAENT 51 bne 4f 52 ld r12,8(r11) /* get RELAENT value in r12 */ 534: addi r11,r11,16 54 b .Ltags 55.Lend_of_list: 56 cmpdi r7,0 /* check we have RELA, RELASZ, RELAENT */ 57 cmpdi cr1,r8,0 58 beq .Lout 59 beq cr1,.Lout 60 cmpdi r12,0 61 beq .Lout 62 63 /* 64 * Work out linktime address of _stext and hence the 65 * relocation offset to be applied. 66 * cur_offset [r7] = rela.run [r9] - rela.link [r7] 67 * _stext.link [r10] = _stext.run [r10] - cur_offset [r7] 68 * final_offset [r3] = _stext.final [r3] - _stext.link [r10] 69 */ 70 subf r7,r7,r9 /* cur_offset */ 71 subf r10,r7,r10 72 subf r3,r10,r3 /* final_offset */ 73 74 /* 75 * Run through the list of relocations and process the 76 * R_PPC64_RELATIVE and R_PPC64_UADDR64 ones. 77 */ 78 divd r8,r8,r12 /* RELASZ / RELAENT */ 79 mtctr r8 80.Lrels: ld r0,8(r9) /* ELF64_R_TYPE(reloc->r_info) */ 81 cmpdi r0,R_PPC64_RELATIVE 82 bne .Luaddr64 83 ld r6,0(r9) /* reloc->r_offset */ 84 ld r0,16(r9) /* reloc->r_addend */ 85 b .Lstore 86.Luaddr64: 87 srdi r14,r0,32 /* ELF64_R_SYM(reloc->r_info) */ 88 clrldi r0,r0,32 89 cmpdi r0,R_PPC64_UADDR64 90 bne .Lnext 91 ld r6,0(r9) 92 ld r0,16(r9) 93 mulli r14,r14,24 /* 24 == sizeof(elf64_sym) */ 94 add r14,r14,r13 /* elf64_sym[ELF64_R_SYM] */ 95 ld r14,8(r14) 96 add r0,r0,r14 97.Lstore: 98 add r0,r0,r3 99 stdx r0,r7,r6 100.Lnext: 101 add r9,r9,r12 102 bdnz .Lrels 103.Lout: 104 blr 105 106.balign 8 107p_dyn: .8byte __dynamic_start - 0b 108p_rela: .8byte __rela_dyn_start - 0b 109p_sym: .8byte __dynamic_symtab - 0b 110p_st: .8byte _stext - 0b 111 112