xref: /qemu/scripts/kvm/kvm_flightrecorder (revision f03868bd5653265e97b253102d77d83ea85efdea)
1b3c09bdeSStefan Hajnoczi#!/usr/bin/env python
2b3c09bdeSStefan Hajnoczi#
3b3c09bdeSStefan Hajnoczi# KVM Flight Recorder - ring buffer tracing script
4b3c09bdeSStefan Hajnoczi#
5b3c09bdeSStefan Hajnoczi# Copyright (C) 2012 IBM Corp
6b3c09bdeSStefan Hajnoczi#
7b3c09bdeSStefan Hajnoczi# Author: Stefan Hajnoczi <stefanha@linux.vnet.ibm.com>
8b3c09bdeSStefan Hajnoczi#
9b3c09bdeSStefan Hajnoczi# This script provides a command-line interface to kvm ftrace and is designed
10b3c09bdeSStefan Hajnoczi# to be used as a flight recorder that is always running.  To start in-memory
11b3c09bdeSStefan Hajnoczi# recording:
12b3c09bdeSStefan Hajnoczi#
13b3c09bdeSStefan Hajnoczi# sudo kvm_flightrecorder start 8192  # 8 MB per-cpu ring buffers
14b3c09bdeSStefan Hajnoczi#
15b3c09bdeSStefan Hajnoczi# The per-cpu ring buffer size can be given in KB as an optional argument to
16b3c09bdeSStefan Hajnoczi# the 'start' subcommand.
17b3c09bdeSStefan Hajnoczi#
18b3c09bdeSStefan Hajnoczi# To stop the flight recorder:
19b3c09bdeSStefan Hajnoczi#
20b3c09bdeSStefan Hajnoczi# sudo kvm_flightrecorder stop
21b3c09bdeSStefan Hajnoczi#
22b3c09bdeSStefan Hajnoczi# To dump the contents of the flight recorder (this can be done when the
23b3c09bdeSStefan Hajnoczi# recorder is stopped or while it is running):
24b3c09bdeSStefan Hajnoczi#
25b3c09bdeSStefan Hajnoczi# sudo kvm_flightrecorder dump >/path/to/dump.txt
26b3c09bdeSStefan Hajnoczi#
27b3c09bdeSStefan Hajnoczi# To observe the trace while it is running, use the 'tail' subcommand:
28b3c09bdeSStefan Hajnoczi#
29b3c09bdeSStefan Hajnoczi# sudo kvm_flightrecorder tail
30b3c09bdeSStefan Hajnoczi#
31b3c09bdeSStefan Hajnoczi# Note that the flight recorder may impact overall system performance by
32b3c09bdeSStefan Hajnoczi# consuming CPU cycles.  No disk I/O is performed since the ring buffer holds a
33b3c09bdeSStefan Hajnoczi# fixed-size in-memory trace.
34b3c09bdeSStefan Hajnoczi
35*f03868bdSEduardo Habkostfrom __future__ import print_function
36b3c09bdeSStefan Hajnocziimport sys
37b3c09bdeSStefan Hajnocziimport os
38b3c09bdeSStefan Hajnoczi
39b3c09bdeSStefan Hajnoczitracing_dir = '/sys/kernel/debug/tracing'
40b3c09bdeSStefan Hajnoczi
41b3c09bdeSStefan Hajnoczidef trace_path(*args):
42b3c09bdeSStefan Hajnoczi    return os.path.join(tracing_dir, *args)
43b3c09bdeSStefan Hajnoczi
44b3c09bdeSStefan Hajnoczidef write_file(path, data):
45b3c09bdeSStefan Hajnoczi    open(path, 'wb').write(data)
46b3c09bdeSStefan Hajnoczi
47b3c09bdeSStefan Hajnoczidef enable_event(subsystem, event, enable):
48b3c09bdeSStefan Hajnoczi    write_file(trace_path('events', subsystem, event, 'enable'), '1' if enable else '0')
49b3c09bdeSStefan Hajnoczi
50b3c09bdeSStefan Hajnoczidef enable_subsystem(subsystem, enable):
51b3c09bdeSStefan Hajnoczi    write_file(trace_path('events', subsystem, 'enable'), '1' if enable else '0')
52b3c09bdeSStefan Hajnoczi
53b3c09bdeSStefan Hajnoczidef start_tracing():
54b3c09bdeSStefan Hajnoczi    enable_subsystem('kvm', True)
55b3c09bdeSStefan Hajnoczi    write_file(trace_path('tracing_on'), '1')
56b3c09bdeSStefan Hajnoczi
57b3c09bdeSStefan Hajnoczidef stop_tracing():
58b3c09bdeSStefan Hajnoczi    write_file(trace_path('tracing_on'), '0')
59b3c09bdeSStefan Hajnoczi    enable_subsystem('kvm', False)
60b3c09bdeSStefan Hajnoczi    write_file(trace_path('events', 'enable'), '0')
61b3c09bdeSStefan Hajnoczi    write_file(trace_path('current_tracer'), 'nop')
62b3c09bdeSStefan Hajnoczi
63b3c09bdeSStefan Hajnoczidef dump_trace():
64b3c09bdeSStefan Hajnoczi    tracefile = open(trace_path('trace'), 'r')
65b3c09bdeSStefan Hajnoczi    try:
66b3c09bdeSStefan Hajnoczi        lines = True
67b3c09bdeSStefan Hajnoczi        while lines:
68b3c09bdeSStefan Hajnoczi            lines = tracefile.readlines(64 * 1024)
69b3c09bdeSStefan Hajnoczi            sys.stdout.writelines(lines)
70b3c09bdeSStefan Hajnoczi    except KeyboardInterrupt:
71b3c09bdeSStefan Hajnoczi        pass
72b3c09bdeSStefan Hajnoczi
73b3c09bdeSStefan Hajnoczidef tail_trace():
74b3c09bdeSStefan Hajnoczi    try:
75b3c09bdeSStefan Hajnoczi        for line in open(trace_path('trace_pipe'), 'r'):
76b3c09bdeSStefan Hajnoczi            sys.stdout.write(line)
77b3c09bdeSStefan Hajnoczi    except KeyboardInterrupt:
78b3c09bdeSStefan Hajnoczi        pass
79b3c09bdeSStefan Hajnoczi
80b3c09bdeSStefan Hajnoczidef usage():
81*f03868bdSEduardo Habkost    print('Usage: %s start [buffer_size_kb] | stop | dump | tail' % sys.argv[0])
82*f03868bdSEduardo Habkost    print('Control the KVM flight recorder tracing.')
83b3c09bdeSStefan Hajnoczi    sys.exit(0)
84b3c09bdeSStefan Hajnoczi
85b3c09bdeSStefan Hajnoczidef main():
86b3c09bdeSStefan Hajnoczi    if len(sys.argv) < 2:
87b3c09bdeSStefan Hajnoczi        usage()
88b3c09bdeSStefan Hajnoczi
89b3c09bdeSStefan Hajnoczi    cmd = sys.argv[1]
90b3c09bdeSStefan Hajnoczi    if cmd == '--version':
91*f03868bdSEduardo Habkost        print('kvm_flightrecorder version 1.0')
92b3c09bdeSStefan Hajnoczi        sys.exit(0)
93b3c09bdeSStefan Hajnoczi
94b3c09bdeSStefan Hajnoczi    if not os.path.isdir(tracing_dir):
95*f03868bdSEduardo Habkost        print('Unable to tracing debugfs directory, try:')
96*f03868bdSEduardo Habkost        print('mount -t debugfs none /sys/kernel/debug')
97b3c09bdeSStefan Hajnoczi        sys.exit(1)
98b3c09bdeSStefan Hajnoczi    if not os.access(tracing_dir, os.W_OK):
99*f03868bdSEduardo Habkost        print('Unable to write to tracing debugfs directory, please run as root')
100b3c09bdeSStefan Hajnoczi        sys.exit(1)
101b3c09bdeSStefan Hajnoczi
102b3c09bdeSStefan Hajnoczi    if cmd == 'start':
103b3c09bdeSStefan Hajnoczi        stop_tracing() # clean up first
104b3c09bdeSStefan Hajnoczi
105b3c09bdeSStefan Hajnoczi        if len(sys.argv) == 3:
106b3c09bdeSStefan Hajnoczi            try:
107b3c09bdeSStefan Hajnoczi                buffer_size_kb = int(sys.argv[2])
108b3c09bdeSStefan Hajnoczi            except ValueError:
109*f03868bdSEduardo Habkost                print('Invalid per-cpu trace buffer size in KB')
110b3c09bdeSStefan Hajnoczi                sys.exit(1)
111b3c09bdeSStefan Hajnoczi            write_file(trace_path('buffer_size_kb'), str(buffer_size_kb))
112*f03868bdSEduardo Habkost            print('Per-CPU ring buffer size set to %d KB' % buffer_size_kb)
113b3c09bdeSStefan Hajnoczi
114b3c09bdeSStefan Hajnoczi        start_tracing()
115*f03868bdSEduardo Habkost        print('KVM flight recorder enabled')
116b3c09bdeSStefan Hajnoczi    elif cmd == 'stop':
117b3c09bdeSStefan Hajnoczi        stop_tracing()
118*f03868bdSEduardo Habkost        print('KVM flight recorder disabled')
119b3c09bdeSStefan Hajnoczi    elif cmd == 'dump':
120b3c09bdeSStefan Hajnoczi        dump_trace()
121b3c09bdeSStefan Hajnoczi    elif cmd == 'tail':
122b3c09bdeSStefan Hajnoczi        tail_trace()
123b3c09bdeSStefan Hajnoczi    else:
124b3c09bdeSStefan Hajnoczi        usage()
125b3c09bdeSStefan Hajnoczi
126b3c09bdeSStefan Hajnocziif __name__ == '__main__':
127b3c09bdeSStefan Hajnoczi    sys.exit(main())
128