.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* Kernel module help for PPC. |
---|
2 | 3 | Copyright (C) 2001 Rusty Russell. |
---|
3 | 4 | |
---|
4 | | - This program is free software; you can redistribute it and/or modify |
---|
5 | | - it under the terms of the GNU General Public License as published by |
---|
6 | | - the Free Software Foundation; either version 2 of the License, or |
---|
7 | | - (at your option) any later version. |
---|
8 | | - |
---|
9 | | - This program is distributed in the hope that it will be useful, |
---|
10 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
11 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
12 | | - GNU General Public License for more details. |
---|
13 | | - |
---|
14 | | - You should have received a copy of the GNU General Public License |
---|
15 | | - along with this program; if not, write to the Free Software |
---|
16 | | - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
---|
17 | 5 | */ |
---|
18 | 6 | |
---|
19 | 7 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
---|
.. | .. |
---|
79 | 67 | return 0; |
---|
80 | 68 | } |
---|
81 | 69 | |
---|
82 | | -static void relaswap(void *_x, void *_y, int size) |
---|
83 | | -{ |
---|
84 | | - uint32_t *x, *y, tmp; |
---|
85 | | - int i; |
---|
86 | | - |
---|
87 | | - y = (uint32_t *)_x; |
---|
88 | | - x = (uint32_t *)_y; |
---|
89 | | - |
---|
90 | | - for (i = 0; i < sizeof(Elf32_Rela) / sizeof(uint32_t); i++) { |
---|
91 | | - tmp = x[i]; |
---|
92 | | - x[i] = y[i]; |
---|
93 | | - y[i] = tmp; |
---|
94 | | - } |
---|
95 | | -} |
---|
96 | | - |
---|
97 | 70 | /* Get the potential trampolines size required of the init and |
---|
98 | 71 | non-init sections */ |
---|
99 | 72 | static unsigned long get_plt_size(const Elf32_Ehdr *hdr, |
---|
.. | .. |
---|
130 | 103 | */ |
---|
131 | 104 | sort((void *)hdr + sechdrs[i].sh_offset, |
---|
132 | 105 | sechdrs[i].sh_size / sizeof(Elf32_Rela), |
---|
133 | | - sizeof(Elf32_Rela), relacmp, relaswap); |
---|
| 106 | + sizeof(Elf32_Rela), relacmp, NULL); |
---|
134 | 107 | |
---|
135 | 108 | ret += count_relocs((void *)hdr |
---|
136 | 109 | + sechdrs[i].sh_offset, |
---|
.. | .. |
---|
172 | 145 | |
---|
173 | 146 | static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) |
---|
174 | 147 | { |
---|
175 | | - if (entry->jump[0] == 0x3d800000 + ((val + 0x8000) >> 16) |
---|
176 | | - && entry->jump[1] == 0x398c0000 + (val & 0xffff)) |
---|
177 | | - return 1; |
---|
178 | | - return 0; |
---|
| 148 | + if (entry->jump[0] != (PPC_INST_ADDIS | __PPC_RT(R12) | PPC_HA(val))) |
---|
| 149 | + return 0; |
---|
| 150 | + if (entry->jump[1] != (PPC_INST_ADDI | __PPC_RT(R12) | __PPC_RA(R12) | |
---|
| 151 | + PPC_LO(val))) |
---|
| 152 | + return 0; |
---|
| 153 | + return 1; |
---|
179 | 154 | } |
---|
180 | 155 | |
---|
181 | 156 | /* Set up a trampoline in the PLT to bounce us to the distant function */ |
---|
.. | .. |
---|
200 | 175 | entry++; |
---|
201 | 176 | } |
---|
202 | 177 | |
---|
203 | | - entry->jump[0] = 0x3d800000+((val+0x8000)>>16); /* lis r12,sym@ha */ |
---|
204 | | - entry->jump[1] = 0x398c0000 + (val&0xffff); /* addi r12,r12,sym@l*/ |
---|
205 | | - entry->jump[2] = 0x7d8903a6; /* mtctr r12 */ |
---|
206 | | - entry->jump[3] = 0x4e800420; /* bctr */ |
---|
| 178 | + /* |
---|
| 179 | + * lis r12, sym@ha |
---|
| 180 | + * addi r12, r12, sym@l |
---|
| 181 | + * mtctr r12 |
---|
| 182 | + * bctr |
---|
| 183 | + */ |
---|
| 184 | + entry->jump[0] = PPC_INST_ADDIS | __PPC_RT(R12) | PPC_HA(val); |
---|
| 185 | + entry->jump[1] = PPC_INST_ADDI | __PPC_RT(R12) | __PPC_RA(R12) | PPC_LO(val); |
---|
| 186 | + entry->jump[2] = PPC_INST_MTCTR | __PPC_RS(R12); |
---|
| 187 | + entry->jump[3] = PPC_INST_BCTR; |
---|
207 | 188 | |
---|
208 | 189 | pr_debug("Initialized plt for 0x%x at %p\n", val, entry); |
---|
209 | 190 | return (uint32_t)entry; |
---|