11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 22d5bf28fSAmerigo Wang /* Kernel module help for x86. 32d5bf28fSAmerigo Wang Copyright (C) 2001 Rusty Russell. 42d5bf28fSAmerigo Wang 52d5bf28fSAmerigo Wang */ 6c767a54bSJoe Perches 7c767a54bSJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 8c767a54bSJoe Perches 92d5bf28fSAmerigo Wang #include <linux/moduleloader.h> 102d5bf28fSAmerigo Wang #include <linux/elf.h> 112d5bf28fSAmerigo Wang #include <linux/vmalloc.h> 122d5bf28fSAmerigo Wang #include <linux/fs.h> 132d5bf28fSAmerigo Wang #include <linux/string.h> 142d5bf28fSAmerigo Wang #include <linux/kernel.h> 15bebf56a1SAndrey Ryabinin #include <linux/kasan.h> 162d5bf28fSAmerigo Wang #include <linux/bug.h> 172d5bf28fSAmerigo Wang #include <linux/mm.h> 185a0e3ad6STejun Heo #include <linux/gfp.h> 19d430d3d7SJason Baron #include <linux/jump_label.h> 20e2b32e67SKees Cook #include <linux/random.h> 215b384f93SJosh Poimboeuf #include <linux/memory.h> 222d5bf28fSAmerigo Wang 2335de5b06SAndy Lutomirski #include <asm/text-patching.h> 242d5bf28fSAmerigo Wang #include <asm/page.h> 2578cac48cSBorislav Petkov #include <asm/setup.h> 26ee9f8fceSJosh Poimboeuf #include <asm/unwind.h> 272d5bf28fSAmerigo Wang 282d5bf28fSAmerigo Wang #if 0 29c767a54bSJoe Perches #define DEBUGP(fmt, ...) \ 30c767a54bSJoe Perches printk(KERN_DEBUG fmt, ##__VA_ARGS__) 312d5bf28fSAmerigo Wang #else 32c767a54bSJoe Perches #define DEBUGP(fmt, ...) \ 33c767a54bSJoe Perches do { \ 34c767a54bSJoe Perches if (0) \ 35c767a54bSJoe Perches printk(KERN_DEBUG fmt, ##__VA_ARGS__); \ 36c767a54bSJoe Perches } while (0) 372d5bf28fSAmerigo Wang #endif 382d5bf28fSAmerigo Wang 39e2b32e67SKees Cook #ifdef CONFIG_RANDOMIZE_BASE 40e2b32e67SKees Cook static unsigned long module_load_offset; 41e2b32e67SKees Cook 429dd721c6SKees Cook /* Mutex protects the module_load_offset. */ 439dd721c6SKees Cook static DEFINE_MUTEX(module_kaslr_mutex); 449dd721c6SKees Cook 45e2b32e67SKees Cook static unsigned long int get_module_load_offset(void) 46e2b32e67SKees Cook { 4778cac48cSBorislav Petkov if (kaslr_enabled()) { 489dd721c6SKees Cook mutex_lock(&module_kaslr_mutex); 49e2b32e67SKees Cook /* 50e2b32e67SKees Cook * Calculate the module_load_offset the first time this 51e2b32e67SKees Cook * code is called. Once calculated it stays the same until 52e2b32e67SKees Cook * reboot. 53e2b32e67SKees Cook */ 54e2b32e67SKees Cook if (module_load_offset == 0) 55e2b32e67SKees Cook module_load_offset = 56e8a533cbSJason A. Donenfeld get_random_u32_inclusive(1, 1024) * PAGE_SIZE; 579dd721c6SKees Cook mutex_unlock(&module_kaslr_mutex); 58e2b32e67SKees Cook } 59e2b32e67SKees Cook return module_load_offset; 60e2b32e67SKees Cook } 61e2b32e67SKees Cook #else 62e2b32e67SKees Cook static unsigned long int get_module_load_offset(void) 63e2b32e67SKees Cook { 64e2b32e67SKees Cook return 0; 65e2b32e67SKees Cook } 66e2b32e67SKees Cook #endif 67e2b32e67SKees Cook 680fdc83b9SAmerigo Wang void *module_alloc(unsigned long size) 690fdc83b9SAmerigo Wang { 7060115fa5SKefeng Wang gfp_t gfp_mask = GFP_KERNEL; 71bebf56a1SAndrey Ryabinin void *p; 72bebf56a1SAndrey Ryabinin 73d0a21265SDavid Rientjes if (PAGE_ALIGN(size) > MODULES_LEN) 740fdc83b9SAmerigo Wang return NULL; 75bebf56a1SAndrey Ryabinin 76bebf56a1SAndrey Ryabinin p = __vmalloc_node_range(size, MODULE_ALIGN, 77e2b32e67SKees Cook MODULES_VADDR + get_module_load_offset(), 784c4eb3ecSThomas Gleixner MODULES_END, gfp_mask, PAGE_KERNEL, 794c4eb3ecSThomas Gleixner VM_FLUSH_RESET_PERMS | VM_DEFER_KMEMLEAK, 804c4eb3ecSThomas Gleixner NUMA_NO_NODE, __builtin_return_address(0)); 814c4eb3ecSThomas Gleixner 8263840de2SAndrey Konovalov if (p && (kasan_alloc_module_shadow(p, size, gfp_mask) < 0)) { 83bebf56a1SAndrey Ryabinin vfree(p); 84bebf56a1SAndrey Ryabinin return NULL; 85bebf56a1SAndrey Ryabinin } 86bebf56a1SAndrey Ryabinin 87bebf56a1SAndrey Ryabinin return p; 880fdc83b9SAmerigo Wang } 890fdc83b9SAmerigo Wang 900fdc83b9SAmerigo Wang #ifdef CONFIG_X86_32 910fdc83b9SAmerigo Wang int apply_relocate(Elf32_Shdr *sechdrs, 920fdc83b9SAmerigo Wang const char *strtab, 930fdc83b9SAmerigo Wang unsigned int symindex, 940fdc83b9SAmerigo Wang unsigned int relsec, 950fdc83b9SAmerigo Wang struct module *me) 960fdc83b9SAmerigo Wang { 970fdc83b9SAmerigo Wang unsigned int i; 980fdc83b9SAmerigo Wang Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr; 990fdc83b9SAmerigo Wang Elf32_Sym *sym; 1000fdc83b9SAmerigo Wang uint32_t *location; 1010fdc83b9SAmerigo Wang 102c767a54bSJoe Perches DEBUGP("Applying relocate section %u to %u\n", 103c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1040fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1050fdc83b9SAmerigo Wang /* This is where to make the change */ 1060fdc83b9SAmerigo Wang location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1070fdc83b9SAmerigo Wang + rel[i].r_offset; 1080fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1090fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1100fdc83b9SAmerigo Wang sym = (Elf32_Sym *)sechdrs[symindex].sh_addr 1110fdc83b9SAmerigo Wang + ELF32_R_SYM(rel[i].r_info); 1120fdc83b9SAmerigo Wang 1130fdc83b9SAmerigo Wang switch (ELF32_R_TYPE(rel[i].r_info)) { 1140fdc83b9SAmerigo Wang case R_386_32: 1150fdc83b9SAmerigo Wang /* We add the value into the location given */ 1160fdc83b9SAmerigo Wang *location += sym->st_value; 1170fdc83b9SAmerigo Wang break; 1180fdc83b9SAmerigo Wang case R_386_PC32: 119bb73d071SFangrui Song case R_386_PLT32: 1202e76c283SGeert Uytterhoeven /* Add the value, subtract its position */ 1210fdc83b9SAmerigo Wang *location += sym->st_value - (uint32_t)location; 1220fdc83b9SAmerigo Wang break; 1230fdc83b9SAmerigo Wang default: 124c767a54bSJoe Perches pr_err("%s: Unknown relocation: %u\n", 1250fdc83b9SAmerigo Wang me->name, ELF32_R_TYPE(rel[i].r_info)); 1260fdc83b9SAmerigo Wang return -ENOEXEC; 1270fdc83b9SAmerigo Wang } 1280fdc83b9SAmerigo Wang } 1290fdc83b9SAmerigo Wang return 0; 1300fdc83b9SAmerigo Wang } 1310fdc83b9SAmerigo Wang #else /*X86_64*/ 1320c05e7bdSSong Liu static int __write_relocate_add(Elf64_Shdr *sechdrs, 1330fdc83b9SAmerigo Wang const char *strtab, 1340fdc83b9SAmerigo Wang unsigned int symindex, 1350fdc83b9SAmerigo Wang unsigned int relsec, 13688fc078aSPeter Zijlstra struct module *me, 1370c05e7bdSSong Liu void *(*write)(void *dest, const void *src, size_t len), 1380c05e7bdSSong Liu bool apply) 1390fdc83b9SAmerigo Wang { 1400fdc83b9SAmerigo Wang unsigned int i; 1410fdc83b9SAmerigo Wang Elf64_Rela *rel = (void *)sechdrs[relsec].sh_addr; 1420fdc83b9SAmerigo Wang Elf64_Sym *sym; 1430fdc83b9SAmerigo Wang void *loc; 1440fdc83b9SAmerigo Wang u64 val; 1450c05e7bdSSong Liu u64 zero = 0ULL; 1460fdc83b9SAmerigo Wang 1470c05e7bdSSong Liu DEBUGP("%s relocate section %u to %u\n", 1480c05e7bdSSong Liu apply ? "Applying" : "Clearing", 149c767a54bSJoe Perches relsec, sechdrs[relsec].sh_info); 1500fdc83b9SAmerigo Wang for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { 1510c05e7bdSSong Liu size_t size; 1520c05e7bdSSong Liu 1530fdc83b9SAmerigo Wang /* This is where to make the change */ 1540fdc83b9SAmerigo Wang loc = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr 1550fdc83b9SAmerigo Wang + rel[i].r_offset; 1560fdc83b9SAmerigo Wang 1570fdc83b9SAmerigo Wang /* This is the symbol it is referring to. Note that all 1580fdc83b9SAmerigo Wang undefined symbols have been resolved. */ 1590fdc83b9SAmerigo Wang sym = (Elf64_Sym *)sechdrs[symindex].sh_addr 1600fdc83b9SAmerigo Wang + ELF64_R_SYM(rel[i].r_info); 1610fdc83b9SAmerigo Wang 1620fdc83b9SAmerigo Wang DEBUGP("type %d st_value %Lx r_addend %Lx loc %Lx\n", 1630fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), 1640fdc83b9SAmerigo Wang sym->st_value, rel[i].r_addend, (u64)loc); 1650fdc83b9SAmerigo Wang 1660fdc83b9SAmerigo Wang val = sym->st_value + rel[i].r_addend; 1670fdc83b9SAmerigo Wang 1680fdc83b9SAmerigo Wang switch (ELF64_R_TYPE(rel[i].r_info)) { 1690fdc83b9SAmerigo Wang case R_X86_64_NONE: 1700c05e7bdSSong Liu continue; /* nothing to write */ 1710fdc83b9SAmerigo Wang case R_X86_64_64: 1720c05e7bdSSong Liu size = 8; 1730fdc83b9SAmerigo Wang break; 1740fdc83b9SAmerigo Wang case R_X86_64_32: 1750c05e7bdSSong Liu if (val != *(u32 *)&val) 1760fdc83b9SAmerigo Wang goto overflow; 1770c05e7bdSSong Liu size = 4; 1780fdc83b9SAmerigo Wang break; 1790fdc83b9SAmerigo Wang case R_X86_64_32S: 1800c05e7bdSSong Liu if ((s64)val != *(s32 *)&val) 1810fdc83b9SAmerigo Wang goto overflow; 1820c05e7bdSSong Liu size = 4; 1830fdc83b9SAmerigo Wang break; 1840fdc83b9SAmerigo Wang case R_X86_64_PC32: 185b21ebf2fSH.J. Lu case R_X86_64_PLT32: 1860fdc83b9SAmerigo Wang val -= (u64)loc; 1870c05e7bdSSong Liu size = 4; 1880fdc83b9SAmerigo Wang break; 189b40a142bSArd Biesheuvel case R_X86_64_PC64: 190b40a142bSArd Biesheuvel val -= (u64)loc; 1910c05e7bdSSong Liu size = 8; 192b40a142bSArd Biesheuvel break; 1930fdc83b9SAmerigo Wang default: 194c767a54bSJoe Perches pr_err("%s: Unknown rela relocation: %llu\n", 1950fdc83b9SAmerigo Wang me->name, ELF64_R_TYPE(rel[i].r_info)); 1960fdc83b9SAmerigo Wang return -ENOEXEC; 1970fdc83b9SAmerigo Wang } 1980fdc83b9SAmerigo Wang 1990c05e7bdSSong Liu if (apply) { 2000c05e7bdSSong Liu if (memcmp(loc, &zero, size)) { 2010c05e7bdSSong Liu pr_err("x86/modules: Invalid relocation target, existing value is nonzero for type %d, loc %p, val %Lx\n", 202eda9cec4SJosh Poimboeuf (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 203eda9cec4SJosh Poimboeuf return -ENOEXEC; 2040c05e7bdSSong Liu } 2050c05e7bdSSong Liu write(loc, &val, size); 2060c05e7bdSSong Liu } else { 2070c05e7bdSSong Liu if (memcmp(loc, &val, size)) { 2080c05e7bdSSong Liu pr_warn("x86/modules: Invalid relocation target, existing value does not match expected value for type %d, loc %p, val %Lx\n", 2090c05e7bdSSong Liu (int)ELF64_R_TYPE(rel[i].r_info), loc, val); 2100c05e7bdSSong Liu return -ENOEXEC; 2110c05e7bdSSong Liu } 2120c05e7bdSSong Liu write(loc, &zero, size); 2130c05e7bdSSong Liu } 2140c05e7bdSSong Liu } 2150c05e7bdSSong Liu return 0; 216eda9cec4SJosh Poimboeuf 2170fdc83b9SAmerigo Wang overflow: 218c767a54bSJoe Perches pr_err("overflow in relocation type %d val %Lx\n", 2190fdc83b9SAmerigo Wang (int)ELF64_R_TYPE(rel[i].r_info), val); 220c767a54bSJoe Perches pr_err("`%s' likely not compiled with -mcmodel=kernel\n", 2210fdc83b9SAmerigo Wang me->name); 2220fdc83b9SAmerigo Wang return -ENOEXEC; 2230fdc83b9SAmerigo Wang } 22488fc078aSPeter Zijlstra 2250c05e7bdSSong Liu static int write_relocate_add(Elf64_Shdr *sechdrs, 22688fc078aSPeter Zijlstra const char *strtab, 22788fc078aSPeter Zijlstra unsigned int symindex, 22888fc078aSPeter Zijlstra unsigned int relsec, 2290c05e7bdSSong Liu struct module *me, 2300c05e7bdSSong Liu bool apply) 23188fc078aSPeter Zijlstra { 23288fc078aSPeter Zijlstra int ret; 23388fc078aSPeter Zijlstra bool early = me->state == MODULE_STATE_UNFORMED; 23488fc078aSPeter Zijlstra void *(*write)(void *, const void *, size_t) = memcpy; 23588fc078aSPeter Zijlstra 2365b384f93SJosh Poimboeuf if (!early) { 23788fc078aSPeter Zijlstra write = text_poke; 2385b384f93SJosh Poimboeuf mutex_lock(&text_mutex); 2395b384f93SJosh Poimboeuf } 24088fc078aSPeter Zijlstra 2410c05e7bdSSong Liu ret = __write_relocate_add(sechdrs, strtab, symindex, relsec, me, 2420c05e7bdSSong Liu write, apply); 24388fc078aSPeter Zijlstra 2445b384f93SJosh Poimboeuf if (!early) { 24588fc078aSPeter Zijlstra text_poke_sync(); 2465b384f93SJosh Poimboeuf mutex_unlock(&text_mutex); 2475b384f93SJosh Poimboeuf } 24888fc078aSPeter Zijlstra 24988fc078aSPeter Zijlstra return ret; 25088fc078aSPeter Zijlstra } 25188fc078aSPeter Zijlstra 2520c05e7bdSSong Liu int apply_relocate_add(Elf64_Shdr *sechdrs, 2530c05e7bdSSong Liu const char *strtab, 2540c05e7bdSSong Liu unsigned int symindex, 2550c05e7bdSSong Liu unsigned int relsec, 2560c05e7bdSSong Liu struct module *me) 2570c05e7bdSSong Liu { 2580c05e7bdSSong Liu return write_relocate_add(sechdrs, strtab, symindex, relsec, me, true); 2590c05e7bdSSong Liu } 2600c05e7bdSSong Liu 2610c05e7bdSSong Liu #ifdef CONFIG_LIVEPATCH 2620c05e7bdSSong Liu void clear_relocate_add(Elf64_Shdr *sechdrs, 2630c05e7bdSSong Liu const char *strtab, 2640c05e7bdSSong Liu unsigned int symindex, 2650c05e7bdSSong Liu unsigned int relsec, 2660c05e7bdSSong Liu struct module *me) 2670c05e7bdSSong Liu { 2680c05e7bdSSong Liu write_relocate_add(sechdrs, strtab, symindex, relsec, me, false); 2690c05e7bdSSong Liu } 2700c05e7bdSSong Liu #endif 2710c05e7bdSSong Liu 2720fdc83b9SAmerigo Wang #endif 2730fdc83b9SAmerigo Wang 2742d5bf28fSAmerigo Wang int module_finalize(const Elf_Ehdr *hdr, 2752d5bf28fSAmerigo Wang const Elf_Shdr *sechdrs, 2762d5bf28fSAmerigo Wang struct module *me) 2772d5bf28fSAmerigo Wang { 278be84d8edSJulian Pidancet const Elf_Shdr *s, *alt = NULL, *locks = NULL, 27975085009SPeter Zijlstra *para = NULL, *orc = NULL, *orc_ip = NULL, 280eaf44c81SThomas Gleixner *retpolines = NULL, *returns = NULL, *ibt_endbr = NULL, 281931ab636SPeter Zijlstra *calls = NULL, *cfi = NULL; 2822d5bf28fSAmerigo Wang char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 2832d5bf28fSAmerigo Wang 2842d5bf28fSAmerigo Wang for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) { 2852d5bf28fSAmerigo Wang if (!strcmp(".altinstructions", secstrings + s->sh_name)) 2862d5bf28fSAmerigo Wang alt = s; 2872d5bf28fSAmerigo Wang if (!strcmp(".smp_locks", secstrings + s->sh_name)) 2882d5bf28fSAmerigo Wang locks = s; 2892d5bf28fSAmerigo Wang if (!strcmp(".parainstructions", secstrings + s->sh_name)) 2902d5bf28fSAmerigo Wang para = s; 291ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind", secstrings + s->sh_name)) 292ee9f8fceSJosh Poimboeuf orc = s; 293ee9f8fceSJosh Poimboeuf if (!strcmp(".orc_unwind_ip", secstrings + s->sh_name)) 294ee9f8fceSJosh Poimboeuf orc_ip = s; 29575085009SPeter Zijlstra if (!strcmp(".retpoline_sites", secstrings + s->sh_name)) 29675085009SPeter Zijlstra retpolines = s; 29715e67227SPeter Zijlstra if (!strcmp(".return_sites", secstrings + s->sh_name)) 29815e67227SPeter Zijlstra returns = s; 299eaf44c81SThomas Gleixner if (!strcmp(".call_sites", secstrings + s->sh_name)) 300eaf44c81SThomas Gleixner calls = s; 301931ab636SPeter Zijlstra if (!strcmp(".cfi_sites", secstrings + s->sh_name)) 302931ab636SPeter Zijlstra cfi = s; 303ed53a0d9SPeter Zijlstra if (!strcmp(".ibt_endbr_seal", secstrings + s->sh_name)) 304ed53a0d9SPeter Zijlstra ibt_endbr = s; 3052d5bf28fSAmerigo Wang } 3062d5bf28fSAmerigo Wang 3075adf3494SPeter Zijlstra /* 3085adf3494SPeter Zijlstra * See alternative_instructions() for the ordering rules between the 3095adf3494SPeter Zijlstra * various patching types. 3105adf3494SPeter Zijlstra */ 3115adf3494SPeter Zijlstra if (para) { 3125adf3494SPeter Zijlstra void *pseg = (void *)para->sh_addr; 3135adf3494SPeter Zijlstra apply_paravirt(pseg, pseg + para->sh_size); 3145adf3494SPeter Zijlstra } 315931ab636SPeter Zijlstra if (retpolines || cfi) { 316931ab636SPeter Zijlstra void *rseg = NULL, *cseg = NULL; 317931ab636SPeter Zijlstra unsigned int rsize = 0, csize = 0; 318931ab636SPeter Zijlstra 319931ab636SPeter Zijlstra if (retpolines) { 320931ab636SPeter Zijlstra rseg = (void *)retpolines->sh_addr; 321931ab636SPeter Zijlstra rsize = retpolines->sh_size; 322931ab636SPeter Zijlstra } 323931ab636SPeter Zijlstra 324931ab636SPeter Zijlstra if (cfi) { 325931ab636SPeter Zijlstra cseg = (void *)cfi->sh_addr; 326931ab636SPeter Zijlstra csize = cfi->sh_size; 327931ab636SPeter Zijlstra } 328931ab636SPeter Zijlstra 329931ab636SPeter Zijlstra apply_fineibt(rseg, rseg + rsize, cseg, cseg + csize); 330931ab636SPeter Zijlstra } 33175085009SPeter Zijlstra if (retpolines) { 33275085009SPeter Zijlstra void *rseg = (void *)retpolines->sh_addr; 33375085009SPeter Zijlstra apply_retpolines(rseg, rseg + retpolines->sh_size); 33475085009SPeter Zijlstra } 33515e67227SPeter Zijlstra if (returns) { 33615e67227SPeter Zijlstra void *rseg = (void *)returns->sh_addr; 33715e67227SPeter Zijlstra apply_returns(rseg, rseg + returns->sh_size); 33815e67227SPeter Zijlstra } 3392d5bf28fSAmerigo Wang if (alt) { 3402d5bf28fSAmerigo Wang /* patch .altinstructions */ 3412d5bf28fSAmerigo Wang void *aseg = (void *)alt->sh_addr; 3422d5bf28fSAmerigo Wang apply_alternatives(aseg, aseg + alt->sh_size); 3432d5bf28fSAmerigo Wang } 344eaf44c81SThomas Gleixner if (calls || para) { 345eaf44c81SThomas Gleixner struct callthunk_sites cs = {}; 346eaf44c81SThomas Gleixner 347eaf44c81SThomas Gleixner if (calls) { 348eaf44c81SThomas Gleixner cs.call_start = (void *)calls->sh_addr; 349eaf44c81SThomas Gleixner cs.call_end = (void *)calls->sh_addr + calls->sh_size; 350eaf44c81SThomas Gleixner } 351eaf44c81SThomas Gleixner 352eaf44c81SThomas Gleixner if (para) { 353eaf44c81SThomas Gleixner cs.pv_start = (void *)para->sh_addr; 354eaf44c81SThomas Gleixner cs.pv_end = (void *)para->sh_addr + para->sh_size; 355eaf44c81SThomas Gleixner } 356eaf44c81SThomas Gleixner 357eaf44c81SThomas Gleixner callthunks_patch_module_calls(&cs, me); 358eaf44c81SThomas Gleixner } 359ed53a0d9SPeter Zijlstra if (ibt_endbr) { 360ed53a0d9SPeter Zijlstra void *iseg = (void *)ibt_endbr->sh_addr; 361*be0fffa5SPeter Zijlstra apply_seal_endbr(iseg, iseg + ibt_endbr->sh_size); 362ed53a0d9SPeter Zijlstra } 363be84d8edSJulian Pidancet if (locks) { 3642d5bf28fSAmerigo Wang void *lseg = (void *)locks->sh_addr; 365ac3b4328SSong Liu void *text = me->mem[MOD_TEXT].base; 366ac3b4328SSong Liu void *text_end = text + me->mem[MOD_TEXT].size; 3672d5bf28fSAmerigo Wang alternatives_smp_module_add(me, me->name, 3682d5bf28fSAmerigo Wang lseg, lseg + locks->sh_size, 369be84d8edSJulian Pidancet text, text_end); 3702d5bf28fSAmerigo Wang } 3712d5bf28fSAmerigo Wang 372ee9f8fceSJosh Poimboeuf if (orc && orc_ip) 373ee9f8fceSJosh Poimboeuf unwind_module_init(me, (void *)orc_ip->sh_addr, orc_ip->sh_size, 374ee9f8fceSJosh Poimboeuf (void *)orc->sh_addr, orc->sh_size); 375ee9f8fceSJosh Poimboeuf 3765336377dSLinus Torvalds return 0; 3772d5bf28fSAmerigo Wang } 3782d5bf28fSAmerigo Wang 3792d5bf28fSAmerigo Wang void module_arch_cleanup(struct module *mod) 3802d5bf28fSAmerigo Wang { 3812d5bf28fSAmerigo Wang alternatives_smp_module_del(mod); 3822d5bf28fSAmerigo Wang } 383