aboutsummaryrefslogtreecommitdiffstats
path: root/arch/blackfin/kernel
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2009-06-25 20:49:51 -0400
committerMike Frysinger <vapier@gentoo.org>2009-09-16 21:28:52 -0400
commita769094061289453e8c331d7746e0e26f5d1e38b (patch)
tree21275817e750549e594ef026be3c1c0711585cb6 /arch/blackfin/kernel
parent459fec9073bca854badc1a719f7c12f5162d0edd (diff)
Blackfin: fix module reloc handling for all memory regions
The current module relocation code has spotty handling wrt different memory regions (like L1 instruction). Rather than try to fix each little spot, use the new common memory functions to greatly simplify everything and make sure it is always correct. Signed-off-by: Mike Frysinger <vapier@gentoo.org>
Diffstat (limited to 'arch/blackfin/kernel')
-rw-r--r--arch/blackfin/kernel/module.c62
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
41void *module_alloc(unsigned long size) 42void *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/*************************************************************************/
201int 202int
202apply_relocate_add(Elf_Shdr * sechdrs, const char *strtab, 203apply_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