2005-04-16 15:20:36 -07:00
/*
* linux / arch / frv / mm / extable . c
*/
2017-01-10 09:51:08 -05:00
# include <linux/extable.h>
2005-04-16 15:20:36 -07:00
# include <linux/spinlock.h>
2016-12-24 11:46:01 -08:00
# include <linux/uaccess.h>
2005-04-16 15:20:36 -07:00
extern const void __memset_end , __memset_user_error_lr , __memset_user_error_handler ;
extern const void __memcpy_end , __memcpy_user_error_lr , __memcpy_user_error_handler ;
extern spinlock_t modlist_lock ;
2016-12-25 14:12:18 -05:00
int fixup_exception ( struct pt_regs * regs )
2005-04-16 15:20:36 -07:00
{
2006-01-08 01:01:19 -08:00
const struct exception_table_entry * extab ;
2016-12-25 14:12:18 -05:00
unsigned long pc = regs - > pc ;
2005-04-16 15:20:36 -07:00
/* determine if the fault lay during a memcpy_user or a memset_user */
2016-12-25 14:12:18 -05:00
if ( regs - > lr = = ( unsigned long ) & __memset_user_error_lr & &
2005-04-16 15:20:36 -07:00
( unsigned long ) & memset < = pc & & pc < ( unsigned long ) & __memset_end
) {
/* the fault occurred in a protected memset
* - we search for the return address ( in LR ) instead of the program counter
* - it was probably during a clear_user ( )
*/
2016-12-25 14:12:18 -05:00
regs - > pc = ( unsigned long ) & __memset_user_error_handler ;
return 1 ;
2005-04-16 15:20:36 -07:00
}
2006-01-08 01:01:19 -08:00
2016-12-25 14:12:18 -05:00
if ( regs - > lr = = ( unsigned long ) & __memcpy_user_error_lr & &
2006-01-08 01:01:19 -08:00
( unsigned long ) & memcpy < = pc & & pc < ( unsigned long ) & __memcpy_end
) {
2005-04-16 15:20:36 -07:00
/* the fault occurred in a protected memset
* - we search for the return address ( in LR ) instead of the program counter
* - it was probably during a copy_to / from_user ( )
*/
2016-12-25 14:12:18 -05:00
regs - > pc = ( unsigned long ) & __memcpy_user_error_handler ;
return 1 ;
2005-04-16 15:20:36 -07:00
}
2006-01-08 01:01:19 -08:00
extab = search_exception_tables ( pc ) ;
2016-12-25 14:12:18 -05:00
if ( extab ) {
regs - > pc = extab - > fixup ;
return 1 ;
}
2005-04-16 15:20:36 -07:00
2006-01-08 01:01:19 -08:00
return 0 ;
2016-12-25 14:12:18 -05:00
}