1 // SPDX-License-Identifier: GPL-2.0 !! 1 /* Kernel module help for PPC. 2 /* Kernel module help for sparc64. !! 2 Copyright (C) 2001 Rusty Russell. 3 * << 4 * Copyright (C) 2001 Rusty Russell. << 5 * Copyright (C) 2002 David S. Miller. << 6 */ << 7 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> 8 #include <linux/moduleloader.h> 19 #include <linux/moduleloader.h> 9 #include <linux/kernel.h> << 10 #include <linux/elf.h> 20 #include <linux/elf.h> 11 #include <linux/vmalloc.h> 21 #include <linux/vmalloc.h> 12 #include <linux/fs.h> 22 #include <linux/fs.h> 13 #include <linux/gfp.h> << 14 #include <linux/string.h> 23 #include <linux/string.h> 15 #include <linux/ctype.h> !! 24 #include <linux/kernel.h> 16 #include <linux/mm.h> !! 25 #include <linux/cache.h> 17 26 18 #include <asm/processor.h> !! 27 #if 0 19 #include <asm/spitfire.h> !! 28 #define DEBUGP printk 20 #include <asm/cacheflush.h> !! 29 #else 21 !! 30 #define DEBUGP(fmt , ...) 22 #include "entry.h" !! 31 #endif 23 !! 32 24 /* Make generic code ignore STT_REGISTER dummy !! 33 LIST_HEAD(module_bug_list); 25 int module_frob_arch_sections(Elf_Ehdr *hdr, !! 34 26 Elf_Shdr *sechdr !! 35 void *module_alloc(unsigned long size) 27 char *secstrings << 28 struct module *m << 29 { 36 { 30 unsigned int symidx; !! 37 if (size == 0) 31 Elf_Sym *sym; !! 38 return NULL; 32 char *strtab; !! 39 return vmalloc(size); 33 int i; !! 40 } 34 !! 41 35 for (symidx = 0; sechdrs[symidx].sh_ty !! 42 /* Free memory returned from module_alloc */ 36 if (symidx == hdr->e_shnum-1) !! 43 void module_free(struct module *mod, void *module_region) 37 printk("%s: no symtab !! 44 { 38 return -ENOEXEC; !! 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; 39 } 66 } >> 67 if (j == i) ret++; 40 } 68 } 41 sym = (Elf_Sym *)sechdrs[symidx].sh_ad !! 69 return ret; 42 strtab = (char *)sechdrs[sechdrs[symid !! 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; 43 81 44 for (i = 1; i < sechdrs[symidx].sh_siz !! 82 /* Everything marked ALLOC (this includes the exported 45 if (sym[i].st_shndx == SHN_UND !! 83 symbols) */ 46 if (ELF_ST_TYPE(sym[i] !! 84 for (i = 1; i < hdr->e_shnum; i++) { 47 sym[i].st_shnd !! 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); 48 } 101 } 49 } 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; 50 return 0; 150 return 0; 51 } 151 } 52 152 53 int apply_relocate_add(Elf_Shdr *sechdrs, !! 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 } >> 184 >> 185 int apply_relocate_add(Elf32_Shdr *sechdrs, 54 const char *strtab, 186 const char *strtab, 55 unsigned int symindex, 187 unsigned int symindex, 56 unsigned int relsec, 188 unsigned int relsec, 57 struct module *me) !! 189 struct module *module) 58 { 190 { 59 unsigned int i; 191 unsigned int i; 60 Elf_Rela *rel = (void *)sechdrs[relsec !! 192 Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 61 Elf_Sym *sym; !! 193 Elf32_Sym *sym; 62 u8 *location; !! 194 uint32_t *location; 63 u32 *loc32; !! 195 uint32_t value; 64 !! 196 65 for (i = 0; i < sechdrs[relsec].sh_siz !! 197 DEBUGP("Applying ADD relocate section %u to %u\n", relsec, 66 Elf_Addr v; !! 198 sechdrs[relsec].sh_info); 67 !! 199 for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 68 /* This is where to make the c 200 /* This is where to make the change */ 69 location = (u8 *)sechdrs[sechd !! 201 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 70 + rel[i].r_offset; !! 202 + rela[i].r_offset; 71 loc32 = (u32 *) location; << 72 << 73 #ifdef CONFIG_SPARC64 << 74 BUG_ON(((u64)location >> (u64) << 75 #endif /* CONFIG_SPARC64 */ << 76 << 77 /* This is the symbol it is re 203 /* This is the symbol it is referring to. Note that all 78 undefined symbols have been 204 undefined symbols have been resolved. */ 79 sym = (Elf_Sym *)sechdrs[symin !! 205 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 80 + ELF_R_SYM(rel[i].r_i !! 206 + ELF32_R_SYM(rela[i].r_info); 81 v = sym->st_value + rel[i].r_a !! 207 /* `Everything is relative'. */ 82 !! 208 value = sym->st_value + rela[i].r_addend; 83 switch (ELF_R_TYPE(rel[i].r_in !! 209 84 case R_SPARC_DISP32: !! 210 switch (ELF32_R_TYPE(rela[i].r_info)) { 85 v -= (Elf_Addr) locati !! 211 case R_PPC_ADDR32: 86 *loc32 = v; !! 212 /* Simply set it */ 87 break; !! 213 *(uint32_t *)location = value; 88 #ifdef CONFIG_SPARC64 << 89 case R_SPARC_64: << 90 location[0] = v >> 56; << 91 location[1] = v >> 48; << 92 location[2] = v >> 40; << 93 location[3] = v >> 32; << 94 location[4] = v >> 24; << 95 location[5] = v >> 16; << 96 location[6] = v >> 8; << 97 location[7] = v >> 0; << 98 break; << 99 << 100 case R_SPARC_WDISP19: << 101 v -= (Elf_Addr) locati << 102 *loc32 = (*loc32 & ~0x << 103 ((v >> 2) & 0x << 104 break; 214 break; 105 215 106 case R_SPARC_OLO10: !! 216 case R_PPC_ADDR16_LO: 107 *loc32 = (*loc32 & ~0x !! 217 /* Low half of the symbol */ 108 (((v & 0x3ff) !! 218 *(uint16_t *)location = value; 109 (ELF_R_TYPE( << 110 & 0x1fff); << 111 break; 219 break; 112 #endif /* CONFIG_SPARC64 */ !! 220 113 !! 221 case R_PPC_ADDR16_HA: 114 case R_SPARC_32: !! 222 /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 115 case R_SPARC_UA32: !! 223 (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 116 location[0] = v >> 24; !! 224 This is the same, only sane. 117 location[1] = v >> 16; !! 225 */ 118 location[2] = v >> 8; !! 226 *(uint16_t *)location = (value + 0x8000) >> 16; 119 location[3] = v >> 0; << 120 break; << 121 << 122 case R_SPARC_WDISP30: << 123 v -= (Elf_Addr) locati << 124 *loc32 = (*loc32 & ~0x << 125 ((v >> 2) & 0x << 126 break; 227 break; 127 228 128 case R_SPARC_WDISP22: !! 229 case R_PPC_REL24: 129 v -= (Elf_Addr) locati !! 230 if ((int)(value - (uint32_t)location) < -0x02000000 130 *loc32 = (*loc32 & ~0x !! 231 || (int)(value - (uint32_t)location) >= 0x02000000) 131 ((v >> 2) & 0x !! 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); 132 break; 251 break; 133 252 134 case R_SPARC_LO10: !! 253 case R_PPC_REL32: 135 *loc32 = (*loc32 & ~0x !! 254 /* 32-bit relative jump. */ 136 break; !! 255 *(uint32_t *)location = value - (uint32_t)location; 137 << 138 case R_SPARC_HI22: << 139 *loc32 = (*loc32 & ~0x << 140 ((v >> 10) & 0 << 141 break; 256 break; 142 257 143 default: 258 default: 144 printk(KERN_ERR "modul !! 259 printk("%s: unknown ADD relocation: %u\n", 145 me->name, !! 260 module->name, 146 (int) (ELF_R_TY !! 261 ELF32_R_TYPE(rela[i].r_info)); 147 return -ENOEXEC; 262 return -ENOEXEC; 148 } 263 } 149 } 264 } 150 return 0; 265 return 0; 151 } 266 } 152 267 153 #ifdef CONFIG_SPARC64 !! 268 /* FIXME: Sort exception table --RR */ 154 static void do_patch_sections(const Elf_Ehdr * << 155 const Elf_Shdr * << 156 { << 157 const Elf_Shdr *s, *sun4v_1insn = NULL << 158 char *secstrings = (void *)hdr + sechd << 159 << 160 for (s = sechdrs; s < sechdrs + hdr->e << 161 if (!strcmp(".sun4v_1insn_patc << 162 sun4v_1insn = s; << 163 if (!strcmp(".sun4v_2insn_patc << 164 sun4v_2insn = s; << 165 } << 166 << 167 if (sun4v_1insn && tlb_type == hypervi << 168 void *p = (void *) sun4v_1insn << 169 sun4v_patch_1insn_range(p, p + << 170 } << 171 if (sun4v_2insn && tlb_type == hypervi << 172 void *p = (void *) sun4v_2insn << 173 sun4v_patch_2insn_range(p, p + << 174 } << 175 } << 176 << 177 int module_finalize(const Elf_Ehdr *hdr, 269 int module_finalize(const Elf_Ehdr *hdr, 178 const Elf_Shdr *sechdrs, 270 const Elf_Shdr *sechdrs, 179 struct module *me) 271 struct module *me) 180 { 272 { 181 do_patch_sections(hdr, sechdrs); !! 273 char *secstrings; >> 274 unsigned int i; >> 275 >> 276 me->arch.bug_table = NULL; >> 277 me->arch.num_bugs = 0; 182 278 183 /* Cheetah's I-cache is fully coherent !! 279 /* Find the __bug_table section, if present */ 184 if (tlb_type == spitfire) { !! 280 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 185 unsigned long va; !! 281 for (i = 1; i < hdr->e_shnum; i++) { 186 !! 282 if (strcmp(secstrings+sechdrs[i].sh_name, "__bug_table")) 187 flushw_all(); !! 283 continue; 188 for (va = 0; va < (PAGE_SIZE !! 284 me->arch.bug_table = (void *) sechdrs[i].sh_addr; 189 spitfire_put_icache_ta !! 285 me->arch.num_bugs = sechdrs[i].sh_size / sizeof(struct bug_entry); 190 __asm__ __volatile__("flush %g !! 286 break; 191 } 287 } 192 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); >> 295 193 return 0; 296 return 0; 194 } 297 } 195 #endif /* CONFIG_SPARC64 */ !! 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; >> 317 } 196 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.