module.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * File: arch/blackfin/kernel/module.c
  3. * Based on:
  4. * Author:
  5. *
  6. * Created:
  7. * Description:
  8. *
  9. * Modified:
  10. * Copyright 2004-2006 Analog Devices Inc.
  11. *
  12. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, see the file COPYING, or write
  26. * to the Free Software Foundation, Inc.,
  27. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #define pr_fmt(fmt) "module %s: " fmt
  30. #include <linux/moduleloader.h>
  31. #include <linux/elf.h>
  32. #include <linux/vmalloc.h>
  33. #include <linux/fs.h>
  34. #include <linux/string.h>
  35. #include <linux/kernel.h>
  36. #include <asm/dma.h>
  37. #include <asm/cacheflush.h>
  38. #include <asm/uaccess.h>
  39. void *module_alloc(unsigned long size)
  40. {
  41. if (size == 0)
  42. return NULL;
  43. return vmalloc(size);
  44. }
  45. /* Free memory returned from module_alloc */
  46. void module_free(struct module *mod, void *module_region)
  47. {
  48. vfree(module_region);
  49. }
  50. /* Transfer the section to the L1 memory */
  51. int
  52. module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
  53. char *secstrings, struct module *mod)
  54. {
  55. /*
  56. * XXX: sechdrs are vmalloced in kernel/module.c
  57. * and would be vfreed just after module is loaded,
  58. * so we hack to keep the only information we needed
  59. * in mod->arch to correctly free L1 I/D sram later.
  60. * NOTE: this breaks the semantic of mod->arch structure.
  61. */
  62. Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
  63. void *dest;
  64. for (s = sechdrs; s < sechdrs_end; ++s) {
  65. const char *shname = secstrings + s->sh_name;
  66. if (s->sh_size == 0)
  67. continue;
  68. if (!strcmp(".l1.text", shname) ||
  69. (!strcmp(".text", shname) &&
  70. (hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
  71. dest = l1_inst_sram_alloc(s->sh_size);
  72. mod->arch.text_l1 = dest;
  73. if (dest == NULL) {
  74. pr_err("L1 inst memory allocation failed\n",
  75. mod->name);
  76. return -1;
  77. }
  78. dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
  79. } else if (!strcmp(".l1.data", shname) ||
  80. (!strcmp(".data", shname) &&
  81. (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
  82. dest = l1_data_sram_alloc(s->sh_size);
  83. mod->arch.data_a_l1 = dest;
  84. if (dest == NULL) {
  85. pr_err("L1 data memory allocation failed\n",
  86. mod->name);
  87. return -1;
  88. }
  89. memcpy(dest, (void *)s->sh_addr, s->sh_size);
  90. } else if (!strcmp(".l1.bss", shname) ||
  91. (!strcmp(".bss", shname) &&
  92. (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
  93. dest = l1_data_sram_zalloc(s->sh_size);
  94. mod->arch.bss_a_l1 = dest;
  95. if (dest == NULL) {
  96. pr_err("L1 data memory allocation failed\n",
  97. mod->name);
  98. return -1;
  99. }
  100. } else if (!strcmp(".l1.data.B", shname)) {
  101. dest = l1_data_B_sram_alloc(s->sh_size);
  102. mod->arch.data_b_l1 = dest;
  103. if (dest == NULL) {
  104. pr_err("L1 data memory allocation failed\n",
  105. mod->name);
  106. return -1;
  107. }
  108. memcpy(dest, (void *)s->sh_addr, s->sh_size);
  109. } else if (!strcmp(".l1.bss.B", shname)) {
  110. dest = l1_data_B_sram_alloc(s->sh_size);
  111. mod->arch.bss_b_l1 = dest;
  112. if (dest == NULL) {
  113. pr_err("L1 data memory allocation failed\n",
  114. mod->name);
  115. return -1;
  116. }
  117. memset(dest, 0, s->sh_size);
  118. } else if (!strcmp(".l2.text", shname) ||
  119. (!strcmp(".text", shname) &&
  120. (hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
  121. dest = l2_sram_alloc(s->sh_size);
  122. mod->arch.text_l2 = dest;
  123. if (dest == NULL) {
  124. pr_err("L2 SRAM allocation failed\n",
  125. mod->name);
  126. return -1;
  127. }
  128. memcpy(dest, (void *)s->sh_addr, s->sh_size);
  129. } else if (!strcmp(".l2.data", shname) ||
  130. (!strcmp(".data", shname) &&
  131. (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
  132. dest = l2_sram_alloc(s->sh_size);
  133. mod->arch.data_l2 = dest;
  134. if (dest == NULL) {
  135. pr_err("L2 SRAM allocation failed\n",
  136. mod->name);
  137. return -1;
  138. }
  139. memcpy(dest, (void *)s->sh_addr, s->sh_size);
  140. } else if (!strcmp(".l2.bss", shname) ||
  141. (!strcmp(".bss", shname) &&
  142. (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
  143. dest = l2_sram_zalloc(s->sh_size);
  144. mod->arch.bss_l2 = dest;
  145. if (dest == NULL) {
  146. pr_err("L2 SRAM allocation failed\n",
  147. mod->name);
  148. return -1;
  149. }
  150. } else
  151. continue;
  152. s->sh_flags &= ~SHF_ALLOC;
  153. s->sh_addr = (unsigned long)dest;
  154. }
  155. return 0;
  156. }
  157. int
  158. apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
  159. unsigned int symindex, unsigned int relsec, struct module *me)
  160. {
  161. pr_err(".rel unsupported\n", me->name);
  162. return -ENOEXEC;
  163. }
  164. /*************************************************************************/
  165. /* FUNCTION : apply_relocate_add */
  166. /* ABSTRACT : Blackfin specific relocation handling for the loadable */
  167. /* modules. Modules are expected to be .o files. */
  168. /* Arithmetic relocations are handled. */
  169. /* We do not expect LSETUP to be split and hence is not */
  170. /* handled. */
  171. /* R_BFIN_BYTE and R_BFIN_BYTE2 are also not handled as the */
  172. /* gas does not generate it. */
  173. /*************************************************************************/
  174. int
  175. apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
  176. unsigned int symindex, unsigned int relsec,
  177. struct module *mod)
  178. {
  179. unsigned int i;
  180. Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
  181. Elf32_Sym *sym;
  182. unsigned long location, value, size;
  183. pr_debug("applying relocate section %u to %u\n", mod->name,
  184. relsec, sechdrs[relsec].sh_info);
  185. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
  186. /* This is where to make the change */
  187. location = sechdrs[sechdrs[relsec].sh_info].sh_addr +
  188. rel[i].r_offset;
  189. /* This is the symbol it is referring to. Note that all
  190. undefined symbols have been resolved. */
  191. sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
  192. + ELF32_R_SYM(rel[i].r_info);
  193. value = sym->st_value;
  194. value += rel[i].r_addend;
  195. #ifdef CONFIG_SMP
  196. if (location >= COREB_L1_DATA_A_START) {
  197. pr_err("cannot relocate in L1: %u (SMP kernel)",
  198. mod->name, ELF32_R_TYPE(rel[i].r_info));
  199. return -ENOEXEC;
  200. }
  201. #endif
  202. pr_debug("location is %lx, value is %lx type is %d\n",
  203. mod->name, location, value, ELF32_R_TYPE(rel[i].r_info));
  204. switch (ELF32_R_TYPE(rel[i].r_info)) {
  205. case R_BFIN_HUIMM16:
  206. value >>= 16;
  207. case R_BFIN_LUIMM16:
  208. case R_BFIN_RIMM16:
  209. size = 2;
  210. break;
  211. case R_BFIN_BYTE4_DATA:
  212. size = 4;
  213. break;
  214. case R_BFIN_PCREL24:
  215. case R_BFIN_PCREL24_JUMP_L:
  216. case R_BFIN_PCREL12_JUMP:
  217. case R_BFIN_PCREL12_JUMP_S:
  218. case R_BFIN_PCREL10:
  219. pr_err("unsupported relocation: %u (no -mlong-calls?)\n",
  220. mod->name, ELF32_R_TYPE(rel[i].r_info));
  221. return -ENOEXEC;
  222. default:
  223. pr_err("unknown relocation: %u\n", mod->name,
  224. ELF32_R_TYPE(rel[i].r_info));
  225. return -ENOEXEC;
  226. }
  227. switch (bfin_mem_access_type(location, size)) {
  228. case BFIN_MEM_ACCESS_CORE:
  229. case BFIN_MEM_ACCESS_CORE_ONLY:
  230. memcpy((void *)location, &value, size);
  231. break;
  232. case BFIN_MEM_ACCESS_DMA:
  233. dma_memcpy((void *)location, &value, size);
  234. break;
  235. case BFIN_MEM_ACCESS_ITEST:
  236. isram_memcpy((void *)location, &value, size);
  237. break;
  238. default:
  239. pr_err("invalid relocation for %#lx\n",
  240. mod->name, location);
  241. return -ENOEXEC;
  242. }
  243. }
  244. return 0;
  245. }
  246. int
  247. module_finalize(const Elf_Ehdr * hdr,
  248. const Elf_Shdr * sechdrs, struct module *mod)
  249. {
  250. unsigned int i, strindex = 0, symindex = 0;
  251. char *secstrings;
  252. long err = 0;
  253. secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
  254. for (i = 1; i < hdr->e_shnum; i++) {
  255. /* Internal symbols and strings. */
  256. if (sechdrs[i].sh_type == SHT_SYMTAB) {
  257. symindex = i;
  258. strindex = sechdrs[i].sh_link;
  259. }
  260. }
  261. for (i = 1; i < hdr->e_shnum; i++) {
  262. const char *strtab = (char *)sechdrs[strindex].sh_addr;
  263. unsigned int info = sechdrs[i].sh_info;
  264. const char *shname = secstrings + sechdrs[i].sh_name;
  265. /* Not a valid relocation section? */
  266. if (info >= hdr->e_shnum)
  267. continue;
  268. /* Only support RELA relocation types */
  269. if (sechdrs[i].sh_type != SHT_RELA)
  270. continue;
  271. if (!strcmp(".rela.l2.text", shname) ||
  272. !strcmp(".rela.l1.text", shname) ||
  273. (!strcmp(".rela.text", shname) &&
  274. (hdr->e_flags & (EF_BFIN_CODE_IN_L1 | EF_BFIN_CODE_IN_L2)))) {
  275. err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
  276. symindex, i, mod);
  277. if (err < 0)
  278. return -ENOEXEC;
  279. }
  280. }
  281. return 0;
  282. }
  283. void module_arch_cleanup(struct module *mod)
  284. {
  285. l1_inst_sram_free(mod->arch.text_l1);
  286. l1_data_A_sram_free(mod->arch.data_a_l1);
  287. l1_data_A_sram_free(mod->arch.bss_a_l1);
  288. l1_data_B_sram_free(mod->arch.data_b_l1);
  289. l1_data_B_sram_free(mod->arch.bss_b_l1);
  290. l2_sram_free(mod->arch.text_l2);
  291. l2_sram_free(mod->arch.data_l2);
  292. l2_sram_free(mod->arch.bss_l2);
  293. }