Merge branch 'akpm'
[linux-2.6/next.git] / arch / blackfin / kernel / module.c
blob4489efc528837f9bf6fd3e7bbb4ae94743906b09
1 /*
2 * Copyright 2004-2009 Analog Devices Inc.
4 * Licensed under the GPL-2 or later
5 */
7 #define pr_fmt(fmt) "module %s: " fmt, mod->name
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>
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)
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.
31 Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
32 void *dest;
34 for (s = sechdrs; s < sechdrs_end; ++s) {
35 const char *shname = secstrings + s->sh_name;
37 if (s->sh_size == 0)
38 continue;
40 if (!strcmp(".l1.text", shname) ||
41 (!strcmp(".text", shname) &&
42 (hdr->e_flags & EF_BFIN_CODE_IN_L1))) {
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;
50 dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
52 } else if (!strcmp(".l1.data", shname) ||
53 (!strcmp(".data", shname) &&
54 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
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;
62 memcpy(dest, (void *)s->sh_addr, s->sh_size);
64 } else if (!strcmp(".l1.bss", shname) ||
65 (!strcmp(".bss", shname) &&
66 (hdr->e_flags & EF_BFIN_DATA_IN_L1))) {
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;
75 } else if (!strcmp(".l1.data.B", shname)) {
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;
83 memcpy(dest, (void *)s->sh_addr, s->sh_size);
85 } else if (!strcmp(".l1.bss.B", shname)) {
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;
93 memset(dest, 0, s->sh_size);
95 } else if (!strcmp(".l2.text", shname) ||
96 (!strcmp(".text", shname) &&
97 (hdr->e_flags & EF_BFIN_CODE_IN_L2))) {
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;
105 memcpy(dest, (void *)s->sh_addr, s->sh_size);
107 } else if (!strcmp(".l2.data", shname) ||
108 (!strcmp(".data", shname) &&
109 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
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;
117 memcpy(dest, (void *)s->sh_addr, s->sh_size);
119 } else if (!strcmp(".l2.bss", shname) ||
120 (!strcmp(".bss", shname) &&
121 (hdr->e_flags & EF_BFIN_DATA_IN_L2))) {
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;
130 } else
131 continue;
133 s->sh_flags &= ~SHF_ALLOC;
134 s->sh_addr = (unsigned long)dest;
137 return 0;
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 /*************************************************************************/
151 apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
152 unsigned int symindex, unsigned int relsec,
153 struct module *mod)
155 unsigned int i;
156 Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
157 Elf32_Sym *sym;
158 unsigned long location, value, size;
160 pr_debug("applying relocate section %u to %u\n",
161 relsec, sechdrs[relsec].sh_info);
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;
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;
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;
181 #endif
183 pr_debug("location is %lx, value is %lx type is %d\n",
184 location, value, ELF32_R_TYPE(rel[i].r_info));
186 switch (ELF32_R_TYPE(rel[i].r_info)) {
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;
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;
207 default:
208 pr_err("unknown relocation: %u\n",
209 ELF32_R_TYPE(rel[i].r_info));
210 return -ENOEXEC;
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;
230 return 0;
234 module_finalize(const Elf_Ehdr * hdr,
235 const Elf_Shdr * sechdrs, struct module *mod)
237 unsigned int i, strindex = 0, symindex = 0;
238 char *secstrings;
239 long err = 0;
241 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
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;
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;
256 /* Not a valid relocation section? */
257 if (info >= hdr->e_shnum)
258 continue;
260 /* Only support RELA relocation types */
261 if (sechdrs[i].sh_type != SHT_RELA)
262 continue;
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)))) {
269 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
270 symindex, i, mod);
271 if (err < 0)
272 return -ENOEXEC;
276 return 0;
279 void module_arch_cleanup(struct module *mod)
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);