]> git.hungrycats.org Git - linux/commitdiff
[PATCH] s390: unified extable code.
authorMartin Schwidefsky <schwidefsky@de.ibm.com>
Mon, 24 Feb 2003 02:46:10 +0000 (18:46 -0800)
committerLinus Torvalds <torvalds@home.transmeta.com>
Mon, 24 Feb 2003 02:46:10 +0000 (18:46 -0800)
update extable support in s390 and s390x

this makes use of the unified extable code.
for 31 bit s390, this is slightly more complicated
than the other architectures, but as long as
no one outside /arch uses search_exception_tables,
everything should work nicely

arch/s390/kernel/traps.c
arch/s390/mm/extable.c
arch/s390/mm/fault.c
arch/s390x/kernel/traps.c
arch/s390x/mm/extable.c
arch/s390x/mm/fault.c
include/asm-s390/uaccess.h
include/asm-s390x/uaccess.h

index 8706fc762fd7af69fe6ff9e1c365ae465f902bdc..5fac68792cd02da3a4407155fbc0b53ca15b54fc 100644 (file)
@@ -268,9 +268,10 @@ static void inline do_trap(long interruption_code, int signr, char *str,
                }
 #endif
         } else {
-                unsigned long fixup = search_exception_table(regs->psw.addr);
+                const struct exception_table_entry *fixup;
+                fixup = search_exception_tables(regs->psw.addr & 0x7fffffff);
                 if (fixup)
-                        regs->psw.addr = fixup;
+                        regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE31;
                 else
                         die(str, regs, interruption_code);
         }
index d408152fd9afd1f90e2f9afc880a054530a28515..8d13d710c696376551ad194bcd284a1a13e69c75 100644 (file)
@@ -2,10 +2,8 @@
  *  arch/s390/mm/extable.c
  *
  *  S390 version
- *    Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- *    Author(s): Hartmut Penner (hp@de.ibm.com)
  *
- *  Derived from "arch/i386/mm/extable.c"
+ *  identical to arch/i386/mm/extable.c
  */
 
 #include <linux/config.h>
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
-                const struct exception_table_entry *last,
-                unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+              const struct exception_table_entry *last,
+              unsigned long value)
 {
-        while (first <= last) {
+       while (first <= last) {
                const struct exception_table_entry *mid;
                long diff;
 
                mid = (last - first) / 2 + first;
                diff = mid->insn - value;
-                if (diff == 0)
-                        return mid->fixup;
-                else if (diff < 0)
-                        first = mid+1;
-                else
-                        last = mid-1;
-        }
-        return 0;
-}
-
-extern spinlock_t modlist_lock;
-
-unsigned long
-search_exception_table(unsigned long addr)
-{
-       struct list_head *i;
-       unsigned long ret = 0;
-
-#ifndef CONFIG_MODULES
-        addr &= 0x7fffffff;  /* remove amode bit from address */
-       /* There is only the kernel to search.  */
-       ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-       if (ret) ret = ret | PSW_ADDR_AMODE31;
-       return ret;
-#else
-       unsigned long flags;
-        addr &= 0x7fffffff;  /* remove amode bit from address */
-
-       /* The kernel is the last "module" -- no need to treat it special. */
-       spin_lock_irqsave(&modlist_lock, flags);
-       list_for_each(i, &extables) {
-               struct exception_table *ex
-                       = list_entry(i, struct exception_table, list);
-               if (ex->num_entries == 0)
-                       continue;
-               ret = search_one_table(ex->entry,
-                                      ex->entry + ex->num_entries - 1, addr);
-               if (ret) {
-                       ret = ret | PSW_ADDR_AMODE31;
-                       break;
-               }
+               if (diff == 0)
+                       return mid;
+               else if (diff < 0)
+                       first = mid+1;
+               else
+                       last = mid-1;
        }
-       spin_unlock_irqrestore(&modlist_lock, flags);
-       return ret;
-#endif
+       return NULL;
 }
index db7b86042388017421908f3935045c0c31b67c48..e4ba1408f680787a240d16728b8857d6a2381523 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/compatmac.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -151,7 +152,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
         struct vm_area_struct * vma;
         unsigned long address;
        int user_address;
-        unsigned long fixup;
+       const struct exception_table_entry *fixup;
        int si_code = SEGV_MAPERR;
 
         tsk = current;
@@ -267,8 +268,9 @@ bad_area:
 
 no_context:
         /* Are we prepared to handle this kernel fault?  */
-        if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
-                regs->psw.addr = fixup;
+       fixup = search_exception_tables(regs->psw.addr & 0x7fffffff);
+       if (fixup) {
+               regs->psw.addr = fixup->fixup | PSW_ADDR_AMODE31;
                 return;
         }
 
index 1c5cd64b3ecd5210fe5d2833019eec76385db3d6..ffd9f52a02caf00acdb5fc0258cb54842adde96f 100644 (file)
@@ -269,9 +269,10 @@ static void inline do_trap(long interruption_code, int signr, char *str,
                }
 #endif
         } else {
-                unsigned long fixup = search_exception_table(regs->psw.addr);
+                const struct exception_table_entry *fixup;
+                fixup = search_exception_tables(regs->psw.addr);
                 if (fixup)
-                        regs->psw.addr = fixup;
+                        regs->psw.addr = fixup->fixup;
                 else
                         die(str, regs, interruption_code);
         }
index 6a5c22c13770a8307e769a9a3120d1e92e3d33c8..8d13d710c696376551ad194bcd284a1a13e69c75 100644 (file)
 #include <linux/spinlock.h>
 #include <asm/uaccess.h>
 
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
-
-static inline unsigned long
-search_one_table(const struct exception_table_entry *first,
-                const struct exception_table_entry *last,
-                unsigned long value)
+/* Simple binary search */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+              const struct exception_table_entry *last,
+              unsigned long value)
 {
-        while (first <= last) {
+       while (first <= last) {
                const struct exception_table_entry *mid;
                long diff;
 
                mid = (last - first) / 2 + first;
                diff = mid->insn - value;
-                if (diff == 0)
-                        return mid->fixup;
-                else if (diff < 0)
-                        first = mid+1;
-                else
-                        last = mid-1;
-        }
-        return 0;
-}
-
-extern spinlock_t modlist_lock;
-
-unsigned long
-search_exception_table(unsigned long addr)
-{
-       unsigned long ret = 0;
-       
-#ifndef CONFIG_MODULES
-       /* There is only the kernel to search.  */
-       ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
-       return ret;
-#else
-       unsigned long flags;
-       struct list_head *i;
-
-       /* The kernel is the last "module" -- no need to treat it special.  */
-       spin_lock_irqsave(&modlist_lock, flags);
-       list_for_each(i, &extables) {
-               struct exception_table *ex
-                       = list_entry(i, struct exception_table, list);
-               if (ex->num_entries == 0)
-                       continue;
-               ret = search_one_table(ex->entry,
-                                      ex->entry + ex->num_entries - 1, addr);
-               if (ret)
-                       break;
+               if (diff == 0)
+                       return mid;
+               else if (diff < 0)
+                       first = mid+1;
+               else
+                       last = mid-1;
        }
-       spin_unlock_irqrestore(&modlist_lock, flags);
-       return ret;
-#endif
+       return NULL;
 }
index ec169b6fc1f25230b535d8a760612ce1d12e1129..676b52fff3f0f3eb2dff93fb9c45d02b9ed5f534 100644 (file)
@@ -24,6 +24,7 @@
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/console.h>
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -151,7 +152,7 @@ extern inline void do_exception(struct pt_regs *regs, unsigned long error_code)
         struct vm_area_struct * vma;
         unsigned long address;
        int user_address;
-        unsigned long fixup;
+       const struct exception_table_entry *fixup;
        int si_code = SEGV_MAPERR;
 
         tsk = current;
@@ -267,8 +268,9 @@ bad_area:
 
 no_context:
         /* Are we prepared to handle this kernel fault?  */
-        if ((fixup = search_exception_table(regs->psw.addr)) != 0) {
-                regs->psw.addr = fixup;
+       fixup = search_exception_tables(regs->psw.addr);
+       if (fixup) {
+               regs->psw.addr = fixup->fixup;
                 return;
         }
 
index fe42387367ec6bc7ff37936c8fabd75113781e43..999a5f3e324c51126d1d4cf7310a909ee07d824c 100644 (file)
@@ -71,10 +71,6 @@ struct exception_table_entry
         unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
-
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
index 70df42b5cdec03942fb710c6eb48989e8359ca44..9369d23ad85fb89df3b29a2c3408e139352c8f60 100644 (file)
@@ -71,10 +71,6 @@ struct exception_table_entry
         unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
-
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.