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