1 // SPDX-License-Identifier: GPL-2.0-or-later !! 1 /* Kernel module help for PPC. 2 /* !! 2 Copyright (C) 2001 Rusty Russell. 3 * OpenRISC module.c << 4 * << 5 * Linux architectural port borrowing liberall << 6 * others. All original copyrights apply as p << 7 * declaration. << 8 * << 9 * Modifications for the OpenRISC architecture << 10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@s << 11 */ << 12 3 >> 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 */ >> 18 #include <linux/module.h> 13 #include <linux/moduleloader.h> 19 #include <linux/moduleloader.h> 14 #include <linux/elf.h> 20 #include <linux/elf.h> >> 21 #include <linux/vmalloc.h> >> 22 #include <linux/fs.h> >> 23 #include <linux/string.h> >> 24 #include <linux/kernel.h> >> 25 #include <linux/cache.h> >> 26 >> 27 #if 0 >> 28 #define DEBUGP printk >> 29 #else >> 30 #define DEBUGP(fmt , ...) >> 31 #endif >> 32 >> 33 LIST_HEAD(module_bug_list); >> 34 >> 35 void *module_alloc(unsigned long size) >> 36 { >> 37 if (size == 0) >> 38 return NULL; >> 39 return vmalloc(size); >> 40 } >> 41 >> 42 /* Free memory returned from module_alloc */ >> 43 void module_free(struct module *mod, void *module_region) >> 44 { >> 45 vfree(module_region); >> 46 /* FIXME: If module_region == mod->init_region, trim exception >> 47 table entries. */ >> 48 } >> 49 >> 50 /* Count how many different relocations (different symbol, different >> 51 addend) */ >> 52 static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) >> 53 { >> 54 unsigned int i, j, ret = 0; >> 55 >> 56 /* Sure, this is order(n^2), but it's usually short, and not >> 57 time critical */ >> 58 for (i = 0; i < num; i++) { >> 59 for (j = 0; j < i; j++) { >> 60 /* If this addend appeared before, it's >> 61 already been counted */ >> 62 if (ELF32_R_SYM(rela[i].r_info) >> 63 == ELF32_R_SYM(rela[j].r_info) >> 64 && rela[i].r_addend == rela[j].r_addend) >> 65 break; >> 66 } >> 67 if (j == i) ret++; >> 68 } >> 69 return ret; >> 70 } >> 71 >> 72 /* Get the potential trampolines size required of the init and >> 73 non-init sections */ >> 74 static unsigned long get_plt_size(const Elf32_Ehdr *hdr, >> 75 const Elf32_Shdr *sechdrs, >> 76 const char *secstrings, >> 77 int is_init) >> 78 { >> 79 unsigned long ret = 0; >> 80 unsigned i; >> 81 >> 82 /* Everything marked ALLOC (this includes the exported >> 83 symbols) */ >> 84 for (i = 1; i < hdr->e_shnum; i++) { >> 85 /* If it's called *.init*, and we're not init, we're >> 86 not interested */ >> 87 if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) >> 88 != is_init) >> 89 continue; >> 90 >> 91 if (sechdrs[i].sh_type == SHT_RELA) { >> 92 DEBUGP("Found relocations in section %u\n", i); >> 93 DEBUGP("Ptr: %p. Number: %u\n", >> 94 (void *)hdr + sechdrs[i].sh_offset, >> 95 sechdrs[i].sh_size / sizeof(Elf32_Rela)); >> 96 ret += count_relocs((void *)hdr >> 97 + sechdrs[i].sh_offset, >> 98 sechdrs[i].sh_size >> 99 / sizeof(Elf32_Rela)) >> 100 * sizeof(struct ppc_plt_entry); >> 101 } >> 102 } >> 103 >> 104 return ret; >> 105 } >> 106 >> 107 int module_frob_arch_sections(Elf32_Ehdr *hdr, >> 108 Elf32_Shdr *sechdrs, >> 109 char *secstrings, >> 110 struct module *me) >> 111 { >> 112 unsigned int i; >> 113 >> 114 /* Find .plt and .init.plt sections */ >> 115 for (i = 0; i < hdr->e_shnum; i++) { >> 116 if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) >> 117 me->arch.init_plt_section = i; >> 118 else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) >> 119 me->arch.core_plt_section = i; >> 120 } >> 121 if (!me->arch.core_plt_section || !me->arch.init_plt_section) { >> 122 printk("Module doesn't contain .plt or .init.plt sections.\n"); >> 123 return -ENOEXEC; >> 124 } >> 125 >> 126 /* Override their sizes */ >> 127 sechdrs[me->arch.core_plt_section].sh_size >> 128 = get_plt_size(hdr, sechdrs, secstrings, 0); >> 129 sechdrs[me->arch.init_plt_section].sh_size >> 130 = get_plt_size(hdr, sechdrs, secstrings, 1); >> 131 return 0; >> 132 } >> 133 >> 134 int apply_relocate(Elf32_Shdr *sechdrs, >> 135 const char *strtab, >> 136 unsigned int symindex, >> 137 unsigned int relsec, >> 138 struct module *module) >> 139 { >> 140 printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", >> 141 module->name); >> 142 return -ENOEXEC; >> 143 } >> 144 >> 145 static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) >> 146 { >> 147 if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) >> 148 && entry->jump[1] == 0x396b0000 + (val & 0xffff)) >> 149 return 1; >> 150 return 0; >> 151 } >> 152 >> 153 /* Set up a trampoline in the PLT to bounce us to the distant function */ >> 154 static uint32_t do_plt_call(void *location, >> 155 Elf32_Addr val, >> 156 Elf32_Shdr *sechdrs, >> 157 struct module *mod) >> 158 { >> 159 struct ppc_plt_entry *entry; >> 160 >> 161 DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); >> 162 /* Init, or core PLT? */ >> 163 if (location >= mod->module_core >> 164 && location < mod->module_core + mod->core_size) >> 165 entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; >> 166 else >> 167 entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; >> 168 >> 169 /* Find this entry, or if that fails, the next avail. entry */ >> 170 while (entry->jump[0]) { >> 171 if (entry_matches(entry, val)) return (uint32_t)entry; >> 172 entry++; >> 173 } >> 174 >> 175 /* Stolen from Paul Mackerras as well... */ >> 176 entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ >> 177 entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ >> 178 entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ >> 179 entry->jump[3] = 0x4e800420; /* bctr */ >> 180 >> 181 DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); >> 182 return (uint32_t)entry; >> 183 } 15 184 16 int apply_relocate_add(Elf32_Shdr *sechdrs, 185 int apply_relocate_add(Elf32_Shdr *sechdrs, 17 const char *strtab, 186 const char *strtab, 18 unsigned int symindex, 187 unsigned int symindex, 19 unsigned int relsec, 188 unsigned int relsec, 20 struct module *me) !! 189 struct module *module) 21 { 190 { 22 unsigned int i; 191 unsigned int i; 23 Elf32_Rela *rel = (void *)sechdrs[rels !! 192 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 24 Elf32_Sym *sym; 193 Elf32_Sym *sym; 25 uint32_t *location; 194 uint32_t *location; 26 uint32_t value; 195 uint32_t value; 27 196 28 pr_debug("Applying relocate section %u !! 197 DEBUGP("Applying ADD relocate section %u to %u\n", relsec, 29 sechdrs[relsec].sh_info); !! 198 sechdrs[relsec].sh_info); 30 for (i = 0; i < sechdrs[relsec].sh_siz !! 199 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 31 /* This is where to make the c 200 /* This is where to make the change */ 32 location = (void *)sechdrs[sec 201 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 33 + rel[i].r_offset; !! 202 + rela[i].r_offset; 34 << 35 /* This is the symbol it is re 203 /* This is the symbol it is referring to. Note that all 36 undefined symbols have been 204 undefined symbols have been resolved. */ 37 sym = (Elf32_Sym *)sechdrs[sym 205 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 38 + ELF32_R_SYM(rel[i].r !! 206 + ELF32_R_SYM(rela[i].r_info); 39 value = sym->st_value + rel[i] !! 207 /* `Everything is relative'. */ >> 208 value = sym->st_value + rela[i].r_addend; 40 209 41 switch (ELF32_R_TYPE(rel[i].r_ !! 210 switch (ELF32_R_TYPE(rela[i].r_info)) { 42 case R_OR1K_32: !! 211 case R_PPC_ADDR32: 43 *location = value; !! 212 /* Simply set it */ 44 break; !! 213 *(uint32_t *)location = value; 45 case R_OR1K_LO_16_IN_INSN: << 46 *((uint16_t *)location << 47 break; 214 break; 48 case R_OR1K_HI_16_IN_INSN: !! 215 49 *((uint16_t *)location !! 216 case R_PPC_ADDR16_LO: >> 217 /* Low half of the symbol */ >> 218 *(uint16_t *)location = value; 50 break; 219 break; 51 case R_OR1K_INSN_REL_26: !! 220 52 value -= (uint32_t)loc !! 221 case R_PPC_ADDR16_HA: 53 value >>= 2; !! 222 /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 54 value &= 0x03ffffff; !! 223 (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 55 value |= *location & 0 !! 224 This is the same, only sane. 56 *location = value; !! 225 */ >> 226 *(uint16_t *)location = (value + 0x8000) >> 16; 57 break; 227 break; 58 case R_OR1K_AHI16: !! 228 59 /* Adjust the operand !! 229 case R_PPC_REL24: 60 value += 0x8000; !! 230 if ((int)(value - (uint32_t)location) < -0x02000000 61 *((uint16_t *)location !! 231 || (int)(value - (uint32_t)location) >= 0x02000000) >> 232 value = do_plt_call(location, value, >> 233 sechdrs, module); >> 234 >> 235 /* Only replace bits 2 through 26 */ >> 236 DEBUGP("REL24 value = %08X. location = %08X\n", >> 237 value, (uint32_t)location); >> 238 DEBUGP("Location before: %08X.\n", >> 239 *(uint32_t *)location); >> 240 *(uint32_t *)location >> 241 = (*(uint32_t *)location & ~0x03fffffc) >> 242 | ((value - (uint32_t)location) >> 243 & 0x03fffffc); >> 244 DEBUGP("Location after: %08X.\n", >> 245 *(uint32_t *)location); >> 246 DEBUGP("ie. jump to %08X+%08X = %08X\n", >> 247 *(uint32_t *)location & 0x03fffffc, >> 248 (uint32_t)location, >> 249 (*(uint32_t *)location & 0x03fffffc) >> 250 + (uint32_t)location); 62 break; 251 break; 63 case R_OR1K_SLO16: !! 252 64 /* Split value lower 1 !! 253 case R_PPC_REL32: 65 value = ((value & 0xf8 !! 254 /* 32-bit relative jump. */ 66 *location = (*location !! 255 *(uint32_t *)location = value - (uint32_t)location; 67 break; 256 break; >> 257 68 default: 258 default: 69 pr_err("module %s: Unk !! 259 printk("%s: unknown ADD relocation: %u\n", 70 me->name, ELF32 !! 260 module->name, 71 break; !! 261 ELF32_R_TYPE(rela[i].r_info)); >> 262 return -ENOEXEC; 72 } 263 } 73 } 264 } >> 265 return 0; >> 266 } >> 267 >> 268 /* FIXME: Sort exception table --RR */ >> 269 int module_finalize(const Elf_Ehdr *hdr, >> 270 const Elf_Shdr *sechdrs, >> 271 struct module *me) >> 272 { >> 273 char *secstrings; >> 274 unsigned int i; >> 275 >> 276 me->arch.bug_table = NULL; >> 277 me->arch.num_bugs = 0; >> 278 >> 279 /* Find the __bug_table section, if present */ >> 280 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; >> 281 for (i = 1; i < hdr->e_shnum; i++) { >> 282 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) >> 283 continue; >> 284 me->arch.bug_table = (void *) sechdrs[i].sh_addr; >> 285 me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); >> 286 break; >> 287 } >> 288 >> 289 /* >> 290 * Strictly speaking this should have a spinlock to protect against >> 291 * traversals, but since we only traverse on BUG()s, a spinlock >> 292 * could potentially lead to deadlock and thus be counter-productive. >> 293 */ >> 294 list_add(&me->arch.bug_list, &module_bug_list); 74 295 75 return 0; 296 return 0; >> 297 } >> 298 >> 299 void module_arch_cleanup(struct module *mod) >> 300 { >> 301 list_del(&mod->arch.bug_list); >> 302 } >> 303 >> 304 struct bug_entry *module_find_bug(unsigned long bugaddr) >> 305 { >> 306 struct mod_arch_specific *mod; >> 307 unsigned int i; >> 308 struct bug_entry *bug; >> 309 >> 310 list_for_each_entry(mod, &module_bug_list, bug_list) { >> 311 bug = mod->bug_table; >> 312 for (i = 0; i < mod->num_bugs; ++i, ++bug) >> 313 if (bugaddr == bug->bug_addr) >> 314 return bug; >> 315 } >> 316 return NULL; 76 } 317 } 77 318
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.