root/src/linux/adm5120/linux-2.6.23/arch/mips/kernel/module.c

Revision 12415, 15.3 kB (checked in by BrainSlayer, 5 months ago)

latest adm5120 update incl. remap patch

Line 
1 /*
2  *  This program is free software; you can redistribute it and/or modify
3  *  it under the terms of the GNU General Public License as published by
4  *  the Free Software Foundation; either version 2 of the License, or
5  *  (at your option) any later version.
6  *
7  *  This program is distributed in the hope that it will be useful,
8  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10  *  GNU General Public License for more details.
11  *
12  *  You should have received a copy of the GNU General Public License
13  *  along with this program; if not, write to the Free Software
14  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
15  *
16  *  Copyright (C) 2001 Rusty Russell.
17  *  Copyright (C) 2003, 2004 Ralf Baechle (ralf@linux-mips.org)
18  *  Copyright (C) 2005 Thiemo Seufer
19  */
20
21 #undef DEBUG
22
23 #include <linux/moduleloader.h>
24 #include <linux/elf.h>
25 #include <linux/vmalloc.h>
26 #include <linux/slab.h>
27 #include <linux/fs.h>
28 #include <linux/string.h>
29 #include <linux/kernel.h>
30 #include <linux/module.h>
31 #include <linux/spinlock.h>
32 #include <linux/mm.h>
33 #include <asm/pgtable.h>        /* MODULE_START */
34
35 struct mips_hi16 {
36         struct mips_hi16 *next;
37         Elf_Addr *addr;
38         Elf_Addr value;
39 };
40
41 static struct mips_hi16 *mips_hi16_list;
42
43 static LIST_HEAD(dbe_list);
44 static DEFINE_SPINLOCK(dbe_lock);
45
46 static void *alloc_phys(unsigned long size)
47 {
48         unsigned order;
49         struct page *page;
50         struct page *p;
51
52         size = PAGE_ALIGN(size);
53         order = get_order(size);
54
55         page = alloc_pages(
56                 GFP_KERNEL | __GFP_NORETRY | __GFP_NOWARN | __GFP_THISNODE,
57                 order);
58         if (!page)
59                 return 0;
60
61         split_page(page, order);
62
63         for (p = page + (size >> PAGE_SHIFT); p < page + (1 << order); ++p)
64                 __free_page(p);
65
66         return page_address(page);
67 }
68
69 static void free_phys(void *ptr, unsigned long size)
70 {
71         struct page *page;
72         struct page *end;
73
74         page = virt_to_page(ptr);
75         end = page + (PAGE_ALIGN(size) >> PAGE_SHIFT);
76
77         for (; page < end; ++page)
78                 __free_pages(page, 0);
79 }
80
81 void *module_alloc(unsigned long size)
82 {
83 #ifdef MODULE_START
84         struct vm_struct *area;
85
86         size = PAGE_ALIGN(size);
87         if (!size)
88                 return NULL;
89
90         area = __get_vm_area(size, VM_ALLOC, MODULE_START, MODULE_END);
91         if (!area)
92                 return NULL;
93
94         return __vmalloc_area(area, GFP_KERNEL, PAGE_KERNEL);
95 #else
96         unsigned addr;
97         void *ptr;
98
99         size = PAGE_ALIGN(size);
100         if (size == 0)
101                 return NULL;
102
103         ptr = alloc_phys(size);
104         if (ptr)
105                 return ptr;
106
107         /* try to allocate contiguos chunk of memory not spanning 256Mb
108            range, so all jump instructions can work */
109         addr = VMALLOC_START;
110         while (addr < VMALLOC_END) {
111                 unsigned end = ALIGN(addr + 1, 1u << 28);
112
113                 if (addr + size <= end) {
114                         struct vm_struct *area
115                                 = __get_vm_area(size, VM_ALLOC, addr, end);
116
117                         if (area)
118                                 return __vmalloc_area(
119                                         area, GFP_KERNEL, PAGE_KERNEL);
120                 }
121                 addr = end;
122         }
123         return NULL;
124 #endif
125 }
126
127 static inline int is_phys(void *ptr)
128 {
129         unsigned addr = (unsigned) ptr;
130         return addr && (addr < VMALLOC_START || addr > VMALLOC_END);
131 }
132
133 /* Free memory returned from module_alloc */
134 void module_free(struct module *mod, void *module_region)
135 {
136         if (is_phys(module_region)) {
137                 if (mod->module_init == module_region)
138                         free_phys(module_region, mod->init_size);
139                 else if (mod->module_core == module_region)
140                         free_phys(module_region, mod->core_size);
141                 else
142                     BUG();
143                 return;
144         }
145
146         vfree(module_region);
147         /* FIXME: If module_region == mod->init_region, trim exception
148            table entries. */
149 }
150
151 int module_frob_arch_sections(Elf_Ehdr *hdr, Elf_Shdr *sechdrs,
152                               char *secstrings, struct module *mod)
153 {
154         return 0;
155 }
156
157 /* Get the potential trampolines size required of the init and
158    non-init sections */
159 static unsigned get_plt_size(const Elf32_Ehdr *hdr,
160                              const Elf32_Shdr *sechdrs,
161                              const char *secstrings,
162                              unsigned symindex,
163                              int is_init)
164 {
165         unsigned long ret = 0;
166         unsigned i, j;
167         Elf_Sym *syms;
168
169         /* Everything marked ALLOC (this includes the exported symbols) */
170         for (i = 1; i < hdr->e_shnum; ++i) {
171                 unsigned int info = sechdrs[i].sh_info;
172
173                 if (sechdrs[i].sh_type != SHT_REL
174                     && sechdrs[i].sh_type != SHT_RELA)
175                         continue;
176
177                 /* Not a valid relocation section? */
178                 if (info >= hdr->e_shnum)
179                         continue;
180
181                 /* Don't bother with non-allocated sections */
182                 if (!(sechdrs[info].sh_flags & SHF_ALLOC))
183                         continue;
184
185                 /* If it's called *.init*, and we're not init, we're
186                    not interested */
187                 if ((strstr(secstrings + sechdrs[i].sh_name, ".init") != 0)
188                     != is_init)
189                         continue;
190
191                 syms = (Elf_Sym *) sechdrs[symindex].sh_addr;
192                 if (sechdrs[i].sh_type == SHT_REL) {
193                         Elf_Mips_Rel *rel = (void *) sechdrs[i].sh_addr;
194                         unsigned size = sechdrs[i].sh_size / sizeof(*rel);
195
196                         for (j = 0; j < size; ++j) {
197                                 Elf_Sym *sym;
198
199                                 if (ELF_MIPS_R_TYPE(rel[j]) != R_MIPS_26)
200                                         continue;
201                                 sym = syms + ELF_MIPS_R_SYM(rel[j]);
202                                 if (!is_init && sym->st_shndx != SHN_UNDEF)
203                                         continue;
204
205                                 ret += sizeof(unsigned[4]);
206                         }
207                 } else {
208                         Elf_Mips_Rela *rela = (void *) sechdrs[i].sh_addr;
209                         unsigned size = sechdrs[i].sh_size / sizeof(*rela);
210
211                         for (j = 0; j < size; ++j) {
212                                 Elf_Sym *sym;
213
214                                 if (ELF_MIPS_R_TYPE(rela[j]) != R_MIPS_26)
215                                         continue;
216                                 sym = syms + ELF_MIPS_R_SYM(rela[j]);
217                                 if (!is_init && sym->st_shndx != SHN_UNDEF)
218                                         continue;
219
220                                 ret += sizeof(unsigned[4]);
221                         }
222                 }
223
224         }
225
226         return ret;
227 }
228
229 int module_relayout(Elf32_Ehdr *hdr,
230                     Elf32_Shdr *sechdrs,
231                     char *secstrings,
232                     unsigned symindex,
233                     struct module *me)
234 {
235         unsigned core_plt_size = get_plt_size(
236             hdr, sechdrs, secstrings, symindex, 0);
237         unsigned init_plt_size = get_plt_size(
238             hdr, sechdrs, secstrings, symindex, 1);
239
240         if (core_plt_size > 0)
241                 me->core_size = PAGE_ALIGN(me->core_size);
242         me->arch.core_plt_offset = me->core_size;
243         me->core_size = me->core_size + core_plt_size;
244
245         me->arch.init_plt_offset = me->init_size;
246         me->init_size = me->init_size + init_plt_size;
247
248         return 0;
249 }
250
251 static int apply_r_mips_none(struct module *me, u32 *location, Elf_Addr v)
252 {
253         return 0;
254 }
255
256 static int apply_r_mips_32_rel(struct module *me, u32 *location, Elf_Addr v)
257 {
258         *location += v;
259
260         return 0;
261 }
262
263 static int apply_r_mips_32_rela(struct module *me, u32 *location, Elf_Addr v)
264 {
265         *location = v;
266
267         return 0;
268 }
269
270 static Elf_Addr add_plt_entry_to(unsigned *plt_offset,
271                                  void *start, unsigned size, Elf_Addr v)
272 {
273         unsigned *tramp = start + *plt_offset;
274         if (*plt_offset == size) return 0;
275
276         *plt_offset += sizeof(unsigned[4]);
277
278         /* adjust carry for addiu */
279         if (v & 0x00008000)
280                 v += 0x10000;
281        
282         tramp[0] = 0x3c190000 | (v >> 16);      /* lui t9, hi16 */
283         tramp[1] = 0x27390000 | (v & 0xffff);   /* addiu t9, t9, lo16 */
284         tramp[2] = 0x03200008;                  /* jr t9 */
285         tramp[3] = 0x00000000;                  /* nop */
286        
287         return (Elf_Addr) tramp;
288 }
289
290 static Elf_Addr add_plt_entry(struct module *me, void *location, Elf_Addr v)
291 {
292         if (location >= me->module_core
293             && location < me->module_core + me->core_size) {
294                 return add_plt_entry_to(&me->arch.core_plt_offset,
295                                         me->module_core, me->core_size, v);
296         } else if (location > me->module_init
297                    && location < me->module_init + me->init_size) {
298                 return add_plt_entry_to(&me->arch.init_plt_offset,
299                                         me->module_init, me->init_size, v);
300         } else {
301                 printk(KERN_ERR "module %s: "
302                        "relocation to unknown segment %u\n",
303                        me->name, v);
304         }
305         return 0;
306 }
307
308 static int apply_r_mips_26_rel(struct module *me, u32 *location, Elf_Addr v)
309 {
310         if (v % 4) {
311                 printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
312                 return -ENOEXEC;
313         }
314
315         if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
316                 v = add_plt_entry(me, location,
317                                   v + ((*location & 0x03ffffff) << 2));
318                 if (v == 0) {
319                 printk(KERN_ERR
320                        "module %s: relocation overflow\n",
321                        me->name);
322                 return -ENOEXEC;
323         }
324                 *location = (*location & ~0x03ffffff) |
325                             ((v >> 2) & 0x03ffffff);
326                 return 0;
327         }
328
329         *location = (*location & ~0x03ffffff) |
330                     ((*location + (v >> 2)) & 0x03ffffff);
331
332         return 0;
333 }
334
335 static int apply_r_mips_26_rela(struct module *me, u32 *location, Elf_Addr v)
336 {
337         if (v % 4) {
338                 printk(KERN_ERR "module %s: dangerous relocation\n", me->name);
339                 return -ENOEXEC;
340         }
341
342         if ((v & 0xf0000000) != (((unsigned long)location + 4) & 0xf0000000)) {
343                 v = add_plt_entry(me, location, v);
344                 if (v == 0) {
345                 printk(KERN_ERR
346                        "module %s: relocation overflow\n",
347                        me->name);
348                 return -ENOEXEC;
349         }
350         }
351
352         *location = (*location & ~0x03ffffff) | ((v >> 2) & 0x03ffffff);
353
354         return 0;
355 }
356
357 static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
358 {
359         struct mips_hi16 *n;
360
361         /*
362          * We cannot relocate this one now because we don't know the value of
363          * the carry we need to add.  Save the information, and let LO16 do the
364          * actual relocation.
365          */
366         n = kmalloc(sizeof *n, GFP_KERNEL);
367         if (!n)
368                 return -ENOMEM;
369
370         n->addr = (Elf_Addr *)location;
371         n->value = v;
372         n->next = mips_hi16_list;
373         mips_hi16_list = n;
374
375         return 0;
376 }
377
378 static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
379 {
380         *location = (*location & 0xffff0000) |
381                     ((((long long) v + 0x8000LL) >> 16) & 0xffff);
382
383         return 0;
384 }
385
386 static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
387 {
388         unsigned long insnlo = *location;
389         Elf_Addr val, vallo;
390
391         /* Sign extend the addend we extract from the lo insn.  */
392         vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
393
394         if (mips_hi16_list != NULL) {
395                 struct mips_hi16 *l;
396
397                 l = mips_hi16_list;
398                 while (l != NULL) {
399                         struct mips_hi16 *next;
400                         unsigned long insn;
401
402                         /*
403                          * The value for the HI16 had best be the same.
404                          */
405                         if (v != l->value)
406                                 goto out_danger;
407
408                         /*
409                          * Do the HI16 relocation.  Note that we actually don't
410                          * need to know anything about the LO16 itself, except
411                          * where to find the low 16 bits of the addend needed
412                          * by the LO16.
413                          */
414                         insn = *l->addr;
415                         val = ((insn & 0xffff) << 16) + vallo;
416                         val += v;
417
418                         /*
419                          * Account for the sign extension that will happen in
420                          * the low bits.
421                          */
422                         val = ((val >> 16) + ((val & 0x8000) != 0)) & 0xffff;
423
424                         insn = (insn & ~0xffff) | val;
425                         *l->addr = insn;
426
427                         next = l->next;
428                         kfree(l);
429                         l = next;
430                 }
431
432                 mips_hi16_list = NULL;
433         }
434
435         /*
436          * Ok, we're done with the HI16 relocs.  Now deal with the LO16.
437          */
438         val = v + vallo;
439         insnlo = (insnlo & ~0xffff) | (val & 0xffff);
440         *location = insnlo;
441
442         return 0;
443
444 out_danger:
445         printk(KERN_ERR "module %s: dangerous " "relocation\n", me->name);
446
447         return -ENOEXEC;
448 }
449
450 static int apply_r_mips_lo16_rela(struct module *me, u32 *location, Elf_Addr v)
451 {
452         *location = (*location & 0xffff0000) | (v & 0xffff);
453
454         return 0;
455 }
456
457 static int apply_r_mips_64_rela(struct module *me, u32 *location, Elf_Addr v)
458 {
459         *(Elf_Addr *)location = v;
460
461         return 0;
462 }
463
464 static int apply_r_mips_higher_rela(struct module *me, u32 *location,
465                                     Elf_Addr v)
466 {
467         *location = (*location & 0xffff0000) |
468                     ((((long long) v + 0x80008000LL) >> 32) & 0xffff);
469
470         return 0;
471 }
472
473 static int apply_r_mips_highest_rela(struct module *me, u32 *location,
474                                      Elf_Addr v)
475 {
476         *location = (*location & 0xffff0000) |
477                     ((((long long) v + 0x800080008000LL) >> 48) & 0xffff);
478
479         return 0;
480 }
481
482 static int (*reloc_handlers_rel[]) (struct module *me, u32 *location,
483                                 Elf_Addr v) = {
484         [R_MIPS_NONE]           = apply_r_mips_none,
485         [R_MIPS_32]             = apply_r_mips_32_rel,
486         [R_MIPS_26]             = apply_r_mips_26_rel,
487         [R_MIPS_HI16]           = apply_r_mips_hi16_rel,
488         [R_MIPS_LO16]           = apply_r_mips_lo16_rel
489 };
490
491 static int (*reloc_handlers_rela[]) (struct module *me, u32 *location,
492                                 Elf_Addr v) = {
493         [R_MIPS_NONE]           = apply_r_mips_none,
494         [R_MIPS_32]             = apply_r_mips_32_rela,
495         [R_MIPS_26]             = apply_r_mips_26_rela,
496         [R_MIPS_HI16]           = apply_r_mips_hi16_rela,
497         [R_MIPS_LO16]           = apply_r_mips_lo16_rela,
498         [R_MIPS_64]             = apply_r_mips_64_rela,
499         [R_MIPS_HIGHER]         = apply_r_mips_higher_rela,
500         [R_MIPS_HIGHEST]        = apply_r_mips_highest_rela
501 };
502
503 int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
504                    unsigned int symindex, unsigned int relsec,
505                    struct module *me)
506 {
507         Elf_Mips_Rel *rel = (void *) sechdrs[relsec].sh_addr;
508         Elf_Sym *sym;
509         u32 *location;
510         unsigned int i;
511         Elf_Addr v;
512         int res;
513
514         pr_debug("Applying relocate section %u to %u\n", relsec,
515                sechdrs[relsec].sh_info);
516
517         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
518                 /* This is where to make the change */
519                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
520                         + rel[i].r_offset;
521                 /* This is the symbol it is referring to */
522                 sym = (Elf_Sym *)sechdrs[symindex].sh_addr
523                         + ELF_MIPS_R_SYM(rel[i]);
524                 if (!sym->st_value) {
525                         /* Ignore unresolved weak symbol */
526                         if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
527                                 continue;
528                         printk(KERN_WARNING "%s: Unknown symbol %s\n",
529                                me->name, strtab + sym->st_name);
530                         return -ENOENT;
531                 }
532
533                 v = sym->st_value;
534
535                 res = reloc_handlers_rel[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
536                 if (res)
537                         return res;
538         }
539
540         return 0;
541 }
542
543 int apply_relocate_add(Elf_Shdr *sechdrs, const char *strtab,
544                        unsigned int symindex, unsigned int relsec,
545                        struct module *me)
546 {
547         Elf_Mips_Rela *rel = (void *) sechdrs[relsec].sh_addr;
548         Elf_Sym *sym;
549         u32 *location;
550         unsigned int i;
551         Elf_Addr v;
552         int res;
553
554         pr_debug("Applying relocate section %u to %u\n", relsec,
555                sechdrs[relsec].sh_info);
556
557         for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
558                 /* This is where to make the change */
559                 location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
560                         + rel[i].r_offset;
561                 /* This is the symbol it is referring to */
562                 sym = (Elf_Sym *)sechdrs[symindex].sh_addr
563                         + ELF_MIPS_R_SYM(rel[i]);
564                 if (!sym->st_value) {
565                         /* Ignore unresolved weak symbol */
566                         if (ELF_ST_BIND(sym->st_info) == STB_WEAK)
567                                 continue;
568                         printk(KERN_WARNING "%s: Unknown symbol %s\n",
569                                me->name, strtab + sym->st_name);
570                         return -ENOENT;
571                 }
572
573                 v = sym->st_value + rel[i].r_addend;
574
575                 res = reloc_handlers_rela[ELF_MIPS_R_TYPE(rel[i])](me, location, v);
576                 if (res)
577                         return res;
578         }
579
580         return 0;
581 }
582
583 /* Given an address, look for it in the module exception tables. */
584 const struct exception_table_entry *search_module_dbetables(unsigned long addr)
585 {
586         unsigned long flags;
587         const struct exception_table_entry *e = NULL;
588         struct mod_arch_specific *dbe;
589
590         spin_lock_irqsave(&dbe_lock, flags);
591         list_for_each_entry(dbe, &dbe_list, dbe_list) {
592                 e = search_extable(dbe->dbe_start, dbe->dbe_end - 1, addr);
593                 if (e)
594                         break;
595         }
596         spin_unlock_irqrestore(&dbe_lock, flags);
597
598         /* Now, if we found one, we are running inside it now, hence
599            we cannot unload the module, hence no refcnt needed. */
600         return e;
601 }
602
603 /* Put in dbe list if neccessary. */
604 int module_finalize(const Elf_Ehdr *hdr,
605                     const Elf_Shdr *sechdrs,
606                     struct module *me)
607 {
608         const Elf_Shdr *s;
609         char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
610
611         INIT_LIST_HEAD(&me->arch.dbe_list);
612         for (s = sechdrs; s < sechdrs + hdr->e_shnum; s++) {
613                 if (strcmp("__dbe_table", secstrings + s->sh_name) != 0)
614                         continue;
615                 me->arch.dbe_start = (void *)s->sh_addr;
616                 me->arch.dbe_end = (void *)s->sh_addr + s->sh_size;
617                 spin_lock_irq(&dbe_lock);
618                 list_add(&me->arch.dbe_list, &dbe_list);
619                 spin_unlock_irq(&dbe_lock);
620         }
621
622         if (me->arch.core_plt_offset < me->core_size
623             && PAGE_ALIGN(me->arch.core_plt_offset) == me->arch.core_plt_offset
624             && is_phys(me->module_core)) {
625                 free_phys(me->module_core + me->arch.core_plt_offset,
626                           me->core_size - me->arch.core_plt_offset);
627                 me->core_size = me->arch.core_plt_offset;
628         }
629         return 0;
630 }
631
632 void module_arch_cleanup(struct module *mod)
633 {
634         spin_lock_irq(&dbe_lock);
635         list_del(&mod->arch.dbe_list);
636         spin_unlock_irq(&dbe_lock);
637 }
Note: See TracBrowser for help on using the browser.