File: /usr/src/linux/arch/sh/mm/extable.c
1 /* $Id: extable.c,v 1.2 2001/03/31 10:43:18 gniibe Exp $
2 *
3 * linux/arch/sh/mm/extable.c
4 * Taken from:
5 * linux/arch/i386/mm/extable.c
6 */
7
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <asm/uaccess.h>
11
12 extern const struct exception_table_entry __start___ex_table[];
13 extern const struct exception_table_entry __stop___ex_table[];
14
15 static inline unsigned long
16 search_one_table(const struct exception_table_entry *first,
17 const struct exception_table_entry *last,
18 unsigned long value)
19 {
20 while (first <= last) {
21 const struct exception_table_entry *mid;
22 long diff;
23
24 mid = (last - first) / 2 + first;
25 diff = mid->insn - value;
26 if (diff == 0)
27 return mid->fixup;
28 else if (diff < 0)
29 first = mid+1;
30 else
31 last = mid-1;
32 }
33 return 0;
34 }
35
36 unsigned long
37 search_exception_table(unsigned long addr)
38 {
39 unsigned long ret;
40
41 #ifndef CONFIG_MODULES
42 /* There is only the kernel to search. */
43 ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr);
44 if (ret) return ret;
45 #else
46 /* The kernel is the last "module" -- no need to treat it special. */
47 struct module *mp;
48 for (mp = module_list; mp != NULL; mp = mp->next) {
49 if (mp->ex_table_start == NULL || !(mp->flags&(MOD_RUNNING|MOD_INITIALIZING)))
50 continue;
51 ret = search_one_table(mp->ex_table_start,
52 mp->ex_table_end - 1, addr);
53 if (ret) return ret;
54 }
55 #endif
56
57 return 0;
58 }
59