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 #include <rv/da_monitor.h> 10 11 #define MODULE_NAME "nrp" 12 13 #include <trace/events/irq.h> 14 #include <trace/events/sched.h> 15 #include <rv_trace.h> 16 #include <monitors/sched/sched.h> 17 18 #include "nrp.h" 19 20 static struct rv_monitor rv_nrp; 21 DECLARE_DA_MON_PER_TASK(nrp, unsigned char); 22 23 #ifdef CONFIG_X86_LOCAL_APIC 24 #include <asm/trace/irq_vectors.h> 25 26 static void handle_vector_irq_entry(void *data, int vector) 27 { 28 da_handle_event_nrp(current, irq_entry_nrp); 29 } 30 31 static void attach_vector_irq(void) 32 { 33 rv_attach_trace_probe("nrp", local_timer_entry, handle_vector_irq_entry); 34 if (IS_ENABLED(CONFIG_IRQ_WORK)) 35 rv_attach_trace_probe("nrp", irq_work_entry, handle_vector_irq_entry); 36 if (IS_ENABLED(CONFIG_SMP)) { 37 rv_attach_trace_probe("nrp", reschedule_entry, handle_vector_irq_entry); 38 rv_attach_trace_probe("nrp", call_function_entry, handle_vector_irq_entry); 39 rv_attach_trace_probe("nrp", call_function_single_entry, handle_vector_irq_entry); 40 } 41 } 42 43 static void detach_vector_irq(void) 44 { 45 rv_detach_trace_probe("nrp", local_timer_entry, handle_vector_irq_entry); 46 if (IS_ENABLED(CONFIG_IRQ_WORK)) 47 rv_detach_trace_probe("nrp", irq_work_entry, handle_vector_irq_entry); 48 if (IS_ENABLED(CONFIG_SMP)) { 49 rv_detach_trace_probe("nrp", reschedule_entry, handle_vector_irq_entry); 50 rv_detach_trace_probe("nrp", call_function_entry, handle_vector_irq_entry); 51 rv_detach_trace_probe("nrp", call_function_single_entry, handle_vector_irq_entry); 52 } 53 } 54 55 #else 56 /* We assume irq_entry tracepoints are sufficient on other architectures */ 57 static void attach_vector_irq(void) { } 58 static void detach_vector_irq(void) { } 59 #endif 60 61 static void handle_irq_entry(void *data, int irq, struct irqaction *action) 62 { 63 da_handle_event_nrp(current, irq_entry_nrp); 64 } 65 66 static void handle_sched_need_resched(void *data, struct task_struct *tsk, 67 int cpu, int tif) 68 { 69 /* 70 * Although need_resched leads to both the rescheduling and preempt_irq 71 * states, it is safer to start the monitor always in preempt_irq, 72 * which may not mirror the system state but makes the monitor simpler, 73 */ 74 if (tif == TIF_NEED_RESCHED) 75 da_handle_start_event_nrp(tsk, sched_need_resched_nrp); 76 } 77 78 static void handle_schedule_entry(void *data, bool preempt) 79 { 80 if (preempt) 81 da_handle_event_nrp(current, schedule_entry_preempt_nrp); 82 else 83 da_handle_event_nrp(current, schedule_entry_nrp); 84 } 85 86 static int enable_nrp(void) 87 { 88 int retval; 89 90 retval = da_monitor_init_nrp(); 91 if (retval) 92 return retval; 93 94 rv_attach_trace_probe("nrp", irq_handler_entry, handle_irq_entry); 95 rv_attach_trace_probe("nrp", sched_set_need_resched_tp, handle_sched_need_resched); 96 rv_attach_trace_probe("nrp", sched_entry_tp, handle_schedule_entry); 97 attach_vector_irq(); 98 99 return 0; 100 } 101 102 static void disable_nrp(void) 103 { 104 rv_nrp.enabled = 0; 105 106 rv_detach_trace_probe("nrp", irq_handler_entry, handle_irq_entry); 107 rv_detach_trace_probe("nrp", sched_set_need_resched_tp, handle_sched_need_resched); 108 rv_detach_trace_probe("nrp", sched_entry_tp, handle_schedule_entry); 109 detach_vector_irq(); 110 111 da_monitor_destroy_nrp(); 112 } 113 114 static struct rv_monitor rv_nrp = { 115 .name = "nrp", 116 .description = "need resched preempts.", 117 .enable = enable_nrp, 118 .disable = disable_nrp, 119 .reset = da_monitor_reset_all_nrp, 120 .enabled = 0, 121 }; 122 123 static int __init register_nrp(void) 124 { 125 return rv_register_monitor(&rv_nrp, &rv_sched); 126 } 127 128 static void __exit unregister_nrp(void) 129 { 130 rv_unregister_monitor(&rv_nrp); 131 } 132 133 module_init(register_nrp); 134 module_exit(unregister_nrp); 135 136 MODULE_LICENSE("GPL"); 137 MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>"); 138 MODULE_DESCRIPTION("nrp: need resched preempts."); 139