diff options
-rw-r--r-- | arch/blackfin/kernel/module.c | 62 |
1 files changed, 34 insertions, 28 deletions
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c index 2ad805e67afc..67fc7a56c865 100644 --- a/arch/blackfin/kernel/module.c +++ b/arch/blackfin/kernel/module.c | |||
@@ -37,6 +37,7 @@ | |||
37 | #include <linux/kernel.h> | 37 | #include <linux/kernel.h> |
38 | #include <asm/dma.h> | 38 | #include <asm/dma.h> |
39 | #include <asm/cacheflush.h> | 39 | #include <asm/cacheflush.h> |
40 | #include <asm/uaccess.h> | ||
40 | 41 | ||
41 | void *module_alloc(unsigned long size) | 42 | void *module_alloc(unsigned long size) |
42 | { | 43 | { |
@@ -199,26 +200,23 @@ apply_relocate(Elf_Shdr * sechdrs, const char *strtab, | |||
199 | /* gas does not generate it. */ | 200 | /* gas does not generate it. */ |
200 | /*************************************************************************/ | 201 | /*************************************************************************/ |
201 | int | 202 | int |
202 | apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | 203 | apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab, |
203 | unsigned int symindex, unsigned int relsec, | 204 | unsigned int symindex, unsigned int relsec, |
204 | struct module *mod) | 205 | struct module *mod) |
205 | { | 206 | { |
206 | unsigned int i; | 207 | unsigned int i; |
207 | unsigned short tmp; | ||
208 | Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; | 208 | Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr; |
209 | Elf32_Sym *sym; | 209 | Elf32_Sym *sym; |
210 | uint32_t *location32; | 210 | unsigned long location, value, size; |
211 | uint16_t *location16; | ||
212 | uint32_t value; | ||
213 | 211 | ||
214 | pr_debug("applying relocate section %u to %u\n", mod->name, | 212 | pr_debug("applying relocate section %u to %u\n", mod->name, |
215 | relsec, sechdrs[relsec].sh_info); | 213 | relsec, sechdrs[relsec].sh_info); |
214 | |||
216 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { | 215 | for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) { |
217 | /* This is where to make the change */ | 216 | /* This is where to make the change */ |
218 | location16 = | 217 | location = sechdrs[sechdrs[relsec].sh_info].sh_addr + |
219 | (uint16_t *) (sechdrs[sechdrs[relsec].sh_info].sh_addr + | 218 | rel[i].r_offset; |
220 | rel[i].r_offset); | 219 | |
221 | location32 = (uint32_t *) location16; | ||
222 | /* This is the symbol it is referring to. Note that all | 220 | /* This is the symbol it is referring to. Note that all |
223 | undefined symbols have been resolved. */ | 221 | undefined symbols have been resolved. */ |
224 | sym = (Elf32_Sym *) sechdrs[symindex].sh_addr | 222 | sym = (Elf32_Sym *) sechdrs[symindex].sh_addr |
@@ -227,39 +225,28 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
227 | value += rel[i].r_addend; | 225 | value += rel[i].r_addend; |
228 | 226 | ||
229 | #ifdef CONFIG_SMP | 227 | #ifdef CONFIG_SMP |
230 | if ((unsigned long)location16 >= COREB_L1_DATA_A_START) { | 228 | if (location >= COREB_L1_DATA_A_START) { |
231 | pr_err("cannot relocate in L1: %u (SMP kernel)", | 229 | pr_err("cannot relocate in L1: %u (SMP kernel)", |
232 | mod->name, ELF32_R_TYPE(rel[i].r_info)); | 230 | mod->name, ELF32_R_TYPE(rel[i].r_info)); |
233 | return -ENOEXEC; | 231 | return -ENOEXEC; |
234 | } | 232 | } |
235 | #endif | 233 | #endif |
236 | 234 | ||
237 | pr_debug("location is %lx, value is %x type is %d\n", | 235 | pr_debug("location is %lx, value is %lx type is %d\n", |
238 | mod->name, (unsigned long)location32, value, | 236 | mod->name, location, value, ELF32_R_TYPE(rel[i].r_info)); |
239 | ELF32_R_TYPE(rel[i].r_info)); | ||
240 | 237 | ||
241 | switch (ELF32_R_TYPE(rel[i].r_info)) { | 238 | switch (ELF32_R_TYPE(rel[i].r_info)) { |
242 | 239 | ||
243 | case R_BFIN_LUIMM16: | ||
244 | tmp = (value & 0xffff); | ||
245 | if ((unsigned long)location16 >= L1_CODE_START) { | ||
246 | dma_memcpy(location16, &tmp, 2); | ||
247 | } else | ||
248 | *location16 = tmp; | ||
249 | break; | ||
250 | case R_BFIN_HUIMM16: | 240 | case R_BFIN_HUIMM16: |
251 | tmp = ((value >> 16) & 0xffff); | 241 | value >>= 16; |
252 | if ((unsigned long)location16 >= L1_CODE_START) { | 242 | case R_BFIN_LUIMM16: |
253 | dma_memcpy(location16, &tmp, 2); | ||
254 | } else | ||
255 | *location16 = tmp; | ||
256 | break; | ||
257 | case R_BFIN_RIMM16: | 243 | case R_BFIN_RIMM16: |
258 | *location16 = (value & 0xffff); | 244 | size = 2; |
259 | break; | 245 | break; |
260 | case R_BFIN_BYTE4_DATA: | 246 | case R_BFIN_BYTE4_DATA: |
261 | *location32 = value; | 247 | size = 4; |
262 | break; | 248 | break; |
249 | |||
263 | case R_BFIN_PCREL24: | 250 | case R_BFIN_PCREL24: |
264 | case R_BFIN_PCREL24_JUMP_L: | 251 | case R_BFIN_PCREL24_JUMP_L: |
265 | case R_BFIN_PCREL12_JUMP: | 252 | case R_BFIN_PCREL12_JUMP: |
@@ -268,12 +255,31 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, | |||
268 | pr_err("unsupported relocation: %u (no -mlong-calls?)\n", | 255 | pr_err("unsupported relocation: %u (no -mlong-calls?)\n", |
269 | mod->name, ELF32_R_TYPE(rel[i].r_info)); | 256 | mod->name, ELF32_R_TYPE(rel[i].r_info)); |
270 | return -ENOEXEC; | 257 | return -ENOEXEC; |
258 | |||
271 | default: | 259 | default: |
272 | pr_err("unknown relocation: %u\n", mod->name, | 260 | pr_err("unknown relocation: %u\n", mod->name, |
273 | ELF32_R_TYPE(rel[i].r_info)); | 261 | ELF32_R_TYPE(rel[i].r_info)); |
274 | return -ENOEXEC; | 262 | return -ENOEXEC; |
275 | } | 263 | } |
264 | |||
265 | switch (bfin_mem_access_type(location, size)) { | ||
266 | case BFIN_MEM_ACCESS_CORE: | ||
267 | case BFIN_MEM_ACCESS_CORE_ONLY: | ||
268 | memcpy((void *)location, &value, size); | ||
269 | break; | ||
270 | case BFIN_MEM_ACCESS_DMA: | ||
271 | dma_memcpy((void *)location, &value, size); | ||
272 | break; | ||
273 | case BFIN_MEM_ACCESS_ITEST: | ||
274 | isram_memcpy((void *)location, &value, size); | ||
275 | break; | ||
276 | default: | ||
277 | pr_err("invalid relocation for %#lx\n", | ||
278 | mod->name, location); | ||
279 | return -ENOEXEC; | ||
280 | } | ||
276 | } | 281 | } |
282 | |||
277 | return 0; | 283 | return 0; |
278 | } | 284 | } |
279 | 285 | ||