Merge branch 'dmi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvar...
[linux-2.6-microblaze.git] / arch / powerpc / kernel / reloc_64.S
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
10 RELA = 7
11 RELACOUNT = 0x6ffffff9
12 R_PPC64_RELATIVE = 22
13
14 /*
15  * r3 = desired final address of kernel
16  */
17 _GLOBAL(relocate)
18         mflr    r0
19         bcl     20,31,$+4
20 0:      mflr    r12             /* r12 has runtime addr of label 0 */
21         mtlr    r0
22         ld      r11,(p_dyn - 0b)(r12)
23         add     r11,r11,r12     /* r11 has runtime addr of .dynamic section */
24         ld      r9,(p_rela - 0b)(r12)
25         add     r9,r9,r12       /* r9 has runtime addr of .rela.dyn section */
26         ld      r10,(p_st - 0b)(r12)
27         add     r10,r10,r12     /* r10 has runtime addr of _stext */
28
29         /*
30          * Scan the dynamic section for the RELA and RELACOUNT entries.
31          */
32         li      r7,0
33         li      r8,0
34 1:      ld      r6,0(r11)       /* get tag */
35         cmpdi   r6,0
36         beq     4f              /* end of list */
37         cmpdi   r6,RELA
38         bne     2f
39         ld      r7,8(r11)       /* get RELA pointer in r7 */
40         b       3f
41 2:      addis   r6,r6,(-RELACOUNT)@ha
42         cmpdi   r6,RELACOUNT@l
43         bne     3f
44         ld      r8,8(r11)       /* get RELACOUNT value in r8 */
45 3:      addi    r11,r11,16
46         b       1b
47 4:      cmpdi   r7,0            /* check we have both RELA and RELACOUNT */
48         cmpdi   cr1,r8,0
49         beq     6f
50         beq     cr1,6f
51
52         /*
53          * Work out linktime address of _stext and hence the
54          * relocation offset to be applied.
55          * cur_offset [r7] = rela.run [r9] - rela.link [r7]
56          * _stext.link [r10] = _stext.run [r10] - cur_offset [r7]
57          * final_offset [r3] = _stext.final [r3] - _stext.link [r10]
58          */
59         subf    r7,r7,r9        /* cur_offset */
60         subf    r10,r7,r10
61         subf    r3,r10,r3       /* final_offset */
62
63         /*
64          * Run through the list of relocations and process the
65          * R_PPC64_RELATIVE ones.
66          */
67         mtctr   r8
68 5:      ld      r0,8(9)         /* ELF64_R_TYPE(reloc->r_info) */
69         cmpdi   r0,R_PPC64_RELATIVE
70         bne     6f
71         ld      r6,0(r9)        /* reloc->r_offset */
72         ld      r0,16(r9)       /* reloc->r_addend */
73         add     r0,r0,r3
74         stdx    r0,r7,r6
75         addi    r9,r9,24
76         bdnz    5b
77
78 6:      blr
79
80 .balign 8
81 p_dyn:  .8byte  __dynamic_start - 0b
82 p_rela: .8byte  __rela_dyn_start - 0b
83 p_st:   .8byte  _stext - 0b
84