diff options
Diffstat (limited to 'arch/x86/mm/extable.c')
-rw-r--r-- | arch/x86/mm/extable.c | 100 |
1 files changed, 28 insertions, 72 deletions
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c index 9dd7e4b7fcde..903ec1e9c326 100644 --- a/arch/x86/mm/extable.c +++ b/arch/x86/mm/extable.c @@ -3,9 +3,6 @@ #include <linux/sort.h> #include <asm/uaccess.h> -typedef bool (*ex_handler_t)(const struct exception_table_entry *, - struct pt_regs *, int); - static inline unsigned long ex_insn_addr(const struct exception_table_entry *x) { @@ -16,56 +13,11 @@ ex_fixup_addr(const struct exception_table_entry *x) { return (unsigned long)&x->fixup + x->fixup; } -static inline ex_handler_t -ex_fixup_handler(const struct exception_table_entry *x) -{ - return (ex_handler_t)((unsigned long)&x->handler + x->handler); -} - -bool ex_handler_default(const struct exception_table_entry *fixup, - struct pt_regs *regs, int trapnr) -{ - regs->ip = ex_fixup_addr(fixup); - return true; -} -EXPORT_SYMBOL(ex_handler_default); - -bool ex_handler_fault(const struct exception_table_entry *fixup, - struct pt_regs *regs, int trapnr) -{ - regs->ip = ex_fixup_addr(fixup); - regs->ax = trapnr; - return true; -} -EXPORT_SYMBOL_GPL(ex_handler_fault); - -bool ex_handler_ext(const struct exception_table_entry *fixup, - struct pt_regs *regs, int trapnr) -{ - /* Special hack for uaccess_err */ - current_thread_info()->uaccess_err = 1; - regs->ip = ex_fixup_addr(fixup); - return true; -} -EXPORT_SYMBOL(ex_handler_ext); - -bool ex_has_fault_handler(unsigned long ip) -{ - const struct exception_table_entry *e; - ex_handler_t handler; - - e = search_exception_tables(ip); - if (!e) - return false; - handler = ex_fixup_handler(e); - - return handler == ex_handler_fault; -} -int fixup_exception(struct pt_regs *regs, int trapnr) +int fixup_exception(struct pt_regs *regs) { - const struct exception_table_entry *e; - ex_handler_t handler; + const struct exception_table_entry *fixup; + unsigned long new_ip; #ifdef CONFIG_PNPBIOS if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { @@ -81,34 +33,42 @@ int fixup_exception(struct pt_regs *regs, int trapnr) } #endif - e = search_exception_tables(regs->ip); - if (!e) - return 0; + fixup = search_exception_tables(regs->ip); + if (fixup) { + new_ip = ex_fixup_addr(fixup); + + if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) { + /* Special hack for uaccess_err */ + current_thread_info()->uaccess_err = 1; + new_ip -= 0x7ffffff0; + } + regs->ip = new_ip; + return 1; + } - handler = ex_fixup_handler(e); - return handler(e, regs, trapnr); + return 0; } /* Restricted version used during very early boot */ int __init early_fixup_exception(unsigned long *ip) { - const struct exception_table_entry *e; + const struct exception_table_entry *fixup; unsigned long new_ip; - ex_handler_t handler; - e = search_exception_tables(*ip); - if (!e) - return 0; + fixup = search_exception_tables(*ip); + if (fixup) { + new_ip = ex_fixup_addr(fixup); - new_ip = ex_fixup_addr(e); - handler = ex_fixup_handler(e); + if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) { + /* uaccess handling not supported during early boot */ + return 0; + } - /* special handling not supported during early boot */ - if (handler != ex_handler_default) - return 0; + *ip = new_ip; + return 1; + } - *ip = new_ip; - return 1; + return 0; } /* @@ -173,8 +133,6 @@ void sort_extable(struct exception_table_entry *start, i += 4; p->fixup += i; i += 4; - p->handler += i; - i += 4; } sort(start, finish - start, sizeof(struct exception_table_entry), @@ -187,8 +145,6 @@ void sort_extable(struct exception_table_entry *start, i += 4; p->fixup -= i; i += 4; - p->handler -= i; - i += 4; } } |