module.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. // SPDX-License-Identifier: GPL-2.0
  2. // Copyright (C) 2005-2017 Andes Technology Corporation
  3. #include <linux/module.h>
  4. #include <linux/elf.h>
  5. #include <linux/vmalloc.h>
  6. #include <linux/moduleloader.h>
  7. #include <asm/pgtable.h>
  8. void *module_alloc(unsigned long size)
  9. {
  10. return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
  11. GFP_KERNEL, PAGE_KERNEL, 0, NUMA_NO_NODE,
  12. __builtin_return_address(0));
  13. }
  14. void module_free(struct module *module, void *region)
  15. {
  16. vfree(region);
  17. }
  18. int module_frob_arch_sections(Elf_Ehdr * hdr,
  19. Elf_Shdr * sechdrs,
  20. char *secstrings, struct module *mod)
  21. {
  22. return 0;
  23. }
  24. void do_reloc16(unsigned int val, unsigned int *loc, unsigned int val_mask,
  25. unsigned int val_shift, unsigned int loc_mask,
  26. unsigned int partial_in_place, unsigned int swap)
  27. {
  28. unsigned int tmp = 0, tmp2 = 0;
  29. __asm__ __volatile__("\tlhi.bi\t%0, [%2], 0\n"
  30. "\tbeqz\t%3, 1f\n"
  31. "\twsbh\t%0, %1\n"
  32. "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
  33. );
  34. tmp2 = tmp & loc_mask;
  35. if (partial_in_place) {
  36. tmp &= (~loc_mask);
  37. tmp =
  38. tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
  39. } else {
  40. tmp = tmp2 | ((val & val_mask) >> val_shift);
  41. }
  42. __asm__ __volatile__("\tbeqz\t%3, 2f\n"
  43. "\twsbh\t%0, %1\n"
  44. "2:\n"
  45. "\tshi.bi\t%0, [%2], 0\n":"=r"(tmp):"0"(tmp),
  46. "r"(loc), "r"(swap)
  47. );
  48. }
  49. void do_reloc32(unsigned int val, unsigned int *loc, unsigned int val_mask,
  50. unsigned int val_shift, unsigned int loc_mask,
  51. unsigned int partial_in_place, unsigned int swap)
  52. {
  53. unsigned int tmp = 0, tmp2 = 0;
  54. __asm__ __volatile__("\tlmw.bi\t%0, [%2], %0, 0\n"
  55. "\tbeqz\t%3, 1f\n"
  56. "\twsbh\t%0, %1\n"
  57. "\trotri\t%0, %1, 16\n"
  58. "1:\n":"=r"(tmp):"0"(tmp), "r"(loc), "r"(swap)
  59. );
  60. tmp2 = tmp & loc_mask;
  61. if (partial_in_place) {
  62. tmp &= (~loc_mask);
  63. tmp =
  64. tmp2 | ((tmp + ((val & val_mask) >> val_shift)) & val_mask);
  65. } else {
  66. tmp = tmp2 | ((val & val_mask) >> val_shift);
  67. }
  68. __asm__ __volatile__("\tbeqz\t%3, 2f\n"
  69. "\twsbh\t%0, %1\n"
  70. "\trotri\t%0, %1, 16\n"
  71. "2:\n"
  72. "\tsmw.bi\t%0, [%2], %0, 0\n":"=r"(tmp):"0"(tmp),
  73. "r"(loc), "r"(swap)
  74. );
  75. }
  76. static inline int exceed_limit(int offset, unsigned int val_mask,
  77. struct module *module, Elf32_Rela * rel,
  78. unsigned int relindex, unsigned int reloc_order)
  79. {
  80. int abs_off = offset < 0 ? ~offset : offset;
  81. if (abs_off & (~val_mask)) {
  82. pr_err("\n%s: relocation type %d out of range.\n"
  83. "please rebuild the kernel module with gcc option \"-Wa,-mno-small-text\".\n",
  84. module->name, ELF32_R_TYPE(rel->r_info));
  85. pr_err("section %d reloc %d offset 0x%x relative 0x%x.\n",
  86. relindex, reloc_order, rel->r_offset, offset);
  87. return true;
  88. }
  89. return false;
  90. }
  91. #ifdef __NDS32_EL__
  92. #define NEED_SWAP 1
  93. #else
  94. #define NEED_SWAP 0
  95. #endif
  96. int
  97. apply_relocate_add(Elf32_Shdr * sechdrs, const char *strtab,
  98. unsigned int symindex, unsigned int relindex,
  99. struct module *module)
  100. {
  101. Elf32_Shdr *symsec = sechdrs + symindex;
  102. Elf32_Shdr *relsec = sechdrs + relindex;
  103. Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
  104. Elf32_Rela *rel = (void *)relsec->sh_addr;
  105. unsigned int i;
  106. for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rela); i++, rel++) {
  107. Elf32_Addr *loc;
  108. Elf32_Sym *sym;
  109. Elf32_Addr v;
  110. s32 offset;
  111. offset = ELF32_R_SYM(rel->r_info);
  112. if (offset < 0
  113. || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
  114. pr_err("%s: bad relocation\n", module->name);
  115. pr_err("section %d reloc %d\n", relindex, i);
  116. return -ENOEXEC;
  117. }
  118. sym = ((Elf32_Sym *) symsec->sh_addr) + offset;
  119. if (rel->r_offset < 0
  120. || rel->r_offset > dstsec->sh_size - sizeof(u16)) {
  121. pr_err("%s: out of bounds relocation\n", module->name);
  122. pr_err("section %d reloc %d offset 0x%0x size %d\n",
  123. relindex, i, rel->r_offset, dstsec->sh_size);
  124. return -ENOEXEC;
  125. }
  126. loc = (Elf32_Addr *) (dstsec->sh_addr + rel->r_offset);
  127. v = sym->st_value + rel->r_addend;
  128. switch (ELF32_R_TYPE(rel->r_info)) {
  129. case R_NDS32_NONE:
  130. case R_NDS32_INSN16:
  131. case R_NDS32_LABEL:
  132. case R_NDS32_LONGCALL1:
  133. case R_NDS32_LONGCALL2:
  134. case R_NDS32_LONGCALL3:
  135. case R_NDS32_LONGCALL4:
  136. case R_NDS32_LONGJUMP1:
  137. case R_NDS32_LONGJUMP2:
  138. case R_NDS32_LONGJUMP3:
  139. case R_NDS32_9_FIXED_RELA:
  140. case R_NDS32_15_FIXED_RELA:
  141. case R_NDS32_17_FIXED_RELA:
  142. case R_NDS32_25_FIXED_RELA:
  143. case R_NDS32_LOADSTORE:
  144. case R_NDS32_DWARF2_OP1_RELA:
  145. case R_NDS32_DWARF2_OP2_RELA:
  146. case R_NDS32_DWARF2_LEB_RELA:
  147. case R_NDS32_RELA_NOP_MIX ... R_NDS32_RELA_NOP_MAX:
  148. break;
  149. case R_NDS32_32_RELA:
  150. do_reloc32(v, loc, 0xffffffff, 0, 0, 0, 0);
  151. break;
  152. case R_NDS32_HI20_RELA:
  153. do_reloc32(v, loc, 0xfffff000, 12, 0xfff00000, 0,
  154. NEED_SWAP);
  155. break;
  156. case R_NDS32_LO12S3_RELA:
  157. do_reloc32(v, loc, 0x00000fff, 3, 0xfffff000, 0,
  158. NEED_SWAP);
  159. break;
  160. case R_NDS32_LO12S2_RELA:
  161. do_reloc32(v, loc, 0x00000fff, 2, 0xfffff000, 0,
  162. NEED_SWAP);
  163. break;
  164. case R_NDS32_LO12S1_RELA:
  165. do_reloc32(v, loc, 0x00000fff, 1, 0xfffff000, 0,
  166. NEED_SWAP);
  167. break;
  168. case R_NDS32_LO12S0_RELA:
  169. case R_NDS32_LO12S0_ORI_RELA:
  170. do_reloc32(v, loc, 0x00000fff, 0, 0xfffff000, 0,
  171. NEED_SWAP);
  172. break;
  173. case R_NDS32_9_PCREL_RELA:
  174. if (exceed_limit
  175. ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
  176. relindex, i))
  177. return -ENOEXEC;
  178. do_reloc16(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
  179. 0xffffff00, 0, NEED_SWAP);
  180. break;
  181. case R_NDS32_15_PCREL_RELA:
  182. if (exceed_limit
  183. ((v - (Elf32_Addr) loc), 0x00003fff, module, rel,
  184. relindex, i))
  185. return -ENOEXEC;
  186. do_reloc32(v - (Elf32_Addr) loc, loc, 0x00007fff, 1,
  187. 0xffffc000, 0, NEED_SWAP);
  188. break;
  189. case R_NDS32_17_PCREL_RELA:
  190. if (exceed_limit
  191. ((v - (Elf32_Addr) loc), 0x0000ffff, module, rel,
  192. relindex, i))
  193. return -ENOEXEC;
  194. do_reloc32(v - (Elf32_Addr) loc, loc, 0x0001ffff, 1,
  195. 0xffff0000, 0, NEED_SWAP);
  196. break;
  197. case R_NDS32_25_PCREL_RELA:
  198. if (exceed_limit
  199. ((v - (Elf32_Addr) loc), 0x00ffffff, module, rel,
  200. relindex, i))
  201. return -ENOEXEC;
  202. do_reloc32(v - (Elf32_Addr) loc, loc, 0x01ffffff, 1,
  203. 0xff000000, 0, NEED_SWAP);
  204. break;
  205. case R_NDS32_WORD_9_PCREL_RELA:
  206. if (exceed_limit
  207. ((v - (Elf32_Addr) loc), 0x000000ff, module, rel,
  208. relindex, i))
  209. return -ENOEXEC;
  210. do_reloc32(v - (Elf32_Addr) loc, loc, 0x000001ff, 1,
  211. 0xffffff00, 0, NEED_SWAP);
  212. break;
  213. case R_NDS32_SDA15S3_RELA:
  214. case R_NDS32_SDA15S2_RELA:
  215. case R_NDS32_SDA15S1_RELA:
  216. case R_NDS32_SDA15S0_RELA:
  217. pr_err("%s: unsupported relocation type %d.\n",
  218. module->name, ELF32_R_TYPE(rel->r_info));
  219. pr_err
  220. ("Small data section access doesn't work in the kernel space; "
  221. "please rebuild the kernel module with gcc option -mcmodel=large.\n");
  222. pr_err("section %d reloc %d offset 0x%x size %d\n",
  223. relindex, i, rel->r_offset, dstsec->sh_size);
  224. break;
  225. default:
  226. pr_err("%s: unsupported relocation type %d.\n",
  227. module->name, ELF32_R_TYPE(rel->r_info));
  228. pr_err("section %d reloc %d offset 0x%x size %d\n",
  229. relindex, i, rel->r_offset, dstsec->sh_size);
  230. }
  231. }
  232. return 0;
  233. }
  234. int
  235. module_finalize(const Elf32_Ehdr * hdr, const Elf_Shdr * sechdrs,
  236. struct module *module)
  237. {
  238. return 0;
  239. }
  240. void module_arch_cleanup(struct module *mod)
  241. {
  242. }