From a054394c2592fa0d44a168b3af0c9a1352468cd9 Mon Sep 17 00:00:00 2001 From: Ivan Kokshaysky Date: Thu, 30 Apr 2009 15:08:47 -0700 Subject: [PATCH] --- yaml --- r: 144367 b: refs/heads/master c: 08a42e86bce511b45ca3eee40f51674b02a777d1 h: refs/heads/master i: 144365: 49c33fccdc01969b9938f456422cbcc8d3c986b1 144363: eeccf3afce2b41d0e8cf3cf638d0154f49b7c2fe 144359: a99982bc8c0ffabb944c9e7bf6cbca29575df263 144351: b3b302e136f55fcd61b734525314e531dec024c1 v: v3 --- [refs] | 2 +- trunk/arch/alpha/include/asm/uaccess.h | 2 ++ trunk/arch/alpha/mm/extable.c | 40 +++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index b7674e6511c0..63a5a3163fbe 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1ffb1c0c64b4a2b75eed1f63cc47f2beb711c92f +refs/heads/master: 08a42e86bce511b45ca3eee40f51674b02a777d1 diff --git a/trunk/arch/alpha/include/asm/uaccess.h b/trunk/arch/alpha/include/asm/uaccess.h index 163f3053001c..b49ec2f8d6e3 100644 --- a/trunk/arch/alpha/include/asm/uaccess.h +++ b/trunk/arch/alpha/include/asm/uaccess.h @@ -507,5 +507,7 @@ struct exception_table_entry (pc) + (_fixup)->fixup.bits.nextinsn; \ }) +#define ARCH_HAS_SORT_EXTABLE +#define ARCH_HAS_SEARCH_EXTABLE #endif /* __ALPHA_UACCESS_H */ diff --git a/trunk/arch/alpha/mm/extable.c b/trunk/arch/alpha/mm/extable.c index dc7aeda15773..62dc379d301a 100644 --- a/trunk/arch/alpha/mm/extable.c +++ b/trunk/arch/alpha/mm/extable.c @@ -3,11 +3,49 @@ */ #include +#include #include +static inline unsigned long ex_to_addr(const struct exception_table_entry *x) +{ + return (unsigned long)&x->insn + x->insn; +} + +static void swap_ex(void *a, void *b, int size) +{ + struct exception_table_entry *ex_a = a, *ex_b = b; + unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b); + unsigned int t = ex_a->fixup.unit; + + ex_a->fixup.unit = ex_b->fixup.unit; + ex_b->fixup.unit = t; + ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn); + ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn); +} + +/* + * The exception table needs to be sorted so that the binary + * search that we use to find entries in it works properly. + * This is used both for the kernel exception table and for + * the exception tables of modules that get loaded. + */ +static int cmp_ex(const void *a, const void *b) +{ + const struct exception_table_entry *x = a, *y = b; + + /* avoid overflow */ + if (ex_to_addr(x) > ex_to_addr(y)) + return 1; + if (ex_to_addr(x) < ex_to_addr(y)) + return -1; + return 0; +} + void sort_extable(struct exception_table_entry *start, struct exception_table_entry *finish) { + sort(start, finish - start, sizeof(struct exception_table_entry), + cmp_ex, swap_ex); } const struct exception_table_entry * @@ -20,7 +58,7 @@ search_extable(const struct exception_table_entry *first, unsigned long mid_value; mid = (last - first) / 2 + first; - mid_value = (unsigned long)&mid->insn + mid->insn; + mid_value = ex_to_addr(mid); if (mid_value == value) return mid; else if (mid_value < value)