1246145Shselasky/* SPDX-License-Identifier: GPL-2.0 */ 2246145Shselasky/* 3246145Shselasky * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4246145Shselasky */ 5246145Shselasky#ifndef _ASM_MODULE_H 6246145Shselasky#define _ASM_MODULE_H 7246145Shselasky 8246145Shselasky#include <asm/inst.h> 9246145Shselasky#include <asm/orc_types.h> 10246145Shselasky#include <asm-generic/module.h> 11246145Shselasky 12246145Shselasky#define RELA_STACK_DEPTH 16 13246145Shselasky 14246145Shselaskystruct mod_section { 15246145Shselasky int shndx; 16246145Shselasky int num_entries; 17246145Shselasky int max_entries; 18246145Shselasky}; 19246145Shselasky 20246145Shselaskystruct mod_arch_specific { 21246145Shselasky struct mod_section got; 22246145Shselasky struct mod_section plt; 23246145Shselasky struct mod_section plt_idx; 24246145Shselasky 25246145Shselasky#ifdef CONFIG_UNWINDER_ORC 26246145Shselasky unsigned int num_orcs; 27246145Shselasky int *orc_unwind_ip; 28246145Shselasky struct orc_entry *orc_unwind; 29246363Shselasky#endif 30246363Shselasky 31246145Shselasky /* For CONFIG_DYNAMIC_FTRACE */ 32246145Shselasky struct plt_entry *ftrace_trampolines; 33246145Shselasky}; 34246145Shselasky 35246145Shselaskystruct got_entry { 36246145Shselasky Elf_Addr symbol_addr; 37246145Shselasky}; 38291405Szbb 39291405Szbbstruct plt_entry { 40291405Szbb u32 inst_lu12iw; 41291405Szbb u32 inst_lu32id; 42246145Shselasky u32 inst_lu52id; 43246145Shselasky u32 inst_jirl; 44246145Shselasky}; 45246145Shselasky 46246145Shselaskystruct plt_idx_entry { 47246145Shselasky Elf_Addr symbol_addr; 48246145Shselasky}; 49246145Shselasky 50294547SwmaElf_Addr module_emit_got_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val); 51294547SwmaElf_Addr module_emit_plt_entry(struct module *mod, Elf_Shdr *sechdrs, Elf_Addr val); 52294547Swma 53294547Swmastatic inline struct got_entry emit_got_entry(Elf_Addr val) 54294547Swma{ 55294547Swma return (struct got_entry) { val }; 56294547Swma} 57294547Swma 58294547Swmastatic inline struct plt_entry emit_plt_entry(unsigned long val) 59294547Swma{ 60294547Swma u32 lu12iw, lu32id, lu52id, jirl; 61294547Swma 62294547Swma lu12iw = larch_insn_gen_lu12iw(LOONGARCH_GPR_T1, ADDR_IMM(val, LU12IW)); 63294547Swma lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID)); 64294547Swma lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID)); 65294547Swma jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, ADDR_IMM(val, ORI)); 66294547Swma 67294547Swma return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl }; 68294547Swma} 69294547Swma 70294547Swmastatic inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val) 71294547Swma{ 72294547Swma return (struct plt_idx_entry) { val }; 73294547Swma} 74294547Swma 75294547Swmastatic inline int get_plt_idx(unsigned long val, Elf_Shdr *sechdrs, const struct mod_section *sec) 76294547Swma{ 77294547Swma int i; 78315221Spfg struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sechdrs[sec->shndx].sh_addr; 79294547Swma 80294547Swma for (i = 0; i < sec->num_entries; i++) { 81294547Swma if (plt_idx[i].symbol_addr == val) 82294547Swma return i; 83294547Swma } 84294547Swma 85294547Swma return -1; 86294547Swma} 87294547Swma 88294547Swmastatic inline struct plt_entry *get_plt_entry(unsigned long val, 89294547Swma Elf_Shdr *sechdrs, 90294547Swma const struct mod_section *sec_plt, 91294547Swma const struct mod_section *sec_plt_idx) 92294547Swma{ 93294547Swma int plt_idx = get_plt_idx(val, sechdrs, sec_plt_idx); 94294547Swma struct plt_entry *plt = (struct plt_entry *)sechdrs[sec_plt->shndx].sh_addr; 95294547Swma 96294547Swma if (plt_idx < 0) 97294547Swma return NULL; 98294547Swma 99294547Swma return plt + plt_idx; 100294547Swma} 101294547Swma 102294547Swmastatic inline struct got_entry *get_got_entry(Elf_Addr val, 103294547Swma Elf_Shdr *sechdrs, 104294547Swma const struct mod_section *sec) 105294547Swma{ 106294547Swma int i; 107294547Swma struct got_entry *got = (struct got_entry *)sechdrs[sec->shndx].sh_addr; 108294547Swma 109294547Swma for (i = 0; i < sec->num_entries; i++) 110294547Swma if (got[i].symbol_addr == val) 111294547Swma return &got[i]; 112294547Swma return NULL; 113294547Swma} 114294547Swma 115294547Swma#endif /* _ASM_MODULE_H */ 116294547Swma