| Mikael Starvik | 21783c9 | 2005-07-27 11:44:40 -0700 | [diff] [blame] | 1 | #include <linux/init.h> | 
 | 2 | #include <linux/errno.h> | 
 | 3 | #include <linux/kernel.h> | 
 | 4 | #include <linux/proc_fs.h> | 
 | 5 | #include <linux/types.h> | 
 | 6 | #include <asm/ptrace.h> | 
 | 7 | #include <asm/uaccess.h> | 
 | 8 |  | 
 | 9 | #define SAMPLE_BUFFER_SIZE 8192 | 
 | 10 |  | 
 | 11 | static char* sample_buffer; | 
 | 12 | static char* sample_buffer_pos; | 
 | 13 | static int prof_running = 0; | 
 | 14 |  | 
 | 15 | void | 
 | 16 | cris_profile_sample(struct pt_regs* regs) | 
 | 17 | { | 
 | 18 |   if (!prof_running) | 
 | 19 |     return; | 
 | 20 |   if (user_mode(regs)) | 
 | 21 |     *(unsigned int*)sample_buffer_pos = current->pid; | 
 | 22 |   else | 
 | 23 |     *(unsigned int*)sample_buffer_pos = 0; | 
 | 24 |   *(unsigned int*)(sample_buffer_pos + 4) = instruction_pointer(regs); | 
 | 25 |   sample_buffer_pos += 8; | 
 | 26 |   if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE) | 
 | 27 |     sample_buffer_pos = sample_buffer; | 
 | 28 | } | 
 | 29 |  | 
 | 30 | static ssize_t | 
 | 31 | read_cris_profile(struct file *file, char __user *buf, size_t count, loff_t *ppos) | 
 | 32 | { | 
 | 33 |   unsigned long p = *ppos; | 
 | 34 |   if (p > SAMPLE_BUFFER_SIZE) | 
 | 35 |     return 0; | 
 | 36 |   if (p + count > SAMPLE_BUFFER_SIZE) | 
 | 37 |     count = SAMPLE_BUFFER_SIZE - p; | 
 | 38 |   if (copy_to_user(buf, sample_buffer + p,count)) | 
 | 39 | 		return -EFAULT; | 
 | 40 |   memset(sample_buffer + p, 0, count); | 
 | 41 |   *ppos += count; | 
 | 42 |   return count; | 
 | 43 | } | 
 | 44 |  | 
 | 45 | static ssize_t | 
 | 46 | write_cris_profile(struct file *file, const char __user *buf, | 
 | 47 |               size_t count, loff_t *ppos) | 
 | 48 | { | 
 | 49 |   sample_buffer_pos = sample_buffer; | 
 | 50 |   memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE); | 
 | 51 | } | 
 | 52 |  | 
 | 53 | static struct file_operations cris_proc_profile_operations = { | 
 | 54 | 	.read		= read_cris_profile, | 
 | 55 | 	.write		= write_cris_profile, | 
 | 56 | }; | 
 | 57 |  | 
 | 58 | static int | 
 | 59 | __init init_cris_profile(void) | 
 | 60 | { | 
 | 61 |   struct proc_dir_entry *entry; | 
 | 62 |   sample_buffer = (char*)kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL); | 
 | 63 |   sample_buffer_pos = sample_buffer; | 
 | 64 |   entry = create_proc_entry("system_profile", S_IWUSR | S_IRUGO, NULL); | 
 | 65 |   if (entry) { | 
 | 66 |     entry->proc_fops = &cris_proc_profile_operations; | 
 | 67 |     entry->size = SAMPLE_BUFFER_SIZE; | 
 | 68 |   } | 
 | 69 |   prof_running = 1; | 
 | 70 |   return 0; | 
 | 71 | } | 
 | 72 |  | 
 | 73 | __initcall(init_cris_profile); |