~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/arch/blackfin/kernel/module.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

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

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp