pcie: modify the capability size assert
[qemu/ar7.git] / scripts / kvm / kvm_stat
blob3cf1181750dba4fa47817eb3678e30931fc64add
1 #!/usr/bin/python
3 # top-like utility for displaying kvm statistics
5 # Copyright 2006-2008 Qumranet Technologies
6 # Copyright 2008-2011 Red Hat, Inc.
8 # Authors:
9 # Avi Kivity <avi@redhat.com>
11 # This work is licensed under the terms of the GNU GPL, version 2. See
12 # the COPYING file in the top-level directory.
14 import curses
15 import sys
16 import os
17 import time
18 import optparse
19 import ctypes
20 import fcntl
21 import resource
22 import struct
23 import re
24 from collections import defaultdict
25 from time import sleep
27 VMX_EXIT_REASONS = {
28 'EXCEPTION_NMI': 0,
29 'EXTERNAL_INTERRUPT': 1,
30 'TRIPLE_FAULT': 2,
31 'PENDING_INTERRUPT': 7,
32 'NMI_WINDOW': 8,
33 'TASK_SWITCH': 9,
34 'CPUID': 10,
35 'HLT': 12,
36 'INVLPG': 14,
37 'RDPMC': 15,
38 'RDTSC': 16,
39 'VMCALL': 18,
40 'VMCLEAR': 19,
41 'VMLAUNCH': 20,
42 'VMPTRLD': 21,
43 'VMPTRST': 22,
44 'VMREAD': 23,
45 'VMRESUME': 24,
46 'VMWRITE': 25,
47 'VMOFF': 26,
48 'VMON': 27,
49 'CR_ACCESS': 28,
50 'DR_ACCESS': 29,
51 'IO_INSTRUCTION': 30,
52 'MSR_READ': 31,
53 'MSR_WRITE': 32,
54 'INVALID_STATE': 33,
55 'MWAIT_INSTRUCTION': 36,
56 'MONITOR_INSTRUCTION': 39,
57 'PAUSE_INSTRUCTION': 40,
58 'MCE_DURING_VMENTRY': 41,
59 'TPR_BELOW_THRESHOLD': 43,
60 'APIC_ACCESS': 44,
61 'EPT_VIOLATION': 48,
62 'EPT_MISCONFIG': 49,
63 'WBINVD': 54,
64 'XSETBV': 55,
65 'APIC_WRITE': 56,
66 'INVPCID': 58,
69 SVM_EXIT_REASONS = {
70 'READ_CR0': 0x000,
71 'READ_CR3': 0x003,
72 'READ_CR4': 0x004,
73 'READ_CR8': 0x008,
74 'WRITE_CR0': 0x010,
75 'WRITE_CR3': 0x013,
76 'WRITE_CR4': 0x014,
77 'WRITE_CR8': 0x018,
78 'READ_DR0': 0x020,
79 'READ_DR1': 0x021,
80 'READ_DR2': 0x022,
81 'READ_DR3': 0x023,
82 'READ_DR4': 0x024,
83 'READ_DR5': 0x025,
84 'READ_DR6': 0x026,
85 'READ_DR7': 0x027,
86 'WRITE_DR0': 0x030,
87 'WRITE_DR1': 0x031,
88 'WRITE_DR2': 0x032,
89 'WRITE_DR3': 0x033,
90 'WRITE_DR4': 0x034,
91 'WRITE_DR5': 0x035,
92 'WRITE_DR6': 0x036,
93 'WRITE_DR7': 0x037,
94 'EXCP_BASE': 0x040,
95 'INTR': 0x060,
96 'NMI': 0x061,
97 'SMI': 0x062,
98 'INIT': 0x063,
99 'VINTR': 0x064,
100 'CR0_SEL_WRITE': 0x065,
101 'IDTR_READ': 0x066,
102 'GDTR_READ': 0x067,
103 'LDTR_READ': 0x068,
104 'TR_READ': 0x069,
105 'IDTR_WRITE': 0x06a,
106 'GDTR_WRITE': 0x06b,
107 'LDTR_WRITE': 0x06c,
108 'TR_WRITE': 0x06d,
109 'RDTSC': 0x06e,
110 'RDPMC': 0x06f,
111 'PUSHF': 0x070,
112 'POPF': 0x071,
113 'CPUID': 0x072,
114 'RSM': 0x073,
115 'IRET': 0x074,
116 'SWINT': 0x075,
117 'INVD': 0x076,
118 'PAUSE': 0x077,
119 'HLT': 0x078,
120 'INVLPG': 0x079,
121 'INVLPGA': 0x07a,
122 'IOIO': 0x07b,
123 'MSR': 0x07c,
124 'TASK_SWITCH': 0x07d,
125 'FERR_FREEZE': 0x07e,
126 'SHUTDOWN': 0x07f,
127 'VMRUN': 0x080,
128 'VMMCALL': 0x081,
129 'VMLOAD': 0x082,
130 'VMSAVE': 0x083,
131 'STGI': 0x084,
132 'CLGI': 0x085,
133 'SKINIT': 0x086,
134 'RDTSCP': 0x087,
135 'ICEBP': 0x088,
136 'WBINVD': 0x089,
137 'MONITOR': 0x08a,
138 'MWAIT': 0x08b,
139 'MWAIT_COND': 0x08c,
140 'XSETBV': 0x08d,
141 'NPF': 0x400,
144 # EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h)
145 AARCH64_EXIT_REASONS = {
146 'UNKNOWN': 0x00,
147 'WFI': 0x01,
148 'CP15_32': 0x03,
149 'CP15_64': 0x04,
150 'CP14_MR': 0x05,
151 'CP14_LS': 0x06,
152 'FP_ASIMD': 0x07,
153 'CP10_ID': 0x08,
154 'CP14_64': 0x0C,
155 'ILL_ISS': 0x0E,
156 'SVC32': 0x11,
157 'HVC32': 0x12,
158 'SMC32': 0x13,
159 'SVC64': 0x15,
160 'HVC64': 0x16,
161 'SMC64': 0x17,
162 'SYS64': 0x18,
163 'IABT': 0x20,
164 'IABT_HYP': 0x21,
165 'PC_ALIGN': 0x22,
166 'DABT': 0x24,
167 'DABT_HYP': 0x25,
168 'SP_ALIGN': 0x26,
169 'FP_EXC32': 0x28,
170 'FP_EXC64': 0x2C,
171 'SERROR': 0x2F,
172 'BREAKPT': 0x30,
173 'BREAKPT_HYP': 0x31,
174 'SOFTSTP': 0x32,
175 'SOFTSTP_HYP': 0x33,
176 'WATCHPT': 0x34,
177 'WATCHPT_HYP': 0x35,
178 'BKPT32': 0x38,
179 'VECTOR32': 0x3A,
180 'BRK64': 0x3C,
183 # From include/uapi/linux/kvm.h, KVM_EXIT_xxx
184 USERSPACE_EXIT_REASONS = {
185 'UNKNOWN': 0,
186 'EXCEPTION': 1,
187 'IO': 2,
188 'HYPERCALL': 3,
189 'DEBUG': 4,
190 'HLT': 5,
191 'MMIO': 6,
192 'IRQ_WINDOW_OPEN': 7,
193 'SHUTDOWN': 8,
194 'FAIL_ENTRY': 9,
195 'INTR': 10,
196 'SET_TPR': 11,
197 'TPR_ACCESS': 12,
198 'S390_SIEIC': 13,
199 'S390_RESET': 14,
200 'DCR': 15,
201 'NMI': 16,
202 'INTERNAL_ERROR': 17,
203 'OSI': 18,
204 'PAPR_HCALL': 19,
205 'S390_UCONTROL': 20,
206 'WATCHDOG': 21,
207 'S390_TSCH': 22,
208 'EPR': 23,
209 'SYSTEM_EVENT': 24,
212 IOCTL_NUMBERS = {
213 'SET_FILTER': 0x40082406,
214 'ENABLE': 0x00002400,
215 'DISABLE': 0x00002401,
216 'RESET': 0x00002403,
219 class Arch(object):
220 """Class that encapsulates global architecture specific data like
221 syscall and ioctl numbers.
224 @staticmethod
225 def get_arch():
226 machine = os.uname()[4]
228 if machine.startswith('ppc'):
229 return ArchPPC()
230 elif machine.startswith('aarch64'):
231 return ArchA64()
232 elif machine.startswith('s390'):
233 return ArchS390()
234 else:
235 # X86_64
236 for line in open('/proc/cpuinfo'):
237 if not line.startswith('flags'):
238 continue
240 flags = line.split()
241 if 'vmx' in flags:
242 return ArchX86(VMX_EXIT_REASONS)
243 if 'svm' in flags:
244 return ArchX86(SVM_EXIT_REASONS)
245 return
247 class ArchX86(Arch):
248 def __init__(self, exit_reasons):
249 self.sc_perf_evt_open = 298
250 self.ioctl_numbers = IOCTL_NUMBERS
251 self.exit_reasons = exit_reasons
253 class ArchPPC(Arch):
254 def __init__(self):
255 self.sc_perf_evt_open = 319
256 self.ioctl_numbers = IOCTL_NUMBERS
257 self.ioctl_numbers['ENABLE'] = 0x20002400
258 self.ioctl_numbers['DISABLE'] = 0x20002401
260 # PPC comes in 32 and 64 bit and some generated ioctl
261 # numbers depend on the wordsize.
262 char_ptr_size = ctypes.sizeof(ctypes.c_char_p)
263 self.ioctl_numbers['SET_FILTER'] = 0x80002406 | char_ptr_size << 16
265 class ArchA64(Arch):
266 def __init__(self):
267 self.sc_perf_evt_open = 241
268 self.ioctl_numbers = IOCTL_NUMBERS
269 self.exit_reasons = AARCH64_EXIT_REASONS
271 class ArchS390(Arch):
272 def __init__(self):
273 self.sc_perf_evt_open = 331
274 self.ioctl_numbers = IOCTL_NUMBERS
275 self.exit_reasons = None
277 ARCH = Arch.get_arch()
280 def walkdir(path):
281 """Returns os.walk() data for specified directory.
283 As it is only a wrapper it returns the same 3-tuple of (dirpath,
284 dirnames, filenames).
286 return next(os.walk(path))
289 def parse_int_list(list_string):
290 """Returns an int list from a string of comma separated integers and
291 integer ranges."""
292 integers = []
293 members = list_string.split(',')
295 for member in members:
296 if '-' not in member:
297 integers.append(int(member))
298 else:
299 int_range = member.split('-')
300 integers.extend(range(int(int_range[0]),
301 int(int_range[1]) + 1))
303 return integers
306 def get_online_cpus():
307 with open('/sys/devices/system/cpu/online') as cpu_list:
308 cpu_string = cpu_list.readline()
309 return parse_int_list(cpu_string)
312 def get_filters():
313 filters = {}
314 filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
315 if ARCH.exit_reasons:
316 filters['kvm_exit'] = ('exit_reason', ARCH.exit_reasons)
317 return filters
319 libc = ctypes.CDLL('libc.so.6', use_errno=True)
320 syscall = libc.syscall
322 class perf_event_attr(ctypes.Structure):
323 _fields_ = [('type', ctypes.c_uint32),
324 ('size', ctypes.c_uint32),
325 ('config', ctypes.c_uint64),
326 ('sample_freq', ctypes.c_uint64),
327 ('sample_type', ctypes.c_uint64),
328 ('read_format', ctypes.c_uint64),
329 ('flags', ctypes.c_uint64),
330 ('wakeup_events', ctypes.c_uint32),
331 ('bp_type', ctypes.c_uint32),
332 ('bp_addr', ctypes.c_uint64),
333 ('bp_len', ctypes.c_uint64),
336 def __init__(self):
337 super(self.__class__, self).__init__()
338 self.type = PERF_TYPE_TRACEPOINT
339 self.size = ctypes.sizeof(self)
340 self.read_format = PERF_FORMAT_GROUP
342 def perf_event_open(attr, pid, cpu, group_fd, flags):
343 return syscall(ARCH.sc_perf_evt_open, ctypes.pointer(attr),
344 ctypes.c_int(pid), ctypes.c_int(cpu),
345 ctypes.c_int(group_fd), ctypes.c_long(flags))
347 PERF_TYPE_TRACEPOINT = 2
348 PERF_FORMAT_GROUP = 1 << 3
350 PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
351 PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
353 class Group(object):
354 def __init__(self):
355 self.events = []
357 def add_event(self, event):
358 self.events.append(event)
360 def read(self):
361 length = 8 * (1 + len(self.events))
362 read_format = 'xxxxxxxx' + 'Q' * len(self.events)
363 return dict(zip([event.name for event in self.events],
364 struct.unpack(read_format,
365 os.read(self.events[0].fd, length))))
367 class Event(object):
368 def __init__(self, name, group, trace_cpu, trace_point, trace_filter,
369 trace_set='kvm'):
370 self.name = name
371 self.fd = None
372 self.setup_event(group, trace_cpu, trace_point, trace_filter,
373 trace_set)
375 def setup_event_attribute(self, trace_set, trace_point):
376 id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', trace_set,
377 trace_point, 'id')
379 event_attr = perf_event_attr()
380 event_attr.config = int(open(id_path).read())
381 return event_attr
383 def setup_event(self, group, trace_cpu, trace_point, trace_filter,
384 trace_set):
385 event_attr = self.setup_event_attribute(trace_set, trace_point)
387 group_leader = -1
388 if group.events:
389 group_leader = group.events[0].fd
391 fd = perf_event_open(event_attr, -1, trace_cpu,
392 group_leader, 0)
393 if fd == -1:
394 err = ctypes.get_errno()
395 raise OSError(err, os.strerror(err),
396 'while calling sys_perf_event_open().')
398 if trace_filter:
399 fcntl.ioctl(fd, ARCH.ioctl_numbers['SET_FILTER'],
400 trace_filter)
402 self.fd = fd
404 def enable(self):
405 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['ENABLE'], 0)
407 def disable(self):
408 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['DISABLE'], 0)
410 def reset(self):
411 fcntl.ioctl(self.fd, ARCH.ioctl_numbers['RESET'], 0)
413 class TracepointProvider(object):
414 def __init__(self):
415 self.group_leaders = []
416 self.filters = get_filters()
417 self._fields = self.get_available_fields()
418 self.setup_traces()
419 self.fields = self._fields
421 def get_available_fields(self):
422 path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
423 fields = walkdir(path)[1]
424 extra = []
425 for field in fields:
426 if field in self.filters:
427 filter_name_, filter_dicts = self.filters[field]
428 for name in filter_dicts:
429 extra.append(field + '(' + name + ')')
430 fields += extra
431 return fields
433 def setup_traces(self):
434 cpus = get_online_cpus()
436 # The constant is needed as a buffer for python libs, std
437 # streams and other files that the script opens.
438 newlim = len(cpus) * len(self._fields) + 50
439 try:
440 softlim_, hardlim = resource.getrlimit(resource.RLIMIT_NOFILE)
442 if hardlim < newlim:
443 # Now we need CAP_SYS_RESOURCE, to increase the hard limit.
444 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, newlim))
445 else:
446 # Raising the soft limit is sufficient.
447 resource.setrlimit(resource.RLIMIT_NOFILE, (newlim, hardlim))
449 except ValueError:
450 sys.exit("NOFILE rlimit could not be raised to {0}".format(newlim))
452 for cpu in cpus:
453 group = Group()
454 for name in self._fields:
455 tracepoint = name
456 tracefilter = None
457 match = re.match(r'(.*)\((.*)\)', name)
458 if match:
459 tracepoint, sub = match.groups()
460 tracefilter = ('%s==%d\0' %
461 (self.filters[tracepoint][0],
462 self.filters[tracepoint][1][sub]))
464 group.add_event(Event(name=name,
465 group=group,
466 trace_cpu=cpu,
467 trace_point=tracepoint,
468 trace_filter=tracefilter))
469 self.group_leaders.append(group)
471 def available_fields(self):
472 return self.get_available_fields()
474 @property
475 def fields(self):
476 return self._fields
478 @fields.setter
479 def fields(self, fields):
480 self._fields = fields
481 for group in self.group_leaders:
482 for index, event in enumerate(group.events):
483 if event.name in fields:
484 event.reset()
485 event.enable()
486 else:
487 # Do not disable the group leader.
488 # It would disable all of its events.
489 if index != 0:
490 event.disable()
492 def read(self):
493 ret = defaultdict(int)
494 for group in self.group_leaders:
495 for name, val in group.read().iteritems():
496 if name in self._fields:
497 ret[name] += val
498 return ret
500 class DebugfsProvider(object):
501 def __init__(self):
502 self._fields = self.get_available_fields()
504 def get_available_fields(self):
505 return walkdir(PATH_DEBUGFS_KVM)[2]
507 @property
508 def fields(self):
509 return self._fields
511 @fields.setter
512 def fields(self, fields):
513 self._fields = fields
515 def read(self):
516 def val(key):
517 return int(file(PATH_DEBUGFS_KVM + '/' + key).read())
518 return dict([(key, val(key)) for key in self._fields])
520 class Stats(object):
521 def __init__(self, providers, fields=None):
522 self.providers = providers
523 self._fields_filter = fields
524 self.values = {}
525 self.update_provider_filters()
527 def update_provider_filters(self):
528 def wanted(key):
529 if not self._fields_filter:
530 return True
531 return re.match(self._fields_filter, key) is not None
533 # As we reset the counters when updating the fields we can
534 # also clear the cache of old values.
535 self.values = {}
536 for provider in self.providers:
537 provider_fields = [key for key in provider.get_available_fields()
538 if wanted(key)]
539 provider.fields = provider_fields
541 @property
542 def fields_filter(self):
543 return self._fields_filter
545 @fields_filter.setter
546 def fields_filter(self, fields_filter):
547 self._fields_filter = fields_filter
548 self.update_provider_filters()
550 def get(self):
551 for provider in self.providers:
552 new = provider.read()
553 for key in provider.fields:
554 oldval = self.values.get(key, (0, 0))
555 newval = new.get(key, 0)
556 newdelta = None
557 if oldval is not None:
558 newdelta = newval - oldval[0]
559 self.values[key] = (newval, newdelta)
560 return self.values
562 LABEL_WIDTH = 40
563 NUMBER_WIDTH = 10
565 class Tui(object):
566 def __init__(self, stats):
567 self.stats = stats
568 self.screen = None
569 self.drilldown = False
570 self.update_drilldown()
572 def __enter__(self):
573 """Initialises curses for later use. Based on curses.wrapper
574 implementation from the Python standard library."""
575 self.screen = curses.initscr()
576 curses.noecho()
577 curses.cbreak()
579 # The try/catch works around a minor bit of
580 # over-conscientiousness in the curses module, the error
581 # return from C start_color() is ignorable.
582 try:
583 curses.start_color()
584 except:
585 pass
587 curses.use_default_colors()
588 return self
590 def __exit__(self, *exception):
591 """Resets the terminal to its normal state. Based on curses.wrappre
592 implementation from the Python standard library."""
593 if self.screen:
594 self.screen.keypad(0)
595 curses.echo()
596 curses.nocbreak()
597 curses.endwin()
599 def update_drilldown(self):
600 if not self.stats.fields_filter:
601 self.stats.fields_filter = r'^[^\(]*$'
603 elif self.stats.fields_filter == r'^[^\(]*$':
604 self.stats.fields_filter = None
606 def refresh(self, sleeptime):
607 self.screen.erase()
608 self.screen.addstr(0, 0, 'kvm statistics - summary', curses.A_BOLD)
609 self.screen.addstr(2, 1, 'Event')
610 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH -
611 len('Total'), 'Total')
612 self.screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 -
613 len('Current'), 'Current')
614 row = 3
615 stats = self.stats.get()
616 def sortkey(x):
617 if stats[x][1]:
618 return (-stats[x][1], -stats[x][0])
619 else:
620 return (0, -stats[x][0])
621 for key in sorted(stats.keys(), key=sortkey):
623 if row >= self.screen.getmaxyx()[0]:
624 break
625 values = stats[key]
626 if not values[0] and not values[1]:
627 break
628 col = 1
629 self.screen.addstr(row, col, key)
630 col += LABEL_WIDTH
631 self.screen.addstr(row, col, '%10d' % (values[0],))
632 col += NUMBER_WIDTH
633 if values[1] is not None:
634 self.screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
635 row += 1
636 self.screen.refresh()
638 def show_filter_selection(self):
639 while True:
640 self.screen.erase()
641 self.screen.addstr(0, 0,
642 "Show statistics for events matching a regex.",
643 curses.A_BOLD)
644 self.screen.addstr(2, 0,
645 "Current regex: {0}"
646 .format(self.stats.fields_filter))
647 self.screen.addstr(3, 0, "New regex: ")
648 curses.echo()
649 regex = self.screen.getstr()
650 curses.noecho()
651 if len(regex) == 0:
652 return
653 try:
654 re.compile(regex)
655 self.stats.fields_filter = regex
656 return
657 except re.error:
658 continue
660 def show_stats(self):
661 sleeptime = 0.25
662 while True:
663 self.refresh(sleeptime)
664 curses.halfdelay(int(sleeptime * 10))
665 sleeptime = 3
666 try:
667 char = self.screen.getkey()
668 if char == 'x':
669 self.drilldown = not self.drilldown
670 self.update_drilldown()
671 if char == 'q':
672 break
673 if char == 'f':
674 self.show_filter_selection()
675 except KeyboardInterrupt:
676 break
677 except curses.error:
678 continue
680 def batch(stats):
681 s = stats.get()
682 time.sleep(1)
683 s = stats.get()
684 for key in sorted(s.keys()):
685 values = s[key]
686 print '%-42s%10d%10d' % (key, values[0], values[1])
688 def log(stats):
689 keys = sorted(stats.get().iterkeys())
690 def banner():
691 for k in keys:
692 print '%s' % k,
693 print
694 def statline():
695 s = stats.get()
696 for k in keys:
697 print ' %9d' % s[k][1],
698 print
699 line = 0
700 banner_repeat = 20
701 while True:
702 time.sleep(1)
703 if line % banner_repeat == 0:
704 banner()
705 statline()
706 line += 1
708 def get_options():
709 description_text = """
710 This script displays various statistics about VMs running under KVM.
711 The statistics are gathered from the KVM debugfs entries and / or the
712 currently available perf traces.
714 The monitoring takes additional cpu cycles and might affect the VM's
715 performance.
717 Requirements:
718 - Access to:
719 /sys/kernel/debug/kvm
720 /sys/kernel/debug/trace/events/*
721 /proc/pid/task
722 - /proc/sys/kernel/perf_event_paranoid < 1 if user has no
723 CAP_SYS_ADMIN and perf events are used.
724 - CAP_SYS_RESOURCE if the hard limit is not high enough to allow
725 the large number of files that are possibly opened.
728 class PlainHelpFormatter(optparse.IndentedHelpFormatter):
729 def format_description(self, description):
730 if description:
731 return description + "\n"
732 else:
733 return ""
735 optparser = optparse.OptionParser(description=description_text,
736 formatter=PlainHelpFormatter())
737 optparser.add_option('-1', '--once', '--batch',
738 action='store_true',
739 default=False,
740 dest='once',
741 help='run in batch mode for one second',
743 optparser.add_option('-l', '--log',
744 action='store_true',
745 default=False,
746 dest='log',
747 help='run in logging mode (like vmstat)',
749 optparser.add_option('-t', '--tracepoints',
750 action='store_true',
751 default=False,
752 dest='tracepoints',
753 help='retrieve statistics from tracepoints',
755 optparser.add_option('-d', '--debugfs',
756 action='store_true',
757 default=False,
758 dest='debugfs',
759 help='retrieve statistics from debugfs',
761 optparser.add_option('-f', '--fields',
762 action='store',
763 default=None,
764 dest='fields',
765 help='fields to display (regex)',
767 (options, _) = optparser.parse_args(sys.argv)
768 return options
770 def get_providers(options):
771 providers = []
773 if options.tracepoints:
774 providers.append(TracepointProvider())
775 if options.debugfs:
776 providers.append(DebugfsProvider())
777 if len(providers) == 0:
778 providers.append(TracepointProvider())
780 return providers
782 def check_access(options):
783 if not os.path.exists('/sys/kernel/debug'):
784 sys.stderr.write('Please enable CONFIG_DEBUG_FS in your kernel.')
785 sys.exit(1)
787 if not os.path.exists(PATH_DEBUGFS_KVM):
788 sys.stderr.write("Please make sure, that debugfs is mounted and "
789 "readable by the current user:\n"
790 "('mount -t debugfs debugfs /sys/kernel/debug')\n"
791 "Also ensure, that the kvm modules are loaded.\n")
792 sys.exit(1)
794 if not os.path.exists(PATH_DEBUGFS_TRACING) and (options.tracepoints
795 or not options.debugfs):
796 sys.stderr.write("Please enable CONFIG_TRACING in your kernel "
797 "when using the option -t (default).\n"
798 "If it is enabled, make {0} readable by the "
799 "current user.\n")
800 if options.tracepoints:
801 sys.exit(1)
803 sys.stderr.write("Falling back to debugfs statistics!\n"
804 options.debugfs = True
805 sleep(5)
807 return options
809 def main():
810 options = get_options()
811 options = check_access(options)
812 providers = get_providers(options)
813 stats = Stats(providers, fields=options.fields)
815 if options.log:
816 log(stats)
817 elif not options.once:
818 with Tui(stats) as tui:
819 tui.show_stats()
820 else:
821 batch(stats)
823 if __name__ == "__main__":
824 main()