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 13 struct mod_section { 14 Elf_Shdr *shdr; 15 int num_entries; 16 int max_entries; 17 }; 18 19 struct mod_arch_specific { 20 struct mod_section plt; 21 struct mod_section plt_idx; 22 }; 23 24 struct plt_entry { 25 u32 inst_lu12iw; 26 u32 inst_lu32id; 27 u32 inst_lu52id; 28 u32 inst_jirl; 29 }; 30 31 struct plt_idx_entry { 32 unsigned long symbol_addr; 33 }; 34 35 Elf_Addr module_emit_plt_entry(struct module *mod, unsigned long val); 36 37 static inline struct plt_entry emit_plt_entry(unsigned long val) 38 { 39 u32 lu12iw, lu32id, lu52id, jirl; 40 41 lu12iw = (lu12iw_op << 25 | (((val >> 12) & 0xfffff) << 5) | LOONGARCH_GPR_T1); 42 lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); 43 lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); 44 jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff)); 45 46 return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; 47 } 48 49 static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val) 50 { 51 return (struct plt_idx_entry) { val }; 52 } 53 54 static inline int get_plt_idx(unsigned long val, const struct mod_section *sec) 55 { 56 int i; 57 struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sec->shdr->sh_addr; 58 59 for (i = 0; i < sec->num_entries; i++) { 60 if (plt_idx[i].symbol_addr == val) 61 return i; 62 } 63 64 return -1; 65 } 66 67 static inline struct plt_entry *get_plt_entry(unsigned long val, 68 const struct mod_section *sec_plt, 69 const struct mod_section *sec_plt_idx) 70 { 71 int plt_idx = get_plt_idx(val, sec_plt_idx); 72 struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr; 73 74 if (plt_idx < 0) 75 return NULL; 76 77 return plt + plt_idx; 78 } 79 80 #endif /* _ASM_MODULE_H */ 81