4 import sys
, os
, time
, optparse
6 class DebugfsProvider(object):
8 self
.base
= '/sys/kernel/debug/kvm'
9 self
._fields
= os
.listdir(self
.base
)
12 def select(self
, fields
):
16 return int(file(self
.base
+ '/' + key
).read())
17 return dict([(key
, val(key
)) for key
in self
._fields
])
21 1: 'EXTERNAL_INTERRUPT',
23 7: 'PENDING_INTERRUPT',
47 36: 'MWAIT_INSTRUCTION',
48 39: 'MONITOR_INSTRUCTION',
49 40: 'PAUSE_INSTRUCTION',
50 41: 'MCE_DURING_VMENTRY',
51 43: 'TPR_BELOW_THRESHOLD',
90 0x065: 'CR0_SEL_WRITE',
114 0x07d: 'TASK_SWITCH',
115 0x07e: 'FERR_FREEZE',
133 vendor_exit_reasons
= {
134 'vmx': vmx_exit_reasons
,
135 'svm': svm_exit_reasons
,
140 for line
in file('/proc/cpuinfo').readlines():
141 if line
.startswith('flags'):
142 for flag
in line
.split():
143 if flag
in vendor_exit_reasons
:
144 exit_reasons
= vendor_exit_reasons
[flag
]
147 'kvm_exit': ('exit_reason', exit_reasons
)
151 return dict((x
[1], x
[0]) for x
in d
.iteritems())
154 filters
[f
] = (filters
[f
][0], invert(filters
[f
][1]))
156 import ctypes
, struct
, array
158 libc
= ctypes
.CDLL('libc.so.6')
159 syscall
= libc
.syscall
160 class perf_event_attr(ctypes
.Structure
):
161 _fields_
= [('type', ctypes
.c_uint32
),
162 ('size', ctypes
.c_uint32
),
163 ('config', ctypes
.c_uint64
),
164 ('sample_freq', ctypes
.c_uint64
),
165 ('sample_type', ctypes
.c_uint64
),
166 ('read_format', ctypes
.c_uint64
),
167 ('flags', ctypes
.c_uint64
),
168 ('wakeup_events', ctypes
.c_uint32
),
169 ('bp_type', ctypes
.c_uint32
),
170 ('bp_addr', ctypes
.c_uint64
),
171 ('bp_len', ctypes
.c_uint64
),
173 def _perf_event_open(attr
, pid
, cpu
, group_fd
, flags
):
174 return syscall(298, ctypes
.pointer(attr
), ctypes
.c_int(pid
),
175 ctypes
.c_int(cpu
), ctypes
.c_int(group_fd
),
176 ctypes
.c_long(flags
))
178 PERF_TYPE_HARDWARE
= 0
179 PERF_TYPE_SOFTWARE
= 1
180 PERF_TYPE_TRACEPOINT
= 2
181 PERF_TYPE_HW_CACHE
= 3
183 PERF_TYPE_BREAKPOINT
= 5
185 PERF_SAMPLE_IP
= 1 << 0
186 PERF_SAMPLE_TID
= 1 << 1
187 PERF_SAMPLE_TIME
= 1 << 2
188 PERF_SAMPLE_ADDR
= 1 << 3
189 PERF_SAMPLE_READ
= 1 << 4
190 PERF_SAMPLE_CALLCHAIN
= 1 << 5
191 PERF_SAMPLE_ID
= 1 << 6
192 PERF_SAMPLE_CPU
= 1 << 7
193 PERF_SAMPLE_PERIOD
= 1 << 8
194 PERF_SAMPLE_STREAM_ID
= 1 << 9
195 PERF_SAMPLE_RAW
= 1 << 10
197 PERF_FORMAT_TOTAL_TIME_ENABLED
= 1 << 0
198 PERF_FORMAT_TOTAL_TIME_RUNNING
= 1 << 1
199 PERF_FORMAT_ID
= 1 << 2
200 PERF_FORMAT_GROUP
= 1 << 3
204 class TracepointProvider(object):
206 self
.base
= '/sys/kernel/debug/tracing/events/kvm/'
208 for f
in os
.listdir(self
.base
)
209 if os
.path
.isdir(self
.base
+ '/' + f
)]
213 subfield
, values
= filters
[f
]
214 for name
, number
in values
.iteritems():
215 extra
.append(f
+ '(' + name
+ ')')
220 def select(self
, _fields
):
221 self
._fields
= _fields
222 cpure
= r
'cpu([0-9]+)'
223 self
.cpus
= [int(re
.match(cpure
, x
).group(1))
224 for x
in os
.listdir('/sys/devices/system/cpu')
225 if re
.match(cpure
, x
)]
227 nfiles
= len(self
.cpus
) * 1000
228 resource
.setrlimit(resource
.RLIMIT_NOFILE
, (nfiles
, nfiles
))
230 self
.group_leaders
= []
231 for cpu
in self
.cpus
:
235 m
= re
.match(r
'(.*)\((.*)\)', f
)
237 fbase
, sub
= m
.groups()
238 attr
= perf_event_attr()
239 attr
.type = PERF_TYPE_TRACEPOINT
240 attr
.size
= ctypes
.sizeof(attr
)
241 id = int(file(self
.base
+ fbase
+ '/id').read())
243 attr
.sample_type
= (PERF_SAMPLE_RAW
246 attr
.sample_period
= 1
247 attr
.read_format
= PERF_FORMAT_GROUP
248 fd
= _perf_event_open(attr
, -1, cpu
, group_leader
, 0)
250 raise Exception('perf_event_open failed')
253 filter = '%s==%d\0' % (filters
[fbase
][0],
254 filters
[fbase
][1][sub
])
255 fcntl
.ioctl(fd
, 0x40082406, filter)
256 if group_leader
== -1:
259 self
.group_leaders
.append(group_leader
)
261 self
.files
= [os
.fdopen(group_leader
)
262 for group_leader
in self
.group_leaders
]
264 ret
= dict([(f
, 0) for f
in self
._fields
])
265 bytes
= 8 * (1 + len(self
._fields
))
266 fmt
= 'xxxxxxxx' + 'q' * len(self
._fields
)
267 for file in self
.files
:
268 a
= struct
.unpack(fmt
, file.read(bytes
))
269 for field
, val
in zip(self
._fields
, a
):
274 def __init__(self
, provider
, fields
= None):
279 return re
.match(fields
, key
) != None
280 self
.provider
= provider
281 self
.values
= dict([(key
, None)
282 for key
in provider
.fields()
284 self
.provider
.select(self
.values
.keys())
286 new
= self
.provider
.read()
287 for key
in self
.provider
.fields():
288 oldval
= self
.values
[key
]
291 if oldval
is not None:
292 newdelta
= newval
- oldval
[0]
293 self
.values
[key
] = (newval
, newdelta
)
296 if not os
.access('/sys/kernel/debug', os
.F_OK
):
297 print 'Please enable CONFIG_DEBUG_FS in your kernel'
299 if not os
.access('/sys/kernel/debug/kvm', os
.F_OK
):
300 print "Please mount debugfs ('mount -t debugfs debugfs /sys/kernel/debug')"
301 print "and ensure the kvm modules are loaded"
307 def tui(screen
, stats
):
308 curses
.use_default_colors()
310 def refresh(sleeptime
):
312 screen
.addstr(0, 0, 'kvm statistics')
317 return (-s
[x
][1], -s
[x
][0])
320 for key
in sorted(s
.keys(), key
= sortkey
):
321 if row
>= screen
.getmaxyx()[0]:
324 if not values
[0] and not values
[1]:
327 screen
.addstr(row
, col
, key
)
329 screen
.addstr(row
, col
, '%10d' % (values
[0],))
331 if values
[1] is not None:
332 screen
.addstr(row
, col
, '%8d' % (values
[1] / sleeptime
,))
339 curses
.halfdelay(int(sleeptime
* 10))
345 except KeyboardInterrupt:
354 for key
in sorted(s
.keys()):
356 print '%-22s%10d%10d' % (key
, values
[0], values
[1])
359 keys
= sorted(stats
.get().iterkeys())
362 print '%10s' % k
[0:9],
367 print ' %9d' % s
[k
][1],
373 if line
% banner_repeat
== 0:
378 options
= optparse
.OptionParser()
379 options
.add_option('-1', '--once', '--batch',
380 action
= 'store_true',
383 help = 'run in batch mode for one second',
385 options
.add_option('-l', '--log',
386 action
= 'store_true',
389 help = 'run in logging mode (like vmstat)',
391 options
.add_option('-f', '--fields',
395 help = 'fields to display (regex)',
397 (options
, args
) = options
.parse_args(sys
.argv
)
400 provider
= TracepointProvider()
402 provider
= DebugfsProvider()
404 stats
= Stats(provider
, fields
= options
.fields
)
408 elif not options
.once
:
409 import curses
.wrapper
410 curses
.wrapper(tui
, stats
)