LCOV - code coverage report
Current view: top level - kernel/trace - trace_preemptirq.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 31 48 64.6 %
Date: 2021-04-22 12:43:58 Functions: 4 6 66.7 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : /*
       3             :  * preemptoff and irqoff tracepoints
       4             :  *
       5             :  * Copyright (C) Joel Fernandes (Google) <joel@joelfernandes.org>
       6             :  */
       7             : 
       8             : #include <linux/kallsyms.h>
       9             : #include <linux/uaccess.h>
      10             : #include <linux/module.h>
      11             : #include <linux/ftrace.h>
      12             : #include <linux/kprobes.h>
      13             : #include "trace.h"
      14             : 
      15             : #define CREATE_TRACE_POINTS
      16             : #include <trace/events/preemptirq.h>
      17             : 
      18             : #ifdef CONFIG_TRACE_IRQFLAGS
      19             : /* Per-cpu variable to prevent redundant calls when IRQs already off */
      20             : static DEFINE_PER_CPU(int, tracing_irq_cpu);
      21             : 
      22             : /*
      23             :  * Like trace_hardirqs_on() but without the lockdep invocation. This is
      24             :  * used in the low level entry code where the ordering vs. RCU is important
      25             :  * and lockdep uses a staged approach which splits the lockdep hardirq
      26             :  * tracking into a RCU on and a RCU off section.
      27             :  */
      28      500019 : void trace_hardirqs_on_prepare(void)
      29             : {
      30      500019 :         if (this_cpu_read(tracing_irq_cpu)) {
      31      500079 :                 if (!in_nmi())
      32      500090 :                         trace_irq_enable(CALLER_ADDR0, CALLER_ADDR1);
      33      500114 :                 tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);
      34      500128 :                 this_cpu_write(tracing_irq_cpu, 0);
      35             :         }
      36      500130 : }
      37             : EXPORT_SYMBOL(trace_hardirqs_on_prepare);
      38             : NOKPROBE_SYMBOL(trace_hardirqs_on_prepare);
      39             : 
      40    12450595 : void trace_hardirqs_on(void)
      41             : {
      42    12450595 :         if (this_cpu_read(tracing_irq_cpu)) {
      43    12456436 :                 if (!in_nmi())
      44    12452698 :                         trace_irq_enable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
      45    12438235 :                 tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);
      46    12437961 :                 this_cpu_write(tracing_irq_cpu, 0);
      47             :         }
      48             : 
      49    12439398 :         lockdep_hardirqs_on_prepare(CALLER_ADDR0);
      50    12427562 :         lockdep_hardirqs_on(CALLER_ADDR0);
      51    12422794 : }
      52             : EXPORT_SYMBOL(trace_hardirqs_on);
      53             : NOKPROBE_SYMBOL(trace_hardirqs_on);
      54             : 
      55             : /*
      56             :  * Like trace_hardirqs_off() but without the lockdep invocation. This is
      57             :  * used in the low level entry code where the ordering vs. RCU is important
      58             :  * and lockdep uses a staged approach which splits the lockdep hardirq
      59             :  * tracking into a RCU on and a RCU off section.
      60             :  */
      61      506969 : void trace_hardirqs_off_finish(void)
      62             : {
      63      506969 :         if (!this_cpu_read(tracing_irq_cpu)) {
      64      507701 :                 this_cpu_write(tracing_irq_cpu, 1);
      65      507682 :                 tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);
      66      507677 :                 if (!in_nmi())
      67      507660 :                         trace_irq_disable(CALLER_ADDR0, CALLER_ADDR1);
      68             :         }
      69             : 
      70      507323 : }
      71             : EXPORT_SYMBOL(trace_hardirqs_off_finish);
      72             : NOKPROBE_SYMBOL(trace_hardirqs_off_finish);
      73             : 
      74    12377762 : void trace_hardirqs_off(void)
      75             : {
      76    12377762 :         lockdep_hardirqs_off(CALLER_ADDR0);
      77             : 
      78    12390156 :         if (!this_cpu_read(tracing_irq_cpu)) {
      79    12394366 :                 this_cpu_write(tracing_irq_cpu, 1);
      80    12395783 :                 tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);
      81    12396675 :                 if (!in_nmi())
      82    12400490 :                         trace_irq_disable_rcuidle(CALLER_ADDR0, CALLER_ADDR1);
      83             :         }
      84    12398722 : }
      85             : EXPORT_SYMBOL(trace_hardirqs_off);
      86             : NOKPROBE_SYMBOL(trace_hardirqs_off);
      87             : 
      88           0 : __visible void trace_hardirqs_on_caller(unsigned long caller_addr)
      89             : {
      90           0 :         if (this_cpu_read(tracing_irq_cpu)) {
      91           0 :                 if (!in_nmi())
      92           0 :                         trace_irq_enable_rcuidle(CALLER_ADDR0, caller_addr);
      93           0 :                 tracer_hardirqs_on(CALLER_ADDR0, caller_addr);
      94           0 :                 this_cpu_write(tracing_irq_cpu, 0);
      95             :         }
      96             : 
      97           0 :         lockdep_hardirqs_on_prepare(CALLER_ADDR0);
      98           0 :         lockdep_hardirqs_on(CALLER_ADDR0);
      99           0 : }
     100             : EXPORT_SYMBOL(trace_hardirqs_on_caller);
     101             : NOKPROBE_SYMBOL(trace_hardirqs_on_caller);
     102             : 
     103           0 : __visible void trace_hardirqs_off_caller(unsigned long caller_addr)
     104             : {
     105           0 :         lockdep_hardirqs_off(CALLER_ADDR0);
     106             : 
     107           0 :         if (!this_cpu_read(tracing_irq_cpu)) {
     108           0 :                 this_cpu_write(tracing_irq_cpu, 1);
     109           0 :                 tracer_hardirqs_off(CALLER_ADDR0, caller_addr);
     110           0 :                 if (!in_nmi())
     111           0 :                         trace_irq_disable_rcuidle(CALLER_ADDR0, caller_addr);
     112             :         }
     113           0 : }
     114             : EXPORT_SYMBOL(trace_hardirqs_off_caller);
     115             : NOKPROBE_SYMBOL(trace_hardirqs_off_caller);
     116             : #endif /* CONFIG_TRACE_IRQFLAGS */
     117             : 
     118             : #ifdef CONFIG_TRACE_PREEMPT_TOGGLE
     119             : 
     120             : void trace_preempt_on(unsigned long a0, unsigned long a1)
     121             : {
     122             :         if (!in_nmi())
     123             :                 trace_preempt_enable_rcuidle(a0, a1);
     124             :         tracer_preempt_on(a0, a1);
     125             : }
     126             : 
     127             : void trace_preempt_off(unsigned long a0, unsigned long a1)
     128             : {
     129             :         if (!in_nmi())
     130             :                 trace_preempt_disable_rcuidle(a0, a1);
     131             :         tracer_preempt_off(a0, a1);
     132             : }
     133             : #endif

Generated by: LCOV version 1.14