Skip to contentSkip to conversation

Exception table cleanup

PATCH New Rusty Russell 1 participant 1 message Jan 5, 2003 Module support

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Exception table cleanup

Re-xmit. Linus, please apply (requires LICENSE patch).

DaveM OKed it. Other archs should be trivial, and the arch maintainers probably want to know about this change anyway.

Rusty.
--
Anyone who quotes me in their sig is an idiot. -- Rusty Russell.

Name: extable cleanup
Author: Rusty Russell
Status: Tested on 2.5.54
Depends: Module/module-license.patch.gz

D: This patch combines the common exception table searching
D: functionality for various architectures, to avoid unneccessary (and
D: currently buggy) duplication, and so that the exception table list
D: and lock can be kept private to module.c.
D:
D: The archs provide "struct exception_table" and "search_extable":
D: the generic infrastructure drives the rest.

kernel/extable.c +7 -35
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/kernel/extable.c .11490-2.5-bk-extable/kernel/extable.c
@@ -16,45 +16,17 @@
     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
 #include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/semaphore.h>
 
 extern const struct exception_table_entry __start___ex_table[];
 extern const struct exception_table_entry __stop___ex_table[];
-extern const struct kernel_symbol __start___ksymtab[];
-extern const struct kernel_symbol __stop___ksymtab[];
-extern const struct kernel_symbol __start___gpl_ksymtab[];
-extern const struct kernel_symbol __stop___gpl_ksymtab[];
 
-/* Protects extables and symbol tables */
-spinlock_t modlist_lock = SPIN_LOCK_UNLOCKED;
-
-/* The exception and symbol tables: start with kernel only. */
-LIST_HEAD(extables);
-LIST_HEAD(symbols);
-
-static struct exception_table kernel_extable;
-static struct kernel_symbol_group kernel_symbols;
-static struct kernel_symbol_group kernel_gpl_symbols;
-
-void __init extable_init(void)
+/* Given an address, look for it in the exception tables. */
+const struct exception_table_entry *search_exception_tables(unsigned long addr)
 {
-	/* Add kernel symbols to symbol table */
-	kernel_symbols.num_syms = (__stop___ksymtab - __start___ksymtab);
-	kernel_symbols.syms = __start___ksymtab;
-	kernel_symbols.gplonly = 0;
-	list_add(&kernel_symbols.list, &symbols);
-	kernel_gpl_symbols.num_syms = (__stop___gpl_ksymtab
-				       - __start___gpl_ksymtab);
-	kernel_gpl_symbols.syms = __start___gpl_ksymtab;
-	kernel_gpl_symbols.gplonly = 1;
-	list_add(&kernel_gpl_symbols.list, &symbols);
+	const struct exception_table_entry *e;
 
-	/* Add kernel exception table to exception tables */
-	kernel_extable.num_entries = (__stop___ex_table -__start___ex_table);
-	kernel_extable.entry = __start___ex_table;
-	list_add(&kernel_extable.list, &extables);
+	e = search_extable(__start___ex_table, __stop___ex_table-1, addr);
+	if (!e)
+		e = search_module_extables(addr);
+	return e;
 }
-
-
kernel/module.c +55 -1

70 lines not on this page · raw message

include/linux/module.h +19 -4
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/include/linux/module.h .11490-2.5-bk-extable/include/linux/module.h
@@ -43,6 +43,12 @@ struct kernel_symbol
 extern int init_module(void);
 extern void cleanup_module(void);
 
+/* Archs provide a method of finding the correct exception table. */
+const struct exception_table_entry *
+search_extable(const struct exception_table_entry *first,
+	       const struct exception_table_entry *last,
+	       unsigned long value);
+
 #ifdef MODULE
 
 /* For replacement modutils, use an alias not a pointer. */
@@ -111,6 +117,9 @@ struct kernel_symbol_group
 	const struct kernel_symbol *syms;
 };
 
+/* Given an address, look for it in the exception tables */
+const struct exception_table_entry *search_exception_tables(unsigned long add);
+
 struct exception_table
 {
 	struct list_head list;
@@ -300,11 +309,21 @@ const char *module_address_lookup(unsign
 				  unsigned long *offset,
 				  char **modname);
 
+/* For extable.c to search modules' exception tables. */
+const struct exception_table_entry *search_module_extables(unsigned long addr);
+
 #else /* !CONFIG_MODULES... */
 #define EXPORT_SYMBOL(sym)
 #define EXPORT_SYMBOL_GPL(sym)
 #define EXPORT_SYMBOL_NOVERS(sym)
 
+/* Given an address, look for it in the exception tables. */
+static inline const struct exception_table_entry *
+search_module_extables(unsigned long addr)
+{
+	return NULL;
+}
+
 /* Get/put a kernel symbol (calls should be symmetric) */
 #define symbol_get(x) (&(x))
 #define symbol_put(x) do { } while(0)
@@ -344,10 +363,6 @@ __attribute__((section(".gnu.linkonce.th
 #endif /* KBUILD_MODNAME */
 #endif /* MODULE */
 
-/* For archs to search exception tables */
-extern struct list_head extables;
-extern spinlock_t modlist_lock;
-
 #define symbol_request(x) try_then_request_module(symbol_get(x), "symbol:" #x)
 
 /* BELOW HERE ALL THESE ARE OBSOLETE AND WILL VANISH */
arch/i386/kernel/traps.c +6 -6
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/i386/kernel/traps.c .11490-2.5-bk-extable/arch/i386/kernel/traps.c
@@ -338,7 +338,7 @@ static inline void do_trap(int trapnr, i
 	}
 
 	kernel_trap: {
-		unsigned long fixup;
+		const struct exception_table_entry *fixup;
 #ifdef CONFIG_PNPBIOS
 		if (unlikely((regs->xcs | 8) == 0x88)) /* 0x80 or 0x88 */
 		{
@@ -354,9 +354,9 @@ static inline void do_trap(int trapnr, i
 		}
 #endif	
 		
-		fixup = search_exception_table(regs->eip);
+		fixup = search_exception_tables(regs->eip);
 		if (fixup)
-			regs->eip = fixup;
+			regs->eip = fixup->fixup;
 		else	
 			die(str, regs, error_code);
 		return;
@@ -435,10 +435,10 @@ gp_in_vm86:
 
 gp_in_kernel:
 	{
-		unsigned long fixup;
-		fixup = search_exception_table(regs->eip);
+		const struct exception_table_entry *fixup;
+		fixup = search_exception_tables(regs->eip);
 		if (fixup) {
-			regs->eip = fixup;
+			regs->eip = fixup->fixup;
 			return;
 		}
 		die("general protection fault", regs, error_code);
arch/i386/mm/extable.c +7 -41

63 lines not on this page · raw message

arch/i386/mm/fault.c +4 -3
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/i386/mm/fault.c .11490-2.5-bk-extable/arch/i386/mm/fault.c
@@ -19,6 +19,7 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 #include <linux/vt_kern.h>		/* For unblank_screen() */
+#include <linux/module.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -154,7 +155,7 @@ asmlinkage void do_page_fault(struct pt_
 	struct vm_area_struct * vma;
 	unsigned long address;
 	unsigned long page;
-	unsigned long fixup;
+	const struct exception_table_entry *fixup;
 	int write;
 	siginfo_t info;
 
@@ -310,8 +311,8 @@ bad_area:
 
 no_context:
 	/* Are we prepared to handle this kernel fault?  */
-	if ((fixup = search_exception_table(regs->eip)) != 0) {
-		regs->eip = fixup;
+	if ((fixup = search_exception_tables(regs->eip)) != NULL) {
+		regs->eip = fixup->fixup;
 		return;
 	}
 
arch/ppc/kernel/traps.c +3 -2
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/ppc/kernel/traps.c .11490-2.5-bk-extable/arch/ppc/kernel/traps.c
@@ -29,6 +29,7 @@
 #include <linux/interrupt.h>
 #include <linux/config.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -115,7 +116,7 @@ void
 MachineCheckException(struct pt_regs *regs)
 {
 #ifdef CONFIG_ALL_PPC
-	unsigned long fixup;
+	const struct exception_table_entry *entry;
 #endif /* CONFIG_ALL_PPC */
 	unsigned long msr = regs->msr;
 
@@ -148,7 +149,7 @@ MachineCheckException(struct pt_regs *re
 	 *  -- paulus.
 	 */
 	if (((msr & 0xffff0000) == 0 || (msr & (0x80000 | 0x40000)))
-	    && (fixup = search_exception_table(regs->nip)) != 0) {
+	    && (entry = search_exception_tables(regs->nip)) != NULL) {
 		/*
 		 * Check that it's a sync instruction, or somewhere
 		 * in the twi; isync; nop sequence that inb/inw/inl uses.
arch/ppc/mm/extable.c +9 -37

72 lines not on this page · raw message

arch/ppc/mm/fault.c +4 -4
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/ppc/mm/fault.c .11490-2.5-bk-extable/arch/ppc/mm/fault.c
@@ -27,6 +27,7 @@
 #include <linux/mm.h>
 #include <linux/interrupt.h>
 #include <linux/highmem.h>
+#include <linux/module.h>
 
 #include <asm/page.h>
 #include <asm/pgtable.h>
@@ -263,12 +264,11 @@ void
 bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
 {
 	extern void die(const char *,struct pt_regs *,long);
-
-	unsigned long fixup;
+	const struct exception_table_entry *entry;
 
 	/* Are we prepared to handle this fault?  */
-	if ((fixup = search_exception_table(regs->nip)) != 0) {
-		regs->nip = fixup;
+	if ((entry = search_exception_tables(regs->nip)) != NULL) {
+		regs->nip = entry->fixup;
 		return;
 	}
 
arch/sparc64/kernel/traps.c +8 -8
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/sparc64/kernel/traps.c .11490-2.5-bk-extable/arch/sparc64/kernel/traps.c
@@ -149,17 +149,17 @@ void data_access_exception (struct pt_re
 
 	if (regs->tstate & TSTATE_PRIV) {
 		/* Test if this comes from uaccess places. */
-		unsigned long fixup, g2;
+		const struct exception_table_entry *entry;
+		unsigned long g2 = regs->u_regs[UREG_G2];
 
-		g2 = regs->u_regs[UREG_G2];
-		if ((fixup = search_exception_table (regs->tpc, &g2))) {
+		if ((entry = search_extables_range(regs->tpc, &g2))) {
 			/* Ouch, somebody is trying ugly VM hole tricks on us... */
 #ifdef DEBUG_EXCEPTIONS
 			printk("Exception: PC<%016lx> faddr<UNKNOWN>\n", regs->tpc);
 			printk("EX_TABLE: insn<%016lx> fixup<%016lx> "
-			       "g2<%016lx>\n", regs->tpc, fixup, g2);
+			       "g2<%016lx>\n", regs->tpc, entry->fixup, g2);
 #endif
-			regs->tpc = fixup;
+			regs->tpc = entry->fixup;
 			regs->tnpc = regs->tpc + 4;
 			regs->u_regs[UREG_G2] = g2;
 			return;
@@ -1370,7 +1370,7 @@ void cheetah_deferred_handler(struct pt_
 			recoverable = 1;
 		} else {
 			unsigned long g2 = regs->u_regs[UREG_G2];
-			unsigned long fixup = search_exception_table(regs->tpc, &g2);
+			unsigned long fixup = search_extables_range(regs->tpc, &g2);
 
 			if (fixup != 0UL) {
 				/* OK, kernel access to userspace. */
@@ -1390,8 +1390,8 @@ void cheetah_deferred_handler(struct pt_
 				/* Only perform fixup if we still have a
 				 * recoverable condition.
 				 */
-				if (fixup != 0UL && recoverable) {
-					regs->tpc = fixup;
+				if (entry && recoverable) {
+					regs->tpc = entry->fixup;
 					regs->tnpc = regs->tpc + 4;
 					regs->u_regs[UREG_G2] = g2;
 				}
arch/sparc64/kernel/unaligned.c +1 -0
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/sparc64/kernel/unaligned.c .11490-2.5-bk-extable/arch/sparc64/kernel/unaligned.c
@@ -10,6 +10,7 @@
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <asm/asi.h>
 #include <asm/ptrace.h>
 #include <asm/pstate.h>
arch/sparc64/mm/extable.c +22 -39

86 lines not on this page · raw message

arch/sparc64/mm/fault.c +2 -1
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/arch/sparc64/mm/fault.c .11490-2.5-bk-extable/arch/sparc64/mm/fault.c
@@ -14,6 +14,7 @@
 #include <linux/mman.h>
 #include <linux/signal.h>
 #include <linux/mm.h>
+#include <linux/module.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
@@ -285,7 +286,7 @@ static void do_kernel_fault(struct pt_re
 	
 		/* Look in asi.h: All _S asis have LS bit set */
 		if ((asi & 0x1) &&
-		    (fixup = search_exception_table (regs->tpc, &g2))) {
+		    (fizup = search_extables_range(regs->tpc, &g2))) {
 			regs->tpc = fixup;
 			regs->tnpc = regs->tpc + 4;
 			regs->u_regs[UREG_G2] = g2;
include/asm-i386/uaccess.h +0 -4
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/include/asm-i386/uaccess.h .11490-2.5-bk-extable/include/asm-i386/uaccess.h
@@ -92,10 +92,6 @@ struct exception_table_entry
 	unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
-
-
 /*
  * These are the main single-value transfer routines.  They automatically
  * use the right size if we just have the right pointer type.
include/asm-ppc/uaccess.h +0 -2
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/include/asm-ppc/uaccess.h .11490-2.5-bk-extable/include/asm-ppc/uaccess.h
@@ -56,8 +56,6 @@ struct exception_table_entry
 	unsigned long insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long);
 extern void sort_exception_table(void);
 
 /*
include/asm-sparc64/uaccess.h +2 -2
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/include/asm-sparc64/uaccess.h .11490-2.5-bk-extable/include/asm-sparc64/uaccess.h
@@ -84,8 +84,8 @@ struct exception_table_entry
         unsigned insn, fixup;
 };
 
-/* Returns 0 if exception not found and fixup otherwise.  */
-extern unsigned long search_exception_table(unsigned long, unsigned long *);
+/* Special exable search, which handles ranges.  Returns fixup */
+unsigned long search_extables_range(unsigned long addr, unsigned long *g2);
 
 extern void __ret_efault(void);
 
init/main.c +0 -2
diff -urpN --exclude TAGS -X /home/rusty/devel/kernel/kernel-patches/current-dontdiff --minimal .11490-2.5-bk-extable.pre/init/main.c .11490-2.5-bk-extable/init/main.c
@@ -61,7 +61,6 @@ extern void init_IRQ(void);
 extern void init_modules(void);
 extern void sock_init(void);
 extern void fork_init(unsigned long);
-extern void extable_init(void);
 extern void mca_init(void);
 extern void sbus_init(void);
 extern void sysctl_init(void);
@@ -391,7 +390,6 @@ asmlinkage void __init start_kernel(void
 		   &__stop___param - &__start___param,
 		   &unknown_bootoption);
 	trap_init();
-	extable_init();
 	rcu_init();
 	init_IRQ();
 	sched_init();