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