module.h 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /* Copyright (C) 2017 Andes Technology Corporation */
  3. #ifndef _ASM_RISCV_MODULE_H
  4. #define _ASM_RISCV_MODULE_H
  5. #include <asm-generic/module.h>
  6. #define MODULE_ARCH_VERMAGIC "riscv"
  7. u64 module_emit_got_entry(struct module *mod, u64 val);
  8. u64 module_emit_plt_entry(struct module *mod, u64 val);
  9. #ifdef CONFIG_MODULE_SECTIONS
  10. struct mod_section {
  11. struct elf64_shdr *shdr;
  12. int num_entries;
  13. int max_entries;
  14. };
  15. struct mod_arch_specific {
  16. struct mod_section got;
  17. struct mod_section plt;
  18. };
  19. struct got_entry {
  20. u64 symbol_addr; /* the real variable address */
  21. };
  22. static inline struct got_entry emit_got_entry(u64 val)
  23. {
  24. return (struct got_entry) {val};
  25. }
  26. static inline struct got_entry *get_got_entry(u64 val,
  27. const struct mod_section *sec)
  28. {
  29. struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
  30. int i;
  31. for (i = 0; i < sec->num_entries; i++) {
  32. if (got[i].symbol_addr == val)
  33. return &got[i];
  34. }
  35. return NULL;
  36. }
  37. struct plt_entry {
  38. /*
  39. * Trampoline code to real target address. The return address
  40. * should be the original (pc+4) before entring plt entry.
  41. * For 8 byte alignment of symbol_addr,
  42. * don't pack structure to remove the padding.
  43. */
  44. u32 insn_auipc; /* auipc t0, 0x0 */
  45. u32 insn_ld; /* ld t1, 0x10(t0) */
  46. u32 insn_jr; /* jr t1 */
  47. u64 symbol_addr; /* the real jump target address */
  48. };
  49. #define OPC_AUIPC 0x0017
  50. #define OPC_LD 0x3003
  51. #define OPC_JALR 0x0067
  52. #define REG_T0 0x5
  53. #define REG_T1 0x6
  54. #define IMM_OFFSET 0x10
  55. static inline struct plt_entry emit_plt_entry(u64 val)
  56. {
  57. /*
  58. * U-Type encoding:
  59. * +------------+----------+----------+
  60. * | imm[31:12] | rd[11:7] | opc[6:0] |
  61. * +------------+----------+----------+
  62. *
  63. * I-Type encoding:
  64. * +------------+------------+--------+----------+----------+
  65. * | imm[31:20] | rs1[19:15] | funct3 | rd[11:7] | opc[6:0] |
  66. * +------------+------------+--------+----------+----------+
  67. *
  68. */
  69. return (struct plt_entry) {
  70. OPC_AUIPC | (REG_T0 << 7),
  71. OPC_LD | (IMM_OFFSET << 20) | (REG_T0 << 15) | (REG_T1 << 7),
  72. OPC_JALR | (REG_T1 << 15),
  73. val
  74. };
  75. }
  76. static inline struct plt_entry *get_plt_entry(u64 val,
  77. const struct mod_section *sec)
  78. {
  79. struct plt_entry *plt = (struct plt_entry *)sec->shdr->sh_addr;
  80. int i;
  81. for (i = 0; i < sec->num_entries; i++) {
  82. if (plt[i].symbol_addr == val)
  83. return &plt[i];
  84. }
  85. return NULL;
  86. }
  87. #endif /* CONFIG_MODULE_SECTIONS */
  88. #endif /* _ASM_RISCV_MODULE_H */