2011-10-31 18:56:19 -05:00
/*
* Stacktrace support for Hexagon
*
2012-09-19 16:22:02 -05:00
* Copyright ( c ) 2010 - 2011 , The Linux Foundation . All rights reserved .
2011-10-31 18:56:19 -05:00
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program ; if not , write to the Free Software
* Foundation , Inc . , 51 Franklin Street , Fifth Floor , Boston , MA
* 02110 - 1301 , USA .
*/
# include <linux/sched.h>
# include <linux/stacktrace.h>
# include <linux/thread_info.h>
# include <linux/module.h>
register unsigned long current_frame_pointer asm ( " r30 " ) ;
struct stackframe {
unsigned long fp ;
unsigned long rets ;
} ;
/*
* Save stack - backtrace addresses into a stack_trace buffer .
*/
void save_stack_trace ( struct stack_trace * trace )
{
unsigned long low , high ;
unsigned long fp ;
struct stackframe * frame ;
int skip = trace - > skip ;
low = ( unsigned long ) task_stack_page ( current ) ;
high = low + THREAD_SIZE ;
fp = current_frame_pointer ;
while ( fp > = low & & fp < = ( high - sizeof ( * frame ) ) ) {
frame = ( struct stackframe * ) fp ;
if ( skip ) {
skip - - ;
} else {
trace - > entries [ trace - > nr_entries + + ] = frame - > rets ;
if ( trace - > nr_entries > = trace - > max_entries )
break ;
}
/*
* The next frame must be at a higher address than the
* current frame .
*/
low = fp + sizeof ( * frame ) ;
fp = frame - > fp ;
}
}
EXPORT_SYMBOL_GPL ( save_stack_trace ) ;