# the COPYING file in the top-level directory.
import curses
-import sys, os, time, optparse
+import sys
+import os
+import time
+import optparse
+import ctypes
+import fcntl
+import resource
+import struct
+import re
+from collections import defaultdict
class DebugfsProvider(object):
def __init__(self):
- self.base = '/sys/kernel/debug/kvm'
- self._fields = os.listdir(self.base)
+ self._fields = walkdir(PATH_DEBUGFS_KVM)[2]
def fields(self):
return self._fields
def select(self, fields):
self._fields = fields
def read(self):
def val(key):
- return int(file(self.base + '/' + key).read())
+ return int(file(PATH_DEBUGFS_KVM + '/' + key).read())
return dict([(key, val(key)) for key in self._fields])
-vmx_exit_reasons = {
- 0: 'EXCEPTION_NMI',
- 1: 'EXTERNAL_INTERRUPT',
- 2: 'TRIPLE_FAULT',
- 7: 'PENDING_INTERRUPT',
- 8: 'NMI_WINDOW',
- 9: 'TASK_SWITCH',
- 10: 'CPUID',
- 12: 'HLT',
- 14: 'INVLPG',
- 15: 'RDPMC',
- 16: 'RDTSC',
- 18: 'VMCALL',
- 19: 'VMCLEAR',
- 20: 'VMLAUNCH',
- 21: 'VMPTRLD',
- 22: 'VMPTRST',
- 23: 'VMREAD',
- 24: 'VMRESUME',
- 25: 'VMWRITE',
- 26: 'VMOFF',
- 27: 'VMON',
- 28: 'CR_ACCESS',
- 29: 'DR_ACCESS',
- 30: 'IO_INSTRUCTION',
- 31: 'MSR_READ',
- 32: 'MSR_WRITE',
- 33: 'INVALID_STATE',
- 36: 'MWAIT_INSTRUCTION',
- 39: 'MONITOR_INSTRUCTION',
- 40: 'PAUSE_INSTRUCTION',
- 41: 'MCE_DURING_VMENTRY',
- 43: 'TPR_BELOW_THRESHOLD',
- 44: 'APIC_ACCESS',
- 48: 'EPT_VIOLATION',
- 49: 'EPT_MISCONFIG',
- 54: 'WBINVD',
- 55: 'XSETBV',
+VMX_EXIT_REASONS = {
+ 'EXCEPTION_NMI': 0,
+ 'EXTERNAL_INTERRUPT': 1,
+ 'TRIPLE_FAULT': 2,
+ 'PENDING_INTERRUPT': 7,
+ 'NMI_WINDOW': 8,
+ 'TASK_SWITCH': 9,
+ 'CPUID': 10,
+ 'HLT': 12,
+ 'INVLPG': 14,
+ 'RDPMC': 15,
+ 'RDTSC': 16,
+ 'VMCALL': 18,
+ 'VMCLEAR': 19,
+ 'VMLAUNCH': 20,
+ 'VMPTRLD': 21,
+ 'VMPTRST': 22,
+ 'VMREAD': 23,
+ 'VMRESUME': 24,
+ 'VMWRITE': 25,
+ 'VMOFF': 26,
+ 'VMON': 27,
+ 'CR_ACCESS': 28,
+ 'DR_ACCESS': 29,
+ 'IO_INSTRUCTION': 30,
+ 'MSR_READ': 31,
+ 'MSR_WRITE': 32,
+ 'INVALID_STATE': 33,
+ 'MWAIT_INSTRUCTION': 36,
+ 'MONITOR_INSTRUCTION': 39,
+ 'PAUSE_INSTRUCTION': 40,
+ 'MCE_DURING_VMENTRY': 41,
+ 'TPR_BELOW_THRESHOLD': 43,
+ 'APIC_ACCESS': 44,
+ 'EPT_VIOLATION': 48,
+ 'EPT_MISCONFIG': 49,
+ 'WBINVD': 54,
+ 'XSETBV': 55,
+ 'APIC_WRITE': 56,
+ 'INVPCID': 58,
}
-svm_exit_reasons = {
- 0x000: 'READ_CR0',
- 0x003: 'READ_CR3',
- 0x004: 'READ_CR4',
- 0x008: 'READ_CR8',
- 0x010: 'WRITE_CR0',
- 0x013: 'WRITE_CR3',
- 0x014: 'WRITE_CR4',
- 0x018: 'WRITE_CR8',
- 0x020: 'READ_DR0',
- 0x021: 'READ_DR1',
- 0x022: 'READ_DR2',
- 0x023: 'READ_DR3',
- 0x024: 'READ_DR4',
- 0x025: 'READ_DR5',
- 0x026: 'READ_DR6',
- 0x027: 'READ_DR7',
- 0x030: 'WRITE_DR0',
- 0x031: 'WRITE_DR1',
- 0x032: 'WRITE_DR2',
- 0x033: 'WRITE_DR3',
- 0x034: 'WRITE_DR4',
- 0x035: 'WRITE_DR5',
- 0x036: 'WRITE_DR6',
- 0x037: 'WRITE_DR7',
- 0x040: 'EXCP_BASE',
- 0x060: 'INTR',
- 0x061: 'NMI',
- 0x062: 'SMI',
- 0x063: 'INIT',
- 0x064: 'VINTR',
- 0x065: 'CR0_SEL_WRITE',
- 0x066: 'IDTR_READ',
- 0x067: 'GDTR_READ',
- 0x068: 'LDTR_READ',
- 0x069: 'TR_READ',
- 0x06a: 'IDTR_WRITE',
- 0x06b: 'GDTR_WRITE',
- 0x06c: 'LDTR_WRITE',
- 0x06d: 'TR_WRITE',
- 0x06e: 'RDTSC',
- 0x06f: 'RDPMC',
- 0x070: 'PUSHF',
- 0x071: 'POPF',
- 0x072: 'CPUID',
- 0x073: 'RSM',
- 0x074: 'IRET',
- 0x075: 'SWINT',
- 0x076: 'INVD',
- 0x077: 'PAUSE',
- 0x078: 'HLT',
- 0x079: 'INVLPG',
- 0x07a: 'INVLPGA',
- 0x07b: 'IOIO',
- 0x07c: 'MSR',
- 0x07d: 'TASK_SWITCH',
- 0x07e: 'FERR_FREEZE',
- 0x07f: 'SHUTDOWN',
- 0x080: 'VMRUN',
- 0x081: 'VMMCALL',
- 0x082: 'VMLOAD',
- 0x083: 'VMSAVE',
- 0x084: 'STGI',
- 0x085: 'CLGI',
- 0x086: 'SKINIT',
- 0x087: 'RDTSCP',
- 0x088: 'ICEBP',
- 0x089: 'WBINVD',
- 0x08a: 'MONITOR',
- 0x08b: 'MWAIT',
- 0x08c: 'MWAIT_COND',
- 0x400: 'NPF',
+SVM_EXIT_REASONS = {
+ 'READ_CR0': 0x000,
+ 'READ_CR3': 0x003,
+ 'READ_CR4': 0x004,
+ 'READ_CR8': 0x008,
+ 'WRITE_CR0': 0x010,
+ 'WRITE_CR3': 0x013,
+ 'WRITE_CR4': 0x014,
+ 'WRITE_CR8': 0x018,
+ 'READ_DR0': 0x020,
+ 'READ_DR1': 0x021,
+ 'READ_DR2': 0x022,
+ 'READ_DR3': 0x023,
+ 'READ_DR4': 0x024,
+ 'READ_DR5': 0x025,
+ 'READ_DR6': 0x026,
+ 'READ_DR7': 0x027,
+ 'WRITE_DR0': 0x030,
+ 'WRITE_DR1': 0x031,
+ 'WRITE_DR2': 0x032,
+ 'WRITE_DR3': 0x033,
+ 'WRITE_DR4': 0x034,
+ 'WRITE_DR5': 0x035,
+ 'WRITE_DR6': 0x036,
+ 'WRITE_DR7': 0x037,
+ 'EXCP_BASE': 0x040,
+ 'INTR': 0x060,
+ 'NMI': 0x061,
+ 'SMI': 0x062,
+ 'INIT': 0x063,
+ 'VINTR': 0x064,
+ 'CR0_SEL_WRITE': 0x065,
+ 'IDTR_READ': 0x066,
+ 'GDTR_READ': 0x067,
+ 'LDTR_READ': 0x068,
+ 'TR_READ': 0x069,
+ 'IDTR_WRITE': 0x06a,
+ 'GDTR_WRITE': 0x06b,
+ 'LDTR_WRITE': 0x06c,
+ 'TR_WRITE': 0x06d,
+ 'RDTSC': 0x06e,
+ 'RDPMC': 0x06f,
+ 'PUSHF': 0x070,
+ 'POPF': 0x071,
+ 'CPUID': 0x072,
+ 'RSM': 0x073,
+ 'IRET': 0x074,
+ 'SWINT': 0x075,
+ 'INVD': 0x076,
+ 'PAUSE': 0x077,
+ 'HLT': 0x078,
+ 'INVLPG': 0x079,
+ 'INVLPGA': 0x07a,
+ 'IOIO': 0x07b,
+ 'MSR': 0x07c,
+ 'TASK_SWITCH': 0x07d,
+ 'FERR_FREEZE': 0x07e,
+ 'SHUTDOWN': 0x07f,
+ 'VMRUN': 0x080,
+ 'VMMCALL': 0x081,
+ 'VMLOAD': 0x082,
+ 'VMSAVE': 0x083,
+ 'STGI': 0x084,
+ 'CLGI': 0x085,
+ 'SKINIT': 0x086,
+ 'RDTSCP': 0x087,
+ 'ICEBP': 0x088,
+ 'WBINVD': 0x089,
+ 'MONITOR': 0x08a,
+ 'MWAIT': 0x08b,
+ 'MWAIT_COND': 0x08c,
+ 'XSETBV': 0x08d,
+ 'NPF': 0x400,
}
-s390_exit_reasons = {
- 0x000: 'UNKNOWN',
- 0x001: 'EXCEPTION',
- 0x002: 'IO',
- 0x003: 'HYPERCALL',
- 0x004: 'DEBUG',
- 0x005: 'HLT',
- 0x006: 'MMIO',
- 0x007: 'IRQ_WINDOW_OPEN',
- 0x008: 'SHUTDOWN',
- 0x009: 'FAIL_ENTRY',
- 0x010: 'INTR',
- 0x011: 'SET_TPR',
- 0x012: 'TPR_ACCESS',
- 0x013: 'S390_SIEIC',
- 0x014: 'S390_RESET',
- 0x015: 'DCR',
- 0x016: 'NMI',
- 0x017: 'INTERNAL_ERROR',
- 0x018: 'OSI',
- 0x019: 'PAPR_HCALL',
+# EC definition of HSR (from arch/arm64/include/asm/kvm_arm.h)
+AARCH64_EXIT_REASONS = {
+ 'UNKNOWN': 0x00,
+ 'WFI': 0x01,
+ 'CP15_32': 0x03,
+ 'CP15_64': 0x04,
+ 'CP14_MR': 0x05,
+ 'CP14_LS': 0x06,
+ 'FP_ASIMD': 0x07,
+ 'CP10_ID': 0x08,
+ 'CP14_64': 0x0C,
+ 'ILL_ISS': 0x0E,
+ 'SVC32': 0x11,
+ 'HVC32': 0x12,
+ 'SMC32': 0x13,
+ 'SVC64': 0x15,
+ 'HVC64': 0x16,
+ 'SMC64': 0x17,
+ 'SYS64': 0x18,
+ 'IABT': 0x20,
+ 'IABT_HYP': 0x21,
+ 'PC_ALIGN': 0x22,
+ 'DABT': 0x24,
+ 'DABT_HYP': 0x25,
+ 'SP_ALIGN': 0x26,
+ 'FP_EXC32': 0x28,
+ 'FP_EXC64': 0x2C,
+ 'SERROR': 0x2F,
+ 'BREAKPT': 0x30,
+ 'BREAKPT_HYP': 0x31,
+ 'SOFTSTP': 0x32,
+ 'SOFTSTP_HYP': 0x33,
+ 'WATCHPT': 0x34,
+ 'WATCHPT_HYP': 0x35,
+ 'BKPT32': 0x38,
+ 'VECTOR32': 0x3A,
+ 'BRK64': 0x3C,
}
-vendor_exit_reasons = {
- 'vmx': vmx_exit_reasons,
- 'svm': svm_exit_reasons,
- 'IBM/S390': s390_exit_reasons,
+# From include/uapi/linux/kvm.h, KVM_EXIT_xxx
+USERSPACE_EXIT_REASONS = {
+ 'UNKNOWN': 0,
+ 'EXCEPTION': 1,
+ 'IO': 2,
+ 'HYPERCALL': 3,
+ 'DEBUG': 4,
+ 'HLT': 5,
+ 'MMIO': 6,
+ 'IRQ_WINDOW_OPEN': 7,
+ 'SHUTDOWN': 8,
+ 'FAIL_ENTRY': 9,
+ 'INTR': 10,
+ 'SET_TPR': 11,
+ 'TPR_ACCESS': 12,
+ 'S390_SIEIC': 13,
+ 'S390_RESET': 14,
+ 'DCR': 15,
+ 'NMI': 16,
+ 'INTERNAL_ERROR': 17,
+ 'OSI': 18,
+ 'PAPR_HCALL': 19,
+ 'S390_UCONTROL': 20,
+ 'WATCHDOG': 21,
+ 'S390_TSCH': 22,
+ 'EPR': 23,
+ 'SYSTEM_EVENT': 24,
}
-syscall_numbers = {
- 'IBM/S390': 331,
+X86_EXIT_REASONS = {
+ 'vmx': VMX_EXIT_REASONS,
+ 'svm': SVM_EXIT_REASONS,
}
-sc_perf_evt_open = 298
-
-exit_reasons = None
+SC_PERF_EVT_OPEN = None
+EXIT_REASONS = None
-for line in file('/proc/cpuinfo').readlines():
- if line.startswith('flags') or line.startswith('vendor_id'):
- for flag in line.split():
- if flag in vendor_exit_reasons:
- exit_reasons = vendor_exit_reasons[flag]
- if flag in syscall_numbers:
- sc_perf_evt_open = syscall_numbers[flag]
-filters = {
- 'kvm_exit': ('exit_reason', exit_reasons)
+IOCTL_NUMBERS = {
+ 'SET_FILTER' : 0x40082406,
+ 'ENABLE' : 0x00002400,
+ 'DISABLE' : 0x00002401,
+ 'RESET' : 0x00002403,
}
-def invert(d):
- return dict((x[1], x[0]) for x in d.iteritems())
+def x86_init(flag):
+ global SC_PERF_EVT_OPEN
+ global EXIT_REASONS
+
+ SC_PERF_EVT_OPEN = 298
+ EXIT_REASONS = X86_EXIT_REASONS[flag]
+
+def s390_init():
+ global SC_PERF_EVT_OPEN
+
+ SC_PERF_EVT_OPEN = 331
+
+def ppc_init():
+ global SC_PERF_EVT_OPEN
+ global IOCTL_NUMBERS
+
+ SC_PERF_EVT_OPEN = 319
+
+ IOCTL_NUMBERS['ENABLE'] = 0x20002400
+ IOCTL_NUMBERS['DISABLE'] = 0x20002401
+ IOCTL_NUMBERS['SET_FILTER'] = 0x80002406 | (ctypes.sizeof(ctypes.c_char_p)
+ << 16)
+
+def aarch64_init():
+ global SC_PERF_EVT_OPEN
+ global EXIT_REASONS
+
+ SC_PERF_EVT_OPEN = 241
+ EXIT_REASONS = AARCH64_EXIT_REASONS
+
+def detect_platform():
+ if os.uname()[4].startswith('ppc'):
+ ppc_init()
+ return
+ elif os.uname()[4].startswith('aarch64'):
+ aarch64_init()
+ return
+
+ for line in file('/proc/cpuinfo').readlines():
+ if line.startswith('flags'):
+ for flag in line.split():
+ if flag in X86_EXIT_REASONS:
+ x86_init(flag)
+ return
+ elif line.startswith('vendor_id'):
+ for flag in line.split():
+ if flag == 'IBM/S390':
+ s390_init()
+ return
+
+detect_platform()
+
-for f in filters:
- filters[f] = (filters[f][0], invert(filters[f][1]))
+def walkdir(path):
+ """Returns os.walk() data for specified directory.
-import ctypes, struct, array
+ As it is only a wrapper it returns the same 3-tuple of (dirpath,
+ dirnames, filenames).
+ """
+ return next(os.walk(path))
+
+filters = {}
+filters['kvm_userspace_exit'] = ('reason', USERSPACE_EXIT_REASONS)
+if EXIT_REASONS:
+ filters['kvm_exit'] = ('exit_reason', EXIT_REASONS)
libc = ctypes.CDLL('libc.so.6')
syscall = libc.syscall
+get_errno = libc.__errno_location
+get_errno.restype = ctypes.POINTER(ctypes.c_int)
+
class perf_event_attr(ctypes.Structure):
_fields_ = [('type', ctypes.c_uint32),
('size', ctypes.c_uint32),
('bp_len', ctypes.c_uint64),
]
def _perf_event_open(attr, pid, cpu, group_fd, flags):
- return syscall(sc_perf_evt_open, ctypes.pointer(attr), ctypes.c_int(pid),
+ return syscall(SC_PERF_EVT_OPEN, ctypes.pointer(attr), ctypes.c_int(pid),
ctypes.c_int(cpu), ctypes.c_int(group_fd),
ctypes.c_long(flags))
-PERF_TYPE_HARDWARE = 0
-PERF_TYPE_SOFTWARE = 1
-PERF_TYPE_TRACEPOINT = 2
-PERF_TYPE_HW_CACHE = 3
-PERF_TYPE_RAW = 4
-PERF_TYPE_BREAKPOINT = 5
-
-PERF_SAMPLE_IP = 1 << 0
-PERF_SAMPLE_TID = 1 << 1
-PERF_SAMPLE_TIME = 1 << 2
-PERF_SAMPLE_ADDR = 1 << 3
-PERF_SAMPLE_READ = 1 << 4
-PERF_SAMPLE_CALLCHAIN = 1 << 5
-PERF_SAMPLE_ID = 1 << 6
-PERF_SAMPLE_CPU = 1 << 7
-PERF_SAMPLE_PERIOD = 1 << 8
-PERF_SAMPLE_STREAM_ID = 1 << 9
-PERF_SAMPLE_RAW = 1 << 10
-
-PERF_FORMAT_TOTAL_TIME_ENABLED = 1 << 0
-PERF_FORMAT_TOTAL_TIME_RUNNING = 1 << 1
-PERF_FORMAT_ID = 1 << 2
-PERF_FORMAT_GROUP = 1 << 3
-
-import re
+PERF_TYPE_TRACEPOINT = 2
+PERF_FORMAT_GROUP = 1 << 3
-sys_tracing = '/sys/kernel/debug/tracing'
+PATH_DEBUGFS_TRACING = '/sys/kernel/debug/tracing'
+PATH_DEBUGFS_KVM = '/sys/kernel/debug/kvm'
class Group(object):
def __init__(self, cpu):
attr = perf_event_attr()
attr.type = PERF_TYPE_TRACEPOINT
attr.size = ctypes.sizeof(attr)
- id_path = os.path.join(sys_tracing, 'events', event_set,
+ id_path = os.path.join(PATH_DEBUGFS_TRACING, 'events', event_set,
tracepoint, 'id')
id = int(file(id_path).read())
attr.config = id
- attr.sample_type = (PERF_SAMPLE_RAW
- | PERF_SAMPLE_TIME
- | PERF_SAMPLE_CPU)
attr.sample_period = 1
attr.read_format = PERF_FORMAT_GROUP
group_leader = -1
group_leader = group.events[0].fd
fd = _perf_event_open(attr, -1, group.cpu, group_leader, 0)
if fd == -1:
- raise Exception('perf_event_open failed')
+ err = get_errno()[0]
+ raise Exception('perf_event_open failed, errno = ' + err.__str__())
if filter:
- import fcntl
- fcntl.ioctl(fd, 0x40082406, filter)
+ fcntl.ioctl(fd, IOCTL_NUMBERS['SET_FILTER'], filter)
self.fd = fd
def enable(self):
- import fcntl
- fcntl.ioctl(self.fd, 0x00002400, 0)
+ fcntl.ioctl(self.fd, IOCTL_NUMBERS['ENABLE'], 0)
def disable(self):
- import fcntl
- fcntl.ioctl(self.fd, 0x00002401, 0)
+ fcntl.ioctl(self.fd, IOCTL_NUMBERS['DISABLE'], 0)
+ def reset(self):
+ fcntl.ioctl(self.fd, IOCTL_NUMBERS['RESET'], 0)
class TracepointProvider(object):
def __init__(self):
- path = os.path.join(sys_tracing, 'events', 'kvm')
- fields = [f
- for f in os.listdir(path)
- if os.path.isdir(os.path.join(path, f))]
+ path = os.path.join(PATH_DEBUGFS_TRACING, 'events', 'kvm')
+ fields = walkdir(path)[1]
extra = []
for f in fields:
if f in filters:
self.select(fields)
def fields(self):
return self._fields
+
+ def _online_cpus(self):
+ l = []
+ pattern = r'cpu([0-9]+)'
+ basedir = '/sys/devices/system/cpu'
+ for entry in os.listdir(basedir):
+ match = re.match(pattern, entry)
+ if not match:
+ continue
+ path = os.path.join(basedir, entry, 'online')
+ if os.path.exists(path) and open(path).read().strip() != '1':
+ continue
+ l.append(int(match.group(1)))
+ return l
+
def _setup(self, _fields):
self._fields = _fields
- cpure = r'cpu([0-9]+)'
- self.cpus = [int(re.match(cpure, x).group(1))
- for x in os.listdir('/sys/devices/system/cpu')
- if re.match(cpure, x)]
- import resource
- nfiles = len(self.cpus) * 1000
+ cpus = self._online_cpus()
+ nfiles = len(cpus) * 1000
resource.setrlimit(resource.RLIMIT_NOFILE, (nfiles, nfiles))
events = []
self.group_leaders = []
- for cpu in self.cpus:
+ for cpu in cpus:
group = Group(cpu)
for name in _fields:
tracepoint = name
for group in self.group_leaders:
for event in group.events:
if event.name in fields:
+ event.reset()
event.enable()
else:
event.disable()
def read(self):
- from collections import defaultdict
ret = defaultdict(int)
for group in self.group_leaders:
for name, val in group.read().iteritems():
return ret
class Stats:
- def __init__(self, provider, fields = None):
- self.provider = provider
+ def __init__(self, providers, fields = None):
+ self.providers = providers
self.fields_filter = fields
self._update()
def _update(self):
def wanted(key):
- import re
if not self.fields_filter:
return True
return re.match(self.fields_filter, key) is not None
- self.values = dict([(key, None)
- for key in provider.fields()
- if wanted(key)])
- self.provider.select(self.values.keys())
+ self.values = dict()
+ for d in providers:
+ provider_fields = [key for key in d.fields() if wanted(key)]
+ for key in provider_fields:
+ self.values[key] = None
+ d.select(provider_fields)
def set_fields_filter(self, fields_filter):
self.fields_filter = fields_filter
self._update()
def get(self):
- new = self.provider.read()
- for key in self.provider.fields():
- oldval = self.values.get(key, (0, 0))
- newval = new[key]
- newdelta = None
- if oldval is not None:
- newdelta = newval - oldval[0]
- self.values[key] = (newval, newdelta)
+ for d in providers:
+ new = d.read()
+ for key in d.fields():
+ oldval = self.values.get(key, (0, 0))
+ newval = new[key]
+ newdelta = None
+ if oldval is not None:
+ newdelta = newval - oldval[0]
+ self.values[key] = (newval, newdelta)
return self.values
if not os.access('/sys/kernel/debug', os.F_OK):
print 'Please enable CONFIG_DEBUG_FS in your kernel'
sys.exit(1)
-if not os.access('/sys/kernel/debug/kvm', os.F_OK):
+if not os.access(PATH_DEBUGFS_KVM, os.F_OK):
print "Please mount debugfs ('mount -t debugfs debugfs /sys/kernel/debug')"
print "and ensure the kvm modules are loaded"
sys.exit(1)
-label_width = 40
-number_width = 10
+LABEL_WIDTH = 40
+NUMBER_WIDTH = 10
def tui(screen, stats):
curses.use_default_colors()
def refresh(sleeptime):
screen.erase()
screen.addstr(0, 0, 'kvm statistics')
- row = 2
+ screen.addstr(2, 1, 'Event')
+ screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH - len('Total'), 'Total')
+ screen.addstr(2, 1 + LABEL_WIDTH + NUMBER_WIDTH + 8 - len('Current'), 'Current')
+ row = 3
s = stats.get()
def sortkey(x):
if s[x][1]:
break
col = 1
screen.addstr(row, col, key)
- col += label_width
+ col += LABEL_WIDTH
screen.addstr(row, col, '%10d' % (values[0],))
- col += number_width
+ col += NUMBER_WIDTH
if values[1] is not None:
screen.addstr(row, col, '%8d' % (values[1] / sleeptime,))
row += 1
dest = 'log',
help = 'run in logging mode (like vmstat)',
)
+options.add_option('-t', '--tracepoints',
+ action = 'store_true',
+ default = False,
+ dest = 'tracepoints',
+ help = 'retrieve statistics from tracepoints',
+ )
+options.add_option('-d', '--debugfs',
+ action = 'store_true',
+ default = False,
+ dest = 'debugfs',
+ help = 'retrieve statistics from debugfs',
+ )
options.add_option('-f', '--fields',
action = 'store',
default = None,
)
(options, args) = options.parse_args(sys.argv)
-try:
- provider = TracepointProvider()
-except:
- provider = DebugfsProvider()
+providers = []
+if options.tracepoints:
+ providers.append(TracepointProvider())
+if options.debugfs:
+ providers.append(DebugfsProvider())
+
+if len(providers) == 0:
+ try:
+ providers = [TracepointProvider()]
+ except:
+ providers = [DebugfsProvider()]
-stats = Stats(provider, fields = options.fields)
+stats = Stats(providers, fields = options.fields)
if options.log:
log(stats)
elif not options.once:
- import curses.wrapper
curses.wrapper(tui, stats)
else:
batch(stats)