Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*  Kernel module help for powerpc.
0003     Copyright (C) 2001, 2003 Rusty Russell IBM Corporation.
0004     Copyright (C) 2008 Freescale Semiconductor, Inc.
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     /* Apply feature fixups */
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 /* CONFIG_PPC64 */
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 /* CONFIG_PPC64_ELF_ABI_V1 */
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 /* CONFIG_PPC_BARRIER_NOSPEC */
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      * Don't do huge page allocations for modules yet until more testing
0100      * is done. STRICT_MODULE_RWX may require extra work to support this
0101      * too.
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     /* First try within 32M limit from _etext to avoid branch trampolines */
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 }