LTTng modularization, import of lttng 0.226
[lttng-modules.git] / probes / kernel-trace.c
CommitLineData
1c8284eb
MD
1/*
2 * ltt/probes/kernel-trace.c
3 *
4 * kernel tracepoint probes.
5 *
6 * (C) Copyright 2009 - Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
7 * Dual LGPL v2.1/GPL v2 license.
8 */
9
10#include <linux/module.h>
11#include <linux/irq.h>
12#include <trace/events/signal.h>
13#include <trace/irq.h>
14#include <trace/sched.h>
15#include <trace/timer.h>
16#include <trace/kernel.h>
17#include <trace/fault.h>
18#include <trace/events/sched.h>
19
20#include "../ltt-tracer.h"
21#include "../ltt-type-serializer.h"
22
23/*
24 * This should probably be added to s390.
25 */
26#ifdef CONFIG_S390
27static struct pt_regs *get_irq_regs(void)
28{
29 return task_pt_regs(current);
30}
31#endif
32
33/*
34 * FIXME :
35 * currently, the specialized tracepoint probes cannot call into other marker
36 * probes, such as ftrace enable/disable. Given we want them to be as fast as
37 * possible, it might not be so bad to lose this flexibility. But that means
38 * such probes would have to connect to tracepoints on their own.
39 */
40
41/* kernel_irq_entry specialized tracepoint probe */
42
43void probe_irq_entry(void *_data, unsigned int id, struct pt_regs *regs,
44 struct irqaction *action);
45
46DEFINE_MARKER_TP(kernel, irq_entry, irq_entry, probe_irq_entry,
47 "ip %lu handler %p irq_id #2u%u kernel_mode #1u%u");
48
49notrace void probe_irq_entry(void *_data, unsigned int id, struct pt_regs *regs,
50 struct irqaction *action)
51{
52 struct marker *marker;
53 struct serialize_long_long_short_char data;
54
55 if (unlikely(!regs))
56 regs = get_irq_regs();
57 if (likely(regs)) {
58 data.f1 = instruction_pointer(regs);
59 data.f4 = !user_mode(regs);
60 } else {
61 data.f1 = 0UL;
62 data.f4 = 1;
63 }
64 data.f2 = (unsigned long) (action ? action->handler : NULL);
65 data.f3 = id;
66
67 marker = &GET_MARKER(kernel, irq_entry);
68 ltt_specialized_trace(marker, marker->single.probe_private,
69 &data, serialize_sizeof(data), sizeof(long));
70}
71
72void probe_irq_next_handler(void *_data, unsigned int id, struct irqaction *action,
73 irqreturn_t prev_ret);
74
75DEFINE_MARKER_TP(kernel, irq_next_handler, irq_next_handler,
76 probe_irq_next_handler,
77 "handler %p prev_ret #1u%u");
78
79notrace void probe_irq_next_handler(void *_data, unsigned int id, struct irqaction *action,
80 irqreturn_t prev_ret)
81{
82 struct marker *marker;
83 struct serialize_long_char data;
84
85 data.f1 = (unsigned long) (action ? action->handler : NULL);
86 data.f2 = prev_ret;
87
88 marker = &GET_MARKER(kernel, irq_next_handler);
89 ltt_specialized_trace(marker, marker->single.probe_private,
90 &data, serialize_sizeof(data), sizeof(long));
91}
92
93/* kernel_irq_exit specialized tracepoint probe */
94
95void probe_irq_exit(void *_data, irqreturn_t retval);
96
97DEFINE_MARKER_TP(kernel, irq_exit, irq_exit, probe_irq_exit,
98 "handled #1u%u");
99
100notrace void probe_irq_exit(void *_data, irqreturn_t retval)
101{
102 struct marker *marker;
103 unsigned char data;
104
105 data = IRQ_RETVAL(retval);
106
107 marker = &GET_MARKER(kernel, irq_exit);
108 ltt_specialized_trace(marker, marker->single.probe_private,
109 &data, sizeof(data), sizeof(data));
110}
111
112/* kernel_softirq_entry specialized tracepoint probe */
113
114void probe_softirq_entry(void *_data, struct softirq_action *h,
115 struct softirq_action *softirq_vec);
116
117DEFINE_MARKER_TP(kernel, softirq_entry, softirq_entry,
118 probe_softirq_entry, "softirq_id #1u%lu");
119
120notrace void probe_softirq_entry(void *_data, struct softirq_action *h,
121 struct softirq_action *softirq_vec)
122{
123 struct marker *marker;
124 unsigned char data;
125
126 data = ((unsigned long)h - (unsigned long)softirq_vec) / sizeof(*h);
127
128 marker = &GET_MARKER(kernel, softirq_entry);
129 ltt_specialized_trace(marker, marker->single.probe_private,
130 &data, sizeof(data), sizeof(data));
131}
132
133/* kernel_softirq_exit specialized tracepoint probe */
134
135void probe_softirq_exit(void *_data, struct softirq_action *h,
136 struct softirq_action *softirq_vec);
137
138DEFINE_MARKER_TP(kernel, softirq_exit, softirq_exit,
139 probe_softirq_exit, "softirq_id #1u%lu");
140
141notrace void probe_softirq_exit(void *_data, struct softirq_action *h,
142 struct softirq_action *softirq_vec)
143{
144 struct marker *marker;
145 unsigned char data;
146
147 data = ((unsigned long)h - (unsigned long)softirq_vec) / sizeof(*h);
148
149 marker = &GET_MARKER(kernel, softirq_exit);
150 ltt_specialized_trace(marker, marker->single.probe_private,
151 &data, sizeof(data), sizeof(data));
152}
153
154/* kernel_softirq_raise specialized tracepoint probe */
155
156void probe_softirq_raise(void *_data, unsigned int nr);
157
158DEFINE_MARKER_TP(kernel, softirq_raise, softirq_raise,
159 probe_softirq_raise, "softirq_id #1u%u");
160
161notrace void probe_softirq_raise(void *_data, unsigned int nr)
162{
163 struct marker *marker;
164 unsigned char data;
165
166 data = nr;
167
168 marker = &GET_MARKER(kernel, softirq_raise);
169 ltt_specialized_trace(marker, marker->single.probe_private,
170 &data, sizeof(data), sizeof(data));
171}
172
173/* Standard probes */
174void probe_irq_tasklet_low_entry(void *_data, struct tasklet_struct *t)
175{
176 trace_mark_tp(kernel, tasklet_low_entry, irq_tasklet_low_entry,
177 probe_irq_tasklet_low_entry, "func %p data %lu",
178 t->func, t->data);
179}
180
181void probe_irq_tasklet_low_exit(void *_data, struct tasklet_struct *t)
182{
183 trace_mark_tp(kernel, tasklet_low_exit, irq_tasklet_low_exit,
184 probe_irq_tasklet_low_exit, "func %p data %lu",
185 t->func, t->data);
186}
187
188void probe_irq_tasklet_high_entry(void *_data, struct tasklet_struct *t)
189{
190 trace_mark_tp(kernel, tasklet_high_entry, irq_tasklet_high_entry,
191 probe_irq_tasklet_high_entry, "func %p data %lu",
192 t->func, t->data);
193}
194
195void probe_irq_tasklet_high_exit(void *_data, struct tasklet_struct *t)
196{
197 trace_mark_tp(kernel, tasklet_high_exit, irq_tasklet_high_exit,
198 probe_irq_tasklet_high_exit, "func %p data %lu",
199 t->func, t->data);
200}
201
202void probe_sched_kthread_stop(void *_data, struct task_struct *t)
203{
204 trace_mark_tp(kernel, kthread_stop, sched_kthread_stop,
205 probe_sched_kthread_stop, "pid %d", t->pid);
206}
207
208void probe_sched_kthread_stop_ret(void *_data, int ret)
209{
210 trace_mark_tp(kernel, kthread_stop_ret, sched_kthread_stop_ret,
211 probe_sched_kthread_stop_ret, "ret %d", ret);
212}
213
214void probe_sched_wait_task(void *_data, struct task_struct *p)
215{
216 trace_mark_tp(kernel, sched_wait_task, sched_wait_task,
217 probe_sched_wait_task, "pid %d state #2d%ld",
218 p->pid, p->state);
219}
220
221/* kernel_sched_try_wakeup specialized tracepoint probe */
222
223void probe_sched_wakeup(void *_data, struct task_struct *p, int success);
224
225DEFINE_MARKER_TP(kernel, sched_try_wakeup, sched_wakeup,
226 probe_sched_wakeup, "pid %d cpu_id %u state #2d%ld");
227
228notrace void probe_sched_wakeup(void *_data, struct task_struct *p, int success)
229{
230 struct marker *marker;
231 struct serialize_int_int_short data;
232
233 data.f1 = p->pid;
234 data.f2 = task_cpu(p);
235 data.f3 = p->state;
236
237 marker = &GET_MARKER(kernel, sched_try_wakeup);
238 ltt_specialized_trace(marker, marker->single.probe_private,
239 &data, serialize_sizeof(data), sizeof(int));
240}
241
242void probe_sched_wakeup_new(void *_data, struct task_struct *p, int success)
243{
244 trace_mark_tp(kernel, sched_wakeup_new_task, sched_wakeup_new,
245 probe_sched_wakeup_new, "pid %d state #2d%ld cpu_id %u",
246 p->pid, p->state, task_cpu(p));
247}
248
249/* kernel_sched_schedule specialized tracepoint probe */
250
251void probe_sched_switch(void *_data, struct task_struct *prev,
252 struct task_struct *next);
253
254DEFINE_MARKER_TP(kernel, sched_schedule, sched_switch, probe_sched_switch,
255 "prev_pid %d next_pid %d prev_state #2d%ld");
256
257notrace void probe_sched_switch(void *_data, struct task_struct *prev,
258 struct task_struct *next)
259{
260 struct marker *marker;
261 struct serialize_int_int_short data;
262
263 data.f1 = prev->pid;
264 data.f2 = next->pid;
265 data.f3 = prev->state;
266
267 marker = &GET_MARKER(kernel, sched_schedule);
268 ltt_specialized_trace(marker, marker->single.probe_private,
269 &data, serialize_sizeof(data), sizeof(int));
270}
271
272void probe_sched_migrate_task(void *_data, struct task_struct *p, int dest_cpu)
273{
274 trace_mark_tp(kernel, sched_migrate_task, sched_migrate_task,
275 probe_sched_migrate_task, "pid %d state #2d%ld dest_cpu %d",
276 p->pid, p->state, dest_cpu);
277}
278
279void probe_sched_signal_send(void *_data, int sig, struct siginfo *info, struct task_struct *t)
280{
281 trace_mark_tp(kernel, send_signal, signal_generate,
282 probe_sched_signal_send, "pid %d signal %d", t->pid, sig);
283}
284
285void probe_sched_process_free(void *_data, struct task_struct *p)
286{
287 trace_mark_tp(kernel, process_free, sched_process_free,
288 probe_sched_process_free, "pid %d", p->pid);
289}
290
291void probe_sched_process_exit(void *_data, struct task_struct *p)
292{
293 trace_mark_tp(kernel, process_exit, sched_process_exit,
294 probe_sched_process_exit, "pid %d", p->pid);
295}
296
297void probe_sched_process_wait(void *_data, struct pid *pid)
298{
299 trace_mark_tp(kernel, process_wait, sched_process_wait,
300 probe_sched_process_wait, "pid %d", pid_nr(pid));
301}
302
303void probe_sched_process_fork(void *_data, struct task_struct *parent,
304 struct task_struct *child)
305{
306 trace_mark_tp(kernel, process_fork, sched_process_fork,
307 probe_sched_process_fork,
308 "parent_pid %d child_pid %d child_tgid %d",
309 parent->pid, child->pid, child->tgid);
310}
311
312void probe_sched_kthread_create(void *_data, void *fn, int pid)
313{
314 trace_mark_tp(kernel, kthread_create, sched_kthread_create,
315 probe_sched_kthread_create,
316 "fn %p pid %d", fn, pid);
317}
318
319void probe_timer_itimer_expired(void *_data, struct signal_struct *sig)
320{
321 trace_mark_tp(kernel, timer_itimer_expired, timer_itimer_expired,
322 probe_timer_itimer_expired, "pid %d",
323 pid_nr(sig->leader_pid));
324}
325
326void probe_timer_itimer_set(void *_data, int which, struct itimerval *value)
327{
328 trace_mark_tp(kernel, timer_itimer_set,
329 timer_itimer_set, probe_timer_itimer_set,
330 "which %d interval_sec %ld interval_usec %ld "
331 "value_sec %ld value_usec %ld",
332 which,
333 value->it_interval.tv_sec,
334 value->it_interval.tv_usec,
335 value->it_value.tv_sec,
336 value->it_value.tv_usec);
337}
338
339/* kernel_timer_set specialized tracepoint probe */
340
341void probe_timer_set(void *_data, struct timer_list *timer);
342
343DEFINE_MARKER_TP(kernel, timer_set, timer_set, probe_timer_set,
344 "expires %lu function %p data %lu");
345
346notrace void probe_timer_set(void *_data, struct timer_list *timer)
347{
348 struct marker *marker;
349 struct serialize_long_long_long data;
350
351 data.f1 = timer->expires;
352 data.f2 = (unsigned long)timer->function;
353 data.f3 = timer->data;
354
355 marker = &GET_MARKER(kernel, timer_set);
356 ltt_specialized_trace(marker, marker->single.probe_private,
357 &data, serialize_sizeof(data), sizeof(long));
358}
359
360void probe_timer_update_time(void *_data, struct timespec *_xtime,
361 struct timespec *_wall_to_monotonic)
362{
363 trace_mark_tp(kernel, timer_update_time, timer_update_time,
364 probe_timer_update_time,
365 "jiffies #8u%llu xtime_sec %ld xtime_nsec %ld "
366 "walltomonotonic_sec %ld walltomonotonic_nsec %ld",
367 (unsigned long long)jiffies_64, _xtime->tv_sec, _xtime->tv_nsec,
368 _wall_to_monotonic->tv_sec, _wall_to_monotonic->tv_nsec);
369}
370
371void probe_timer_timeout(void *_data, struct task_struct *p)
372{
373 trace_mark_tp(kernel, timer_timeout, timer_timeout,
374 probe_timer_timeout, "pid %d", p->pid);
375}
376
377void probe_kernel_printk(void *_data, unsigned long retaddr)
378{
379 trace_mark_tp(kernel, printk, kernel_printk,
380 probe_kernel_printk, "ip 0x%lX", retaddr);
381}
382
383void probe_kernel_vprintk(void *_data, unsigned long retaddr, char *buf, int len)
384{
385 if (len > 0) {
386 unsigned int loglevel;
387 int mark_len;
388 char *mark_buf;
389 char saved_char;
390
391 if (buf[0] == '<' && buf[1] >= '0' &&
392 buf[1] <= '7' && buf[2] == '>') {
393 loglevel = buf[1] - '0';
394 mark_buf = &buf[3];
395 mark_len = len - 3;
396 } else {
397 loglevel = default_message_loglevel;
398 mark_buf = buf;
399 mark_len = len;
400 }
401 if (mark_buf[mark_len - 1] == '\n')
402 mark_len--;
403 saved_char = mark_buf[mark_len];
404 mark_buf[mark_len] = '\0';
405 trace_mark_tp(kernel, vprintk, kernel_vprintk,
406 probe_kernel_vprintk,
407 "loglevel #1u%u string %s ip 0x%lX",
408 loglevel, mark_buf, retaddr);
409 mark_buf[mark_len] = saved_char;
410 }
411}
412
413#ifdef CONFIG_MODULES
414void probe_kernel_module_free(void *_data, struct module *mod)
415{
416 trace_mark_tp(kernel, module_free, kernel_module_free,
417 probe_kernel_module_free, "name %s", mod->name);
418}
419
420void probe_kernel_module_load(void *_data, struct module *mod)
421{
422 trace_mark_tp(kernel, module_load, kernel_module_load,
423 probe_kernel_module_load, "name %s", mod->name);
424}
425#endif
426
427void probe_kernel_panic(void *_data, const char *fmt, va_list args)
428{
429 char info[64];
430 vsnprintf(info, sizeof(info), fmt, args);
431 trace_mark_tp(kernel, panic, kernel_panic, probe_kernel_panic,
432 "info %s", info);
433}
434
435void probe_kernel_kernel_kexec(void *_data, struct kimage *image)
436{
437 trace_mark_tp(kernel, kernel_kexec, kernel_kernel_kexec,
438 probe_kernel_kernel_kexec, "image %p", image);
439}
440
441void probe_kernel_crash_kexec(void *_data, struct kimage *image, struct pt_regs *regs)
442{
443 trace_mark_tp(kernel, crash_kexec, kernel_crash_kexec,
444 probe_kernel_crash_kexec, "image %p ip %p", image,
445 regs ? (void *)instruction_pointer(regs) : NULL);
446}
447
448/* kernel_page_fault_entry specialized tracepoint probe */
449
450void probe_kernel_page_fault_entry(void *_data, struct pt_regs *regs, int trapnr,
451 struct mm_struct *mm, struct vm_area_struct *vma,
452 unsigned long address, int write_access);
453
454DEFINE_MARKER_TP(kernel, page_fault_entry, page_fault_entry,
455 probe_kernel_page_fault_entry,
456 "ip #p%lu address #p%lu trap_id #2u%u write_access #1u%u");
457
458notrace void probe_kernel_page_fault_entry(void *_data, struct pt_regs *regs, int trapnr,
459 struct mm_struct *mm, struct vm_area_struct *vma,
460 unsigned long address, int write_access)
461{
462 struct marker *marker;
463 struct serialize_long_long_short_char data;
464
465 if (likely(regs))
466 data.f1 = instruction_pointer(regs);
467 else
468 data.f1 = 0UL;
469 data.f2 = address;
470 data.f3 = (unsigned short)trapnr;
471 data.f4 = (unsigned char)!!write_access;
472
473 marker = &GET_MARKER(kernel, page_fault_entry);
474 ltt_specialized_trace(marker, marker->single.probe_private,
475 &data, serialize_sizeof(data), sizeof(long));
476}
477
478/* kernel_page_fault_exit specialized tracepoint probe */
479
480void probe_kernel_page_fault_exit(void *_data, int res);
481
482DEFINE_MARKER_TP(kernel, page_fault_exit, page_fault_exit,
483 probe_kernel_page_fault_exit,
484 "res %d");
485
486notrace void probe_kernel_page_fault_exit(void *_data, int res)
487{
488 struct marker *marker;
489
490 marker = &GET_MARKER(kernel, page_fault_exit);
491 ltt_specialized_trace(marker, marker->single.probe_private,
492 &res, sizeof(res), sizeof(res));
493}
494
495/* kernel_page_fault_nosem_entry specialized tracepoint probe */
496
497void probe_kernel_page_fault_nosem_entry(void *_data, struct pt_regs *regs,
498 int trapnr, unsigned long address);
499
500DEFINE_MARKER_TP(kernel, page_fault_nosem_entry, page_fault_nosem_entry,
501 probe_kernel_page_fault_nosem_entry,
502 "ip #p%lu address #p%lu trap_id #2u%u");
503
504notrace void probe_kernel_page_fault_nosem_entry(void *_data, struct pt_regs *regs,
505 int trapnr, unsigned long address)
506{
507 struct marker *marker;
508 struct serialize_long_long_short data;
509
510 if (likely(regs))
511 data.f1 = instruction_pointer(regs);
512 else
513 data.f1 = 0UL;
514 data.f2 = address;
515 data.f3 = (unsigned short)trapnr;
516
517 marker = &GET_MARKER(kernel, page_fault_nosem_entry);
518 ltt_specialized_trace(marker, marker->single.probe_private,
519 &data, serialize_sizeof(data), sizeof(long));
520}
521
522/* kernel_page_fault_nosem_exit specialized tracepoint probe */
523
524void probe_kernel_page_fault_nosem_exit(void *_data, int res);
525
526DEFINE_MARKER_TP(kernel, page_fault_nosem_exit, page_fault_nosem_exit,
527 probe_kernel_page_fault_nosem_exit,
528 MARK_NOARGS);
529
530notrace void probe_kernel_page_fault_nosem_exit(void *_data, int res)
531{
532 struct marker *marker;
533
534 marker = &GET_MARKER(kernel, page_fault_nosem_exit);
535 ltt_specialized_trace(marker, marker->single.probe_private,
536 NULL, 0, 0);
537}
538
539/* kernel_page_fault_get_user_entry specialized tracepoint probe */
540
541void probe_kernel_page_fault_get_user_entry(void *_data, struct mm_struct *mm,
542 struct vm_area_struct *vma, unsigned long address, int write_access);
543
544DEFINE_MARKER_TP(kernel, page_fault_get_user_entry, page_fault_get_user_entry,
545 probe_kernel_page_fault_get_user_entry,
546 "address #p%lu write_access #1u%u");
547
548notrace void probe_kernel_page_fault_get_user_entry(void *_data, struct mm_struct *mm,
549 struct vm_area_struct *vma, unsigned long address, int write_access)
550{
551 struct marker *marker;
552 struct serialize_long_char data;
553
554 data.f1 = address;
555 data.f2 = (unsigned char)!!write_access;
556
557 marker = &GET_MARKER(kernel, page_fault_get_user_entry);
558 ltt_specialized_trace(marker, marker->single.probe_private,
559 &data, serialize_sizeof(data), sizeof(long));
560}
561
562/* kernel_page_fault_get_user_exit specialized tracepoint probe */
563
564void probe_kernel_page_fault_get_user_exit(void *_data, int res);
565
566DEFINE_MARKER_TP(kernel, page_fault_get_user_exit, page_fault_get_user_exit,
567 probe_kernel_page_fault_get_user_exit,
568 "res %d");
569
570notrace void probe_kernel_page_fault_get_user_exit(void *_data, int res)
571{
572 struct marker *marker;
573
574 marker = &GET_MARKER(kernel, page_fault_get_user_exit);
575 ltt_specialized_trace(marker, marker->single.probe_private,
576 &res, sizeof(res), sizeof(res));
577}
578
579MODULE_LICENSE("GPL and additional rights");
580MODULE_AUTHOR("Mathieu Desnoyers");
581MODULE_DESCRIPTION("kernel Tracepoint Probes");
This page took 0.046567 seconds and 4 git commands to generate.