Signed-off-by: Avi Kivity <avi@xxxxxxxxxx> --- kvm/kvm_stat | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 100 insertions(+), 1 deletions(-) diff --git a/kvm/kvm_stat b/kvm/kvm_stat index 75424fc..9b0392b 100755 --- a/kvm/kvm_stat +++ b/kvm/kvm_stat @@ -16,6 +16,100 @@ class DebugfsProvider(object): return int(file(self.base + '/' + key).read()) return dict([(key, val(key)) for key in self._fields]) +import ctypes, struct, array + +libc = ctypes.CDLL('libc.so.6') +syscall = libc.syscall +class perf_event_attr(ctypes.Structure): + _fields_ = [('type', ctypes.c_uint32), + ('size', ctypes.c_uint32), + ('config', ctypes.c_uint64), + ('sample_freq', ctypes.c_uint64), + ('sample_type', ctypes.c_uint64), + ('read_format', ctypes.c_uint64), + ('flags', ctypes.c_uint64), + ('wakeup_events', ctypes.c_uint32), + ('bp_type', ctypes.c_uint32), + ('bp_addr', ctypes.c_uint64), + ('bp_len', ctypes.c_uint64), + ] +def _perf_event_open(attr, pid, cpu, group_fd, flags): + return syscall(298, 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 + + +class TracepointProvider(object): + def __init__(self): + self.base = '/sys/kernel/debug/tracing/events/kvm/' + fields = [f + for f in os.listdir(self.base) + if os.path.isdir(self.base + '/' + f)] + self.select(fields) + def fields(self): + return self._fields + def select(self, _fields): + self._fields = _fields + self.cpus = [0, 1] + fds = [] + self.group_leaders = [] + for cpu in self.cpus: + group_leader = -1 + for f in _fields: + attr = perf_event_attr() + attr.type = PERF_TYPE_TRACEPOINT + attr.size = ctypes.sizeof(attr) + id = int(file(self.base + f + '/id').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 + fd = _perf_event_open(attr, -1, cpu, group_leader, 0) + if fd == -1: + raise Exception('perf_event_open failed') + if group_leader == -1: + group_leader = fd + fds.append(fd) + self.group_leaders.append(group_leader) + self.fds = fds + self.files = [os.fdopen(group_leader) + for group_leader in self.group_leaders] + def read(self): + ret = dict([(f, 0) for f in self._fields]) + bytes = 8 * (1 + len(self._fields)) + fmt = 'xxxxxxxx' + 'q' * len(self._fields) + for file in self.files: + a = struct.unpack(fmt, file.read(bytes)) + for field, val in zip(self._fields, a): + ret[field] += val + return ret + class Stats: def __init__(self, provider, fields = None): def wanted(key): @@ -133,7 +227,12 @@ options.add_option('-f', '--fields', ) (options, args) = options.parse_args(sys.argv) -stats = Stats(provider = DebugfsProvider(), fields = options.fields) +try: + provider = TracepointProvider() +except: + provider = DebugfsProvider() + +stats = Stats(provider, fields = options.fields) if options.log: log(stats) -- 1.7.1 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html