diff options
author | Ard Biesheuvel <ard.biesheuvel@linaro.org> | 2016-03-22 17:28:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-03-22 18:36:02 -0400 |
commit | 8fe9752ef10343a8edb603cb93abc2bfae34e748 (patch) | |
tree | b30425aa5cdec70940610e9fd0b6b96dbd544ab0 | |
parent | 29934b0fb8ff5afa61832ea56aec65befab30511 (diff) |
ia64/extable: use generic search and sort routines
Replace the arch specific versions of search_extable() and
sort_extable() with calls to the generic ones, which now support
relative exception tables as well.
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Acked-by: Tony Luck <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r-- | arch/ia64/include/asm/uaccess.h | 8 | ||||
-rw-r--r-- | arch/ia64/mm/extable.c | 97 |
2 files changed, 4 insertions, 101 deletions
diff --git a/arch/ia64/include/asm/uaccess.h b/arch/ia64/include/asm/uaccess.h index 4f3fb6ccbf21..2189d5ddc1ee 100644 --- a/arch/ia64/include/asm/uaccess.h +++ b/arch/ia64/include/asm/uaccess.h | |||
@@ -341,13 +341,11 @@ extern unsigned long __strnlen_user (const char __user *, long); | |||
341 | __su_ret; \ | 341 | __su_ret; \ |
342 | }) | 342 | }) |
343 | 343 | ||
344 | /* Generic code can't deal with the location-relative format that we use for compactness. */ | 344 | #define ARCH_HAS_RELATIVE_EXTABLE |
345 | #define ARCH_HAS_SORT_EXTABLE | ||
346 | #define ARCH_HAS_SEARCH_EXTABLE | ||
347 | 345 | ||
348 | struct exception_table_entry { | 346 | struct exception_table_entry { |
349 | int addr; /* location-relative address of insn this fixup is for */ | 347 | int insn; /* location-relative address of insn this fixup is for */ |
350 | int cont; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ | 348 | int fixup; /* location-relative continuation addr.; if bit 2 is set, r9 is set to 0 */ |
351 | }; | 349 | }; |
352 | 350 | ||
353 | extern void ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e); | 351 | extern void ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e); |
diff --git a/arch/ia64/mm/extable.c b/arch/ia64/mm/extable.c index c99a41e29fe8..8f70bb2d0c37 100644 --- a/arch/ia64/mm/extable.c +++ b/arch/ia64/mm/extable.c | |||
@@ -5,107 +5,12 @@ | |||
5 | * David Mosberger-Tang <davidm@hpl.hp.com> | 5 | * David Mosberger-Tang <davidm@hpl.hp.com> |
6 | */ | 6 | */ |
7 | 7 | ||
8 | #include <linux/sort.h> | ||
9 | |||
10 | #include <asm/uaccess.h> | 8 | #include <asm/uaccess.h> |
11 | #include <linux/module.h> | ||
12 | |||
13 | static int cmp_ex(const void *a, const void *b) | ||
14 | { | ||
15 | const struct exception_table_entry *l = a, *r = b; | ||
16 | u64 lip = (u64) &l->addr + l->addr; | ||
17 | u64 rip = (u64) &r->addr + r->addr; | ||
18 | |||
19 | /* avoid overflow */ | ||
20 | if (lip > rip) | ||
21 | return 1; | ||
22 | if (lip < rip) | ||
23 | return -1; | ||
24 | return 0; | ||
25 | } | ||
26 | |||
27 | static void swap_ex(void *a, void *b, int size) | ||
28 | { | ||
29 | struct exception_table_entry *l = a, *r = b, tmp; | ||
30 | u64 delta = (u64) r - (u64) l; | ||
31 | |||
32 | tmp = *l; | ||
33 | l->addr = r->addr + delta; | ||
34 | l->cont = r->cont + delta; | ||
35 | r->addr = tmp.addr - delta; | ||
36 | r->cont = tmp.cont - delta; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Sort the exception table. It's usually already sorted, but there | ||
41 | * may be unordered entries due to multiple text sections (such as the | ||
42 | * .init text section). Note that the exception-table-entries contain | ||
43 | * location-relative addresses, which requires a bit of care during | ||
44 | * sorting to avoid overflows in the offset members (e.g., it would | ||
45 | * not be safe to make a temporary copy of an exception-table entry on | ||
46 | * the stack, because the stack may be more than 2GB away from the | ||
47 | * exception-table). | ||
48 | */ | ||
49 | void sort_extable (struct exception_table_entry *start, | ||
50 | struct exception_table_entry *finish) | ||
51 | { | ||
52 | sort(start, finish - start, sizeof(struct exception_table_entry), | ||
53 | cmp_ex, swap_ex); | ||
54 | } | ||
55 | |||
56 | static inline unsigned long ex_to_addr(const struct exception_table_entry *x) | ||
57 | { | ||
58 | return (unsigned long)&x->addr + x->addr; | ||
59 | } | ||
60 | |||
61 | #ifdef CONFIG_MODULES | ||
62 | /* | ||
63 | * Any entry referring to the module init will be at the beginning or | ||
64 | * the end. | ||
65 | */ | ||
66 | void trim_init_extable(struct module *m) | ||
67 | { | ||
68 | /*trim the beginning*/ | ||
69 | while (m->num_exentries && | ||
70 | within_module_init(ex_to_addr(&m->extable[0]), m)) { | ||
71 | m->extable++; | ||
72 | m->num_exentries--; | ||
73 | } | ||
74 | /*trim the end*/ | ||
75 | while (m->num_exentries && | ||
76 | within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), | ||
77 | m)) | ||
78 | m->num_exentries--; | ||
79 | } | ||
80 | #endif /* CONFIG_MODULES */ | ||
81 | |||
82 | const struct exception_table_entry * | ||
83 | search_extable (const struct exception_table_entry *first, | ||
84 | const struct exception_table_entry *last, | ||
85 | unsigned long ip) | ||
86 | { | ||
87 | const struct exception_table_entry *mid; | ||
88 | unsigned long mid_ip; | ||
89 | long diff; | ||
90 | |||
91 | while (first <= last) { | ||
92 | mid = &first[(last - first)/2]; | ||
93 | mid_ip = (u64) &mid->addr + mid->addr; | ||
94 | diff = mid_ip - ip; | ||
95 | if (diff == 0) | ||
96 | return mid; | ||
97 | else if (diff < 0) | ||
98 | first = mid + 1; | ||
99 | else | ||
100 | last = mid - 1; | ||
101 | } | ||
102 | return NULL; | ||
103 | } | ||
104 | 9 | ||
105 | void | 10 | void |
106 | ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e) | 11 | ia64_handle_exception (struct pt_regs *regs, const struct exception_table_entry *e) |
107 | { | 12 | { |
108 | long fix = (u64) &e->cont + e->cont; | 13 | long fix = (u64) &e->fixup + e->fixup; |
109 | 14 | ||
110 | regs->r8 = -EFAULT; | 15 | regs->r8 = -EFAULT; |
111 | if (fix & 4) | 16 | if (fix & 4) |