2019-05-27 08:55:05 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2008-06-21 02:31:01 +10:00
/* Kernel module help for powerpc.
Copyright ( C ) 2001 , 2003 Rusty Russell IBM Corporation .
Copyright ( C ) 2008 Freescale Semiconductor , Inc .
*/
# include <linux/elf.h>
# include <linux/moduleloader.h>
# include <linux/err.h>
# include <linux/vmalloc.h>
2021-05-03 19:17:55 +10:00
# include <linux/mm.h>
2008-06-21 02:31:01 +10:00
# include <linux/bug.h>
# include <asm/module.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2008-06-21 02:31:01 +10:00
# include <asm/firmware.h>
# include <linux/sort.h>
2013-10-28 09:20:51 -05:00
# include <asm/setup.h>
2021-04-01 13:30:41 +00:00
# include <asm/sections.h>
2008-06-21 02:31:01 +10:00
2016-09-06 15:32:40 +10:00
static LIST_HEAD ( module_bug_list ) ;
2008-06-21 02:31:01 +10:00
static const Elf_Shdr * find_section ( const Elf_Ehdr * hdr ,
const Elf_Shdr * sechdrs ,
const char * name )
{
char * secstrings ;
unsigned int i ;
secstrings = ( char * ) hdr + sechdrs [ hdr - > e_shstrndx ] . sh_offset ;
for ( i = 1 ; i < hdr - > e_shnum ; i + + )
if ( strcmp ( secstrings + sechdrs [ i ] . sh_name , name ) = = 0 )
return & sechdrs [ i ] ;
return NULL ;
}
int module_finalize ( const Elf_Ehdr * hdr ,
const Elf_Shdr * sechdrs , struct module * me )
{
const Elf_Shdr * sect ;
2016-03-03 15:26:54 +11:00
int rc ;
rc = module_finalize_ftrace ( me , sechdrs ) ;
if ( rc )
return rc ;
2008-06-21 02:31:01 +10:00
/* Apply feature fixups */
sect = find_section ( hdr , sechdrs , " __ftr_fixup " ) ;
if ( sect ! = NULL )
do_feature_fixups ( cur_cpu_spec - > cpu_features ,
( void * ) sect - > sh_addr ,
( void * ) sect - > sh_addr + sect - > sh_size ) ;
2008-12-18 19:13:32 +00:00
sect = find_section ( hdr , sechdrs , " __mmu_ftr_fixup " ) ;
if ( sect ! = NULL )
do_feature_fixups ( cur_cpu_spec - > mmu_features ,
( void * ) sect - > sh_addr ,
( void * ) sect - > sh_addr + sect - > sh_size ) ;
2008-06-21 02:31:01 +10:00
# ifdef CONFIG_PPC64
sect = find_section ( hdr , sechdrs , " __fw_ftr_fixup " ) ;
if ( sect ! = NULL )
do_feature_fixups ( powerpc_firmware_features ,
( void * ) sect - > sh_addr ,
( void * ) sect - > sh_addr + sect - > sh_size ) ;
2018-07-28 09:06:34 +10:00
# endif /* CONFIG_PPC64 */
2018-04-24 14:15:56 +10:00
2018-05-29 12:21:00 +05:30
# ifdef PPC64_ELF_ABI_v1
sect = find_section ( hdr , sechdrs , " .opd " ) ;
if ( sect ! = NULL ) {
me - > arch . start_opd = sect - > sh_addr ;
me - > arch . end_opd = sect - > sh_addr + sect - > sh_size ;
}
# endif /* PPC64_ELF_ABI_v1 */
2018-07-28 09:06:34 +10:00
# ifdef CONFIG_PPC_BARRIER_NOSPEC
2018-04-24 14:15:56 +10:00
sect = find_section ( hdr , sechdrs , " __spec_barrier_fixup " ) ;
if ( sect ! = NULL )
do_barrier_nospec_fixups_range ( barrier_nospec_enabled ,
( void * ) sect - > sh_addr ,
( void * ) sect - > sh_addr + sect - > sh_size ) ;
2018-07-28 09:06:34 +10:00
# endif /* CONFIG_PPC_BARRIER_NOSPEC */
2008-06-21 02:31:01 +10:00
2008-07-02 01:16:40 +10:00
sect = find_section ( hdr , sechdrs , " __lwsync_fixup " ) ;
if ( sect ! = NULL )
do_lwsync_fixups ( cur_cpu_spec - > cpu_features ,
( void * ) sect - > sh_addr ,
( void * ) sect - > sh_addr + sect - > sh_size ) ;
2008-06-21 02:31:01 +10:00
return 0 ;
}
2020-06-29 11:15:21 +00:00
2021-04-01 13:30:41 +00:00
static __always_inline void *
__module_alloc ( unsigned long size , unsigned long start , unsigned long end )
{
2021-06-09 11:34:25 +10:00
pgprot_t prot = strict_module_rwx_enabled ( ) ? PAGE_KERNEL : PAGE_KERNEL_EXEC ;
2021-05-03 19:17:55 +10:00
/*
* Don ' t do huge page allocations for modules yet until more testing
* is done . STRICT_MODULE_RWX may require extra work to support this
* too .
*/
2021-06-09 11:34:25 +10:00
return __vmalloc_node_range ( size , 1 , start , end , GFP_KERNEL , prot ,
2021-05-03 19:17:55 +10:00
VM_FLUSH_RESET_PERMS | VM_NO_HUGE_VMAP ,
NUMA_NO_NODE , __builtin_return_address ( 0 ) ) ;
2021-04-01 13:30:41 +00:00
}
2020-06-29 11:15:21 +00:00
void * module_alloc ( unsigned long size )
{
2021-05-03 19:17:55 +10:00
# ifdef MODULES_VADDR
2021-04-01 13:30:41 +00:00
unsigned long limit = ( unsigned long ) _etext - SZ_32M ;
void * ptr = NULL ;
2020-06-29 11:15:21 +00:00
BUILD_BUG_ON ( TASK_SIZE > MODULES_VADDR ) ;
2021-04-01 13:30:41 +00:00
/* First try within 32M limit from _etext to avoid branch trampolines */
if ( MODULES_VADDR < PAGE_OFFSET & & MODULES_END > limit )
ptr = __module_alloc ( size , limit , MODULES_END ) ;
if ( ! ptr )
ptr = __module_alloc ( size , MODULES_VADDR , MODULES_END ) ;
return ptr ;
2021-05-03 19:17:55 +10:00
# else
return __module_alloc ( size , VMALLOC_START , VMALLOC_END ) ;
2020-06-29 11:15:21 +00:00
# endif
2021-05-03 19:17:55 +10:00
}