#include <linux/module.h>
#include <asm/uaccess.h>
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+}
+
const struct exception_table_entry *
search_extable(const struct exception_table_entry *first,
const struct exception_table_entry *last,
#include <linux/module.h>
#include <asm/uaccess.h>
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
-
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
#include <linux/module.h>
#include <asm/uaccess.h>
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
-
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
# Makefile for the linux cris-specific parts of the memory manager.
#
-obj-y := init.o fault.o tlb.o extable.o ioremap.o
+obj-y := init.o fault.o tlb.o ioremap.o
+++ /dev/null
-/*
- * linux/arch/cris/mm/extable.c
- *
- * $Log: extable.c,v $
- * Revision 1.4 2003/01/09 14:42:52 starvik
- * Merge of Linux 2.5.55
- *
- * Revision 1.3 2002/11/21 07:24:54 starvik
- * Made search_exception_table similar to implementation for other archs
- * (now compiles with CONFIG_MODULES)
- *
- * Revision 1.2 2002/11/18 07:36:55 starvik
- * Removed warning
- *
- * Revision 1.1 2001/12/17 13:59:27 bjornw
- * Initial revision
- *
- * Revision 1.3 2001/09/27 13:52:40 bjornw
- * Harmonize underscore-ness with other parts
- *
- *
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
#
# Note 2! The CFLAGS definition is now in the main makefile...
-obj-y := init.o fault.o memory.o kmap.o extable.o
+obj-y := init.o fault.o memory.o kmap.o
+++ /dev/null
-/*
- * linux/arch/h8300/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
#include <linux/spinlock.h>
#include <asm/uaccess.h>
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
-
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
#include <asm/uaccess.h>
#include <asm/module.h>
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+}
+
const struct exception_table_entry *
search_extable (const struct exception_table_entry *first,
const struct exception_table_entry *last,
# Makefile for the linux m68k-specific parts of the memory manager.
#
-obj-y := init.o fault.o extable.o hwtest.o
+obj-y := init.o fault.o hwtest.o
ifndef CONFIG_SUN3
obj-y += kmap.o memory.o motorola.o
+++ /dev/null
-/*
- * linux/arch/m68k/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[];
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- while (first <= last) {
- const struct exception_table_entry *mid;
- long diff;
-
- mid = (last - first) / 2 + first;
- diff = value - mid->insn;
- if (diff >= 0 && diff <= 2)
- return mid;
- else if (diff > 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
-
# Makefile for the linux m68knommu specific parts of the memory manager.
#
-obj-y += init.o fault.o memory.o kmap.o extable.o
+obj-y += init.o fault.o memory.o kmap.o
+++ /dev/null
-/*
- * linux/arch/m68knommu/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
# Makefile for the Linux/MIPS-specific parts of the memory manager.
#
-obj-y += cache.o extable.o fault.o loadmmu.o pgtable.o
+obj-y += cache.o fault.o loadmmu.o pgtable.o
obj-$(CONFIG_MIPS32) += ioremap.o pgtable-32.o
obj-$(CONFIG_MIPS64) += pgtable-64.o
+++ /dev/null
-/*
- * linux/arch/i386/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
# Makefile for arch/parisc/mm
#
-obj-y := init.o fault.o extable.o ioremap.o
+obj-y := init.o fault.o ioremap.o
+++ /dev/null
-/*
- * Kernel exception handling table support. Derived from arch/i386/mm/extable.c.
- *
- * Copyright (C) 2000 Hewlett-Packard Co
- * Copyright (C) 2000 John Marvin (jsm@fc.hp.com)
- */
-
-#include <asm/uaccess.h>
-
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long addr)
-{
- /* Abort early if the search value is out of range. */
-
- if ((addr < first->addr) || (addr > last->addr))
- return 0;
-
- while (first <= last) {
- const struct exception_table_entry *mid;
- long diff;
-
- mid = first + ((last - first)/2);
- diff = mid->addr - addr;
-
- if (diff == 0)
- return mid;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
-
- return 0;
-}
-
return 0;
}
-/* FIXME: Sort exception table --RR */
int module_finalize(const Elf_Ehdr *hdr,
const Elf_Shdr *sechdrs,
struct module *me)
EXTRA_AFLAGS := -Wa,-mppc64bridge
endif
-obj-y := fault.o init.o mem_pieces.o extable.o \
+obj-y := fault.o init.o mem_pieces.o \
mmu_context.o pgtable.o
obj-$(CONFIG_PPC_STD_MMU) += hashtable.o ppc_mmu.o tlb.o
+++ /dev/null
-/*
- * arch/ppc/mm/extable.c
- *
- * from arch/i386/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-extern struct exception_table_entry __start___ex_table[];
-extern struct exception_table_entry __stop___ex_table[];
-
-/*
- * The exception table needs to be sorted because we use the macros
- * which put things into the exception table in a variety of segments
- * such as the prep, pmac, chrp, etc. segments as well as the init
- * segment and the main kernel text segment.
- */
-static inline void
-sort_ex_table(struct exception_table_entry *start,
- struct exception_table_entry *finish)
-{
- struct exception_table_entry el, *p, *q;
-
- /* insertion sort */
- for (p = start + 1; p < finish; ++p) {
- /* start .. p-1 is sorted */
- if (p[0].insn < p[-1].insn) {
- /* move element p down to its right place */
- el = *p;
- q = p;
- do {
- /* el comes before q[-1], move q[-1] up one */
- q[0] = q[-1];
- --q;
- } while (q > start && el.insn < q[-1].insn);
- *q = el;
- }
- }
-}
-
-void __init
-sort_exception_table(void)
-{
- sort_ex_table(__start___ex_table, __stop___ex_table);
-}
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
*/
list_add(&me->arch.bug_list, &module_bug_list);
- sort_ex_table((struct exception_table_entry *)me->extable,
- (struct exception_table_entry *)me->extable +
- me->num_exentries);
-
return 0;
}
}
extern void (*calibrate_delay)(void);
-extern void sort_exception_table(void);
/*
* Called into from start_kernel, after lock_kernel has been called.
ppc_md.setup_arch();
paging_init();
- sort_exception_table();
ppc64_boot_msg(0x15, "Setup Done");
}
EXTRA_CFLAGS += -mno-minimal-toc
-obj-y := fault.o init.o extable.o imalloc.o hash_utils.o hash_low.o
+obj-y := fault.o init.o imalloc.o hash_utils.o hash_low.o
obj-$(CONFIG_DISCONTIGMEM) += numa.o
obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+++ /dev/null
-/*
- * arch/ppc64/mm/extable.c
- *
- * from arch/i386/mm/extable.c
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <asm/uaccess.h>
-
-extern struct exception_table_entry __start___ex_table[];
-extern struct exception_table_entry __stop___ex_table[];
-
-/*
- * The exception table needs to be sorted because we use the macros
- * which put things into the exception table in a variety of segments
- * as well as the init segment and the main kernel text segment.
- *
- * Also used for modules.
- */
-void __init_or_module sort_ex_table(struct exception_table_entry *start,
- struct exception_table_entry *finish)
-{
- struct exception_table_entry el, *p, *q;
-
- /* insertion sort */
- for (p = start + 1; p < finish; ++p) {
- /* start .. p-1 is sorted */
- if (p[0].insn < p[-1].insn) {
- /* move element p down to its right place */
- el = *p;
- q = p;
- do {
- /* el comes before q[-1], move q[-1] up one */
- q[0] = q[-1];
- --q;
- } while (q > start && el.insn < q[-1].insn);
- *q = el;
- }
- }
-}
-
-void __init
-sort_exception_table(void)
-{
- sort_ex_table(__start___ex_table, __stop___ex_table);
-}
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
# Makefile for the linux s390-specific parts of the memory manager.
#
-obj-y := init.o fault.o ioremap.o extable.o
+obj-y := init.o fault.o ioremap.o
+++ /dev/null
-/*
- * arch/s390/mm/extable.c
- *
- * S390 version
- *
- * identical to arch/i386/mm/extable.c
- */
-
-#include <linux/config.h>
-#include <linux/module.h>
-#include <linux/spinlock.h>
-#include <asm/uaccess.h>
-
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
- return NULL;
-}
#include <linux/module.h>
#include <asm/uaccess.h>
-/* Simple binary search */
-const struct exception_table_entry *
-search_extable(const struct exception_table_entry *first,
- const struct exception_table_entry *last,
- unsigned long value)
-{
- 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;
- else if (diff < 0)
- first = mid+1;
- else
- last = mid-1;
- }
-
- return NULL;
-}
-
int fixup_exception(struct pt_regs *regs)
{
const struct exception_table_entry *fixup;
#include <linux/module.h>
#include <asm/uaccess.h>
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+}
+
/* Caller knows they are in a range if ret->fixup == 0 */
const struct exception_table_entry *
search_extable(const struct exception_table_entry *start,
extern const struct exception_table_entry __start___ex_table[];
extern const struct exception_table_entry __stop___ex_table[];
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+}
+
/* Caller knows they are in a range if ret->fixup == 0 */
const struct exception_table_entry *
search_extable(const struct exception_table_entry *start,
/* When an exception handler is in an non standard section (like __init)
the fixup table can end up unordered. Fix that here. */
-static __init int check_extable(void)
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
{
- extern struct exception_table_entry __start___ex_table[];
- extern struct exception_table_entry __stop___ex_table[];
struct exception_table_entry *e;
int change;
best (and simplest) sort algorithm. */
do {
change = 0;
- for (e = __start___ex_table+1; e < __stop___ex_table; e++) {
+ for (e = start+1; e < finish; e++) {
if (e->insn < e[-1].insn) {
struct exception_table_entry tmp = e[-1];
e[-1] = e[0];
} while (change != 0);
return 0;
}
-core_initcall(check_extable);
unsigned long insn, fixup;
};
-extern void sort_exception_table(void);
-
/*
* These are the main single-value transfer routines. They automatically
* use the right size if we just have the right pointer type.
/* Returns 0 if exception not found and fixup otherwise. */
extern unsigned long search_exception_table(unsigned long);
-extern void sort_exception_table(void);
/*
* These are the main single-value transfer routines. They automatically
search_extable(const struct exception_table_entry *first,
const struct exception_table_entry *last,
unsigned long value);
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish);
+void sort_main_extable(void);
#ifdef MODULE
#define ___module_cat(a,b) __mod_ ## a ## b
page_address_init();
mem_init();
kmem_cache_init();
+ sort_main_extable();
if (late_time_init)
late_time_init();
calibrate_delay();
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
+#include <linux/init.h>
#include <asm/uaccess.h>
#include <asm/sections.h>
-extern const struct exception_table_entry __start___ex_table[];
-extern const struct exception_table_entry __stop___ex_table[];
+extern struct exception_table_entry __start___ex_table[];
+extern struct exception_table_entry __stop___ex_table[];
+
+/* Sort the kernel's built-in exception table */
+void __init sort_main_extable(void)
+{
+ sort_extable(__start___ex_table, __stop___ex_table);
+}
/* Given an address, look for it in the exception tables. */
const struct exception_table_entry *search_exception_tables(unsigned long addr)
struct module *mod;
long err = 0;
void *percpu = NULL, *ptr = NULL; /* Stops spurious gcc warning */
+ struct exception_table_entry *extable;
DEBUGP("load_module: umod=%p, len=%lu, uargs=%p\n",
umod, len, uargs);
}
#endif
- /* Set up exception table */
- mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
- mod->extable = (void *)sechdrs[exindex].sh_addr;
-
/* Now do relocations. */
for (i = 1; i < hdr->e_shnum; i++) {
const char *strtab = (char *)sechdrs[strindex].sh_addr;
goto cleanup;
}
+ /* Set up and sort exception table */
+ mod->num_exentries = sechdrs[exindex].sh_size / sizeof(*mod->extable);
+ mod->extable = extable = (void *)sechdrs[exindex].sh_addr;
+ sort_extable(extable, extable + mod->num_exentries);
+
/* Finally, copy percpu area over. */
percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
sechdrs[pcpuindex].sh_size);
lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
bust_spinlocks.o rbtree.o radix-tree.o dump_stack.o \
kobject.o idr.o div64.o parser.o int_sqrt.o mask.o \
- bitmap.o
+ bitmap.o extable.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
--- /dev/null
+/*
+ * lib/extable.c
+ * Derived from arch/ppc/mm/extable.c and arch/i386/mm/extable.c.
+ *
+ * Copyright (C) 2004 Paul Mackerras, IBM Corp.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <asm/uaccess.h>
+
+extern struct exception_table_entry __start___ex_table[];
+extern struct exception_table_entry __stop___ex_table[];
+
+/*
+ * The exception table needs to be sorted so that the binary
+ * search that we use to find entries in it works properly.
+ * This is used both for the kernel exception table and for
+ * the exception tables of modules that get loaded.
+ */
+void sort_extable(struct exception_table_entry *start,
+ struct exception_table_entry *finish)
+{
+ struct exception_table_entry el, *p, *q;
+
+ /* insertion sort */
+ for (p = start + 1; p < finish; ++p) {
+ /* start .. p-1 is sorted */
+ if (p[0].insn < p[-1].insn) {
+ /* move element p down to its right place */
+ el = *p;
+ q = p;
+ do {
+ /* el comes before q[-1], move q[-1] up one */
+ q[0] = q[-1];
+ --q;
+ } while (q > start && el.insn < q[-1].insn);
+ *q = el;
+ }
+ }
+}
+
+/*
+ * Search one exception table for an entry corresponding to the
+ * given instruction address, and return the address of the entry,
+ * or NULL if none is found.
+ * We use a binary search, and thus we assume that the table is
+ * already sorted.
+ */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+ const struct exception_table_entry *last,
+ unsigned long value)
+{
+ 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;
+ if (diff < 0)
+ first = mid+1;
+ else
+ last = mid-1;
+ }
+ return NULL;
+}