From 763952d08b9c89726151a72f90bca90d0828302d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Jun 2014 17:54:30 +1000 Subject: kvm_stat: Only consider online cpus In kvm_stat we grovel through /sys to find out how many cpus are in the system. However if a cpu is offline it will still be present in /sys, and the perf_event_open() will fail. Modify the logic to only return online cpus. We need to be careful on systems which don't support cpu hotplug, the online file will not be present at all. Signed-off-by: Michael Ellerman Signed-off-by: Paolo Bonzini --- scripts/kvm/kvm_stat | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) (limited to 'scripts/kvm/kvm_stat') diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index d7e97e7488..2a788bc34c 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -311,18 +311,30 @@ class TracepointProvider(object): 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)] + cpus = self._online_cpus() import resource - nfiles = len(self.cpus) * 1000 + 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 -- cgit v1.2.3 From 27d318a88583b2bb263292a4d35931a3bc8d2b7a Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Jun 2014 17:54:31 +1000 Subject: kvm_stat: Fix the non-x86 exit reasons In kvm_stat we have a dictionary of exit reasons for s390. Firstly these are not s390 specific, they are the generic exit reasons. So rename the dictionary to reflect that, and add it separately to filters[]. Secondly, the values are defined using hex, but in the kernel header they are decimal. That means values above 9 in kvm_stat are incorrect. While we're there, fix the whitespace to match the rest of the file. Signed-off-by: Michael Ellerman Signed-off-by: Paolo Bonzini --- scripts/kvm/kvm_stat | 57 +++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 27 deletions(-) (limited to 'scripts/kvm/kvm_stat') diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index 2a788bc34c..4ec1fa5b63 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -141,33 +141,37 @@ svm_exit_reasons = { 0x400: 'NPF', } -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', +# From include/uapi/linux/kvm.h, KVM_EXIT_xxx +userspace_exit_reasons = { + 0: 'UNKNOWN', + 1: 'EXCEPTION', + 2: 'IO', + 3: 'HYPERCALL', + 4: 'DEBUG', + 5: 'HLT', + 6: 'MMIO', + 7: 'IRQ_WINDOW_OPEN', + 8: 'SHUTDOWN', + 9: 'FAIL_ENTRY', + 10: 'INTR', + 11: 'SET_TPR', + 12: 'TPR_ACCESS', + 13: 'S390_SIEIC', + 14: 'S390_RESET', + 15: 'DCR', + 16: 'NMI', + 17: 'INTERNAL_ERROR', + 18: 'OSI', + 19: 'PAPR_HCALL', + 20: 'S390_UCONTROL', + 21: 'WATCHDOG', + 22: 'S390_TSCH', + 23: 'EPR', } vendor_exit_reasons = { 'vmx': vmx_exit_reasons, 'svm': svm_exit_reasons, - 'IBM/S390': s390_exit_reasons, } syscall_numbers = { @@ -185,15 +189,14 @@ for line in file('/proc/cpuinfo').readlines(): 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) -} def invert(d): return dict((x[1], x[0]) for x in d.iteritems()) -for f in filters: - filters[f] = (filters[f][0], invert(filters[f][1])) +filters = {} +filters['kvm_userspace_exit'] = ('reason', invert(userspace_exit_reasons)) +if exit_reasons: + filters['kvm_exit'] = ('exit_reason', invert(exit_reasons)) import ctypes, struct, array -- cgit v1.2.3 From 4d4103ff32ee4c88857727515b5e596a1debc227 Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Jun 2014 17:54:32 +1000 Subject: kvm_stat: Rework platform detection The current platform detection is a little bit messy. We look for lines in /proc/cpuinfo starting with 'flags' OR 'vendor-id', and scan both for values we know will only occur in one or the other. We also keep scanning once we've found a value, which could be a feature, but isn't in this case. We'd also like to add another platform, powerpc, which will just make it worse. So clean it up in preparation. Signed-off-by: Michael Ellerman Signed-off-by: Paolo Bonzini --- scripts/kvm/kvm_stat | 41 +++++++++++++++++++++++++++-------------- 1 file changed, 27 insertions(+), 14 deletions(-) (limited to 'scripts/kvm/kvm_stat') diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index 4ec1fa5b63..00d4c5dffa 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -169,26 +169,39 @@ userspace_exit_reasons = { 23: 'EPR', } -vendor_exit_reasons = { +x86_exit_reasons = { 'vmx': vmx_exit_reasons, 'svm': svm_exit_reasons, } -syscall_numbers = { - 'IBM/S390': 331, -} - -sc_perf_evt_open = 298 - +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] +def x86_init(flag): + globals().update({ + 'sc_perf_evt_open' : 298, + 'exit_reasons' : x86_exit_reasons[flag], + }) + +def s390_init(): + globals().update({ + 'sc_perf_evt_open' : 331 + }) + +def detect_platform(): + 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() def invert(d): return dict((x[1], x[0]) for x in d.iteritems()) -- cgit v1.2.3 From a15d5642a03a0b6c6cf327e497e688d1ba4c676d Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Jun 2014 17:54:34 +1000 Subject: kvm_stat: Abstract ioctl numbers Unfortunately ioctl numbers are platform specific, so abstract them out of the code so they can be overridden. As it happens x86 and s390 share the same values, so nothing needs to change yet. Signed-off-by: Michael Ellerman Signed-off-by: Paolo Bonzini --- scripts/kvm/kvm_stat | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'scripts/kvm/kvm_stat') diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index 00d4c5dffa..a65d0a364d 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -177,6 +177,12 @@ x86_exit_reasons = { sc_perf_evt_open = None exit_reasons = None +ioctl_numbers = { + 'SET_FILTER' : 0x40082406, + 'ENABLE' : 0x00002400, + 'DISABLE' : 0x00002401, +} + def x86_init(flag): globals().update({ 'sc_perf_evt_open' : 298, @@ -301,14 +307,14 @@ class Event(object): raise Exception('perf_event_open failed') 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) class TracepointProvider(object): def __init__(self): -- cgit v1.2.3 From 4725398f9309d05936fec2eaaa6e97e01e25545e Mon Sep 17 00:00:00 2001 From: Michael Ellerman Date: Tue, 17 Jun 2014 17:54:35 +1000 Subject: kvm_stat: Add powerpc support Add support for powerpc platforms. We use uname -m, which allows us to detect ppc, ppc64 and ppc64le/el. Signed-off-by: Michael Ellerman Signed-off-by: Paolo Bonzini --- scripts/kvm/kvm_stat | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'scripts/kvm/kvm_stat') diff --git a/scripts/kvm/kvm_stat b/scripts/kvm/kvm_stat index a65d0a364d..7b1437ca21 100755 --- a/scripts/kvm/kvm_stat +++ b/scripts/kvm/kvm_stat @@ -12,7 +12,7 @@ # the COPYING file in the top-level directory. import curses -import sys, os, time, optparse +import sys, os, time, optparse, ctypes class DebugfsProvider(object): def __init__(self): @@ -194,7 +194,21 @@ def s390_init(): 'sc_perf_evt_open' : 331 }) +def ppc_init(): + globals().update({ + 'sc_perf_evt_open' : 319, + 'ioctl_numbers' : { + 'SET_FILTER' : 0x80002406 | (ctypes.sizeof(ctypes.c_char_p) << 16), + 'ENABLE' : 0x20002400, + 'DISABLE' : 0x20002401, + } + }) + def detect_platform(): + if os.uname()[4].startswith('ppc'): + ppc_init() + return + for line in file('/proc/cpuinfo').readlines(): if line.startswith('flags'): for flag in line.split(): @@ -217,7 +231,7 @@ filters['kvm_userspace_exit'] = ('reason', invert(userspace_exit_reasons)) if exit_reasons: filters['kvm_exit'] = ('exit_reason', invert(exit_reasons)) -import ctypes, struct, array +import struct, array libc = ctypes.CDLL('libc.so.6') syscall = libc.syscall -- cgit v1.2.3