| .. | .. |
|---|
| 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; |
|---|