Exception table cleanup
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
@@ -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
@@ -43,6 +43,12 @@ struct kernel_symbolextern 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_groupconst 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(unsignunsigned 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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -149,17 +149,17 @@ void data_access_exception (struct pt_reif (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
@@ -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
@@ -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
@@ -92,10 +92,6 @@ struct exception_table_entryunsigned 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
@@ -56,8 +56,6 @@ struct exception_table_entryunsigned 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
@@ -84,8 +84,8 @@ struct exception_table_entryunsigned 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
@@ -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 ();