• Adrian Hunter's avatar
    perf intel-pt: Fix "context_switch event has no tid" error · 7d537a8d
    Adrian Hunter authored
    A context_switch event can have no tid because pids can be detached from
    a task while the task is still running (in do_exit()). Note this won't
    happen with per-task contexts because then tracing stops at
    perf_event_exit_task()
    
    If a task with no tid gets preempted, or a dying task gets preempted and
    its parent releases it, when it subsequently gets switched back in,
    Intel PT will not be able to determine what task is running and prints
    an error "context_switch event has no tid". However, it is not really an
    error because the task is in kernel space and the decoder can continue
    to decode successfully. Fix by changing the error to be only a logged
    message, and make allowance for tid == -1.
    
    Example:
    
      Using 5.9-rc4 with Preemptible Kernel (Low-Latency Desktop) e.g.
      $ uname -r
      5.9.0-rc4
      $ grep PREEMPT .config
      # CONFIG_PREEMPT_NONE is not set
      # CONFIG_PREEMPT_VOLUNTARY is not set
      CONFIG_PREEMPT=y
      CONFIG_PREEMPT_COUNT=y
      CONFIG_PREEMPTION=y
      CONFIG_PREEMPT_RCU=y
      CONFIG_PREEMPT_NOTIFIERS=y
      CONFIG_DRM_I915_PREEMPT_TIMEOUT=640
      CONFIG_DEBUG_PREEMPT=y
      # CONFIG_PREEMPT_TRACER is not set
      # CONFIG_PREEMPTIRQ_DELAY_TEST is not set
    
    Before:
    
      $ cat forkit.c
    
      #include <sys/types.h>
      #include <unistd.h>
      #include <sys/wait.h>
    
      int main()
      {
              pid_t child;
              int status = 0;
    
              child = fork();
              if (child == 0)
                      return 123;
              wait(&status);
              return 0;
      }
    
      $ gcc -o forkit forkit.c
      $ sudo ~/bin/perf record --kcore -a -m,64M -e intel_pt/cyc/k &
      [1] 11016
      $ taskset 2 ./forkit
      $ sudo pkill perf
      $ [ perf record: Woken up 1 times to write data ]
      [ perf record: Captured and wrote 17.262 MB perf.data ]
    
      [1]+  Terminated              sudo ~/bin/perf record --kcore -a -m,64M -e intel_pt/cyc/k
      $ sudo ~/bin/perf script --show-task-events --show-switch-events --itrace=iqqe-o -C 1 --ns | grep -C 2 forkit
      context_switch event has no tid
               taskset 11019 [001] 66663.270045029:          1 instructions:k:  ffffffffb1d9f844 strnlen_user+0xb4 ([kernel.kallsyms])
               taskset 11019 [001] 66663.270201816:          1 instructions:k:  ffffffffb1a83121 unmap_page_range+0x561 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270327553: PERF_RECORD_COMM exec: forkit:11019/11019
                forkit 11019 [001] 66663.270420028:          1 instructions:k:  ffffffffb1db9537 __clear_user+0x27 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270648704:          1 instructions:k:  ffffffffb18829e6 do_user_addr_fault+0xf6 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270833163:          1 instructions:k:  ffffffffb230a825 irqentry_exit_to_user_mode+0x15 ([kernel.kallsyms])
                forkit 11019 [001] 66663.271092359:          1 instructions:k:  ffffffffb1aea3d9 lock_page_memcg+0x9 ([kernel.kallsyms])
                forkit 11019 [001] 66663.271207092: PERF_RECORD_FORK(11020:11020):(11019:11019)
                forkit 11019 [001] 66663.271234775: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid: 11020/11020
                forkit 11020 [001] 66663.271238407: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid: 11019/11019
                forkit 11020 [001] 66663.271312066:          1 instructions:k:  ffffffffb1a88140 handle_mm_fault+0x10 ([kernel.kallsyms])
                forkit 11020 [001] 66663.271476225: PERF_RECORD_EXIT(11020:11020):(11019:11019)
                forkit 11020 [001] 66663.271497488: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid: 11019/11019
                forkit 11019 [001] 66663.271500523: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid: 11020/11020
                forkit 11019 [001] 66663.271517241:          1 instructions:k:  ffffffffb24012cd error_entry+0x6d ([kernel.kallsyms])
                forkit 11019 [001] 66663.271664080: PERF_RECORD_EXIT(11019:11019):(1386:1386)
    
    After:
    
      $ sudo ~/bin/perf script --show-task-events --show-switch-events --itrace=iqqe-o -C 1 --ns | grep -C 2 forkit
               taskset 11019 [001] 66663.270045029:          1 instructions:k:  ffffffffb1d9f844 strnlen_user+0xb4 ([kernel.kallsyms])
               taskset 11019 [001] 66663.270201816:          1 instructions:k:  ffffffffb1a83121 unmap_page_range+0x561 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270327553: PERF_RECORD_COMM exec: forkit:11019/11019
                forkit 11019 [001] 66663.270420028:          1 instructions:k:  ffffffffb1db9537 __clear_user+0x27 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270648704:          1 instructions:k:  ffffffffb18829e6 do_user_addr_fault+0xf6 ([kernel.kallsyms])
                forkit 11019 [001] 66663.270833163:          1 instructions:k:  ffffffffb230a825 irqentry_exit_to_user_mode+0x15 ([kernel.kallsyms])
                forkit 11019 [001] 66663.271092359:          1 instructions:k:  ffffffffb1aea3d9 lock_page_memcg+0x9 ([kernel.kallsyms])
                forkit 11019 [001] 66663.271207092: PERF_RECORD_FORK(11020:11020):(11019:11019)
                forkit 11019 [001] 66663.271234775: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid: 11020/11020
                forkit 11020 [001] 66663.271238407: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid: 11019/11019
                forkit 11020 [001] 66663.271312066:          1 instructions:k:  ffffffffb1a88140 handle_mm_fault+0x10 ([kernel.kallsyms])
                forkit 11020 [001] 66663.271476225: PERF_RECORD_EXIT(11020:11020):(11019:11019)
                forkit 11020 [001] 66663.271497488: PERF_RECORD_SWITCH_CPU_WIDE OUT preempt  next pid/tid: 11019/11019
                forkit 11019 [001] 66663.271500523: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid: 11020/11020
                forkit 11019 [001] 66663.271517241:          1 instructions:k:  ffffffffb24012cd error_entry+0x6d ([kernel.kallsyms])
                forkit 11019 [001] 66663.271664080: PERF_RECORD_EXIT(11019:11019):(1386:1386)
                forkit 11019 [001] 66663.271688752: PERF_RECORD_SWITCH_CPU_WIDE OUT          next pid/tid:    -1/-1
                   :-1    -1 [001] 66663.271692086: PERF_RECORD_SWITCH_CPU_WIDE IN           prev pid/tid: 11019/11019
                    :-1    -1 [001] 66663.271707466:          1 instructions:k:  ffffffffb18eb096 update_load_avg+0x306 ([kernel.kallsyms])
    
    Fixes: 86c27869 ("perf intel-pt: Add support for PERF_RECORD_SWITCH")
    Signed-off-by: default avatarAdrian Hunter <adrian.hunter@intel.com>
    Cc: Andi Kleen <ak@linux.intel.com>
    Cc: Jiri Olsa <jolsa@redhat.com>
    Cc: Yu-cheng Yu <yu-cheng.yu@intel.com>
    Link: http://lore.kernel.org/lkml/20200909084923.9096-3-adrian.hunter@intel.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
    7d537a8d
intel-pt.c 87.7 KB