Lynx framebuffers multidomain implementation.
[linux/elbrus.git] / kernel / watch_preempt.c
bloba6169e13cc5a68440b300333ef3f1038d3c4d835
2 #include <linux/module.h>
3 #include <linux/fs.h>
4 #include <linux/init.h>
5 #include <linux/interrupt.h>
6 #include <linux/irqnr.h>
7 #include <linux/proc_fs.h>
8 #include <linux/seq_file.h>
9 #include <linux/timex.h>
10 #include <linux/delay.h>
11 #include <linux/sched.h>
12 #include <asm/uaccess.h>
14 int do_watch_preempt_disable = 0;
15 EXPORT_SYMBOL(do_watch_preempt_disable);
17 DEFINE_PER_CPU(u64, max_prmtdsbled);
18 DEFINE_PER_CPU(u64, tm_prmtdsbled);
19 DEFINE_PER_CPU(u32, nowatch_set);
21 static u32 nowatch_mask = NOPWATCH_DEAD | NOPWATCH_LOCTIM | NEVER_PWATCH;
22 static u64 max_tm;
23 static int num_dumps;
24 #ifdef CONFIG_LATENCY_TRACE
25 static int do_stop_tracing;
26 static u64 tm_stop_tracing;
27 #endif
29 #define peempt_value() (preempt_count() & ~PREEMPT_ACTIVE)
32 #ifdef CONFIG_E90
33 extern u64 get_usec_from_start(void);
34 #endif
37 void save_tm_prmtdsbl(int val)
39 if (val == peempt_value()) {
40 #ifdef CONFIG_E90
41 __get_cpu_var(tm_prmtdsbled) = get_usec_from_start() << 1;
42 #else
43 __get_cpu_var(tm_prmtdsbled) = get_cycles();
44 #endif
47 EXPORT_SYMBOL(save_tm_prmtdsbl);
49 void chck_tm_prmtdsbl(int val)
51 u64 stm = __get_cpu_var(tm_prmtdsbled);
52 #ifdef CONFIG_MCST
53 if (peempt_value() == val) {
54 current->my_last_ipi_prmt_enable =
55 (unsigned long)__builtin_return_address(0);
57 #endif
58 if (stm == 0) {
59 return;
61 if (peempt_value() == val) {
62 if (__get_cpu_var(nowatch_set) & nowatch_mask) {
63 /* Not intersting case for us */
64 __get_cpu_var(nowatch_set) = 0;
65 __get_cpu_var(tm_prmtdsbled) = 0;
66 return;
68 #ifdef CONFIG_E90
69 u64 delta = (get_usec_from_start() << 1) - stm;
70 if (delta > 2000000) {
71 /* we can get wrong value . skip */
72 __get_cpu_var(tm_prmtdsbled) = 0;
73 return;
75 #else
76 u64 delta = get_cycles() - stm;
77 #endif
78 __get_cpu_var(tm_prmtdsbled) = 0;
79 if (delta > __get_cpu_var(max_prmtdsbled)) {
80 __get_cpu_var(max_prmtdsbled) = delta;
82 #ifdef CONFIG_LATENCY_TRACE
83 if (tm_stop_tracing && delta > tm_stop_tracing) {
84 end_tracing();
85 tm_stop_tracing = 0;
86 pr_info("Tracing stopped. delta = 0x%lld\n", delta);
88 #endif
89 #ifdef CONFIG_FTRACE
90 if (delta > 40000)
91 trace_printk("PREEMPT delta=%lld\n", delta);
92 #endif
93 if (max_tm && delta > max_tm && num_dumps > 0) {
94 num_dumps--;
95 if (num_dumps <= 0) {
96 max_tm = 0;
98 WARN(1, "Preempt disable time too long on CPU%d: %llu\n",
99 smp_processor_id(), delta);
103 EXPORT_SYMBOL(chck_tm_prmtdsbl);
105 /* show max prrempt disable time for each CPU */
107 static void *wp_seq_start(struct seq_file *f, loff_t *pos)
109 return (*pos <= num_possible_cpus()) ? pos : NULL;
112 static void *wp_seq_next(struct seq_file *f, void *v, loff_t *pos)
114 (*pos)++;
115 if (*pos >= NR_CPUS)
116 return NULL;
117 return pos;
120 static void wp_seq_stop(struct seq_file *f, void *v)
122 /* Nothing to do */
125 static ssize_t wp_write(struct file *file, const char __user *buf,
126 size_t count, loff_t *ppos)
128 char c;
129 int cpu;
130 char mb[32];
131 char *me;
132 unsigned long l;
133 if (count == 0) {
134 return 0;
136 if (get_user(c, buf)) {
137 return -EFAULT;
139 if (c == '0') {
140 do_watch_preempt_disable = 0;
141 return count;
143 if (c == '1') {
144 if (do_watch_preempt_disable) {
145 do_watch_preempt_disable = 0;
146 udelay(100);
148 for_each_possible_cpu(cpu) {
149 per_cpu(max_prmtdsbled, cpu) = 0;
150 per_cpu(tm_prmtdsbled, cpu) = 0;
152 do_watch_preempt_disable = 1;
153 return count;
155 if (c == 't') {
156 l = (count > 32) ? 32 : (count - 1);
157 if (copy_from_user(mb, buf + 1, l)) {
158 return -EFAULT;
160 max_tm = usecs_2cycles(simple_strtoul(mb, &me, 10));
161 if (*me == 'n') {
162 num_dumps = simple_strtoul(me + 1, NULL, 10);
164 if (num_dumps == 0) {
165 num_dumps = 1;
167 return count;
169 if (c == 'n') {
170 l = (count > 32) ? 32 : (count - 1);
171 if (copy_from_user(mb, buf + 1, l)) {
172 return -EFAULT;
174 num_dumps = simple_strtoul(mb, NULL, 10);
175 return count;
177 if (c == 'N') {
178 l = (count > 32) ? 32 : (count - 1);
179 if (copy_from_user(mb, buf + 1, l)) {
180 return -EFAULT;
182 if (!strncmp(mb, "loctim", 6)) {
183 nowatch_mask |= NOPWATCH_LOCTIM;
184 } else if (!strncmp(mb, "tsbgrow", 7)) {
185 nowatch_mask |= NOPWATCH_TSBGROW;
186 } else if (!strncmp(mb, "sched", 5)) {
187 nowatch_mask |= NOPWATCH_SCHED;
188 } else if (!strncmp(mb, "exitmm", 6)) {
189 nowatch_mask |= NOPWATCH_EXITMM;
190 } else {
191 return -EFAULT;
193 return count;
195 if (c == 'Y') {
196 l = (count > 32) ? 32 : (count - 1);
197 if (copy_from_user(mb, buf + 1, l)) {
198 return -EFAULT;
200 if (!strncmp(mb, "loctim", 6)) {
201 nowatch_mask &= ~NOPWATCH_LOCTIM;
202 } else if (!strncmp(mb, "tsbgrow", 7)) {
203 nowatch_mask &= ~NOPWATCH_TSBGROW;
204 } else if (!strncmp(mb, "sched", 5)) {
205 nowatch_mask &= ~NOPWATCH_SCHED;
206 } else if (!strncmp(mb, "exitmm", 6)) {
207 nowatch_mask &= ~NOPWATCH_EXITMM;
208 } else {
209 return -EFAULT;
211 return count;
214 #ifdef CONFIG_LATENCY_TRACE
215 if (c == 'T') {
216 l = (count > 32) ? 32 : (count - 1);
217 if (copy_from_user(mb, buf + 1, l)) {
218 return -EFAULT;
220 if (tm_stop_tracing) {
221 end_tracing();
223 tm_stop_tracing = usecs_2cycles(simple_strtoul(mb, NULL, 10));
224 begin_tracing();
225 return count;
228 #endif
229 #if defined(CONFIG_E90S) || defined(__e2k__)
230 extern void print_IO_LOCAL_APICS(void);
231 if (c == 'A') {
232 print_IO_LOCAL_APICS();
233 return count;
235 #endif
238 return -EINVAL;
242 int show_wp(struct seq_file *p, void *v)
244 int i = *(loff_t *) v;
246 if (!cpu_online(i)) {
247 return 0;
249 seq_printf(p, "CPU%d\t%llu usecs\n", i,
250 cycles_2usec(per_cpu(max_prmtdsbled, i)));
251 return 0;
254 static const struct seq_operations wp_seq_ops = {
255 .start = wp_seq_start,
256 .next = wp_seq_next,
257 .stop = wp_seq_stop,
258 .show = show_wp,
261 static int wp_open(struct inode *inode, struct file *filp)
263 return seq_open(filp, &wp_seq_ops);
266 static const struct file_operations proc_wp_operations = {
267 .open = wp_open,
268 .read = seq_read,
269 .write = wp_write,
270 .llseek = seq_lseek,
271 .release = seq_release,
274 static int __init proc_wp_init(void)
276 proc_create("watch-preempt", 0, NULL, &proc_wp_operations);
277 return 0;
279 module_init(proc_wp_init);