2 * linux/arch/sparc/mm/extable.c
5 #include <linux/config.h>
6 #include <linux/module.h>
7 #include <asm/uaccess.h>
9 extern const struct exception_table_entry __start___ex_table[];
10 extern const struct exception_table_entry __stop___ex_table[];
13 search_one_table(const struct exception_table_entry *start,
14 const struct exception_table_entry *end,
15 unsigned long value, unsigned long *g2)
17 const struct exception_table_entry *walk;
19 /* Single insn entries are encoded as:
20 * word 1: insn address
21 * word 2: fixup code address
23 * Range entries are encoded as:
24 * word 1: first insn address
26 * word 3: last insn address + 4 bytes
27 * word 4: fixup code address
29 * See asm/uaccess.h for more details.
32 /* 1. Try to find an exact match. */
33 for (walk = start; walk <= end; walk++) {
34 if (walk->fixup == 0) {
35 /* A range entry, skip both parts. */
40 if (walk->insn == value)
44 /* 2. Try to find a range match. */
45 for (walk = start; walk <= (end - 1); walk++) {
49 if (walk[0].insn <= value &&
50 walk[1].insn > value) {
51 *g2 = (value - walk[0].insn) / 4;
60 extern spinlock_t modlist_lock;
63 search_exception_table(unsigned long addr, unsigned long *g2)
65 unsigned long ret = 0, flags;
67 #ifndef CONFIG_MODULES
68 /* There is only the kernel to search. */
69 ret = search_one_table(__start___ex_table,
70 __stop___ex_table-1, addr, g2);
73 /* The kernel is the last "module" -- no need to treat it special. */
76 spin_lock_irqsave(&modlist_lock, flags);
77 for (mp = module_list; mp != NULL; mp = mp->next) {
78 if (mp->ex_table_start == NULL || !(mp->flags & (MOD_RUNNING | MOD_INITIALIZING)))
80 ret = search_one_table(mp->ex_table_start,
81 mp->ex_table_end-1, addr, g2);
85 spin_unlock_irqrestore(&modlist_lock, flags);