0001
0002
0003
0004
0005
0006
0007 #include <linux/elf.h>
0008 #include <linux/moduleloader.h>
0009 #include <linux/err.h>
0010 #include <linux/vmalloc.h>
0011 #include <linux/mm.h>
0012 #include <linux/bug.h>
0013 #include <asm/module.h>
0014 #include <linux/uaccess.h>
0015 #include <asm/firmware.h>
0016 #include <linux/sort.h>
0017 #include <asm/setup.h>
0018 #include <asm/sections.h>
0019
0020 static LIST_HEAD(module_bug_list);
0021
0022 static const Elf_Shdr *find_section(const Elf_Ehdr *hdr,
0023 const Elf_Shdr *sechdrs,
0024 const char *name)
0025 {
0026 char *secstrings;
0027 unsigned int i;
0028
0029 secstrings = (char *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
0030 for (i = 1; i < hdr->e_shnum; i++)
0031 if (strcmp(secstrings+sechdrs[i].sh_name, name) == 0)
0032 return &sechdrs[i];
0033 return NULL;
0034 }
0035
0036 int module_finalize(const Elf_Ehdr *hdr,
0037 const Elf_Shdr *sechdrs, struct module *me)
0038 {
0039 const Elf_Shdr *sect;
0040 int rc;
0041
0042 rc = module_finalize_ftrace(me, sechdrs);
0043 if (rc)
0044 return rc;
0045
0046
0047 sect = find_section(hdr, sechdrs, "__ftr_fixup");
0048 if (sect != NULL)
0049 do_feature_fixups(cur_cpu_spec->cpu_features,
0050 (void *)sect->sh_addr,
0051 (void *)sect->sh_addr + sect->sh_size);
0052
0053 sect = find_section(hdr, sechdrs, "__mmu_ftr_fixup");
0054 if (sect != NULL)
0055 do_feature_fixups(cur_cpu_spec->mmu_features,
0056 (void *)sect->sh_addr,
0057 (void *)sect->sh_addr + sect->sh_size);
0058
0059 #ifdef CONFIG_PPC64
0060 sect = find_section(hdr, sechdrs, "__fw_ftr_fixup");
0061 if (sect != NULL)
0062 do_feature_fixups(powerpc_firmware_features,
0063 (void *)sect->sh_addr,
0064 (void *)sect->sh_addr + sect->sh_size);
0065 #endif
0066
0067 #ifdef CONFIG_PPC64_ELF_ABI_V1
0068 sect = find_section(hdr, sechdrs, ".opd");
0069 if (sect != NULL) {
0070 me->arch.start_opd = sect->sh_addr;
0071 me->arch.end_opd = sect->sh_addr + sect->sh_size;
0072 }
0073 #endif
0074
0075 #ifdef CONFIG_PPC_BARRIER_NOSPEC
0076 sect = find_section(hdr, sechdrs, "__spec_barrier_fixup");
0077 if (sect != NULL)
0078 do_barrier_nospec_fixups_range(barrier_nospec_enabled,
0079 (void *)sect->sh_addr,
0080 (void *)sect->sh_addr + sect->sh_size);
0081 #endif
0082
0083 sect = find_section(hdr, sechdrs, "__lwsync_fixup");
0084 if (sect != NULL)
0085 do_lwsync_fixups(cur_cpu_spec->cpu_features,
0086 (void *)sect->sh_addr,
0087 (void *)sect->sh_addr + sect->sh_size);
0088
0089 return 0;
0090 }
0091
0092 static __always_inline void *
0093 __module_alloc(unsigned long size, unsigned long start, unsigned long end, bool nowarn)
0094 {
0095 pgprot_t prot = strict_module_rwx_enabled() ? PAGE_KERNEL : PAGE_KERNEL_EXEC;
0096 gfp_t gfp = GFP_KERNEL | (nowarn ? __GFP_NOWARN : 0);
0097
0098
0099
0100
0101
0102
0103 return __vmalloc_node_range(size, 1, start, end, gfp, prot,
0104 VM_FLUSH_RESET_PERMS,
0105 NUMA_NO_NODE, __builtin_return_address(0));
0106 }
0107
0108 void *module_alloc(unsigned long size)
0109 {
0110 #ifdef MODULES_VADDR
0111 unsigned long limit = (unsigned long)_etext - SZ_32M;
0112 void *ptr = NULL;
0113
0114 BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
0115
0116
0117 if (MODULES_VADDR < PAGE_OFFSET && MODULES_END > limit)
0118 ptr = __module_alloc(size, limit, MODULES_END, true);
0119
0120 if (!ptr)
0121 ptr = __module_alloc(size, MODULES_VADDR, MODULES_END, false);
0122
0123 return ptr;
0124 #else
0125 return __module_alloc(size, VMALLOC_START, VMALLOC_END, false);
0126 #endif
0127 }