blob: c65cabda5ab49d805247121b467f7a24c5fe80dd [file] [log] [blame]
Jan Kiszka626c4272011-10-07 09:37:49 +02001#!/usr/bin/python
2#
3# top-like utility for displaying kvm statistics
4#
5# Copyright 2006-2008 Qumranet Technologies
6# Copyright 2008-2011 Red Hat, Inc.
7#
8# Authors:
9# Avi Kivity <avi@redhat.com>
10#
11# This work is licensed under the terms of the GNU GPL, version 2. See
12# the COPYING file in the top-level directory.
13
14import curses
Michael Ellerman47253982014-06-17 17:54:35 +100015import sys, os, time, optparse, ctypes
Wei Huang874b1cf2015-01-21 16:15:31 -050016from ctypes import *
Jan Kiszka626c4272011-10-07 09:37:49 +020017
18class DebugfsProvider(object):
19 def __init__(self):
20 self.base = '/sys/kernel/debug/kvm'
21 self._fields = os.listdir(self.base)
22 def fields(self):
23 return self._fields
24 def select(self, fields):
25 self._fields = fields
26 def read(self):
27 def val(key):
28 return int(file(self.base + '/' + key).read())
29 return dict([(key, val(key)) for key in self._fields])
30
31vmx_exit_reasons = {
32 0: 'EXCEPTION_NMI',
33 1: 'EXTERNAL_INTERRUPT',
34 2: 'TRIPLE_FAULT',
35 7: 'PENDING_INTERRUPT',
36 8: 'NMI_WINDOW',
37 9: 'TASK_SWITCH',
38 10: 'CPUID',
39 12: 'HLT',
40 14: 'INVLPG',
41 15: 'RDPMC',
42 16: 'RDTSC',
43 18: 'VMCALL',
44 19: 'VMCLEAR',
45 20: 'VMLAUNCH',
46 21: 'VMPTRLD',
47 22: 'VMPTRST',
48 23: 'VMREAD',
49 24: 'VMRESUME',
50 25: 'VMWRITE',
51 26: 'VMOFF',
52 27: 'VMON',
53 28: 'CR_ACCESS',
54 29: 'DR_ACCESS',
55 30: 'IO_INSTRUCTION',
56 31: 'MSR_READ',
57 32: 'MSR_WRITE',
58 33: 'INVALID_STATE',
59 36: 'MWAIT_INSTRUCTION',
60 39: 'MONITOR_INSTRUCTION',
61 40: 'PAUSE_INSTRUCTION',
62 41: 'MCE_DURING_VMENTRY',
63 43: 'TPR_BELOW_THRESHOLD',
64 44: 'APIC_ACCESS',
65 48: 'EPT_VIOLATION',
66 49: 'EPT_MISCONFIG',
67 54: 'WBINVD',
68 55: 'XSETBV',
Wei Huang2c9d5352015-01-21 16:15:30 -050069 56: 'APIC_WRITE',
70 58: 'INVPCID',
Jan Kiszka626c4272011-10-07 09:37:49 +020071}
72
73svm_exit_reasons = {
74 0x000: 'READ_CR0',
75 0x003: 'READ_CR3',
76 0x004: 'READ_CR4',
77 0x008: 'READ_CR8',
78 0x010: 'WRITE_CR0',
79 0x013: 'WRITE_CR3',
80 0x014: 'WRITE_CR4',
81 0x018: 'WRITE_CR8',
82 0x020: 'READ_DR0',
83 0x021: 'READ_DR1',
84 0x022: 'READ_DR2',
85 0x023: 'READ_DR3',
86 0x024: 'READ_DR4',
87 0x025: 'READ_DR5',
88 0x026: 'READ_DR6',
89 0x027: 'READ_DR7',
90 0x030: 'WRITE_DR0',
91 0x031: 'WRITE_DR1',
92 0x032: 'WRITE_DR2',
93 0x033: 'WRITE_DR3',
94 0x034: 'WRITE_DR4',
95 0x035: 'WRITE_DR5',
96 0x036: 'WRITE_DR6',
97 0x037: 'WRITE_DR7',
98 0x040: 'EXCP_BASE',
99 0x060: 'INTR',
100 0x061: 'NMI',
101 0x062: 'SMI',
102 0x063: 'INIT',
103 0x064: 'VINTR',
104 0x065: 'CR0_SEL_WRITE',
105 0x066: 'IDTR_READ',
106 0x067: 'GDTR_READ',
107 0x068: 'LDTR_READ',
108 0x069: 'TR_READ',
109 0x06a: 'IDTR_WRITE',
110 0x06b: 'GDTR_WRITE',
111 0x06c: 'LDTR_WRITE',
112 0x06d: 'TR_WRITE',
113 0x06e: 'RDTSC',
114 0x06f: 'RDPMC',
115 0x070: 'PUSHF',
116 0x071: 'POPF',
117 0x072: 'CPUID',
118 0x073: 'RSM',
119 0x074: 'IRET',
120 0x075: 'SWINT',
121 0x076: 'INVD',
122 0x077: 'PAUSE',
123 0x078: 'HLT',
124 0x079: 'INVLPG',
125 0x07a: 'INVLPGA',
126 0x07b: 'IOIO',
127 0x07c: 'MSR',
128 0x07d: 'TASK_SWITCH',
129 0x07e: 'FERR_FREEZE',
130 0x07f: 'SHUTDOWN',
131 0x080: 'VMRUN',
132 0x081: 'VMMCALL',
133 0x082: 'VMLOAD',
134 0x083: 'VMSAVE',
135 0x084: 'STGI',
136 0x085: 'CLGI',
137 0x086: 'SKINIT',
138 0x087: 'RDTSCP',
139 0x088: 'ICEBP',
140 0x089: 'WBINVD',
141 0x08a: 'MONITOR',
142 0x08b: 'MWAIT',
143 0x08c: 'MWAIT_COND',
Wei Huang2c9d5352015-01-21 16:15:30 -0500144 0x08d: 'XSETBV',
Jan Kiszka626c4272011-10-07 09:37:49 +0200145 0x400: 'NPF',
146}
147
Wei Huangedecf5e2015-01-30 13:17:08 -0500148# EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h)
149aarch64_exit_reasons = {
150 0x00: 'UNKNOWN',
151 0x01: 'WFI',
152 0x03: 'CP15_32',
153 0x04: 'CP15_64',
154 0x05: 'CP14_MR',
155 0x06: 'CP14_LS',
156 0x07: 'FP_ASIMD',
157 0x08: 'CP10_ID',
158 0x0C: 'CP14_64',
159 0x0E: 'ILL_ISS',
160 0x11: 'SVC32',
161 0x12: 'HVC32',
162 0x13: 'SMC32',
163 0x15: 'SVC64',
164 0x16: 'HVC64',
165 0x17: 'SMC64',
166 0x18: 'SYS64',
167 0x20: 'IABT',
168 0x21: 'IABT_HYP',
169 0x22: 'PC_ALIGN',
170 0x24: 'DABT',
171 0x25: 'DABT_HYP',
172 0x26: 'SP_ALIGN',
173 0x28: 'FP_EXC32',
174 0x2C: 'FP_EXC64',
175 0x2F: 'SERROR',
176 0x30: 'BREAKPT',
177 0x31: 'BREAKPT_HYP',
178 0x32: 'SOFTSTP',
179 0x33: 'SOFTSTP_HYP',
180 0x34: 'WATCHPT',
181 0x35: 'WATCHPT_HYP',
182 0x38: 'BKPT32',
183 0x3A: 'VECTOR32',
184 0x3C: 'BRK64',
185}
186
Michael Ellerman27d318a2014-06-17 17:54:31 +1000187# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
188userspace_exit_reasons = {
189 0: 'UNKNOWN',
190 1: 'EXCEPTION',
191 2: 'IO',
192 3: 'HYPERCALL',
193 4: 'DEBUG',
194 5: 'HLT',
195 6: 'MMIO',
196 7: 'IRQ_WINDOW_OPEN',
197 8: 'SHUTDOWN',
198 9: 'FAIL_ENTRY',
199 10: 'INTR',
200 11: 'SET_TPR',
201 12: 'TPR_ACCESS',
202 13: 'S390_SIEIC',
203 14: 'S390_RESET',
204 15: 'DCR',
205 16: 'NMI',
206 17: 'INTERNAL_ERROR',
207 18: 'OSI',
208 19: 'PAPR_HCALL',
209 20: 'S390_UCONTROL',
210 21: 'WATCHDOG',
211 22: 'S390_TSCH',
212 23: 'EPR',
Wei Huang2c9d5352015-01-21 16:15:30 -0500213 24: 'SYSTEM_EVENT',
Jens Freimannc5854ac2012-06-06 02:05:18 +0000214}
215
Michael Ellerman4d4103f2014-06-17 17:54:32 +1000216x86_exit_reasons = {
Jan Kiszka626c4272011-10-07 09:37:49 +0200217 'vmx': vmx_exit_reasons,
218 'svm': svm_exit_reasons,
219}
220
Michael Ellerman4d4103f2014-06-17 17:54:32 +1000221sc_perf_evt_open = None
Jan Kiszka626c4272011-10-07 09:37:49 +0200222exit_reasons = None
223
Michael Ellermana15d5642014-06-17 17:54:34 +1000224ioctl_numbers = {
225 'SET_FILTER' : 0x40082406,
226 'ENABLE' : 0x00002400,
227 'DISABLE' : 0x00002401,
Wei Huangfc116ef2015-01-23 15:56:04 -0500228 'RESET' : 0x00002403,
Michael Ellermana15d5642014-06-17 17:54:34 +1000229}
230
Michael Ellerman4d4103f2014-06-17 17:54:32 +1000231def x86_init(flag):
232 globals().update({
233 'sc_perf_evt_open' : 298,
234 'exit_reasons' : x86_exit_reasons[flag],
235 })
236
237def s390_init():
238 globals().update({
239 'sc_perf_evt_open' : 331
240 })
241
Michael Ellerman47253982014-06-17 17:54:35 +1000242def ppc_init():
243 globals().update({
244 'sc_perf_evt_open' : 319,
245 'ioctl_numbers' : {
246 'SET_FILTER' : 0x80002406 | (ctypes.sizeof(ctypes.c_char_p) << 16),
247 'ENABLE' : 0x20002400,
248 'DISABLE' : 0x20002401,
249 }
250 })
251
Wei Huangedcbc402015-01-21 16:15:29 -0500252def aarch64_init():
253 globals().update({
Wei Huangedecf5e2015-01-30 13:17:08 -0500254 'sc_perf_evt_open' : 241,
255 'exit_reasons' : aarch64_exit_reasons,
Wei Huangedcbc402015-01-21 16:15:29 -0500256 })
257
Michael Ellerman4d4103f2014-06-17 17:54:32 +1000258def detect_platform():
Michael Ellerman47253982014-06-17 17:54:35 +1000259 if os.uname()[4].startswith('ppc'):
260 ppc_init()
261 return
Wei Huangedcbc402015-01-21 16:15:29 -0500262 elif os.uname()[4].startswith('aarch64'):
263 aarch64_init()
264 return
Michael Ellerman47253982014-06-17 17:54:35 +1000265
Michael Ellerman4d4103f2014-06-17 17:54:32 +1000266 for line in file('/proc/cpuinfo').readlines():
267 if line.startswith('flags'):
268 for flag in line.split():
269 if flag in x86_exit_reasons:
270 x86_init(flag)
271 return
272 elif line.startswith('vendor_id'):
273 for flag in line.split():
274 if flag == 'IBM/S390':
275 s390_init()
276 return
277
278detect_platform()
Jan Kiszka626c4272011-10-07 09:37:49 +0200279
280def invert(d):
281 return dict((x[1], x[0]) for x in d.iteritems())
282
Michael Ellerman27d318a2014-06-17 17:54:31 +1000283filters = {}
284filters['kvm_userspace_exit'] = ('reason', invert(userspace_exit_reasons))
285if exit_reasons:
286 filters['kvm_exit'] = ('exit_reason', invert(exit_reasons))
Jan Kiszka626c4272011-10-07 09:37:49 +0200287
Michael Ellerman47253982014-06-17 17:54:35 +1000288import struct, array
Jan Kiszka626c4272011-10-07 09:37:49 +0200289
290libc = ctypes.CDLL('libc.so.6')
291syscall = libc.syscall
Wei Huang874b1cf2015-01-21 16:15:31 -0500292get_errno = libc.__errno_location
293get_errno.restype = POINTER(c_int)
294
Jan Kiszka626c4272011-10-07 09:37:49 +0200295class perf_event_attr(ctypes.Structure):
296 _fields_ = [('type', ctypes.c_uint32),
297 ('size', ctypes.c_uint32),
298 ('config', ctypes.c_uint64),
299 ('sample_freq', ctypes.c_uint64),
300 ('sample_type', ctypes.c_uint64),
301 ('read_format', ctypes.c_uint64),
302 ('flags', ctypes.c_uint64),
303 ('wakeup_events', ctypes.c_uint32),
304 ('bp_type', ctypes.c_uint32),
305 ('bp_addr', ctypes.c_uint64),
306 ('bp_len', ctypes.c_uint64),
307 ]
308def _perf_event_open(attr, pid, cpu, group_fd, flags):
Heinz Graalfs1b3e6f82012-10-29 02:13:20 +0000309 return syscall(sc_perf_evt_open, ctypes.pointer(attr), ctypes.c_int(pid),
Jan Kiszka626c4272011-10-07 09:37:49 +0200310 ctypes.c_int(cpu), ctypes.c_int(group_fd),
311 ctypes.c_long(flags))
312
313PERF_TYPE_HARDWARE = 0
314PERF_TYPE_SOFTWARE = 1
315PERF_TYPE_TRACEPOINT = 2
316PERF_TYPE_HW_CACHE = 3
317PERF_TYPE_RAW = 4
318PERF_TYPE_BREAKPOINT = 5
319
320PERF_SAMPLE_IP = 1 << 0
321PERF_SAMPLE_TID = 1 << 1
322PERF_SAMPLE_TIME = 1 << 2
323PERF_SAMPLE_ADDR = 1 << 3
324PERF_SAMPLE_READ = 1 << 4
325PERF_SAMPLE_CALLCHAIN = 1 << 5
326PERF_SAMPLE_ID = 1 << 6
327PERF_SAMPLE_CPU = 1 << 7
328PERF_SAMPLE_PERIOD = 1 << 8
329PERF_SAMPLE_STREAM_ID = 1 << 9
330PERF_SAMPLE_RAW = 1 << 10
331
332PERF_FORMAT_TOTAL_TIME_ENABLED = 1 << 0
333PERF_FORMAT_TOTAL_TIME_RUNNING = 1 << 1
334PERF_FORMAT_ID = 1 << 2
335PERF_FORMAT_GROUP = 1 << 3
336
337import re
338
339sys_tracing = '/sys/kernel/debug/tracing'
340
341class Group(object):
342 def __init__(self, cpu):
343 self.events = []
344 self.group_leader = None
345 self.cpu = cpu
346 def add_event(self, name, event_set, tracepoint, filter = None):
347 self.events.append(Event(group = self,
348 name = name, event_set = event_set,
349 tracepoint = tracepoint, filter = filter))
350 if len(self.events) == 1:
351 self.file = os.fdopen(self.events[0].fd)
352 def read(self):
353 bytes = 8 * (1 + len(self.events))
354 fmt = 'xxxxxxxx' + 'q' * len(self.events)
355 return dict(zip([event.name for event in self.events],
356 struct.unpack(fmt, self.file.read(bytes))))
357
358class Event(object):
359 def __init__(self, group, name, event_set, tracepoint, filter = None):
360 self.name = name
361 attr = perf_event_attr()
362 attr.type = PERF_TYPE_TRACEPOINT
363 attr.size = ctypes.sizeof(attr)
364 id_path = os.path.join(sys_tracing, 'events', event_set,
365 tracepoint, 'id')
366 id = int(file(id_path).read())
367 attr.config = id
368 attr.sample_type = (PERF_SAMPLE_RAW
369 | PERF_SAMPLE_TIME
370 | PERF_SAMPLE_CPU)
371 attr.sample_period = 1
372 attr.read_format = PERF_FORMAT_GROUP
373 group_leader = -1
374 if group.events:
375 group_leader = group.events[0].fd
376 fd = _perf_event_open(attr, -1, group.cpu, group_leader, 0)
377 if fd == -1:
Wei Huang874b1cf2015-01-21 16:15:31 -0500378 err = get_errno()[0]
379 raise Exception('perf_event_open failed, errno = ' + err.__str__())
Jan Kiszka626c4272011-10-07 09:37:49 +0200380 if filter:
381 import fcntl
Michael Ellermana15d5642014-06-17 17:54:34 +1000382 fcntl.ioctl(fd, ioctl_numbers['SET_FILTER'], filter)
Jan Kiszka626c4272011-10-07 09:37:49 +0200383 self.fd = fd
384 def enable(self):
385 import fcntl
Michael Ellermana15d5642014-06-17 17:54:34 +1000386 fcntl.ioctl(self.fd, ioctl_numbers['ENABLE'], 0)
Jan Kiszka626c4272011-10-07 09:37:49 +0200387 def disable(self):
388 import fcntl
Michael Ellermana15d5642014-06-17 17:54:34 +1000389 fcntl.ioctl(self.fd, ioctl_numbers['DISABLE'], 0)
Wei Huangfc116ef2015-01-23 15:56:04 -0500390 def reset(self):
391 import fcntl
392 fcntl.ioctl(self.fd, ioctl_numbers['RESET'], 0)
Jan Kiszka626c4272011-10-07 09:37:49 +0200393
394class TracepointProvider(object):
395 def __init__(self):
396 path = os.path.join(sys_tracing, 'events', 'kvm')
397 fields = [f
398 for f in os.listdir(path)
399 if os.path.isdir(os.path.join(path, f))]
400 extra = []
401 for f in fields:
402 if f in filters:
403 subfield, values = filters[f]
404 for name, number in values.iteritems():
405 extra.append(f + '(' + name + ')')
406 fields += extra
407 self._setup(fields)
408 self.select(fields)
409 def fields(self):
410 return self._fields
Michael Ellerman763952d2014-06-17 17:54:30 +1000411
412 def _online_cpus(self):
413 l = []
414 pattern = r'cpu([0-9]+)'
415 basedir = '/sys/devices/system/cpu'
416 for entry in os.listdir(basedir):
417 match = re.match(pattern, entry)
418 if not match:
419 continue
420 path = os.path.join(basedir, entry, 'online')
421 if os.path.exists(path) and open(path).read().strip() != '1':
422 continue
423 l.append(int(match.group(1)))
424 return l
425
Jan Kiszka626c4272011-10-07 09:37:49 +0200426 def _setup(self, _fields):
427 self._fields = _fields
Michael Ellerman763952d2014-06-17 17:54:30 +1000428 cpus = self._online_cpus()
Jan Kiszka626c4272011-10-07 09:37:49 +0200429 import resource
Michael Ellerman763952d2014-06-17 17:54:30 +1000430 nfiles = len(cpus) * 1000
Jan Kiszka626c4272011-10-07 09:37:49 +0200431 resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
432 events = []
433 self.group_leaders = []
Michael Ellerman763952d2014-06-17 17:54:30 +1000434 for cpu in cpus:
Jan Kiszka626c4272011-10-07 09:37:49 +0200435 group = Group(cpu)
436 for name in _fields:
437 tracepoint = name
438 filter = None
439 m = re.match(r'(.*)\((.*)\)', name)
440 if m:
441 tracepoint, sub = m.groups()
442 filter = '%s==%d\0' % (filters[tracepoint][0],
443 filters[tracepoint][1][sub])
444 event = group.add_event(name, event_set = 'kvm',
445 tracepoint = tracepoint,
446 filter = filter)
447 self.group_leaders.append(group)
448 def select(self, fields):
449 for group in self.group_leaders:
450 for event in group.events:
451 if event.name in fields:
Wei Huangfc116ef2015-01-23 15:56:04 -0500452 event.reset()
Jan Kiszka626c4272011-10-07 09:37:49 +0200453 event.enable()
454 else:
455 event.disable()
456 def read(self):
457 from collections import defaultdict
458 ret = defaultdict(int)
459 for group in self.group_leaders:
460 for name, val in group.read().iteritems():
461 ret[name] += val
462 return ret
463
464class Stats:
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200465 def __init__(self, providers, fields = None):
466 self.providers = providers
Jan Kiszka626c4272011-10-07 09:37:49 +0200467 self.fields_filter = fields
468 self._update()
469 def _update(self):
470 def wanted(key):
471 import re
472 if not self.fields_filter:
473 return True
474 return re.match(self.fields_filter, key) is not None
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200475 self.values = dict()
476 for d in providers:
477 provider_fields = [key for key in d.fields() if wanted(key)]
478 for key in provider_fields:
479 self.values[key] = None
480 d.select(provider_fields)
Jan Kiszka626c4272011-10-07 09:37:49 +0200481 def set_fields_filter(self, fields_filter):
482 self.fields_filter = fields_filter
483 self._update()
484 def get(self):
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200485 for d in providers:
486 new = d.read()
487 for key in d.fields():
488 oldval = self.values.get(key, (0, 0))
489 newval = new[key]
490 newdelta = None
491 if oldval is not None:
492 newdelta = newval - oldval[0]
493 self.values[key] = (newval, newdelta)
Jan Kiszka626c4272011-10-07 09:37:49 +0200494 return self.values
495
496if not os.access('/sys/kernel/debug', os.F_OK):
497 print 'Please enable CONFIG_DEBUG_FS in your kernel'
498 sys.exit(1)
499if not os.access('/sys/kernel/debug/kvm', os.F_OK):
500 print "Please mount debugfs ('mount -t debugfs debugfs /sys/kernel/debug')"
501 print "and ensure the kvm modules are loaded"
502 sys.exit(1)
503
504label_width = 40
505number_width = 10
506
507def tui(screen, stats):
508 curses.use_default_colors()
509 curses.noecho()
510 drilldown = False
511 fields_filter = stats.fields_filter
512 def update_drilldown():
513 if not fields_filter:
514 if drilldown:
515 stats.set_fields_filter(None)
516 else:
517 stats.set_fields_filter(r'^[^\(]*$')
518 update_drilldown()
519 def refresh(sleeptime):
520 screen.erase()
521 screen.addstr(0, 0, 'kvm statistics')
522 row = 2
523 s = stats.get()
524 def sortkey(x):
525 if s[x][1]:
526 return (-s[x][1], -s[x][0])
527 else:
528 return (0, -s[x][0])
529 for key in sorted(s.keys(), key = sortkey):
530 if row >= screen.getmaxyx()[0]:
531 break
532 values = s[key]
533 if not values[0] and not values[1]:
534 break
535 col = 1
536 screen.addstr(row, col, key)
537 col += label_width
538 screen.addstr(row, col, '%10d' % (values[0],))
539 col += number_width
540 if values[1] is not None:
541 screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
542 row += 1
543 screen.refresh()
544
545 sleeptime = 0.25
546 while True:
547 refresh(sleeptime)
548 curses.halfdelay(int(sleeptime * 10))
549 sleeptime = 3
550 try:
551 c = screen.getkey()
552 if c == 'x':
553 drilldown = not drilldown
554 update_drilldown()
555 if c == 'q':
556 break
557 except KeyboardInterrupt:
558 break
559 except curses.error:
560 continue
561
562def batch(stats):
563 s = stats.get()
564 time.sleep(1)
565 s = stats.get()
566 for key in sorted(s.keys()):
567 values = s[key]
568 print '%-22s%10d%10d' % (key, values[0], values[1])
569
570def log(stats):
571 keys = sorted(stats.get().iterkeys())
572 def banner():
573 for k in keys:
574 print '%10s' % k[0:9],
575 print
576 def statline():
577 s = stats.get()
578 for k in keys:
579 print ' %9d' % s[k][1],
580 print
581 line = 0
582 banner_repeat = 20
583 while True:
584 time.sleep(1)
585 if line % banner_repeat == 0:
586 banner()
587 statline()
588 line += 1
589
590options = optparse.OptionParser()
591options.add_option('-1', '--once', '--batch',
592 action = 'store_true',
593 default = False,
594 dest = 'once',
595 help = 'run in batch mode for one second',
596 )
597options.add_option('-l', '--log',
598 action = 'store_true',
599 default = False,
600 dest = 'log',
601 help = 'run in logging mode (like vmstat)',
602 )
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200603options.add_option('-t', '--tracepoints',
604 action = 'store_true',
605 default = False,
606 dest = 'tracepoints',
607 help = 'retrieve statistics from tracepoints',
608 )
609options.add_option('-d', '--debugfs',
610 action = 'store_true',
611 default = False,
612 dest = 'debugfs',
613 help = 'retrieve statistics from debugfs',
614 )
Jan Kiszka626c4272011-10-07 09:37:49 +0200615options.add_option('-f', '--fields',
616 action = 'store',
617 default = None,
618 dest = 'fields',
619 help = 'fields to display (regex)',
620 )
621(options, args) = options.parse_args(sys.argv)
622
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200623providers = []
624if options.tracepoints:
625 providers.append(TracepointProvider())
626if options.debugfs:
627 providers.append(DebugfsProvider())
Jan Kiszka626c4272011-10-07 09:37:49 +0200628
Paolo Bonzinib763adf2014-05-21 12:42:26 +0200629if len(providers) == 0:
630 try:
631 providers = [TracepointProvider()]
632 except:
633 providers = [DebugfsProvider()]
634
635stats = Stats(providers, fields = options.fields)
Jan Kiszka626c4272011-10-07 09:37:49 +0200636
637if options.log:
638 log(stats)
639elif not options.once:
640 import curses.wrapper
641 curses.wrapper(tui, stats)
642else:
643 batch(stats)