diff options
author | Vineet Gupta <vgupta@synopsys.com> | 2013-01-29 08:58:05 -0500 |
---|---|---|
committer | Vineet Gupta <vgupta@synopsys.com> | 2013-02-15 12:46:01 -0500 |
commit | fa1c3ff935179453801d763940c38c3ac2d581eb (patch) | |
tree | c1dc9ee709d952921f85d4766441167927549892 /arch/arc | |
parent | 4788a5942bc896803c87005be8c6dd14c373a2d3 (diff) |
ARC: Module support
Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Diffstat (limited to 'arch/arc')
-rw-r--r-- | arch/arc/include/asm/module.h | 4 | ||||
-rw-r--r-- | arch/arc/kernel/Makefile | 2 | ||||
-rw-r--r-- | arch/arc/kernel/module.c | 87 |
3 files changed, 93 insertions, 0 deletions
diff --git a/arch/arc/include/asm/module.h b/arch/arc/include/asm/module.h index 165d768d00cf..234b4354e2b3 100644 --- a/arch/arc/include/asm/module.h +++ b/arch/arc/include/asm/module.h | |||
@@ -14,4 +14,8 @@ | |||
14 | 14 | ||
15 | #include <asm-generic/module.h> | 15 | #include <asm-generic/module.h> |
16 | 16 | ||
17 | #define MODULE_PROC_FAMILY "ARC700" | ||
18 | |||
19 | #define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY | ||
20 | |||
17 | #endif /* _ASM_ARC_MODULE_H */ | 21 | #endif /* _ASM_ARC_MODULE_H */ |
diff --git a/arch/arc/kernel/Makefile b/arch/arc/kernel/Makefile index f4885891dabb..f32f65f98850 100644 --- a/arch/arc/kernel/Makefile +++ b/arch/arc/kernel/Makefile | |||
@@ -12,6 +12,8 @@ obj-y := arcksyms.o setup.o irq.o time.o reset.o ptrace.o entry.o process.o | |||
12 | obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o | 12 | obj-y += signal.o traps.o sys.o troubleshoot.o stacktrace.o clk.o |
13 | obj-y += devtree.o | 13 | obj-y += devtree.o |
14 | 14 | ||
15 | obj-$(CONFIG_MODULES) += arcksyms.o module.o | ||
16 | |||
15 | obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o | 17 | obj-$(CONFIG_ARC_FPU_SAVE_RESTORE) += fpu.o |
16 | CFLAGS_fpu.o += -mdpfp | 18 | CFLAGS_fpu.o += -mdpfp |
17 | 19 | ||
diff --git a/arch/arc/kernel/module.c b/arch/arc/kernel/module.c new file mode 100644 index 000000000000..a1bb70d6e97d --- /dev/null +++ b/arch/arc/kernel/module.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com) | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/moduleloader.h> | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/elf.h> | ||
13 | #include <linux/vmalloc.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/string.h> | ||
17 | |||
18 | static inline void arc_write_me(unsigned short *addr, unsigned long value) | ||
19 | { | ||
20 | *addr = (value & 0xffff0000) >> 16; | ||
21 | *(addr + 1) = (value & 0xffff); | ||
22 | } | ||
23 | |||
24 | int apply_relocate_add(Elf32_Shdr *sechdrs, | ||
25 | const char *strtab, | ||
26 | unsigned int symindex, /* sec index for sym tbl */ | ||
27 | unsigned int relsec, /* sec index for relo sec */ | ||
28 | struct module *module) | ||
29 | { | ||
30 | int i, n; | ||
31 | Elf32_Rela *rel_entry = (void *)sechdrs[relsec].sh_addr; | ||
32 | Elf32_Sym *sym_entry, *sym_sec; | ||
33 | Elf32_Addr relocation; | ||
34 | Elf32_Addr location; | ||
35 | Elf32_Addr sec_to_patch; | ||
36 | int relo_type; | ||
37 | |||
38 | sec_to_patch = sechdrs[sechdrs[relsec].sh_info].sh_addr; | ||
39 | sym_sec = (Elf32_Sym *) sechdrs[symindex].sh_addr; | ||
40 | n = sechdrs[relsec].sh_size / sizeof(*rel_entry); | ||
41 | |||
42 | pr_debug("\n========== Module Sym reloc ===========================\n"); | ||
43 | pr_debug("Section to fixup %x\n", sec_to_patch); | ||
44 | pr_debug("=========================================================\n"); | ||
45 | pr_debug("rela->r_off | rela->addend | sym->st_value | ADDR | VALUE\n"); | ||
46 | pr_debug("=========================================================\n"); | ||
47 | |||
48 | /* Loop thru entries in relocation section */ | ||
49 | for (i = 0; i < n; i++) { | ||
50 | |||
51 | /* This is where to make the change */ | ||
52 | location = sec_to_patch + rel_entry[i].r_offset; | ||
53 | |||
54 | /* This is the symbol it is referring to. Note that all | ||
55 | undefined symbols have been resolved. */ | ||
56 | sym_entry = sym_sec + ELF32_R_SYM(rel_entry[i].r_info); | ||
57 | |||
58 | relocation = sym_entry->st_value + rel_entry[i].r_addend; | ||
59 | |||
60 | pr_debug("\t%x\t\t%x\t\t%x %x %x [%s]\n", | ||
61 | rel_entry[i].r_offset, rel_entry[i].r_addend, | ||
62 | sym_entry->st_value, location, relocation, | ||
63 | strtab + sym_entry->st_name); | ||
64 | |||
65 | /* This assumes modules are built with -mlong-calls | ||
66 | * so any branches/jumps are absolute 32 bit jmps | ||
67 | * global data access again is abs 32 bit. | ||
68 | * Both of these are handled by same relocation type | ||
69 | */ | ||
70 | relo_type = ELF32_R_TYPE(rel_entry[i].r_info); | ||
71 | |||
72 | if (likely(R_ARC_32_ME == relo_type)) | ||
73 | arc_write_me((unsigned short *)location, relocation); | ||
74 | else if (R_ARC_32 == relo_type) | ||
75 | *((Elf32_Addr *) location) = relocation; | ||
76 | else | ||
77 | goto relo_err; | ||
78 | |||
79 | } | ||
80 | return 0; | ||
81 | |||
82 | relo_err: | ||
83 | pr_err("%s: unknown relocation: %u\n", | ||
84 | module->name, ELF32_R_TYPE(rel_entry[i].r_info)); | ||
85 | return -ENOEXEC; | ||
86 | |||
87 | } | ||