1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | #undef TRACE_SYSTEM |
3 | #define TRACE_SYSTEM irq_vectors |
4 | |
5 | #if !defined(_TRACE_IRQ_VECTORS_H) || defined(TRACE_HEADER_MULTI_READ) |
6 | #define _TRACE_IRQ_VECTORS_H |
7 | |
8 | #include <linux/tracepoint.h> |
9 | #include <asm/trace/common.h> |
10 | |
11 | #ifdef CONFIG_X86_LOCAL_APIC |
12 | |
13 | extern int trace_resched_ipi_reg(void); |
14 | extern void trace_resched_ipi_unreg(void); |
15 | |
16 | DECLARE_EVENT_CLASS(x86_irq_vector, |
17 | |
18 | TP_PROTO(int vector), |
19 | |
20 | TP_ARGS(vector), |
21 | |
22 | TP_STRUCT__entry( |
23 | __field( int, vector ) |
24 | ), |
25 | |
26 | TP_fast_assign( |
27 | __entry->vector = vector; |
28 | ), |
29 | |
30 | TP_printk("vector=%d" , __entry->vector) ); |
31 | |
32 | #define DEFINE_IRQ_VECTOR_EVENT(name) \ |
33 | DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \ |
34 | TP_PROTO(int vector), \ |
35 | TP_ARGS(vector), NULL, NULL); \ |
36 | DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ |
37 | TP_PROTO(int vector), \ |
38 | TP_ARGS(vector), NULL, NULL); |
39 | |
40 | #define DEFINE_RESCHED_IPI_EVENT(name) \ |
41 | DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \ |
42 | TP_PROTO(int vector), \ |
43 | TP_ARGS(vector), \ |
44 | trace_resched_ipi_reg, \ |
45 | trace_resched_ipi_unreg); \ |
46 | DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ |
47 | TP_PROTO(int vector), \ |
48 | TP_ARGS(vector), \ |
49 | trace_resched_ipi_reg, \ |
50 | trace_resched_ipi_unreg); |
51 | |
52 | /* |
53 | * local_timer - called when entering/exiting a local timer interrupt |
54 | * vector handler |
55 | */ |
56 | DEFINE_IRQ_VECTOR_EVENT(local_timer); |
57 | |
58 | /* |
59 | * spurious_apic - called when entering/exiting a spurious apic vector handler |
60 | */ |
61 | DEFINE_IRQ_VECTOR_EVENT(spurious_apic); |
62 | |
63 | /* |
64 | * error_apic - called when entering/exiting an error apic vector handler |
65 | */ |
66 | DEFINE_IRQ_VECTOR_EVENT(error_apic); |
67 | |
68 | /* |
69 | * x86_platform_ipi - called when entering/exiting a x86 platform ipi interrupt |
70 | * vector handler |
71 | */ |
72 | DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi); |
73 | |
74 | #ifdef CONFIG_IRQ_WORK |
75 | /* |
76 | * irq_work - called when entering/exiting a irq work interrupt |
77 | * vector handler |
78 | */ |
79 | DEFINE_IRQ_VECTOR_EVENT(irq_work); |
80 | |
81 | /* |
82 | * We must dis-allow sampling irq_work_exit() because perf event sampling |
83 | * itself can cause irq_work, which would lead to an infinite loop; |
84 | * |
85 | * 1) irq_work_exit happens |
86 | * 2) generates perf sample |
87 | * 3) generates irq_work |
88 | * 4) goto 1 |
89 | */ |
90 | TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0); |
91 | #endif |
92 | |
93 | /* |
94 | * The ifdef is required because that tracepoint macro hell emits tracepoint |
95 | * code in files which include this header even if the tracepoint is not |
96 | * enabled. Brilliant stuff that. |
97 | */ |
98 | #ifdef CONFIG_SMP |
99 | /* |
100 | * reschedule - called when entering/exiting a reschedule vector handler |
101 | */ |
102 | DEFINE_RESCHED_IPI_EVENT(reschedule); |
103 | |
104 | /* |
105 | * call_function - called when entering/exiting a call function interrupt |
106 | * vector handler |
107 | */ |
108 | DEFINE_IRQ_VECTOR_EVENT(call_function); |
109 | |
110 | /* |
111 | * call_function_single - called when entering/exiting a call function |
112 | * single interrupt vector handler |
113 | */ |
114 | DEFINE_IRQ_VECTOR_EVENT(call_function_single); |
115 | #endif |
116 | |
117 | #ifdef CONFIG_X86_MCE_THRESHOLD |
118 | /* |
119 | * threshold_apic - called when entering/exiting a threshold apic interrupt |
120 | * vector handler |
121 | */ |
122 | DEFINE_IRQ_VECTOR_EVENT(threshold_apic); |
123 | #endif |
124 | |
125 | #ifdef CONFIG_X86_MCE_AMD |
126 | /* |
127 | * deferred_error_apic - called when entering/exiting a deferred apic interrupt |
128 | * vector handler |
129 | */ |
130 | DEFINE_IRQ_VECTOR_EVENT(deferred_error_apic); |
131 | #endif |
132 | |
133 | #ifdef CONFIG_X86_THERMAL_VECTOR |
134 | /* |
135 | * thermal_apic - called when entering/exiting a thermal apic interrupt |
136 | * vector handler |
137 | */ |
138 | DEFINE_IRQ_VECTOR_EVENT(thermal_apic); |
139 | #endif |
140 | |
141 | TRACE_EVENT(vector_config, |
142 | |
143 | TP_PROTO(unsigned int irq, unsigned int vector, |
144 | unsigned int cpu, unsigned int apicdest), |
145 | |
146 | TP_ARGS(irq, vector, cpu, apicdest), |
147 | |
148 | TP_STRUCT__entry( |
149 | __field( unsigned int, irq ) |
150 | __field( unsigned int, vector ) |
151 | __field( unsigned int, cpu ) |
152 | __field( unsigned int, apicdest ) |
153 | ), |
154 | |
155 | TP_fast_assign( |
156 | __entry->irq = irq; |
157 | __entry->vector = vector; |
158 | __entry->cpu = cpu; |
159 | __entry->apicdest = apicdest; |
160 | ), |
161 | |
162 | TP_printk("irq=%u vector=%u cpu=%u apicdest=0x%08x" , |
163 | __entry->irq, __entry->vector, __entry->cpu, |
164 | __entry->apicdest) |
165 | ); |
166 | |
167 | DECLARE_EVENT_CLASS(vector_mod, |
168 | |
169 | TP_PROTO(unsigned int irq, unsigned int vector, |
170 | unsigned int cpu, unsigned int prev_vector, |
171 | unsigned int prev_cpu), |
172 | |
173 | TP_ARGS(irq, vector, cpu, prev_vector, prev_cpu), |
174 | |
175 | TP_STRUCT__entry( |
176 | __field( unsigned int, irq ) |
177 | __field( unsigned int, vector ) |
178 | __field( unsigned int, cpu ) |
179 | __field( unsigned int, prev_vector ) |
180 | __field( unsigned int, prev_cpu ) |
181 | ), |
182 | |
183 | TP_fast_assign( |
184 | __entry->irq = irq; |
185 | __entry->vector = vector; |
186 | __entry->cpu = cpu; |
187 | __entry->prev_vector = prev_vector; |
188 | __entry->prev_cpu = prev_cpu; |
189 | |
190 | ), |
191 | |
192 | TP_printk("irq=%u vector=%u cpu=%u prev_vector=%u prev_cpu=%u" , |
193 | __entry->irq, __entry->vector, __entry->cpu, |
194 | __entry->prev_vector, __entry->prev_cpu) |
195 | ); |
196 | |
197 | #define DEFINE_IRQ_VECTOR_MOD_EVENT(name) \ |
198 | DEFINE_EVENT_FN(vector_mod, name, \ |
199 | TP_PROTO(unsigned int irq, unsigned int vector, \ |
200 | unsigned int cpu, unsigned int prev_vector, \ |
201 | unsigned int prev_cpu), \ |
202 | TP_ARGS(irq, vector, cpu, prev_vector, prev_cpu), NULL, NULL); \ |
203 | |
204 | DEFINE_IRQ_VECTOR_MOD_EVENT(vector_update); |
205 | DEFINE_IRQ_VECTOR_MOD_EVENT(vector_clear); |
206 | |
207 | DECLARE_EVENT_CLASS(vector_reserve, |
208 | |
209 | TP_PROTO(unsigned int irq, int ret), |
210 | |
211 | TP_ARGS(irq, ret), |
212 | |
213 | TP_STRUCT__entry( |
214 | __field( unsigned int, irq ) |
215 | __field( int, ret ) |
216 | ), |
217 | |
218 | TP_fast_assign( |
219 | __entry->irq = irq; |
220 | __entry->ret = ret; |
221 | ), |
222 | |
223 | TP_printk("irq=%u ret=%d" , __entry->irq, __entry->ret) |
224 | ); |
225 | |
226 | #define DEFINE_IRQ_VECTOR_RESERVE_EVENT(name) \ |
227 | DEFINE_EVENT_FN(vector_reserve, name, \ |
228 | TP_PROTO(unsigned int irq, int ret), \ |
229 | TP_ARGS(irq, ret), NULL, NULL); \ |
230 | |
231 | DEFINE_IRQ_VECTOR_RESERVE_EVENT(vector_reserve_managed); |
232 | DEFINE_IRQ_VECTOR_RESERVE_EVENT(vector_reserve); |
233 | |
234 | TRACE_EVENT(vector_alloc, |
235 | |
236 | TP_PROTO(unsigned int irq, unsigned int vector, bool reserved, |
237 | int ret), |
238 | |
239 | TP_ARGS(irq, vector, reserved, ret), |
240 | |
241 | TP_STRUCT__entry( |
242 | __field( unsigned int, irq ) |
243 | __field( unsigned int, vector ) |
244 | __field( bool, reserved ) |
245 | __field( int, ret ) |
246 | ), |
247 | |
248 | TP_fast_assign( |
249 | __entry->irq = irq; |
250 | __entry->vector = ret < 0 ? 0 : vector; |
251 | __entry->reserved = reserved; |
252 | __entry->ret = ret > 0 ? 0 : ret; |
253 | ), |
254 | |
255 | TP_printk("irq=%u vector=%u reserved=%d ret=%d" , |
256 | __entry->irq, __entry->vector, |
257 | __entry->reserved, __entry->ret) |
258 | ); |
259 | |
260 | TRACE_EVENT(vector_alloc_managed, |
261 | |
262 | TP_PROTO(unsigned int irq, unsigned int vector, |
263 | int ret), |
264 | |
265 | TP_ARGS(irq, vector, ret), |
266 | |
267 | TP_STRUCT__entry( |
268 | __field( unsigned int, irq ) |
269 | __field( unsigned int, vector ) |
270 | __field( int, ret ) |
271 | ), |
272 | |
273 | TP_fast_assign( |
274 | __entry->irq = irq; |
275 | __entry->vector = ret < 0 ? 0 : vector; |
276 | __entry->ret = ret > 0 ? 0 : ret; |
277 | ), |
278 | |
279 | TP_printk("irq=%u vector=%u ret=%d" , |
280 | __entry->irq, __entry->vector, __entry->ret) |
281 | ); |
282 | |
283 | DECLARE_EVENT_CLASS(vector_activate, |
284 | |
285 | TP_PROTO(unsigned int irq, bool is_managed, bool can_reserve, |
286 | bool reserve), |
287 | |
288 | TP_ARGS(irq, is_managed, can_reserve, reserve), |
289 | |
290 | TP_STRUCT__entry( |
291 | __field( unsigned int, irq ) |
292 | __field( bool, is_managed ) |
293 | __field( bool, can_reserve ) |
294 | __field( bool, reserve ) |
295 | ), |
296 | |
297 | TP_fast_assign( |
298 | __entry->irq = irq; |
299 | __entry->is_managed = is_managed; |
300 | __entry->can_reserve = can_reserve; |
301 | __entry->reserve = reserve; |
302 | ), |
303 | |
304 | TP_printk("irq=%u is_managed=%d can_reserve=%d reserve=%d" , |
305 | __entry->irq, __entry->is_managed, __entry->can_reserve, |
306 | __entry->reserve) |
307 | ); |
308 | |
309 | #define DEFINE_IRQ_VECTOR_ACTIVATE_EVENT(name) \ |
310 | DEFINE_EVENT_FN(vector_activate, name, \ |
311 | TP_PROTO(unsigned int irq, bool is_managed, \ |
312 | bool can_reserve, bool reserve), \ |
313 | TP_ARGS(irq, is_managed, can_reserve, reserve), NULL, NULL); \ |
314 | |
315 | DEFINE_IRQ_VECTOR_ACTIVATE_EVENT(vector_activate); |
316 | DEFINE_IRQ_VECTOR_ACTIVATE_EVENT(vector_deactivate); |
317 | |
318 | TRACE_EVENT(vector_teardown, |
319 | |
320 | TP_PROTO(unsigned int irq, bool is_managed, bool has_reserved), |
321 | |
322 | TP_ARGS(irq, is_managed, has_reserved), |
323 | |
324 | TP_STRUCT__entry( |
325 | __field( unsigned int, irq ) |
326 | __field( bool, is_managed ) |
327 | __field( bool, has_reserved ) |
328 | ), |
329 | |
330 | TP_fast_assign( |
331 | __entry->irq = irq; |
332 | __entry->is_managed = is_managed; |
333 | __entry->has_reserved = has_reserved; |
334 | ), |
335 | |
336 | TP_printk("irq=%u is_managed=%d has_reserved=%d" , |
337 | __entry->irq, __entry->is_managed, __entry->has_reserved) |
338 | ); |
339 | |
340 | TRACE_EVENT(vector_setup, |
341 | |
342 | TP_PROTO(unsigned int irq, bool is_legacy, int ret), |
343 | |
344 | TP_ARGS(irq, is_legacy, ret), |
345 | |
346 | TP_STRUCT__entry( |
347 | __field( unsigned int, irq ) |
348 | __field( bool, is_legacy ) |
349 | __field( int, ret ) |
350 | ), |
351 | |
352 | TP_fast_assign( |
353 | __entry->irq = irq; |
354 | __entry->is_legacy = is_legacy; |
355 | __entry->ret = ret; |
356 | ), |
357 | |
358 | TP_printk("irq=%u is_legacy=%d ret=%d" , |
359 | __entry->irq, __entry->is_legacy, __entry->ret) |
360 | ); |
361 | |
362 | TRACE_EVENT(vector_free_moved, |
363 | |
364 | TP_PROTO(unsigned int irq, unsigned int cpu, unsigned int vector, |
365 | bool is_managed), |
366 | |
367 | TP_ARGS(irq, cpu, vector, is_managed), |
368 | |
369 | TP_STRUCT__entry( |
370 | __field( unsigned int, irq ) |
371 | __field( unsigned int, cpu ) |
372 | __field( unsigned int, vector ) |
373 | __field( bool, is_managed ) |
374 | ), |
375 | |
376 | TP_fast_assign( |
377 | __entry->irq = irq; |
378 | __entry->cpu = cpu; |
379 | __entry->vector = vector; |
380 | __entry->is_managed = is_managed; |
381 | ), |
382 | |
383 | TP_printk("irq=%u cpu=%u vector=%u is_managed=%d" , |
384 | __entry->irq, __entry->cpu, __entry->vector, |
385 | __entry->is_managed) |
386 | ); |
387 | |
388 | |
389 | #endif /* CONFIG_X86_LOCAL_APIC */ |
390 | |
391 | #undef TRACE_INCLUDE_PATH |
392 | #undef TRACE_INCLUDE_FILE |
393 | #define TRACE_INCLUDE_PATH . |
394 | #define TRACE_INCLUDE_FILE irq_vectors |
395 | #endif /* _TRACE_IRQ_VECTORS_H */ |
396 | |
397 | /* This part must be outside protection */ |
398 | #include <trace/define_trace.h> |
399 | |