1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/ftrace.h> 3 #include <linux/tracepoint.h> 4 #include <linux/kernel.h> 5 #include <linux/module.h> 6 #include <linux/init.h> 7 #include <linux/rv.h> 8 #include <rv/instrumentation.h> 9 10 #define MODULE_NAME "scpd" 11 12 #include <trace/events/sched.h> 13 #include <trace/events/preemptirq.h> 14 #include <rv_trace.h> 15 #include <monitors/sched/sched.h> 16 17 #define RV_MON_TYPE RV_MON_PER_CPU 18 #include "scpd.h" 19 #include <rv/da_monitor.h> 20 21 static void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip) 22 { 23 da_handle_event(preempt_disable_scpd); 24 } 25 26 static void handle_preempt_enable(void *data, unsigned long ip, unsigned long parent_ip) 27 { 28 da_handle_start_event(preempt_enable_scpd); 29 } 30 31 static void handle_schedule_entry(void *data, bool preempt) 32 { 33 da_handle_event(schedule_entry_scpd); 34 } 35 36 static void handle_schedule_exit(void *data, bool is_switch) 37 { 38 da_handle_event(schedule_exit_scpd); 39 } 40 41 static int enable_scpd(void) 42 { 43 int retval; 44 45 retval = da_monitor_init(); 46 if (retval) 47 return retval; 48 49 rv_attach_trace_probe("scpd", preempt_disable, handle_preempt_disable); 50 rv_attach_trace_probe("scpd", preempt_enable, handle_preempt_enable); 51 rv_attach_trace_probe("scpd", sched_entry_tp, handle_schedule_entry); 52 rv_attach_trace_probe("scpd", sched_exit_tp, handle_schedule_exit); 53 54 return 0; 55 } 56 57 static void disable_scpd(void) 58 { 59 rv_this.enabled = 0; 60 61 rv_detach_trace_probe("scpd", preempt_disable, handle_preempt_disable); 62 rv_detach_trace_probe("scpd", preempt_enable, handle_preempt_enable); 63 rv_detach_trace_probe("scpd", sched_entry_tp, handle_schedule_entry); 64 rv_detach_trace_probe("scpd", sched_exit_tp, handle_schedule_exit); 65 66 da_monitor_destroy(); 67 } 68 69 static struct rv_monitor rv_this = { 70 .name = "scpd", 71 .description = "schedule called with preemption disabled.", 72 .enable = enable_scpd, 73 .disable = disable_scpd, 74 .reset = da_monitor_reset_all, 75 .enabled = 0, 76 }; 77 78 static int __init register_scpd(void) 79 { 80 return rv_register_monitor(&rv_this, &rv_sched); 81 } 82 83 static void __exit unregister_scpd(void) 84 { 85 rv_unregister_monitor(&rv_this); 86 } 87 88 module_init(register_scpd); 89 module_exit(unregister_scpd); 90 91 MODULE_LICENSE("GPL"); 92 MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 93 MODULE_DESCRIPTION("scpd: schedule called with preemption disabled."); 94