ia64: allocate percpu area for cpu0 like percpu areas for other cpus
[linux-2.6.git] / arch / m68k / kernel / module.c
1 /*
2  * This file is subject to the terms and conditions of the GNU General Public
3  * License.  See the file COPYING in the main directory of this archive
4  * for more details.
5  */
6
7 #include <linux/moduleloader.h>
8 #include <linux/elf.h>
9 #include <linux/vmalloc.h>
10 #include <linux/fs.h>
11 #include <linux/string.h>
12 #include <linux/kernel.h>
13
14 #if 0
15 #define DEBUGP printk
16 #else
17 #define DEBUGP(fmt...)
18 #endif
19
20 #ifdef CONFIG_MODULES
21
22 void *module_alloc(unsigned long size)
23 {
24         if (size == 0)
25                 return NULL;
26         return vmalloc(size);
27 }
28
29
30 /* Free memory returned from module_alloc */
31 void module_free(struct module *mod, void *module_region)
32 {
33         vfree(module_region);
34 }
35
36 /* We don't need anything special. */
37 int module_frob_arch_sections(Elf_Ehdr *hdr,
38                               Elf_Shdr *sechdrs,
39                               char *secstrings,
40                               struct module *mod)
41 {
42         return 0;
43 }
44
45 int apply_relocate(Elf32_Shdr *sechdrs,
46                    const char *strtab,
47                    unsigned int symindex,
48                    unsigned int relsec,
49                    struct module *me)
50 {
51         unsigned int i;
52         Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
53         Elf32_Sym *sym;
54         uint32_t *location;
55
56         DEBUGP("Applying relocate section %u to %u\n", relsec,
57                sechdrs[relsec].sh_info);
58         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
59                 /* This is where to make the change */
60                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
61                         + rel[i].r_offset;
62                 /* This is the symbol it is referring to.  Note that all
63                    undefined symbols have been resolved.  */
64                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
65                         + ELF32_R_SYM(rel[i].r_info);
66
67                 switch (ELF32_R_TYPE(rel[i].r_info)) {
68                 case R_68K_32:
69                         /* We add the value into the location given */
70                         *location += sym->st_value;
71                         break;
72                 case R_68K_PC32:
73                         /* Add the value, subtract its postition */
74                         *location += sym->st_value - (uint32_t)location;
75                         break;
76                 default:
77                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
78                                me->name, ELF32_R_TYPE(rel[i].r_info));
79                         return -ENOEXEC;
80                 }
81         }
82         return 0;
83 }
84
85 int apply_relocate_add(Elf32_Shdr *sechdrs,
86                        const char *strtab,
87                        unsigned int symindex,
88                        unsigned int relsec,
89                        struct module *me)
90 {
91         unsigned int i;
92         Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
93         Elf32_Sym *sym;
94         uint32_t *location;
95
96         DEBUGP("Applying relocate_add section %u to %u\n", relsec,
97                sechdrs[relsec].sh_info);
98         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
99                 /* This is where to make the change */
100                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
101                         + rel[i].r_offset;
102                 /* This is the symbol it is referring to.  Note that all
103                    undefined symbols have been resolved.  */
104                 sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
105                         + ELF32_R_SYM(rel[i].r_info);
106
107                 switch (ELF32_R_TYPE(rel[i].r_info)) {
108                 case R_68K_32:
109                         /* We add the value into the location given */
110                         *location = rel[i].r_addend + sym->st_value;
111                         break;
112                 case R_68K_PC32:
113                         /* Add the value, subtract its postition */
114                         *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
115                         break;
116                 default:
117                         printk(KERN_ERR "module %s: Unknown relocation: %u\n",
118                                me->name, ELF32_R_TYPE(rel[i].r_info));
119                         return -ENOEXEC;
120                 }
121         }
122         return 0;
123 }
124
125 int module_finalize(const Elf_Ehdr *hdr,
126                     const Elf_Shdr *sechdrs,
127                     struct module *mod)
128 {
129         module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
130
131         return 0;
132 }
133
134 void module_arch_cleanup(struct module *mod)
135 {
136 }
137
138 #endif /* CONFIG_MODULES */
139
140 void module_fixup(struct module *mod, struct m68k_fixup_info *start,
141                   struct m68k_fixup_info *end)
142 {
143         struct m68k_fixup_info *fixup;
144
145         for (fixup = start; fixup < end; fixup++) {
146                 switch (fixup->type) {
147                 case m68k_fixup_memoffset:
148                         *(u32 *)fixup->addr = m68k_memoffset;
149                         break;
150                 case m68k_fixup_vnode_shift:
151                         *(u16 *)fixup->addr += m68k_virt_to_node_shift;
152                         break;
153                 }
154         }
155 }