1*2d5bf28fSAmerigo Wang /* Kernel module help for x86. 2*2d5bf28fSAmerigo Wang Copyright (C) 2001 Rusty Russell. 3*2d5bf28fSAmerigo Wang 4*2d5bf28fSAmerigo Wang This program is free software; you can redistribute it and/or modify 5*2d5bf28fSAmerigo Wang it under the terms of the GNU General Public License as published by 6*2d5bf28fSAmerigo Wang the Free Software Foundation; either version 2 of the License, or 7*2d5bf28fSAmerigo Wang (at your option) any later version. 8*2d5bf28fSAmerigo Wang 9*2d5bf28fSAmerigo Wang This program is distributed in the hope that it will be useful, 10*2d5bf28fSAmerigo Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 11*2d5bf28fSAmerigo Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12*2d5bf28fSAmerigo Wang GNU General Public License for more details. 13*2d5bf28fSAmerigo Wang 14*2d5bf28fSAmerigo Wang You should have received a copy of the GNU General Public License 15*2d5bf28fSAmerigo Wang along with this program; if not, write to the Free Software 16*2d5bf28fSAmerigo Wang Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 17*2d5bf28fSAmerigo Wang */ 18*2d5bf28fSAmerigo Wang #include <linux/moduleloader.h> 19*2d5bf28fSAmerigo Wang #include <linux/elf.h> 20*2d5bf28fSAmerigo Wang #include <linux/vmalloc.h> 21*2d5bf28fSAmerigo Wang #include <linux/fs.h> 22*2d5bf28fSAmerigo Wang #include <linux/string.h> 23*2d5bf28fSAmerigo Wang #include <linux/kernel.h> 24*2d5bf28fSAmerigo Wang #include <linux/bug.h> 25*2d5bf28fSAmerigo Wang #include <linux/mm.h> 26*2d5bf28fSAmerigo Wang 27*2d5bf28fSAmerigo Wang #include <asm/system.h> 28*2d5bf28fSAmerigo Wang #include <asm/page.h> 29*2d5bf28fSAmerigo Wang #include <asm/pgtable.h> 30*2d5bf28fSAmerigo Wang 31*2d5bf28fSAmerigo Wang #if 0 32*2d5bf28fSAmerigo Wang #define DEBUGP printk 33*2d5bf28fSAmerigo Wang #else 34*2d5bf28fSAmerigo Wang #define DEBUGP(fmt...) 35*2d5bf28fSAmerigo Wang #endif 36*2d5bf28fSAmerigo Wang 37*2d5bf28fSAmerigo Wang /* Free memory returned from module_alloc */ 38*2d5bf28fSAmerigo Wang void module_free(struct module *mod, void *module_region) 39*2d5bf28fSAmerigo Wang { 40*2d5bf28fSAmerigo Wang vfree(module_region); 41*2d5bf28fSAmerigo Wang /* FIXME: If module_region == mod->init_region, trim exception 42*2d5bf28fSAmerigo Wang table entries. */ 43*2d5bf28fSAmerigo Wang } 44*2d5bf28fSAmerigo Wang 45*2d5bf28fSAmerigo Wang /* We don't need anything special. */ 46*2d5bf28fSAmerigo Wang int module_frob_arch_sections(Elf_Ehdr *hdr, 47*2d5bf28fSAmerigo Wang Elf_Shdr *sechdrs, 48*2d5bf28fSAmerigo Wang char *secstrings, 49*2d5bf28fSAmerigo Wang struct module *mod) 50*2d5bf28fSAmerigo Wang { 51*2d5bf28fSAmerigo Wang return 0; 52*2d5bf28fSAmerigo Wang } 53*2d5bf28fSAmerigo Wang 54*2d5bf28fSAmerigo Wang int module_finalize(const Elf_Ehdr *hdr, 55*2d5bf28fSAmerigo Wang const Elf_Shdr *sechdrs, 56*2d5bf28fSAmerigo Wang struct module *me) 57*2d5bf28fSAmerigo Wang { 58*2d5bf28fSAmerigo Wang const Elf_Shdr *s, *text = NULL, *alt = NULL, *locks = NULL, 59*2d5bf28fSAmerigo Wang *para = NULL; 60*2d5bf28fSAmerigo Wang char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 61*2d5bf28fSAmerigo Wang 62*2d5bf28fSAmerigo Wang for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 63*2d5bf28fSAmerigo Wang if (!strcmp(".text", secstrings + s->sh_name)) 64*2d5bf28fSAmerigo Wang text = s; 65*2d5bf28fSAmerigo Wang if (!strcmp(".altinstructions", secstrings + s->sh_name)) 66*2d5bf28fSAmerigo Wang alt = s; 67*2d5bf28fSAmerigo Wang if (!strcmp(".smp_locks", secstrings + s->sh_name)) 68*2d5bf28fSAmerigo Wang locks = s; 69*2d5bf28fSAmerigo Wang if (!strcmp(".parainstructions", secstrings + s->sh_name)) 70*2d5bf28fSAmerigo Wang para = s; 71*2d5bf28fSAmerigo Wang } 72*2d5bf28fSAmerigo Wang 73*2d5bf28fSAmerigo Wang if (alt) { 74*2d5bf28fSAmerigo Wang /* patch .altinstructions */ 75*2d5bf28fSAmerigo Wang void *aseg = (void *)alt->sh_addr; 76*2d5bf28fSAmerigo Wang apply_alternatives(aseg, aseg + alt->sh_size); 77*2d5bf28fSAmerigo Wang } 78*2d5bf28fSAmerigo Wang if (locks && text) { 79*2d5bf28fSAmerigo Wang void *lseg = (void *)locks->sh_addr; 80*2d5bf28fSAmerigo Wang void *tseg = (void *)text->sh_addr; 81*2d5bf28fSAmerigo Wang alternatives_smp_module_add(me, me->name, 82*2d5bf28fSAmerigo Wang lseg, lseg + locks->sh_size, 83*2d5bf28fSAmerigo Wang tseg, tseg + text->sh_size); 84*2d5bf28fSAmerigo Wang } 85*2d5bf28fSAmerigo Wang 86*2d5bf28fSAmerigo Wang if (para) { 87*2d5bf28fSAmerigo Wang void *pseg = (void *)para->sh_addr; 88*2d5bf28fSAmerigo Wang apply_paravirt(pseg, pseg + para->sh_size); 89*2d5bf28fSAmerigo Wang } 90*2d5bf28fSAmerigo Wang 91*2d5bf28fSAmerigo Wang return module_bug_finalize(hdr, sechdrs, me); 92*2d5bf28fSAmerigo Wang } 93*2d5bf28fSAmerigo Wang 94*2d5bf28fSAmerigo Wang void module_arch_cleanup(struct module *mod) 95*2d5bf28fSAmerigo Wang { 96*2d5bf28fSAmerigo Wang alternatives_smp_module_del(mod); 97*2d5bf28fSAmerigo Wang module_bug_cleanup(mod); 98*2d5bf28fSAmerigo Wang } 99