18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012 ARM Ltd. 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci#ifndef __ASM_MODULE_H 68c2ecf20Sopenharmony_ci#define __ASM_MODULE_H 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include <asm-generic/module.h> 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#ifdef CONFIG_ARM64_MODULE_PLTS 118c2ecf20Sopenharmony_cistruct mod_plt_sec { 128c2ecf20Sopenharmony_ci int plt_shndx; 138c2ecf20Sopenharmony_ci int plt_num_entries; 148c2ecf20Sopenharmony_ci int plt_max_entries; 158c2ecf20Sopenharmony_ci}; 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_cistruct mod_arch_specific { 188c2ecf20Sopenharmony_ci struct mod_plt_sec core; 198c2ecf20Sopenharmony_ci struct mod_plt_sec init; 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci /* for CONFIG_DYNAMIC_FTRACE */ 228c2ecf20Sopenharmony_ci struct plt_entry *ftrace_trampolines; 238c2ecf20Sopenharmony_ci}; 248c2ecf20Sopenharmony_ci#endif 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciu64 module_emit_plt_entry(struct module *mod, Elf64_Shdr *sechdrs, 278c2ecf20Sopenharmony_ci void *loc, const Elf64_Rela *rela, 288c2ecf20Sopenharmony_ci Elf64_Sym *sym); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ciu64 module_emit_veneer_for_adrp(struct module *mod, Elf64_Shdr *sechdrs, 318c2ecf20Sopenharmony_ci void *loc, u64 val); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#ifdef CONFIG_RANDOMIZE_BASE 348c2ecf20Sopenharmony_ciextern u64 module_alloc_base; 358c2ecf20Sopenharmony_ci#else 368c2ecf20Sopenharmony_ci#define module_alloc_base ((u64)_etext - MODULES_VSIZE) 378c2ecf20Sopenharmony_ci#endif 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct plt_entry { 408c2ecf20Sopenharmony_ci /* 418c2ecf20Sopenharmony_ci * A program that conforms to the AArch64 Procedure Call Standard 428c2ecf20Sopenharmony_ci * (AAPCS64) must assume that a veneer that alters IP0 (x16) and/or 438c2ecf20Sopenharmony_ci * IP1 (x17) may be inserted at any branch instruction that is 448c2ecf20Sopenharmony_ci * exposed to a relocation that supports long branches. Since that 458c2ecf20Sopenharmony_ci * is exactly what we are dealing with here, we are free to use x16 468c2ecf20Sopenharmony_ci * as a scratch register in the PLT veneers. 478c2ecf20Sopenharmony_ci */ 488c2ecf20Sopenharmony_ci __le32 adrp; /* adrp x16, .... */ 498c2ecf20Sopenharmony_ci __le32 add; /* add x16, x16, #0x.... */ 508c2ecf20Sopenharmony_ci __le32 br; /* br x16 */ 518c2ecf20Sopenharmony_ci}; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_cistatic inline bool is_forbidden_offset_for_adrp(void *place) 548c2ecf20Sopenharmony_ci{ 558c2ecf20Sopenharmony_ci return IS_ENABLED(CONFIG_ARM64_ERRATUM_843419) && 568c2ecf20Sopenharmony_ci cpus_have_const_cap(ARM64_WORKAROUND_843419) && 578c2ecf20Sopenharmony_ci ((u64)place & 0xfff) >= 0xff8; 588c2ecf20Sopenharmony_ci} 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_cistruct plt_entry get_plt_entry(u64 dst, void *pc); 618c2ecf20Sopenharmony_cibool plt_entries_equal(const struct plt_entry *a, const struct plt_entry *b); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cistatic inline bool plt_entry_is_initialized(const struct plt_entry *e) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci return e->adrp || e->add || e->br; 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#endif /* __ASM_MODULE_H */ 69