blob: d2f978ad129aa7794a9920f14a014c0dfc502a0f [file] [log] [blame]
Greg Kroah-Hartmanb2441312017-11-01 15:07:57 +01001// SPDX-License-Identifier: GPL-2.0
Mikael Starvik21783c92005-07-27 11:44:40 -07002#include <linux/init.h>
3#include <linux/errno.h>
4#include <linux/kernel.h>
5#include <linux/proc_fs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +09006#include <linux/slab.h>
Mikael Starvik21783c92005-07-27 11:44:40 -07007#include <linux/types.h>
8#include <asm/ptrace.h>
Linus Torvalds7c0f6ba2016-12-24 11:46:01 -08009#include <linux/uaccess.h>
Mikael Starvik21783c92005-07-27 11:44:40 -070010
11#define SAMPLE_BUFFER_SIZE 8192
12
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020013static char *sample_buffer;
14static char *sample_buffer_pos;
Mikael Starvik21783c92005-07-27 11:44:40 -070015static int prof_running = 0;
16
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020017void cris_profile_sample(struct pt_regs *regs)
Mikael Starvik21783c92005-07-27 11:44:40 -070018{
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070019 if (!prof_running)
20 return;
21
22 if (user_mode(regs))
23 *(unsigned int*)sample_buffer_pos = current->pid;
24 else
25 *(unsigned int*)sample_buffer_pos = 0;
26
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020027 *(unsigned int *)(sample_buffer_pos + 4) = instruction_pointer(regs);
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070028 sample_buffer_pos += 8;
29
30 if (sample_buffer_pos == sample_buffer + SAMPLE_BUFFER_SIZE)
31 sample_buffer_pos = sample_buffer;
Mikael Starvik21783c92005-07-27 11:44:40 -070032}
33
34static ssize_t
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070035read_cris_profile(struct file *file, char __user *buf,
36 size_t count, loff_t *ppos)
Mikael Starvik21783c92005-07-27 11:44:40 -070037{
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070038 unsigned long p = *ppos;
Akinobu Mitaed62f772008-07-23 21:28:46 -070039 ssize_t ret;
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070040
Akinobu Mitaed62f772008-07-23 21:28:46 -070041 ret = simple_read_from_buffer(buf, count, ppos, sample_buffer,
42 SAMPLE_BUFFER_SIZE);
43 if (ret < 0)
44 return ret;
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070045
Akinobu Mitaed62f772008-07-23 21:28:46 -070046 memset(sample_buffer + p, 0, ret);
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070047
Akinobu Mitaed62f772008-07-23 21:28:46 -070048 return ret;
Mikael Starvik21783c92005-07-27 11:44:40 -070049}
50
51static ssize_t
52write_cris_profile(struct file *file, const char __user *buf,
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070053 size_t count, loff_t *ppos)
Mikael Starvik21783c92005-07-27 11:44:40 -070054{
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070055 sample_buffer_pos = sample_buffer;
56 memset(sample_buffer, 0, SAMPLE_BUFFER_SIZE);
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020057 return count < SAMPLE_BUFFER_SIZE ? count : SAMPLE_BUFFER_SIZE;
Mikael Starvik21783c92005-07-27 11:44:40 -070058}
59
Arjan van de Ven5dfe4c92007-02-12 00:55:31 -080060static const struct file_operations cris_proc_profile_operations = {
Mikael Starvik21783c92005-07-27 11:44:40 -070061 .read = read_cris_profile,
62 .write = write_cris_profile,
Arnd Bergmann6038f372010-08-15 18:52:59 +020063 .llseek = default_llseek,
Mikael Starvik21783c92005-07-27 11:44:40 -070064};
65
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020066static int __init init_cris_profile(void)
Mikael Starvik21783c92005-07-27 11:44:40 -070067{
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070068 struct proc_dir_entry *entry;
69
70 sample_buffer = kmalloc(SAMPLE_BUFFER_SIZE, GFP_KERNEL);
71 if (!sample_buffer) {
72 return -ENOMEM;
73 }
74
75 sample_buffer_pos = sample_buffer;
76
Denis V. Lunevc2938192008-04-29 01:02:23 -070077 entry = proc_create("system_profile", S_IWUSR | S_IRUGO, NULL,
78 &cris_proc_profile_operations);
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070079 if (entry) {
Geert Uytterhoeven254844d2013-05-07 11:20:26 +020080 proc_set_size(entry, SAMPLE_BUFFER_SIZE);
Cyrill Gorcunov542401d2007-05-06 14:50:56 -070081 }
82 prof_running = 1;
83
84 return 0;
Mikael Starvik21783c92005-07-27 11:44:40 -070085}
Mikael Starvik21783c92005-07-27 11:44:40 -070086__initcall(init_cris_profile);
Jesper Nilssonc1c8f552010-08-04 11:44:08 +020087