1/* 2 * linux/arch/frv/mm/extable.c 3 */ 4 5#include <linux/module.h> 6#include <linux/spinlock.h> 7#include <asm/uaccess.h> 8 9extern const void __memset_end, __memset_user_error_lr, __memset_user_error_handler; 10extern const void __memcpy_end, __memcpy_user_error_lr, __memcpy_user_error_handler; 11extern spinlock_t modlist_lock; 12 13 14/*****************************************************************************/ 15/* 16 * see if there's a fixup handler available to deal with a kernel fault 17 */ 18unsigned long search_exception_table(unsigned long pc) 19{ 20 const struct exception_table_entry *extab; 21 22 /* determine if the fault lay during a memcpy_user or a memset_user */ 23 if (__frame->lr == (unsigned long) &__memset_user_error_lr && 24 (unsigned long) &memset <= pc && pc < (unsigned long) &__memset_end 25 ) { 26 /* the fault occurred in a protected memset 27 * - we search for the return address (in LR) instead of the program counter 28 * - it was probably during a clear_user() 29 */ 30 return (unsigned long) &__memset_user_error_handler; 31 } 32 33 if (__frame->lr == (unsigned long) &__memcpy_user_error_lr && 34 (unsigned long) &memcpy <= pc && pc < (unsigned long) &__memcpy_end 35 ) { 36 /* the fault occurred in a protected memset 37 * - we search for the return address (in LR) instead of the program counter 38 * - it was probably during a copy_to/from_user() 39 */ 40 return (unsigned long) &__memcpy_user_error_handler; 41 } 42 43 extab = search_exception_tables(pc); 44 if (extab) 45 return extab->fixup; 46 47 return 0; 48 49} /* end search_exception_table() */ 50