diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 1997-09-12 01:29:55 +0000 |
commit | 545f435ebcfd94a1e7c20b46efe81b4d6ac4e698 (patch) | |
tree | e9ce4bc598d06374bda906f18365984bf22a526a /arch/ppc/mm/extable.c | |
parent | 4291a610eef89d0d5c69d9a10ee6560e1aa36c74 (diff) |
Merge with Linux 2.1.55. More bugfixes and goodies from my private
CVS archive.
Diffstat (limited to 'arch/ppc/mm/extable.c')
-rw-r--r-- | arch/ppc/mm/extable.c | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/arch/ppc/mm/extable.c b/arch/ppc/mm/extable.c new file mode 100644 index 000000000..77e3171bc --- /dev/null +++ b/arch/ppc/mm/extable.c @@ -0,0 +1,65 @@ +/* + * linux/arch/ppc/mm/extable.c + * + * from linux/arch/i386/mm/extable.c + */ + +#include <linux/config.h> +#include <linux/module.h> +#include <asm/uaccess.h> + +extern const struct exception_table_entry __start___ex_table[]; +extern const struct exception_table_entry __stop___ex_table[]; + +static inline unsigned long +search_one_table(const struct exception_table_entry *first, + const struct exception_table_entry *last, + unsigned long value) +{ + const struct exception_table_entry *mid; + for ( mid = first; mid < last; mid++) + { + if ( mid->insn == value ) + return mid->fixup; + } + return 0; +#if 0 + while (first <= last) { + const struct exception_table_entry *mid; + long diff; + mid = (last - first) / 2 + first; + diff = mid->insn - value; + if (diff == 0) + return mid->fixup; + else if (diff < 0) + first = mid+1; + else + last = mid-1; + } +#endif + return 0; +} + +unsigned long +search_exception_table(unsigned long addr) +{ + unsigned long ret; + +#if 1 /*ndef CONFIG_MODULES*/ + /* There is only the kernel to search. */ + ret = search_one_table(__start___ex_table, __stop___ex_table-1, addr); + if (ret) return ret; +#else + /* The kernel is the last "module" -- no need to treat it special. */ + struct module *mp; + for (mp = module_list; mp != NULL; mp = mp->next) { + if (mp->ex_table_start == NULL) + continue; + ret = search_one_table(mp->ex_table_start, + mp->ex_table_end - 1, addr); + if (ret) return ret; + } +#endif + + return 0; +} |