diff options
| -rw-r--r-- | arch/alpha/include/asm/uaccess.h | 2 | ||||
| -rw-r--r-- | arch/alpha/mm/extable.c | 40 |
2 files changed, 41 insertions, 1 deletions
diff --git a/arch/alpha/include/asm/uaccess.h b/arch/alpha/include/asm/uaccess.h index 163f3053001c..b49ec2f8d6e3 100644 --- a/arch/alpha/include/asm/uaccess.h +++ b/arch/alpha/include/asm/uaccess.h | |||
| @@ -507,5 +507,7 @@ struct exception_table_entry | |||
| 507 | (pc) + (_fixup)->fixup.bits.nextinsn; \ | 507 | (pc) + (_fixup)->fixup.bits.nextinsn; \ |
| 508 | }) | 508 | }) |
| 509 | 509 | ||
| 510 | #define ARCH_HAS_SORT_EXTABLE | ||
| 511 | #define ARCH_HAS_SEARCH_EXTABLE | ||
| 510 | 512 | ||
| 511 | #endif /* __ALPHA_UACCESS_H */ | 513 | #endif /* __ALPHA_UACCESS_H */ |
diff --git a/arch/alpha/mm/extable.c b/arch/alpha/mm/extable.c index dc7aeda15773..62dc379d301a 100644 --- a/arch/alpha/mm/extable.c +++ b/arch/alpha/mm/extable.c | |||
| @@ -3,11 +3,49 @@ | |||
| 3 | */ | 3 | */ |
| 4 | 4 | ||
| 5 | #include <linux/module.h> | 5 | #include <linux/module.h> |
| 6 | #include <linux/sort.h> | ||
| 6 | #include <asm/uaccess.h> | 7 | #include <asm/uaccess.h> |
| 7 | 8 | ||
| 9 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
| 10 | { | ||
| 11 | return (unsigned long)&x->insn + x->insn; | ||
| 12 | } | ||
| 13 | |||
| 14 | static void swap_ex(void *a, void *b, int size) | ||
| 15 | { | ||
| 16 | struct exception_table_entry *ex_a = a, *ex_b = b; | ||
| 17 | unsigned long addr_a = ex_to_addr(ex_a), addr_b = ex_to_addr(ex_b); | ||
| 18 | unsigned int t = ex_a->fixup.unit; | ||
| 19 | |||
| 20 | ex_a->fixup.unit = ex_b->fixup.unit; | ||
| 21 | ex_b->fixup.unit = t; | ||
| 22 | ex_a->insn = (int)(addr_b - (unsigned long)&ex_a->insn); | ||
| 23 | ex_b->insn = (int)(addr_a - (unsigned long)&ex_b->insn); | ||
| 24 | } | ||
| 25 | |||
| 26 | /* | ||
| 27 | * The exception table needs to be sorted so that the binary | ||
| 28 | * search that we use to find entries in it works properly. | ||
| 29 | * This is used both for the kernel exception table and for | ||
| 30 | * the exception tables of modules that get loaded. | ||
| 31 | */ | ||
| 32 | static int cmp_ex(const void *a, const void *b) | ||
| 33 | { | ||
| 34 | const struct exception_table_entry *x = a, *y = b; | ||
| 35 | |||
| 36 | /* avoid overflow */ | ||
| 37 | if (ex_to_addr(x) > ex_to_addr(y)) | ||
| 38 | return 1; | ||
| 39 | if (ex_to_addr(x) < ex_to_addr(y)) | ||
| 40 | return -1; | ||
| 41 | return 0; | ||
| 42 | } | ||
| 43 | |||
| 8 | void sort_extable(struct exception_table_entry *start, | 44 | void sort_extable(struct exception_table_entry *start, |
| 9 | struct exception_table_entry *finish) | 45 | struct exception_table_entry *finish) |
| 10 | { | 46 | { |
| 47 | sort(start, finish - start, sizeof(struct exception_table_entry), | ||
| 48 | cmp_ex, swap_ex); | ||
| 11 | } | 49 | } |
| 12 | 50 | ||
| 13 | const struct exception_table_entry * | 51 | const struct exception_table_entry * |
| @@ -20,7 +58,7 @@ search_extable(const struct exception_table_entry *first, | |||
| 20 | unsigned long mid_value; | 58 | unsigned long mid_value; |
| 21 | 59 | ||
| 22 | mid = (last - first) / 2 + first; | 60 | mid = (last - first) / 2 + first; |
| 23 | mid_value = (unsigned long)&mid->insn + mid->insn; | 61 | mid_value = ex_to_addr(mid); |
| 24 | if (mid_value == value) | 62 | if (mid_value == value) |
| 25 | return mid; | 63 | return mid; |
| 26 | else if (mid_value < value) | 64 | else if (mid_value < value) |
