1/* SPDX-License-Identifier: GPL-2.0 */ 2/* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 */ 5#ifndef _ASM_MODULE_H 6#define _ASM_MODULE_H 7 8#include <asm/inst.h> 9#include <asm-generic/module.h> 10 11#define RELA_STACK_DEPTH 16 12 13struct mod_section { 14 int shndx; 15 int num_entries; 16 int max_entries; 17}; 18 19struct mod_arch_specific { 20 struct mod_section got; 21 struct mod_section plt; 22 struct mod_section plt_idx; 23 24 /* For CONFIG_DYNAMIC_FTRACE */ 25 struct plt_entry *ftrace_trampolines; 26}; 27 28struct got_entry { 29 Elf_Addr symbol_addr; 30}; 31 32struct plt_entry { 33 u32 inst_lu12iw; 34 u32 inst_lu32id; 35 u32 inst_lu52id; 36 u32 inst_jirl; 37}; 38 39struct plt_idx_entry { 40 Elf_Addr symbol_addr; 41}; 42 43Elf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val); 44Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val); 45 46static inline struct got_entry emit_got_entry(Elf_Addr val) 47{ 48 return (struct got_entry) { val }; 49} 50 51static inline struct plt_entry emit_plt_entry(unsigned long val) 52{ 53 u32 lu12iw, lu32id, lu52id, jirl; 54 55 lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW)); 56 lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); 57 lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); 58 jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI)); 59 60 return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; 61} 62 63static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val) 64{ 65 return (struct plt_idx_entry) { val }; 66} 67 68static inline int get_plt_idx(unsigned long val, Elf_Shdr *sechdrs, const struct mod_section *sec) 69{ 70 int i; 71 struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sechdrs[sec->shndx].sh_addr; 72 73 for (i = 0; i < sec->num_entries; i++) { 74 if (plt_idx[i].symbol_addr == val) 75 return i; 76 } 77 78 return -1; 79} 80 81static inline struct plt_entry *get_plt_entry(unsigned long val, 82 Elf_Shdr *sechdrs, 83 const struct mod_section *sec_plt, 84 const struct mod_section *sec_plt_idx) 85{ 86 int plt_idx = get_plt_idx(val, sechdrs, sec_plt_idx); 87 struct plt_entry *plt = (struct plt_entry *)sechdrs[sec_plt->shndx].sh_addr; 88 89 if (plt_idx < 0) 90 return NULL; 91 92 return plt + plt_idx; 93} 94 95static inline struct got_entry *get_got_entry(Elf_Addr val, 96 Elf_Shdr *sechdrs, 97 const struct mod_section *sec) 98{ 99 int i; 100 struct got_entry *got = (struct got_entry *)sechdrs[sec->shndx].sh_addr; 101 102 for (i = 0; i < sec->num_entries; i++) 103 if (got[i].symbol_addr == val) 104 return &got[i]; 105 return NULL; 106} 107 108#endif /* _ASM_MODULE_H */ 109