1/* 2 * linux/arch/alpha/mm/extable.c 3 */ 4 5#include <linux/module.h> 6#include <linux/sort.h> 7#include <asm/uaccess.h> 8 9static inline unsigned long ex_to_addr(const struct exception_table_entry *x) 10{ 11 return (unsigned long)&x->insn + x->insn; 12} 13 14static 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 */ 32static 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 44void sort_extable(struct exception_table_entry *start, 45 struct exception_table_entry *finish) 46{ 47 sort(start, finish - start, sizeof(struct exception_table_entry), 48 cmp_ex, swap_ex); 49} 50 51#ifdef CONFIG_MODULES 52/* 53 * Any entry referring to the module init will be at the beginning or 54 * the end. 55 */ 56void trim_init_extable(struct module *m) 57{ 58 /*trim the beginning*/ 59 while (m->num_exentries && 60 within_module_init(ex_to_addr(&m->extable[0]), m)) { 61 m->extable++; 62 m->num_exentries--; 63 } 64 /*trim the end*/ 65 while (m->num_exentries && 66 within_module_init(ex_to_addr(&m->extable[m->num_exentries-1]), 67 m)) 68 m->num_exentries--; 69} 70#endif /* CONFIG_MODULES */ 71 72const struct exception_table_entry * 73search_extable(const struct exception_table_entry *first, 74 const struct exception_table_entry *last, 75 unsigned long value) 76{ 77 while (first <= last) { 78 const struct exception_table_entry *mid; 79 unsigned long mid_value; 80 81 mid = (last - first) / 2 + first; 82 mid_value = ex_to_addr(mid); 83 if (mid_value == value) 84 return mid; 85 else if (mid_value < value) 86 first = mid+1; 87 else 88 last = mid-1; 89 } 90 91 return NULL; 92} 93