2003-02-03 19:59:31

by Martin Schwidefsky

[permalink] [raw]
Subject: [PATCH] s390 fixes (5/12).

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
diff -urN linux-2.5.59/arch/s390/kernel/traps.c linux-2.5.59-s390/arch/s390/kernel/traps.c
--- linux-2.5.59/arch/s390/kernel/traps.c Fri Jan 17 03:22:00 2003
+++ linux-2.5.59-s390/arch/s390/kernel/traps.c Mon Feb 3 20:49:35 2003
@@ -268,9 +268,10 @@
}
#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);
}
diff -urN linux-2.5.59/arch/s390/mm/extable.c linux-2.5.59-s390/arch/s390/mm/extable.c
--- linux-2.5.59/arch/s390/mm/extable.c Fri Jan 17 03:22:24 2003
+++ linux-2.5.59-s390/arch/s390/mm/extable.c Mon Feb 3 20:49:35 2003
@@ -2,10 +2,8 @@
* arch/s390/mm/extable.c
*
* S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
- * Author(s): Hartmut Penner ([email protected])
*
- * Derived from "arch/i386/mm/extable.c"
+ * identical to arch/i386/mm/extable.c
*/

#include <linux/config.h>
@@ -13,63 +11,24 @@
#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;
}
diff -urN linux-2.5.59/arch/s390/mm/fault.c linux-2.5.59-s390/arch/s390/mm/fault.c
--- linux-2.5.59/arch/s390/mm/fault.c Fri Jan 17 03:22:28 2003
+++ linux-2.5.59-s390/arch/s390/mm/fault.c Mon Feb 3 20:49:35 2003
@@ -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 @@
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 @@

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;
}

diff -urN linux-2.5.59/arch/s390x/kernel/traps.c linux-2.5.59-s390/arch/s390x/kernel/traps.c
--- linux-2.5.59/arch/s390x/kernel/traps.c Fri Jan 17 03:22:26 2003
+++ linux-2.5.59-s390/arch/s390x/kernel/traps.c Mon Feb 3 20:49:35 2003
@@ -269,9 +269,10 @@
}
#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);
}
diff -urN linux-2.5.59/arch/s390x/mm/extable.c linux-2.5.59-s390/arch/s390x/mm/extable.c
--- linux-2.5.59/arch/s390x/mm/extable.c Fri Jan 17 03:21:50 2003
+++ linux-2.5.59-s390/arch/s390x/mm/extable.c Mon Feb 3 20:49:35 2003
@@ -11,58 +11,24 @@
#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;
}
diff -urN linux-2.5.59/arch/s390x/mm/fault.c linux-2.5.59-s390/arch/s390x/mm/fault.c
--- linux-2.5.59/arch/s390x/mm/fault.c Fri Jan 17 03:22:00 2003
+++ linux-2.5.59-s390/arch/s390x/mm/fault.c Mon Feb 3 20:49:35 2003
@@ -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 @@
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 @@

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;
}

diff -urN linux-2.5.59/include/asm-s390/uaccess.h linux-2.5.59-s390/include/asm-s390/uaccess.h
--- linux-2.5.59/include/asm-s390/uaccess.h Fri Jan 17 03:21:42 2003
+++ linux-2.5.59-s390/include/asm-s390/uaccess.h Mon Feb 3 20:49:35 2003
@@ -71,10 +71,6 @@
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.
diff -urN linux-2.5.59/include/asm-s390x/uaccess.h linux-2.5.59-s390/include/asm-s390x/uaccess.h
--- linux-2.5.59/include/asm-s390x/uaccess.h Fri Jan 17 03:21:38 2003
+++ linux-2.5.59-s390/include/asm-s390x/uaccess.h Mon Feb 3 20:49:35 2003
@@ -71,10 +71,6 @@
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.