]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/s390/kernel/module.c
[S390] module function call optimization
[karo-tx-linux.git] / arch / s390 / kernel / module.c
index 39d1dd752529a3c345091b336d8819b1744fe5cb..eed4a00cb676238f7fdbc3b1ccc9dbde7ecb0b98 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/string.h>
 #include <linux/kernel.h>
 #include <linux/moduleloader.h>
+#include <linux/bug.h>
 
 #if 0
 #define DEBUGP printk
@@ -309,15 +310,20 @@ apply_rela(Elf_Rela *rela, Elf_Addr base, Elf_Sym *symtab,
                        info->plt_initialized = 1;
                }
                if (r_type == R_390_PLTOFF16 ||
-                   r_type == R_390_PLTOFF32
-                   || r_type == R_390_PLTOFF64
-                       )
+                   r_type == R_390_PLTOFF32 ||
+                   r_type == R_390_PLTOFF64)
                        val = me->arch.plt_offset - me->arch.got_offset +
                                info->plt_offset + rela->r_addend;
-               else
-                       val =  (Elf_Addr) me->module_core +
-                               me->arch.plt_offset + info->plt_offset + 
-                               rela->r_addend - loc;
+               else {
+                       if (!((r_type == R_390_PLT16DBL &&
+                              val - loc + 0xffffUL < 0x1ffffeUL) ||
+                             (r_type == R_390_PLT32DBL &&
+                              val - loc + 0xffffffffULL < 0x1fffffffeULL)))
+                               val = (Elf_Addr) me->module_core +
+                                       me->arch.plt_offset +
+                                       info->plt_offset;
+                       val += rela->r_addend - loc;
+               }
                if (r_type == R_390_PLT16DBL)
                        *(unsigned short *) loc = val >> 1;
                else if (r_type == R_390_PLTOFF16)
@@ -398,9 +404,10 @@ int module_finalize(const Elf_Ehdr *hdr,
                    struct module *me)
 {
        vfree(me->arch.syminfo);
-       return 0;
+       return module_bug_finalize(hdr, sechdrs, me);
 }
 
 void module_arch_cleanup(struct module *mod)
 {
+       module_bug_cleanup(mod);
 }