18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci#ifndef _ASM_POWERPC_SECTIONS_H
38c2ecf20Sopenharmony_ci#define _ASM_POWERPC_SECTIONS_H
48c2ecf20Sopenharmony_ci#ifdef __KERNEL__
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/elf.h>
78c2ecf20Sopenharmony_ci#include <linux/uaccess.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#define arch_is_kernel_initmem_freed arch_is_kernel_initmem_freed
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include <asm-generic/sections.h>
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ciextern bool init_mem_is_free;
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_cistatic inline int arch_is_kernel_initmem_freed(unsigned long addr)
168c2ecf20Sopenharmony_ci{
178c2ecf20Sopenharmony_ci	if (!init_mem_is_free)
188c2ecf20Sopenharmony_ci		return 0;
198c2ecf20Sopenharmony_ci
208c2ecf20Sopenharmony_ci	return addr >= (unsigned long)__init_begin &&
218c2ecf20Sopenharmony_ci		addr < (unsigned long)__init_end;
228c2ecf20Sopenharmony_ci}
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ciextern char __head_end[];
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#ifdef __powerpc64__
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciextern char __start_interrupts[];
298c2ecf20Sopenharmony_ciextern char __end_interrupts[];
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ciextern char __prom_init_toc_start[];
328c2ecf20Sopenharmony_ciextern char __prom_init_toc_end[];
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_POWERNV
358c2ecf20Sopenharmony_ciextern char start_real_trampolines[];
368c2ecf20Sopenharmony_ciextern char end_real_trampolines[];
378c2ecf20Sopenharmony_ciextern char start_virt_trampolines[];
388c2ecf20Sopenharmony_ciextern char end_virt_trampolines[];
398c2ecf20Sopenharmony_ci#endif
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline unsigned long kernel_toc_addr(void)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	/* Defined by the linker, see vmlinux.lds.S */
448c2ecf20Sopenharmony_ci	extern unsigned long __toc_start;
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	/*
478c2ecf20Sopenharmony_ci	 * The TOC register (r2) points 32kB into the TOC, so that 64kB of
488c2ecf20Sopenharmony_ci	 * the TOC can be addressed using a single machine instruction.
498c2ecf20Sopenharmony_ci	 */
508c2ecf20Sopenharmony_ci	return (unsigned long)(&__toc_start) + 0x8000UL;
518c2ecf20Sopenharmony_ci}
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_cistatic inline int overlaps_interrupt_vector_text(unsigned long start,
548c2ecf20Sopenharmony_ci							unsigned long end)
558c2ecf20Sopenharmony_ci{
568c2ecf20Sopenharmony_ci	unsigned long real_start, real_end;
578c2ecf20Sopenharmony_ci	real_start = __start_interrupts - _stext;
588c2ecf20Sopenharmony_ci	real_end = __end_interrupts - _stext;
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	return start < (unsigned long)__va(real_end) &&
618c2ecf20Sopenharmony_ci		(unsigned long)__va(real_start) < end;
628c2ecf20Sopenharmony_ci}
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistatic inline int overlaps_kernel_text(unsigned long start, unsigned long end)
658c2ecf20Sopenharmony_ci{
668c2ecf20Sopenharmony_ci	return start < (unsigned long)__init_end &&
678c2ecf20Sopenharmony_ci		(unsigned long)_stext < end;
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci#ifdef PPC64_ELF_ABI_v1
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci#define HAVE_DEREFERENCE_FUNCTION_DESCRIPTOR 1
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci#undef dereference_function_descriptor
758c2ecf20Sopenharmony_cistatic inline void *dereference_function_descriptor(void *ptr)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	struct ppc64_opd_entry *desc = ptr;
788c2ecf20Sopenharmony_ci	void *p;
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_ci	if (!get_kernel_nofault(p, (void *)&desc->funcaddr))
818c2ecf20Sopenharmony_ci		ptr = p;
828c2ecf20Sopenharmony_ci	return ptr;
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#undef dereference_kernel_function_descriptor
868c2ecf20Sopenharmony_cistatic inline void *dereference_kernel_function_descriptor(void *ptr)
878c2ecf20Sopenharmony_ci{
888c2ecf20Sopenharmony_ci	if (ptr < (void *)__start_opd || ptr >= (void *)__end_opd)
898c2ecf20Sopenharmony_ci		return ptr;
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci	return dereference_function_descriptor(ptr);
928c2ecf20Sopenharmony_ci}
938c2ecf20Sopenharmony_ci#endif /* PPC64_ELF_ABI_v1 */
948c2ecf20Sopenharmony_ci
958c2ecf20Sopenharmony_ci#endif
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_ci#endif /* __KERNEL__ */
988c2ecf20Sopenharmony_ci#endif	/* _ASM_POWERPC_SECTIONS_H */
99