diff options
Diffstat (limited to 'kernel/trace/trace.h')
-rw-r--r-- | kernel/trace/trace.h | 134 |
1 files changed, 121 insertions, 13 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index c75d7988902c..57d7e5397d56 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -287,20 +287,62 @@ struct tracer { | |||
287 | struct tracer_flags *flags; | 287 | struct tracer_flags *flags; |
288 | bool print_max; | 288 | bool print_max; |
289 | bool use_max_tr; | 289 | bool use_max_tr; |
290 | bool allocated_snapshot; | ||
290 | }; | 291 | }; |
291 | 292 | ||
292 | 293 | ||
293 | /* Only current can touch trace_recursion */ | 294 | /* Only current can touch trace_recursion */ |
294 | #define trace_recursion_inc() do { (current)->trace_recursion++; } while (0) | ||
295 | #define trace_recursion_dec() do { (current)->trace_recursion--; } while (0) | ||
296 | 295 | ||
297 | /* Ring buffer has the 10 LSB bits to count */ | 296 | /* |
298 | #define trace_recursion_buffer() ((current)->trace_recursion & 0x3ff) | 297 | * For function tracing recursion: |
299 | 298 | * The order of these bits are important. | |
300 | /* for function tracing recursion */ | 299 | * |
301 | #define TRACE_INTERNAL_BIT (1<<11) | 300 | * When function tracing occurs, the following steps are made: |
302 | #define TRACE_GLOBAL_BIT (1<<12) | 301 | * If arch does not support a ftrace feature: |
303 | #define TRACE_CONTROL_BIT (1<<13) | 302 | * call internal function (uses INTERNAL bits) which calls... |
303 | * If callback is registered to the "global" list, the list | ||
304 | * function is called and recursion checks the GLOBAL bits. | ||
305 | * then this function calls... | ||
306 | * The function callback, which can use the FTRACE bits to | ||
307 | * check for recursion. | ||
308 | * | ||
309 | * Now if the arch does not suppport a feature, and it calls | ||
310 | * the global list function which calls the ftrace callback | ||
311 | * all three of these steps will do a recursion protection. | ||
312 | * There's no reason to do one if the previous caller already | ||
313 | * did. The recursion that we are protecting against will | ||
314 | * go through the same steps again. | ||
315 | * | ||
316 | * To prevent the multiple recursion checks, if a recursion | ||
317 | * bit is set that is higher than the MAX bit of the current | ||
318 | * check, then we know that the check was made by the previous | ||
319 | * caller, and we can skip the current check. | ||
320 | */ | ||
321 | enum { | ||
322 | TRACE_BUFFER_BIT, | ||
323 | TRACE_BUFFER_NMI_BIT, | ||
324 | TRACE_BUFFER_IRQ_BIT, | ||
325 | TRACE_BUFFER_SIRQ_BIT, | ||
326 | |||
327 | /* Start of function recursion bits */ | ||
328 | TRACE_FTRACE_BIT, | ||
329 | TRACE_FTRACE_NMI_BIT, | ||
330 | TRACE_FTRACE_IRQ_BIT, | ||
331 | TRACE_FTRACE_SIRQ_BIT, | ||
332 | |||
333 | /* GLOBAL_BITs must be greater than FTRACE_BITs */ | ||
334 | TRACE_GLOBAL_BIT, | ||
335 | TRACE_GLOBAL_NMI_BIT, | ||
336 | TRACE_GLOBAL_IRQ_BIT, | ||
337 | TRACE_GLOBAL_SIRQ_BIT, | ||
338 | |||
339 | /* INTERNAL_BITs must be greater than GLOBAL_BITs */ | ||
340 | TRACE_INTERNAL_BIT, | ||
341 | TRACE_INTERNAL_NMI_BIT, | ||
342 | TRACE_INTERNAL_IRQ_BIT, | ||
343 | TRACE_INTERNAL_SIRQ_BIT, | ||
344 | |||
345 | TRACE_CONTROL_BIT, | ||
304 | 346 | ||
305 | /* | 347 | /* |
306 | * Abuse of the trace_recursion. | 348 | * Abuse of the trace_recursion. |
@@ -309,11 +351,77 @@ struct tracer { | |||
309 | * was called in irq context but we have irq tracing off. Since this | 351 | * was called in irq context but we have irq tracing off. Since this |
310 | * can only be modified by current, we can reuse trace_recursion. | 352 | * can only be modified by current, we can reuse trace_recursion. |
311 | */ | 353 | */ |
312 | #define TRACE_IRQ_BIT (1<<13) | 354 | TRACE_IRQ_BIT, |
355 | }; | ||
356 | |||
357 | #define trace_recursion_set(bit) do { (current)->trace_recursion |= (1<<(bit)); } while (0) | ||
358 | #define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(1<<(bit)); } while (0) | ||
359 | #define trace_recursion_test(bit) ((current)->trace_recursion & (1<<(bit))) | ||
360 | |||
361 | #define TRACE_CONTEXT_BITS 4 | ||
362 | |||
363 | #define TRACE_FTRACE_START TRACE_FTRACE_BIT | ||
364 | #define TRACE_FTRACE_MAX ((1 << (TRACE_FTRACE_START + TRACE_CONTEXT_BITS)) - 1) | ||
365 | |||
366 | #define TRACE_GLOBAL_START TRACE_GLOBAL_BIT | ||
367 | #define TRACE_GLOBAL_MAX ((1 << (TRACE_GLOBAL_START + TRACE_CONTEXT_BITS)) - 1) | ||
368 | |||
369 | #define TRACE_LIST_START TRACE_INTERNAL_BIT | ||
370 | #define TRACE_LIST_MAX ((1 << (TRACE_LIST_START + TRACE_CONTEXT_BITS)) - 1) | ||
371 | |||
372 | #define TRACE_CONTEXT_MASK TRACE_LIST_MAX | ||
373 | |||
374 | static __always_inline int trace_get_context_bit(void) | ||
375 | { | ||
376 | int bit; | ||
313 | 377 | ||
314 | #define trace_recursion_set(bit) do { (current)->trace_recursion |= (bit); } while (0) | 378 | if (in_interrupt()) { |
315 | #define trace_recursion_clear(bit) do { (current)->trace_recursion &= ~(bit); } while (0) | 379 | if (in_nmi()) |
316 | #define trace_recursion_test(bit) ((current)->trace_recursion & (bit)) | 380 | bit = 0; |
381 | |||
382 | else if (in_irq()) | ||
383 | bit = 1; | ||
384 | else | ||
385 | bit = 2; | ||
386 | } else | ||
387 | bit = 3; | ||
388 | |||
389 | return bit; | ||
390 | } | ||
391 | |||
392 | static __always_inline int trace_test_and_set_recursion(int start, int max) | ||
393 | { | ||
394 | unsigned int val = current->trace_recursion; | ||
395 | int bit; | ||
396 | |||
397 | /* A previous recursion check was made */ | ||
398 | if ((val & TRACE_CONTEXT_MASK) > max) | ||
399 | return 0; | ||
400 | |||
401 | bit = trace_get_context_bit() + start; | ||
402 | if (unlikely(val & (1 << bit))) | ||
403 | return -1; | ||
404 | |||
405 | val |= 1 << bit; | ||
406 | current->trace_recursion = val; | ||
407 | barrier(); | ||
408 | |||
409 | return bit; | ||
410 | } | ||
411 | |||
412 | static __always_inline void trace_clear_recursion(int bit) | ||
413 | { | ||
414 | unsigned int val = current->trace_recursion; | ||
415 | |||
416 | if (!bit) | ||
417 | return; | ||
418 | |||
419 | bit = 1 << bit; | ||
420 | val &= ~bit; | ||
421 | |||
422 | barrier(); | ||
423 | current->trace_recursion = val; | ||
424 | } | ||
317 | 425 | ||
318 | #define TRACE_PIPE_ALL_CPU -1 | 426 | #define TRACE_PIPE_ALL_CPU -1 |
319 | 427 | ||