1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */ 2*4882a593Smuzhiyun #ifndef _ASM_POWERPC_SECTIONS_H 3*4882a593Smuzhiyun #define _ASM_POWERPC_SECTIONS_H 4*4882a593Smuzhiyun #ifdef __KERNEL__ 5*4882a593Smuzhiyun 6*4882a593Smuzhiyun #include <linux/elf.h> 7*4882a593Smuzhiyun #include <linux/uaccess.h> 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun #define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed 10*4882a593Smuzhiyun 11*4882a593Smuzhiyun #include <asm-generic/sections.h> 12*4882a593Smuzhiyun 13*4882a593Smuzhiyun extern bool init_mem_is_free; 14*4882a593Smuzhiyun arch_is_kernel_initmem_freed(unsigned long addr)15*4882a593Smuzhiyunstatic inline int arch_is_kernel_initmem_freed(unsigned long addr) 16*4882a593Smuzhiyun { 17*4882a593Smuzhiyun if (!init_mem_is_free) 18*4882a593Smuzhiyun return 0; 19*4882a593Smuzhiyun 20*4882a593Smuzhiyun return addr >= (unsigned long)__init_begin && 21*4882a593Smuzhiyun addr < (unsigned long)__init_end; 22*4882a593Smuzhiyun } 23*4882a593Smuzhiyun 24*4882a593Smuzhiyun extern char __head_end[]; 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun #ifdef __powerpc64__ 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun extern char __start_interrupts[]; 29*4882a593Smuzhiyun extern char __end_interrupts[]; 30*4882a593Smuzhiyun 31*4882a593Smuzhiyun extern char __prom_init_toc_start[]; 32*4882a593Smuzhiyun extern char __prom_init_toc_end[]; 33*4882a593Smuzhiyun 34*4882a593Smuzhiyun #ifdef CONFIG_PPC_POWERNV 35*4882a593Smuzhiyun extern char start_real_trampolines[]; 36*4882a593Smuzhiyun extern char end_real_trampolines[]; 37*4882a593Smuzhiyun extern char start_virt_trampolines[]; 38*4882a593Smuzhiyun extern char end_virt_trampolines[]; 39*4882a593Smuzhiyun #endif 40*4882a593Smuzhiyun in_kernel_text(unsigned long addr)41*4882a593Smuzhiyunstatic inline int in_kernel_text(unsigned long addr) 42*4882a593Smuzhiyun { 43*4882a593Smuzhiyun if (addr >= (unsigned long)_stext && addr < (unsigned long)__init_end) 44*4882a593Smuzhiyun return 1; 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun return 0; 47*4882a593Smuzhiyun } 48*4882a593Smuzhiyun kernel_toc_addr(void)49*4882a593Smuzhiyunstatic inline unsigned long kernel_toc_addr(void) 50*4882a593Smuzhiyun { 51*4882a593Smuzhiyun /* Defined by the linker, see vmlinux.lds.S */ 52*4882a593Smuzhiyun extern unsigned long __toc_start; 53*4882a593Smuzhiyun 54*4882a593Smuzhiyun /* 55*4882a593Smuzhiyun * The TOC register (r2) points 32kB into the TOC, so that 64kB of 56*4882a593Smuzhiyun * the TOC can be addressed using a single machine instruction. 57*4882a593Smuzhiyun */ 58*4882a593Smuzhiyun return (unsigned long)(&__toc_start) + 0x8000UL; 59*4882a593Smuzhiyun } 60*4882a593Smuzhiyun overlaps_interrupt_vector_text(unsigned long start,unsigned long end)61*4882a593Smuzhiyunstatic inline int overlaps_interrupt_vector_text(unsigned long start, 62*4882a593Smuzhiyun unsigned long end) 63*4882a593Smuzhiyun { 64*4882a593Smuzhiyun unsigned long real_start, real_end; 65*4882a593Smuzhiyun real_start = __start_interrupts - _stext; 66*4882a593Smuzhiyun real_end = __end_interrupts - _stext; 67*4882a593Smuzhiyun 68*4882a593Smuzhiyun return start < (unsigned long)__va(real_end) && 69*4882a593Smuzhiyun (unsigned long)__va(real_start) < end; 70*4882a593Smuzhiyun } 71*4882a593Smuzhiyun overlaps_kernel_text(unsigned long start,unsigned long end)72*4882a593Smuzhiyunstatic inline int overlaps_kernel_text(unsigned long start, unsigned long end) 73*4882a593Smuzhiyun { 74*4882a593Smuzhiyun return start < (unsigned long)__init_end && 75*4882a593Smuzhiyun (unsigned long)_stext < end; 76*4882a593Smuzhiyun } 77*4882a593Smuzhiyun 78*4882a593Smuzhiyun #ifdef PPC64_ELF_ABI_v1 79*4882a593Smuzhiyun 80*4882a593Smuzhiyun #define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1 81*4882a593Smuzhiyun 82*4882a593Smuzhiyun #undef dereference_function_descriptor dereference_function_descriptor(void * ptr)83*4882a593Smuzhiyunstatic inline void *dereference_function_descriptor(void *ptr) 84*4882a593Smuzhiyun { 85*4882a593Smuzhiyun struct ppc64_opd_entry *desc = ptr; 86*4882a593Smuzhiyun void *p; 87*4882a593Smuzhiyun 88*4882a593Smuzhiyun if (!get_kernel_nofault(p, (void *)&desc->funcaddr)) 89*4882a593Smuzhiyun ptr = p; 90*4882a593Smuzhiyun return ptr; 91*4882a593Smuzhiyun } 92*4882a593Smuzhiyun 93*4882a593Smuzhiyun #undef dereference_kernel_function_descriptor dereference_kernel_function_descriptor(void * ptr)94*4882a593Smuzhiyunstatic inline void *dereference_kernel_function_descriptor(void *ptr) 95*4882a593Smuzhiyun { 96*4882a593Smuzhiyun if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd) 97*4882a593Smuzhiyun return ptr; 98*4882a593Smuzhiyun 99*4882a593Smuzhiyun return dereference_function_descriptor(ptr); 100*4882a593Smuzhiyun } 101*4882a593Smuzhiyun #endif /* PPC64_ELF_ABI_v1 */ 102*4882a593Smuzhiyun 103*4882a593Smuzhiyun #endif 104*4882a593Smuzhiyun 105*4882a593Smuzhiyun #endif /* __KERNEL__ */ 106*4882a593Smuzhiyun #endif /* _ASM_POWERPC_SECTIONS_H */ 107