xref: /linux/kernel/trace/rv/monitors/opid/opid.c (revision 4ff261e725d7376c12e745fdbe8a33cd6dbd5a83)
1*61438453SGabriele Monaco // SPDX-License-Identifier: GPL-2.0
2*61438453SGabriele Monaco #include <linux/ftrace.h>
3*61438453SGabriele Monaco #include <linux/tracepoint.h>
4*61438453SGabriele Monaco #include <linux/kernel.h>
5*61438453SGabriele Monaco #include <linux/module.h>
6*61438453SGabriele Monaco #include <linux/init.h>
7*61438453SGabriele Monaco #include <linux/rv.h>
8*61438453SGabriele Monaco #include <rv/instrumentation.h>
9*61438453SGabriele Monaco #include <rv/da_monitor.h>
10*61438453SGabriele Monaco 
11*61438453SGabriele Monaco #define MODULE_NAME "opid"
12*61438453SGabriele Monaco 
13*61438453SGabriele Monaco #include <trace/events/sched.h>
14*61438453SGabriele Monaco #include <trace/events/irq.h>
15*61438453SGabriele Monaco #include <trace/events/preemptirq.h>
16*61438453SGabriele Monaco #include <rv_trace.h>
17*61438453SGabriele Monaco #include <monitors/sched/sched.h>
18*61438453SGabriele Monaco 
19*61438453SGabriele Monaco #include "opid.h"
20*61438453SGabriele Monaco 
21*61438453SGabriele Monaco static struct rv_monitor rv_opid;
22*61438453SGabriele Monaco DECLARE_DA_MON_PER_CPU(opid, unsigned char);
23*61438453SGabriele Monaco 
24*61438453SGabriele Monaco #ifdef CONFIG_X86_LOCAL_APIC
25*61438453SGabriele Monaco #include <asm/trace/irq_vectors.h>
26*61438453SGabriele Monaco 
handle_vector_irq_entry(void * data,int vector)27*61438453SGabriele Monaco static void handle_vector_irq_entry(void *data, int vector)
28*61438453SGabriele Monaco {
29*61438453SGabriele Monaco 	da_handle_event_opid(irq_entry_opid);
30*61438453SGabriele Monaco }
31*61438453SGabriele Monaco 
attach_vector_irq(void)32*61438453SGabriele Monaco static void attach_vector_irq(void)
33*61438453SGabriele Monaco {
34*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", local_timer_entry, handle_vector_irq_entry);
35*61438453SGabriele Monaco 	if (IS_ENABLED(CONFIG_IRQ_WORK))
36*61438453SGabriele Monaco 		rv_attach_trace_probe("opid", irq_work_entry, handle_vector_irq_entry);
37*61438453SGabriele Monaco 	if (IS_ENABLED(CONFIG_SMP)) {
38*61438453SGabriele Monaco 		rv_attach_trace_probe("opid", reschedule_entry, handle_vector_irq_entry);
39*61438453SGabriele Monaco 		rv_attach_trace_probe("opid", call_function_entry, handle_vector_irq_entry);
40*61438453SGabriele Monaco 		rv_attach_trace_probe("opid", call_function_single_entry, handle_vector_irq_entry);
41*61438453SGabriele Monaco 	}
42*61438453SGabriele Monaco }
43*61438453SGabriele Monaco 
detach_vector_irq(void)44*61438453SGabriele Monaco static void detach_vector_irq(void)
45*61438453SGabriele Monaco {
46*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", local_timer_entry, handle_vector_irq_entry);
47*61438453SGabriele Monaco 	if (IS_ENABLED(CONFIG_IRQ_WORK))
48*61438453SGabriele Monaco 		rv_detach_trace_probe("opid", irq_work_entry, handle_vector_irq_entry);
49*61438453SGabriele Monaco 	if (IS_ENABLED(CONFIG_SMP)) {
50*61438453SGabriele Monaco 		rv_detach_trace_probe("opid", reschedule_entry, handle_vector_irq_entry);
51*61438453SGabriele Monaco 		rv_detach_trace_probe("opid", call_function_entry, handle_vector_irq_entry);
52*61438453SGabriele Monaco 		rv_detach_trace_probe("opid", call_function_single_entry, handle_vector_irq_entry);
53*61438453SGabriele Monaco 	}
54*61438453SGabriele Monaco }
55*61438453SGabriele Monaco 
56*61438453SGabriele Monaco #else
57*61438453SGabriele Monaco /* We assume irq_entry tracepoints are sufficient on other architectures */
attach_vector_irq(void)58*61438453SGabriele Monaco static void attach_vector_irq(void) { }
detach_vector_irq(void)59*61438453SGabriele Monaco static void detach_vector_irq(void) { }
60*61438453SGabriele Monaco #endif
61*61438453SGabriele Monaco 
handle_irq_disable(void * data,unsigned long ip,unsigned long parent_ip)62*61438453SGabriele Monaco static void handle_irq_disable(void *data, unsigned long ip, unsigned long parent_ip)
63*61438453SGabriele Monaco {
64*61438453SGabriele Monaco 	da_handle_event_opid(irq_disable_opid);
65*61438453SGabriele Monaco }
66*61438453SGabriele Monaco 
handle_irq_enable(void * data,unsigned long ip,unsigned long parent_ip)67*61438453SGabriele Monaco static void handle_irq_enable(void *data, unsigned long ip, unsigned long parent_ip)
68*61438453SGabriele Monaco {
69*61438453SGabriele Monaco 	da_handle_event_opid(irq_enable_opid);
70*61438453SGabriele Monaco }
71*61438453SGabriele Monaco 
handle_irq_entry(void * data,int irq,struct irqaction * action)72*61438453SGabriele Monaco static void handle_irq_entry(void *data, int irq, struct irqaction *action)
73*61438453SGabriele Monaco {
74*61438453SGabriele Monaco 	da_handle_event_opid(irq_entry_opid);
75*61438453SGabriele Monaco }
76*61438453SGabriele Monaco 
handle_preempt_disable(void * data,unsigned long ip,unsigned long parent_ip)77*61438453SGabriele Monaco static void handle_preempt_disable(void *data, unsigned long ip, unsigned long parent_ip)
78*61438453SGabriele Monaco {
79*61438453SGabriele Monaco 	da_handle_event_opid(preempt_disable_opid);
80*61438453SGabriele Monaco }
81*61438453SGabriele Monaco 
handle_preempt_enable(void * data,unsigned long ip,unsigned long parent_ip)82*61438453SGabriele Monaco static void handle_preempt_enable(void *data, unsigned long ip, unsigned long parent_ip)
83*61438453SGabriele Monaco {
84*61438453SGabriele Monaco 	da_handle_event_opid(preempt_enable_opid);
85*61438453SGabriele Monaco }
86*61438453SGabriele Monaco 
handle_sched_need_resched(void * data,struct task_struct * tsk,int cpu,int tif)87*61438453SGabriele Monaco static void handle_sched_need_resched(void *data, struct task_struct *tsk, int cpu, int tif)
88*61438453SGabriele Monaco {
89*61438453SGabriele Monaco 	/* The monitor's intitial state is not in_irq */
90*61438453SGabriele Monaco 	if (this_cpu_read(hardirq_context))
91*61438453SGabriele Monaco 		da_handle_event_opid(sched_need_resched_opid);
92*61438453SGabriele Monaco 	else
93*61438453SGabriele Monaco 		da_handle_start_event_opid(sched_need_resched_opid);
94*61438453SGabriele Monaco }
95*61438453SGabriele Monaco 
handle_sched_waking(void * data,struct task_struct * p)96*61438453SGabriele Monaco static void handle_sched_waking(void *data, struct task_struct *p)
97*61438453SGabriele Monaco {
98*61438453SGabriele Monaco 	/* The monitor's intitial state is not in_irq */
99*61438453SGabriele Monaco 	if (this_cpu_read(hardirq_context))
100*61438453SGabriele Monaco 		da_handle_event_opid(sched_waking_opid);
101*61438453SGabriele Monaco 	else
102*61438453SGabriele Monaco 		da_handle_start_event_opid(sched_waking_opid);
103*61438453SGabriele Monaco }
104*61438453SGabriele Monaco 
enable_opid(void)105*61438453SGabriele Monaco static int enable_opid(void)
106*61438453SGabriele Monaco {
107*61438453SGabriele Monaco 	int retval;
108*61438453SGabriele Monaco 
109*61438453SGabriele Monaco 	retval = da_monitor_init_opid();
110*61438453SGabriele Monaco 	if (retval)
111*61438453SGabriele Monaco 		return retval;
112*61438453SGabriele Monaco 
113*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", irq_disable, handle_irq_disable);
114*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", irq_enable, handle_irq_enable);
115*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", irq_handler_entry, handle_irq_entry);
116*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", preempt_disable, handle_preempt_disable);
117*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", preempt_enable, handle_preempt_enable);
118*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", sched_set_need_resched_tp, handle_sched_need_resched);
119*61438453SGabriele Monaco 	rv_attach_trace_probe("opid", sched_waking, handle_sched_waking);
120*61438453SGabriele Monaco 	attach_vector_irq();
121*61438453SGabriele Monaco 
122*61438453SGabriele Monaco 	return 0;
123*61438453SGabriele Monaco }
124*61438453SGabriele Monaco 
disable_opid(void)125*61438453SGabriele Monaco static void disable_opid(void)
126*61438453SGabriele Monaco {
127*61438453SGabriele Monaco 	rv_opid.enabled = 0;
128*61438453SGabriele Monaco 
129*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", irq_disable, handle_irq_disable);
130*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", irq_enable, handle_irq_enable);
131*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", irq_handler_entry, handle_irq_entry);
132*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", preempt_disable, handle_preempt_disable);
133*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", preempt_enable, handle_preempt_enable);
134*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", sched_set_need_resched_tp, handle_sched_need_resched);
135*61438453SGabriele Monaco 	rv_detach_trace_probe("opid", sched_waking, handle_sched_waking);
136*61438453SGabriele Monaco 	detach_vector_irq();
137*61438453SGabriele Monaco 
138*61438453SGabriele Monaco 	da_monitor_destroy_opid();
139*61438453SGabriele Monaco }
140*61438453SGabriele Monaco 
141*61438453SGabriele Monaco /*
142*61438453SGabriele Monaco  * This is the monitor register section.
143*61438453SGabriele Monaco  */
144*61438453SGabriele Monaco static struct rv_monitor rv_opid = {
145*61438453SGabriele Monaco 	.name = "opid",
146*61438453SGabriele Monaco 	.description = "operations with preemption and irq disabled.",
147*61438453SGabriele Monaco 	.enable = enable_opid,
148*61438453SGabriele Monaco 	.disable = disable_opid,
149*61438453SGabriele Monaco 	.reset = da_monitor_reset_all_opid,
150*61438453SGabriele Monaco 	.enabled = 0,
151*61438453SGabriele Monaco };
152*61438453SGabriele Monaco 
register_opid(void)153*61438453SGabriele Monaco static int __init register_opid(void)
154*61438453SGabriele Monaco {
155*61438453SGabriele Monaco 	return rv_register_monitor(&rv_opid, &rv_sched);
156*61438453SGabriele Monaco }
157*61438453SGabriele Monaco 
unregister_opid(void)158*61438453SGabriele Monaco static void __exit unregister_opid(void)
159*61438453SGabriele Monaco {
160*61438453SGabriele Monaco 	rv_unregister_monitor(&rv_opid);
161*61438453SGabriele Monaco }
162*61438453SGabriele Monaco 
163*61438453SGabriele Monaco module_init(register_opid);
164*61438453SGabriele Monaco module_exit(unregister_opid);
165*61438453SGabriele Monaco 
166*61438453SGabriele Monaco MODULE_LICENSE("GPL");
167*61438453SGabriele Monaco MODULE_AUTHOR("Gabriele Monaco <gmonaco@redhat.com>");
168*61438453SGabriele Monaco MODULE_DESCRIPTION("opid: operations with preemption and irq disabled.");
169