2005-07-27 11:44:40 -07:00
# include <linux/init.h>
# include <linux/errno.h>
# include <linux/kernel.h>
# include <linux/proc_fs.h>
# include <linux/types.h>
# include <asm/ptrace.h>
# include <asm/uaccess.h>
# define SAMPLE_BUFFER_SIZE 8192
static char * sample_buffer ;
static char * sample_buffer_pos ;
static int prof_running = 0 ;
void
cris_profile_sample ( struct pt_regs * regs )
{
2007-05-06 14:50:56 -07:00
if ( ! prof_running )
return ;
if ( user_mode ( regs ) )
* ( unsigned int * ) sample_buffer_pos = current - > pid ;
else
* ( unsigned int * ) sample_buffer_pos = 0 ;
* ( unsigned int * ) ( sample_buffer_pos + 4 ) = instruction_pointer ( regs ) ;
sample_buffer_pos + = 8 ;
if ( sample_buffer_pos = = sample_buffer + SAMPLE_BUFFER_SIZE )
sample_buffer_pos = sample_buffer ;
2005-07-27 11:44:40 -07:00
}
static ssize_t
2007-05-06 14:50:56 -07:00
read_cris_profile ( struct file * file , char __user * buf ,
size_t count , loff_t * ppos )
2005-07-27 11:44:40 -07:00
{
2007-05-06 14:50:56 -07:00
unsigned long p = * ppos ;
if ( p > SAMPLE_BUFFER_SIZE )
return 0 ;
if ( p + count > SAMPLE_BUFFER_SIZE )
count = SAMPLE_BUFFER_SIZE - p ;
if ( copy_to_user ( buf , sample_buffer + p , count ) )
2005-07-27 11:44:40 -07:00
return - EFAULT ;
2007-05-06 14:50:56 -07:00
memset ( sample_buffer + p , 0 , count ) ;
* ppos + = count ;
return count ;
2005-07-27 11:44:40 -07:00
}
static ssize_t
write_cris_profile ( struct file * file , const char __user * buf ,
2007-05-06 14:50:56 -07:00
size_t count , loff_t * ppos )
2005-07-27 11:44:40 -07:00
{
2007-05-06 14:50:56 -07:00
sample_buffer_pos = sample_buffer ;
memset ( sample_buffer , 0 , SAMPLE_BUFFER_SIZE ) ;
2005-07-27 11:44:40 -07:00
}
2007-02-12 00:55:31 -08:00
static const struct file_operations cris_proc_profile_operations = {
2005-07-27 11:44:40 -07:00
. read = read_cris_profile ,
. write = write_cris_profile ,
} ;
static int
__init init_cris_profile ( void )
{
2007-05-06 14:50:56 -07:00
struct proc_dir_entry * entry ;
sample_buffer = kmalloc ( SAMPLE_BUFFER_SIZE , GFP_KERNEL ) ;
if ( ! sample_buffer ) {
return - ENOMEM ;
}
sample_buffer_pos = sample_buffer ;
entry = create_proc_entry ( " system_profile " , S_IWUSR | S_IRUGO , NULL ) ;
if ( entry ) {
entry - > proc_fops = & cris_proc_profile_operations ;
entry - > size = SAMPLE_BUFFER_SIZE ;
}
prof_running = 1 ;
return 0 ;
2005-07-27 11:44:40 -07:00
}
__initcall ( init_cris_profile ) ;