aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel/module.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-01-07 15:00:25 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-07 15:00:25 -0500
commit5bb47b9ff3d16d40f8d45380b373497a545fa280 (patch)
treee13dd34395473342dc75eff5cbaf5b1ea753631c /arch/blackfin/kernel/module.c
parent2f2408a88cf8fa43febfd7fb5783e61b2937b0f9 (diff)
parent06af15e086e39a5a2a2413973a64af8e10122f28 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/cooloney/blackfin-2.6: (171 commits) Blackfin arch: fix bug - BF527 0.2 silicon has different CPUID (DSPID) value Blackfin arch: Enlarge flash partition for kenel for bf533/bf537 boards Blackfin arch: fix bug: kernel crash when enable SDIO host driver Blackfin arch: Print FP at level KERN_NOTICE Blackfin arch: drop ad73311 test code Blackfin arch: update board default configs Blackfin arch: Set PB4 as the default irq for bf548 board v1.4+. Blackfin arch: fix typo in early printk bit size processing Blackfin arch: enable reprogram cclk and sclk for bf518f-ezbrd Blackfin arch: add SDIO host driver platform data Blackfin arch: fix bug - kernel stops at initial console Blackfin arch: fix bug - kernel crash after config IP for ethernet port Blackfin arch: add sdh support for bf518f-ezbrd Blackfin arch: fix bug - kernel detects BF532 incorrectly Blackfin arch: add () to avoid warnings from gcc Blackfin arch: change HWTRACE Kconfig and set it on default Blackfin arch: Clean oprofile build path for blackfin Blackfin arch: remove hardware PM code, oprofile not use it Blackfin arch: rewrite get_sclk()/get_vco() Blackfin arch: cleanup and unify the ins functions ...
Diffstat (limited to 'arch/blackfin/kernel/module.c')
-rw-r--r--arch/blackfin/kernel/module.c152
1 files changed, 18 insertions, 134 deletions
diff --git a/arch/blackfin/kernel/module.c b/arch/blackfin/kernel/module.c
index e1bebc80a5bf..1bd7f2d018a8 100644
--- a/arch/blackfin/kernel/module.c
+++ b/arch/blackfin/kernel/module.c
@@ -37,111 +37,6 @@
37#include <asm/dma.h> 37#include <asm/dma.h>
38#include <asm/cacheflush.h> 38#include <asm/cacheflush.h>
39 39
40/*
41 * handle arithmetic relocations.
42 * See binutils/bfd/elf32-bfin.c for more details
43 */
44#define RELOC_STACK_SIZE 100
45static uint32_t reloc_stack[RELOC_STACK_SIZE];
46static unsigned int reloc_stack_tos;
47
48#define is_reloc_stack_empty() ((reloc_stack_tos > 0)?0:1)
49
50static void reloc_stack_push(uint32_t value)
51{
52 reloc_stack[reloc_stack_tos++] = value;
53}
54
55static uint32_t reloc_stack_pop(void)
56{
57 return reloc_stack[--reloc_stack_tos];
58}
59
60static uint32_t reloc_stack_operate(unsigned int oper, struct module *mod)
61{
62 uint32_t value;
63
64 switch (oper) {
65 case R_add:
66 value = reloc_stack[reloc_stack_tos - 2] +
67 reloc_stack[reloc_stack_tos - 1];
68 reloc_stack_tos -= 2;
69 break;
70 case R_sub:
71 value = reloc_stack[reloc_stack_tos - 2] -
72 reloc_stack[reloc_stack_tos - 1];
73 reloc_stack_tos -= 2;
74 break;
75 case R_mult:
76 value = reloc_stack[reloc_stack_tos - 2] *
77 reloc_stack[reloc_stack_tos - 1];
78 reloc_stack_tos -= 2;
79 break;
80 case R_div:
81 value = reloc_stack[reloc_stack_tos - 2] /
82 reloc_stack[reloc_stack_tos - 1];
83 reloc_stack_tos -= 2;
84 break;
85 case R_mod:
86 value = reloc_stack[reloc_stack_tos - 2] %
87 reloc_stack[reloc_stack_tos - 1];
88 reloc_stack_tos -= 2;
89 break;
90 case R_lshift:
91 value = reloc_stack[reloc_stack_tos - 2] <<
92 reloc_stack[reloc_stack_tos - 1];
93 reloc_stack_tos -= 2;
94 break;
95 case R_rshift:
96 value = reloc_stack[reloc_stack_tos - 2] >>
97 reloc_stack[reloc_stack_tos - 1];
98 reloc_stack_tos -= 2;
99 break;
100 case R_and:
101 value = reloc_stack[reloc_stack_tos - 2] &
102 reloc_stack[reloc_stack_tos - 1];
103 reloc_stack_tos -= 2;
104 break;
105 case R_or:
106 value = reloc_stack[reloc_stack_tos - 2] |
107 reloc_stack[reloc_stack_tos - 1];
108 reloc_stack_tos -= 2;
109 break;
110 case R_xor:
111 value = reloc_stack[reloc_stack_tos - 2] ^
112 reloc_stack[reloc_stack_tos - 1];
113 reloc_stack_tos -= 2;
114 break;
115 case R_land:
116 value = reloc_stack[reloc_stack_tos - 2] &&
117 reloc_stack[reloc_stack_tos - 1];
118 reloc_stack_tos -= 2;
119 break;
120 case R_lor:
121 value = reloc_stack[reloc_stack_tos - 2] ||
122 reloc_stack[reloc_stack_tos - 1];
123 reloc_stack_tos -= 2;
124 break;
125 case R_neg:
126 value = -reloc_stack[reloc_stack_tos - 1];
127 reloc_stack_tos--;
128 break;
129 case R_comp:
130 value = ~reloc_stack[reloc_stack_tos - 1];
131 reloc_stack_tos -= 1;
132 break;
133 default:
134 printk(KERN_WARNING "module %s: unhandled reloction\n",
135 mod->name);
136 return 0;
137 }
138
139 /* now push the new value back on stack */
140 reloc_stack_push(value);
141
142 return value;
143}
144
145void *module_alloc(unsigned long size) 40void *module_alloc(unsigned long size)
146{ 41{
147 if (size == 0) 42 if (size == 0)
@@ -334,16 +229,18 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
334 undefined symbols have been resolved. */ 229 undefined symbols have been resolved. */
335 sym = (Elf32_Sym *) sechdrs[symindex].sh_addr 230 sym = (Elf32_Sym *) sechdrs[symindex].sh_addr
336 + ELF32_R_SYM(rel[i].r_info); 231 + ELF32_R_SYM(rel[i].r_info);
337 if (is_reloc_stack_empty()) { 232 value = sym->st_value;
338 value = sym->st_value;
339 } else {
340 value = reloc_stack_pop();
341 }
342 value += rel[i].r_addend; 233 value += rel[i].r_addend;
343 pr_debug("location is %x, value is %x type is %d \n", 234 pr_debug("location is %x, value is %x type is %d \n",
344 (unsigned int) location32, value, 235 (unsigned int) location32, value,
345 ELF32_R_TYPE(rel[i].r_info)); 236 ELF32_R_TYPE(rel[i].r_info));
346 237#ifdef CONFIG_SMP
238 if ((unsigned long)location16 >= COREB_L1_DATA_A_START) {
239 printk(KERN_ERR "module %s: cannot relocate in L1: %u (SMP kernel)",
240 mod->name, ELF32_R_TYPE(rel[i].r_info));
241 return -ENOEXEC;
242 }
243#endif
347 switch (ELF32_R_TYPE(rel[i].r_info)) { 244 switch (ELF32_R_TYPE(rel[i].r_info)) {
348 245
349 case R_pcrel24: 246 case R_pcrel24:
@@ -355,6 +252,12 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
355 location32 = (uint32_t *) location16; 252 location32 = (uint32_t *) location16;
356 value -= (uint32_t) location32; 253 value -= (uint32_t) location32;
357 value >>= 1; 254 value >>= 1;
255 if ((value & 0xFF000000) != 0 &&
256 (value & 0xFF000000) != 0xFF000000) {
257 printk(KERN_ERR "module %s: relocation overflow\n",
258 mod->name);
259 return -ENOEXEC;
260 }
358 pr_debug("value is %x, before %x-%x after %x-%x\n", value, 261 pr_debug("value is %x, before %x-%x after %x-%x\n", value,
359 *location16, *(location16 + 1), 262 *location16, *(location16 + 1),
360 (*location16 & 0xff00) | (value >> 16 & 0x00ff), 263 (*location16 & 0xff00) | (value >> 16 & 0x00ff),
@@ -399,28 +302,6 @@ apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab,
399 pr_debug("before %x after %x\n", *location32, value); 302 pr_debug("before %x after %x\n", *location32, value);
400 *location32 = value; 303 *location32 = value;
401 break; 304 break;
402 case R_push:
403 reloc_stack_push(value);
404 break;
405 case R_const:
406 reloc_stack_push(rel[i].r_addend);
407 break;
408 case R_add:
409 case R_sub:
410 case R_mult:
411 case R_div:
412 case R_mod:
413 case R_lshift:
414 case R_rshift:
415 case R_and:
416 case R_or:
417 case R_xor:
418 case R_land:
419 case R_lor:
420 case R_neg:
421 case R_comp:
422 reloc_stack_operate(ELF32_R_TYPE(rel[i].r_info), mod);
423 break;
424 default: 305 default:
425 printk(KERN_ERR "module %s: Unknown relocation: %u\n", 306 printk(KERN_ERR "module %s: Unknown relocation: %u\n",
426 mod->name, ELF32_R_TYPE(rel[i].r_info)); 307 mod->name, ELF32_R_TYPE(rel[i].r_info));
@@ -436,6 +317,7 @@ module_finalize(const Elf_Ehdr * hdr,
436{ 317{
437 unsigned int i, strindex = 0, symindex = 0; 318 unsigned int i, strindex = 0, symindex = 0;
438 char *secstrings; 319 char *secstrings;
320 long err = 0;
439 321
440 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset; 322 secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
441 323
@@ -460,8 +342,10 @@ module_finalize(const Elf_Ehdr * hdr,
460 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) || 342 (strcmp(".rela.l1.text", secstrings + sechdrs[i].sh_name) == 0) ||
461 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) && 343 ((strcmp(".rela.text", secstrings + sechdrs[i].sh_name) == 0) &&
462 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) { 344 (hdr->e_flags & (EF_BFIN_CODE_IN_L1|EF_BFIN_CODE_IN_L2))))) {
463 apply_relocate_add((Elf_Shdr *) sechdrs, strtab, 345 err = apply_relocate_add((Elf_Shdr *) sechdrs, strtab,
464 symindex, i, mod); 346 symindex, i, mod);
347 if (err < 0)
348 return -ENOEXEC;
465 } 349 }
466 } 350 }
467 return 0; 351 return 0;