1ed981856SPaul Mackerras /* Kernel module help for PPC. 2ed981856SPaul Mackerras Copyright (C) 2001 Rusty Russell. 3ed981856SPaul Mackerras 4ed981856SPaul Mackerras This program is free software; you can redistribute it and/or modify 5ed981856SPaul Mackerras it under the terms of the GNU General Public License as published by 6ed981856SPaul Mackerras the Free Software Foundation; either version 2 of the License, or 7ed981856SPaul Mackerras (at your option) any later version. 8ed981856SPaul Mackerras 9ed981856SPaul Mackerras This program is distributed in the hope that it will be useful, 10ed981856SPaul Mackerras but WITHOUT ANY WARRANTY; without even the implied warranty of 11ed981856SPaul Mackerras MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12ed981856SPaul Mackerras GNU General Public License for more details. 13ed981856SPaul Mackerras 14ed981856SPaul Mackerras You should have received a copy of the GNU General Public License 15ed981856SPaul Mackerras along with this program; if not, write to the Free Software 16ed981856SPaul Mackerras Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17ed981856SPaul Mackerras */ 18ed981856SPaul Mackerras #include <linux/module.h> 19ed981856SPaul Mackerras #include <linux/moduleloader.h> 20ed981856SPaul Mackerras #include <linux/elf.h> 21ed981856SPaul Mackerras #include <linux/vmalloc.h> 22ed981856SPaul Mackerras #include <linux/fs.h> 23ed981856SPaul Mackerras #include <linux/string.h> 24ed981856SPaul Mackerras #include <linux/kernel.h> 25ed981856SPaul Mackerras #include <linux/cache.h> 26ed981856SPaul Mackerras 2721c4ff80SBenjamin Herrenschmidt #include "setup.h" 2821c4ff80SBenjamin Herrenschmidt 29ed981856SPaul Mackerras #if 0 30ed981856SPaul Mackerras #define DEBUGP printk 31ed981856SPaul Mackerras #else 32ed981856SPaul Mackerras #define DEBUGP(fmt , ...) 33ed981856SPaul Mackerras #endif 34ed981856SPaul Mackerras 35ed981856SPaul Mackerras LIST_HEAD(module_bug_list); 36ed981856SPaul Mackerras 37ed981856SPaul Mackerras void *module_alloc(unsigned long size) 38ed981856SPaul Mackerras { 39ed981856SPaul Mackerras if (size == 0) 40ed981856SPaul Mackerras return NULL; 41ed981856SPaul Mackerras return vmalloc(size); 42ed981856SPaul Mackerras } 43ed981856SPaul Mackerras 44ed981856SPaul Mackerras /* Free memory returned from module_alloc */ 45ed981856SPaul Mackerras void module_free(struct module *mod, void *module_region) 46ed981856SPaul Mackerras { 47ed981856SPaul Mackerras vfree(module_region); 48ed981856SPaul Mackerras /* FIXME: If module_region == mod->init_region, trim exception 49ed981856SPaul Mackerras table entries. */ 50ed981856SPaul Mackerras } 51ed981856SPaul Mackerras 52ed981856SPaul Mackerras /* Count how many different relocations (different symbol, different 53ed981856SPaul Mackerras addend) */ 54ed981856SPaul Mackerras static unsigned int count_relocs(const Elf32_Rela *rela, unsigned int num) 55ed981856SPaul Mackerras { 56ed981856SPaul Mackerras unsigned int i, j, ret = 0; 57ed981856SPaul Mackerras 58ed981856SPaul Mackerras /* Sure, this is order(n^2), but it's usually short, and not 59ed981856SPaul Mackerras time critical */ 60ed981856SPaul Mackerras for (i = 0; i < num; i++) { 61ed981856SPaul Mackerras for (j = 0; j < i; j++) { 62ed981856SPaul Mackerras /* If this addend appeared before, it's 63ed981856SPaul Mackerras already been counted */ 64ed981856SPaul Mackerras if (ELF32_R_SYM(rela[i].r_info) 65ed981856SPaul Mackerras == ELF32_R_SYM(rela[j].r_info) 66ed981856SPaul Mackerras && rela[i].r_addend == rela[j].r_addend) 67ed981856SPaul Mackerras break; 68ed981856SPaul Mackerras } 69ed981856SPaul Mackerras if (j == i) ret++; 70ed981856SPaul Mackerras } 71ed981856SPaul Mackerras return ret; 72ed981856SPaul Mackerras } 73ed981856SPaul Mackerras 74ed981856SPaul Mackerras /* Get the potential trampolines size required of the init and 75ed981856SPaul Mackerras non-init sections */ 76ed981856SPaul Mackerras static unsigned long get_plt_size(const Elf32_Ehdr *hdr, 77ed981856SPaul Mackerras const Elf32_Shdr *sechdrs, 78ed981856SPaul Mackerras const char *secstrings, 79ed981856SPaul Mackerras int is_init) 80ed981856SPaul Mackerras { 81ed981856SPaul Mackerras unsigned long ret = 0; 82ed981856SPaul Mackerras unsigned i; 83ed981856SPaul Mackerras 84ed981856SPaul Mackerras /* Everything marked ALLOC (this includes the exported 85ed981856SPaul Mackerras symbols) */ 86ed981856SPaul Mackerras for (i = 1; i < hdr->e_shnum; i++) { 87ed981856SPaul Mackerras /* If it's called *.init*, and we're not init, we're 88ed981856SPaul Mackerras not interested */ 89ed981856SPaul Mackerras if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0) 90ed981856SPaul Mackerras != is_init) 91ed981856SPaul Mackerras continue; 92ed981856SPaul Mackerras 93ed981856SPaul Mackerras /* We don't want to look at debug sections. */ 94ed981856SPaul Mackerras if (strstr(secstrings + sechdrs[i].sh_name, ".debug") != 0) 95ed981856SPaul Mackerras continue; 96ed981856SPaul Mackerras 97ed981856SPaul Mackerras if (sechdrs[i].sh_type == SHT_RELA) { 98ed981856SPaul Mackerras DEBUGP("Found relocations in section %u\n", i); 99ed981856SPaul Mackerras DEBUGP("Ptr: %p. Number: %u\n", 100ed981856SPaul Mackerras (void *)hdr + sechdrs[i].sh_offset, 101ed981856SPaul Mackerras sechdrs[i].sh_size / sizeof(Elf32_Rela)); 102ed981856SPaul Mackerras ret += count_relocs((void *)hdr 103ed981856SPaul Mackerras + sechdrs[i].sh_offset, 104ed981856SPaul Mackerras sechdrs[i].sh_size 105ed981856SPaul Mackerras / sizeof(Elf32_Rela)) 106ed981856SPaul Mackerras * sizeof(struct ppc_plt_entry); 107ed981856SPaul Mackerras } 108ed981856SPaul Mackerras } 109ed981856SPaul Mackerras 110ed981856SPaul Mackerras return ret; 111ed981856SPaul Mackerras } 112ed981856SPaul Mackerras 113ed981856SPaul Mackerras int module_frob_arch_sections(Elf32_Ehdr *hdr, 114ed981856SPaul Mackerras Elf32_Shdr *sechdrs, 115ed981856SPaul Mackerras char *secstrings, 116ed981856SPaul Mackerras struct module *me) 117ed981856SPaul Mackerras { 118ed981856SPaul Mackerras unsigned int i; 119ed981856SPaul Mackerras 120ed981856SPaul Mackerras /* Find .plt and .init.plt sections */ 121ed981856SPaul Mackerras for (i = 0; i < hdr->e_shnum; i++) { 122ed981856SPaul Mackerras if (strcmp(secstrings + sechdrs[i].sh_name, ".init.plt") == 0) 123ed981856SPaul Mackerras me->arch.init_plt_section = i; 124ed981856SPaul Mackerras else if (strcmp(secstrings + sechdrs[i].sh_name, ".plt") == 0) 125ed981856SPaul Mackerras me->arch.core_plt_section = i; 126ed981856SPaul Mackerras } 127ed981856SPaul Mackerras if (!me->arch.core_plt_section || !me->arch.init_plt_section) { 128ed981856SPaul Mackerras printk("Module doesn't contain .plt or .init.plt sections.\n"); 129ed981856SPaul Mackerras return -ENOEXEC; 130ed981856SPaul Mackerras } 131ed981856SPaul Mackerras 132ed981856SPaul Mackerras /* Override their sizes */ 133ed981856SPaul Mackerras sechdrs[me->arch.core_plt_section].sh_size 134ed981856SPaul Mackerras = get_plt_size(hdr, sechdrs, secstrings, 0); 135ed981856SPaul Mackerras sechdrs[me->arch.init_plt_section].sh_size 136ed981856SPaul Mackerras = get_plt_size(hdr, sechdrs, secstrings, 1); 137ed981856SPaul Mackerras return 0; 138ed981856SPaul Mackerras } 139ed981856SPaul Mackerras 140ed981856SPaul Mackerras int apply_relocate(Elf32_Shdr *sechdrs, 141ed981856SPaul Mackerras const char *strtab, 142ed981856SPaul Mackerras unsigned int symindex, 143ed981856SPaul Mackerras unsigned int relsec, 144ed981856SPaul Mackerras struct module *module) 145ed981856SPaul Mackerras { 146ed981856SPaul Mackerras printk(KERN_ERR "%s: Non-ADD RELOCATION unsupported\n", 147ed981856SPaul Mackerras module->name); 148ed981856SPaul Mackerras return -ENOEXEC; 149ed981856SPaul Mackerras } 150ed981856SPaul Mackerras 151ed981856SPaul Mackerras static inline int entry_matches(struct ppc_plt_entry *entry, Elf32_Addr val) 152ed981856SPaul Mackerras { 153ed981856SPaul Mackerras if (entry->jump[0] == 0x3d600000 + ((val + 0x8000) >> 16) 154ed981856SPaul Mackerras && entry->jump[1] == 0x396b0000 + (val & 0xffff)) 155ed981856SPaul Mackerras return 1; 156ed981856SPaul Mackerras return 0; 157ed981856SPaul Mackerras } 158ed981856SPaul Mackerras 159ed981856SPaul Mackerras /* Set up a trampoline in the PLT to bounce us to the distant function */ 160ed981856SPaul Mackerras static uint32_t do_plt_call(void *location, 161ed981856SPaul Mackerras Elf32_Addr val, 162ed981856SPaul Mackerras Elf32_Shdr *sechdrs, 163ed981856SPaul Mackerras struct module *mod) 164ed981856SPaul Mackerras { 165ed981856SPaul Mackerras struct ppc_plt_entry *entry; 166ed981856SPaul Mackerras 167ed981856SPaul Mackerras DEBUGP("Doing plt for call to 0x%x at 0x%x\n", val, (unsigned int)location); 168ed981856SPaul Mackerras /* Init, or core PLT? */ 169ed981856SPaul Mackerras if (location >= mod->module_core 170ed981856SPaul Mackerras && location < mod->module_core + mod->core_size) 171ed981856SPaul Mackerras entry = (void *)sechdrs[mod->arch.core_plt_section].sh_addr; 172ed981856SPaul Mackerras else 173ed981856SPaul Mackerras entry = (void *)sechdrs[mod->arch.init_plt_section].sh_addr; 174ed981856SPaul Mackerras 175ed981856SPaul Mackerras /* Find this entry, or if that fails, the next avail. entry */ 176ed981856SPaul Mackerras while (entry->jump[0]) { 177ed981856SPaul Mackerras if (entry_matches(entry, val)) return (uint32_t)entry; 178ed981856SPaul Mackerras entry++; 179ed981856SPaul Mackerras } 180ed981856SPaul Mackerras 181ed981856SPaul Mackerras /* Stolen from Paul Mackerras as well... */ 182ed981856SPaul Mackerras entry->jump[0] = 0x3d600000+((val+0x8000)>>16); /* lis r11,sym@ha */ 183ed981856SPaul Mackerras entry->jump[1] = 0x396b0000 + (val&0xffff); /* addi r11,r11,sym@l*/ 184ed981856SPaul Mackerras entry->jump[2] = 0x7d6903a6; /* mtctr r11 */ 185ed981856SPaul Mackerras entry->jump[3] = 0x4e800420; /* bctr */ 186ed981856SPaul Mackerras 187ed981856SPaul Mackerras DEBUGP("Initialized plt for 0x%x at %p\n", val, entry); 188ed981856SPaul Mackerras return (uint32_t)entry; 189ed981856SPaul Mackerras } 190ed981856SPaul Mackerras 191ed981856SPaul Mackerras int apply_relocate_add(Elf32_Shdr *sechdrs, 192ed981856SPaul Mackerras const char *strtab, 193ed981856SPaul Mackerras unsigned int symindex, 194ed981856SPaul Mackerras unsigned int relsec, 195ed981856SPaul Mackerras struct module *module) 196ed981856SPaul Mackerras { 197ed981856SPaul Mackerras unsigned int i; 198ed981856SPaul Mackerras Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr; 199ed981856SPaul Mackerras Elf32_Sym *sym; 200ed981856SPaul Mackerras uint32_t *location; 201ed981856SPaul Mackerras uint32_t value; 202ed981856SPaul Mackerras 203ed981856SPaul Mackerras DEBUGP("Applying ADD relocate section %u to %u\n", relsec, 204ed981856SPaul Mackerras sechdrs[relsec].sh_info); 205ed981856SPaul Mackerras for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) { 206ed981856SPaul Mackerras /* This is where to make the change */ 207ed981856SPaul Mackerras location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 208ed981856SPaul Mackerras + rela[i].r_offset; 209ed981856SPaul Mackerras /* This is the symbol it is referring to. Note that all 210ed981856SPaul Mackerras undefined symbols have been resolved. */ 211ed981856SPaul Mackerras sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 212ed981856SPaul Mackerras + ELF32_R_SYM(rela[i].r_info); 213ed981856SPaul Mackerras /* `Everything is relative'. */ 214ed981856SPaul Mackerras value = sym->st_value + rela[i].r_addend; 215ed981856SPaul Mackerras 216ed981856SPaul Mackerras switch (ELF32_R_TYPE(rela[i].r_info)) { 217ed981856SPaul Mackerras case R_PPC_ADDR32: 218ed981856SPaul Mackerras /* Simply set it */ 219ed981856SPaul Mackerras *(uint32_t *)location = value; 220ed981856SPaul Mackerras break; 221ed981856SPaul Mackerras 222ed981856SPaul Mackerras case R_PPC_ADDR16_LO: 223ed981856SPaul Mackerras /* Low half of the symbol */ 224ed981856SPaul Mackerras *(uint16_t *)location = value; 225ed981856SPaul Mackerras break; 226ed981856SPaul Mackerras 227ed981856SPaul Mackerras case R_PPC_ADDR16_HA: 228ed981856SPaul Mackerras /* Sign-adjusted lower 16 bits: PPC ELF ABI says: 229ed981856SPaul Mackerras (((x >> 16) + ((x & 0x8000) ? 1 : 0))) & 0xFFFF. 230ed981856SPaul Mackerras This is the same, only sane. 231ed981856SPaul Mackerras */ 232ed981856SPaul Mackerras *(uint16_t *)location = (value + 0x8000) >> 16; 233ed981856SPaul Mackerras break; 234ed981856SPaul Mackerras 235ed981856SPaul Mackerras case R_PPC_REL24: 236ed981856SPaul Mackerras if ((int)(value - (uint32_t)location) < -0x02000000 237ed981856SPaul Mackerras || (int)(value - (uint32_t)location) >= 0x02000000) 238ed981856SPaul Mackerras value = do_plt_call(location, value, 239ed981856SPaul Mackerras sechdrs, module); 240ed981856SPaul Mackerras 241ed981856SPaul Mackerras /* Only replace bits 2 through 26 */ 242ed981856SPaul Mackerras DEBUGP("REL24 value = %08X. location = %08X\n", 243ed981856SPaul Mackerras value, (uint32_t)location); 244ed981856SPaul Mackerras DEBUGP("Location before: %08X.\n", 245ed981856SPaul Mackerras *(uint32_t *)location); 246ed981856SPaul Mackerras *(uint32_t *)location 247ed981856SPaul Mackerras = (*(uint32_t *)location & ~0x03fffffc) 248ed981856SPaul Mackerras | ((value - (uint32_t)location) 249ed981856SPaul Mackerras & 0x03fffffc); 250ed981856SPaul Mackerras DEBUGP("Location after: %08X.\n", 251ed981856SPaul Mackerras *(uint32_t *)location); 252ed981856SPaul Mackerras DEBUGP("ie. jump to %08X+%08X = %08X\n", 253ed981856SPaul Mackerras *(uint32_t *)location & 0x03fffffc, 254ed981856SPaul Mackerras (uint32_t)location, 255ed981856SPaul Mackerras (*(uint32_t *)location & 0x03fffffc) 256ed981856SPaul Mackerras + (uint32_t)location); 257ed981856SPaul Mackerras break; 258ed981856SPaul Mackerras 259ed981856SPaul Mackerras case R_PPC_REL32: 260ed981856SPaul Mackerras /* 32-bit relative jump. */ 261ed981856SPaul Mackerras *(uint32_t *)location = value - (uint32_t)location; 262ed981856SPaul Mackerras break; 263ed981856SPaul Mackerras 264ed981856SPaul Mackerras default: 265ed981856SPaul Mackerras printk("%s: unknown ADD relocation: %u\n", 266ed981856SPaul Mackerras module->name, 267ed981856SPaul Mackerras ELF32_R_TYPE(rela[i].r_info)); 268ed981856SPaul Mackerras return -ENOEXEC; 269ed981856SPaul Mackerras } 270ed981856SPaul Mackerras } 271ed981856SPaul Mackerras return 0; 272ed981856SPaul Mackerras } 273ed981856SPaul Mackerras 27421c4ff80SBenjamin Herrenschmidt static const Elf_Shdr *find_section(const Elf_Ehdr *hdr, 27521c4ff80SBenjamin Herrenschmidt const Elf_Shdr *sechdrs, 27621c4ff80SBenjamin Herrenschmidt const char *name) 27721c4ff80SBenjamin Herrenschmidt { 27821c4ff80SBenjamin Herrenschmidt char *secstrings; 27921c4ff80SBenjamin Herrenschmidt unsigned int i; 28021c4ff80SBenjamin Herrenschmidt 28121c4ff80SBenjamin Herrenschmidt secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 28221c4ff80SBenjamin Herrenschmidt for (i = 1; i < hdr->e_shnum; i++) 28321c4ff80SBenjamin Herrenschmidt if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0) 28421c4ff80SBenjamin Herrenschmidt return &sechdrs[i]; 28521c4ff80SBenjamin Herrenschmidt return NULL; 28621c4ff80SBenjamin Herrenschmidt } 28721c4ff80SBenjamin Herrenschmidt 288ed981856SPaul Mackerras int module_finalize(const Elf_Ehdr *hdr, 289ed981856SPaul Mackerras const Elf_Shdr *sechdrs, 290ed981856SPaul Mackerras struct module *me) 291ed981856SPaul Mackerras { 29221c4ff80SBenjamin Herrenschmidt const Elf_Shdr *sect; 293ed981856SPaul Mackerras 294ed981856SPaul Mackerras me->arch.bug_table = NULL; 295ed981856SPaul Mackerras me->arch.num_bugs = 0; 296ed981856SPaul Mackerras 297ed981856SPaul Mackerras /* Find the __bug_table section, if present */ 29821c4ff80SBenjamin Herrenschmidt sect = find_section(hdr, sechdrs, "__bug_table"); 29921c4ff80SBenjamin Herrenschmidt if (sect != NULL) { 30021c4ff80SBenjamin Herrenschmidt me->arch.bug_table = (void *) sect->sh_addr; 30121c4ff80SBenjamin Herrenschmidt me->arch.num_bugs = sect->sh_size / sizeof(struct bug_entry); 302ed981856SPaul Mackerras } 303ed981856SPaul Mackerras 304ed981856SPaul Mackerras /* 305ed981856SPaul Mackerras * Strictly speaking this should have a spinlock to protect against 306ed981856SPaul Mackerras * traversals, but since we only traverse on BUG()s, a spinlock 307ed981856SPaul Mackerras * could potentially lead to deadlock and thus be counter-productive. 308ed981856SPaul Mackerras */ 309ed981856SPaul Mackerras list_add(&me->arch.bug_list, &module_bug_list); 310ed981856SPaul Mackerras 31121c4ff80SBenjamin Herrenschmidt /* Apply feature fixups */ 31221c4ff80SBenjamin Herrenschmidt sect = find_section(hdr, sechdrs, "__ftr_fixup"); 31321c4ff80SBenjamin Herrenschmidt if (sect != NULL) 31421c4ff80SBenjamin Herrenschmidt do_feature_fixups(cur_cpu_spec->cpu_features, 31521c4ff80SBenjamin Herrenschmidt (void *)sect->sh_addr, 31621c4ff80SBenjamin Herrenschmidt (void *)sect->sh_addr + sect->sh_size); 31721c4ff80SBenjamin Herrenschmidt 318ed981856SPaul Mackerras return 0; 319ed981856SPaul Mackerras } 320ed981856SPaul Mackerras 321ed981856SPaul Mackerras void module_arch_cleanup(struct module *mod) 322ed981856SPaul Mackerras { 323ed981856SPaul Mackerras list_del(&mod->arch.bug_list); 324ed981856SPaul Mackerras } 325ed981856SPaul Mackerras 326ed981856SPaul Mackerras struct bug_entry *module_find_bug(unsigned long bugaddr) 327ed981856SPaul Mackerras { 328ed981856SPaul Mackerras struct mod_arch_specific *mod; 329ed981856SPaul Mackerras unsigned int i; 330ed981856SPaul Mackerras struct bug_entry *bug; 331ed981856SPaul Mackerras 332ed981856SPaul Mackerras list_for_each_entry(mod, &module_bug_list, bug_list) { 333ed981856SPaul Mackerras bug = mod->bug_table; 334ed981856SPaul Mackerras for (i = 0; i < mod->num_bugs; ++i, ++bug) 335ed981856SPaul Mackerras if (bugaddr == bug->bug_addr) 336ed981856SPaul Mackerras return bug; 337ed981856SPaul Mackerras } 338ed981856SPaul Mackerras return NULL; 339ed981856SPaul Mackerras } 340