3 # by Mark Williamson, (C) 2004 Intel Research Cambridge
5 # Program for reformatting trace buffer output according to user-supplied rules
7 import re
, sys
, string
, signal
, struct
, os
, getopt
, operator
10 print >> sys
.stderr
, \
11 "Usage: " + sys
.argv
[0] + """ defs-file
12 Parses trace data in binary format, as output by kvmtrace and
13 reformats it according to the rules in a file of definitions. The
14 rules in this file should have the format ({ and } show grouping
15 and are not part of the syntax):
17 {event_id}{whitespace}{text format string}
19 The textual format string may include format specifiers, such as:
20 %(ts)d, %(event)d, %(pid)d %(vcpu)d %(1)d, %(2)d,
22 [ the 'd' format specifier outputs in decimal, alternatively 'x'
23 will output in hexadecimal and 'o' will output in octal ]
25 Which correspond to the event ID, timestamp counter, pid
26 , vcpu and the 5 data fields from the trace record. There should be
27 one such rule for each type of event.
28 Depending on your system and the volume of trace buffer data,
29 this script may not be able to keep up with the output of kvmtrace
30 if it is piped directly. In these circumstances you should have
31 kvmtrace output to a file for processing off-line.
33 kvmtrace_format has the following additional switches
34 -s - if this switch is set additional trace statistics are
35 created and printed at the end of the output
39 def read_defs(defs_file
):
44 reg
= re
.compile('(\S+)\s+(\S.*)')
51 if line
[0] == '#' or line
[0] == '\n':
56 if not m
: print >> sys
.stderr
, "Bad format file" ; sys
.exit(1)
58 defs
[str(eval(m
.group(1)))] = m
.group(2)
66 # ppc instruction decoding for event type 0x00020019 (PPC_INSTR)
67 # some globals for statistic summaries
68 stat_ppc_instr_mnemonic
= {};
69 stat_ppc_instr_spr
= {};
70 stat_ppc_instr_dcr
= {};
71 stat_ppc_instr_tlb
= {};
73 def ppc_instr_print_summary(sortedlist
, colname
):
74 print "\n\n%14s + %10s" % (colname
, "count")
75 print "%s" % (15*"-"+"+"+11*"-")
77 for value
, key
in sortedlist
:
79 print "%14s | %10d" % (value
, key
)
80 print "%14s = %10d" % ("sum", sum)
83 def ppc_instr_summary():
84 # don't print empty statistics
85 if stat_ppc_instr_mnemonic
:
86 ppc_instr_print_summary(sorted(stat_ppc_instr_mnemonic
.iteritems(), key
=operator
.itemgetter(1), reverse
=True), "mnemonic")
87 if stat_ppc_instr_spr
:
88 ppc_instr_print_summary(sorted(stat_ppc_instr_spr
.iteritems(), key
=operator
.itemgetter(1), reverse
=True), "mnemonic-spr")
89 if stat_ppc_instr_dcr
:
90 ppc_instr_print_summary(sorted(stat_ppc_instr_dcr
.iteritems(), key
=operator
.itemgetter(1), reverse
=True), "mnemonic-dcr")
91 if stat_ppc_instr_tlb
:
92 ppc_instr_print_summary(sorted(stat_ppc_instr_tlb
.iteritems(), key
=operator
.itemgetter(1), reverse
=True), "mnemonic-tlb")
98 return (instr
>> 1) & 0x3ff;
101 return ((instr
>> 16) & 0x1f) |
((instr
>> 6) & 0x3e0)
104 return ((instr
>> 16) & 0x1f) |
((instr
>> 6) & 0x3e0);
106 def get_tlbwe_type(instr
):
107 ws
= (instr
>> 11) & 0x1f;
120 elif get_op(instr
)==19:
121 if get_xop(instr
) == 50:
125 elif get_op(instr
)==31:
126 if get_xop(instr
) == 83:
129 elif get_xop(instr
) == 87:
132 elif get_xop(instr
) == 131:
135 elif get_xop(instr
) == 146:
138 elif get_xop(instr
) == 163:
141 elif get_xop(instr
) == 215:
144 elif get_xop(instr
) == 247:
147 elif get_xop(instr
) == 279:
150 elif get_xop(instr
) == 311:
153 elif get_xop(instr
) == 323:
156 elif get_xop(instr
) == 339:
159 elif get_xop(instr
) == 407:
162 elif get_xop(instr
) == 439:
165 elif get_xop(instr
) == 451:
168 elif get_xop(instr
) == 467:
171 elif get_xop(instr
) == 470:
174 elif get_xop(instr
) == 534:
177 elif get_xop(instr
) == 566:
180 elif get_xop(instr
) == 662:
183 elif get_xop(instr
) == 978:
186 elif get_xop(instr
) == 914:
189 elif get_xop(instr
) == 790:
192 elif get_xop(instr
) == 918:
195 elif get_xop(instr
) == 966:
201 elif get_op(instr
) == 32:
204 elif get_op(instr
) == 33:
207 elif get_op(instr
) == 34:
210 elif get_op(instr
) == 35:
213 elif get_op(instr
) == 36:
216 elif get_op(instr
) == 37:
219 elif get_op(instr
) == 38:
222 elif get_op(instr
) == 39:
225 elif get_op(instr
) == 40:
228 elif get_op(instr
) == 41:
231 elif get_op(instr
) == 44:
234 elif get_op(instr
) == 45:
240 def get_sprn_name(sprn
):
326 def get_special(instr
):
327 name
= get_name(instr
);
328 if stat_ppc_instr_mnemonic
.has_key(name
):
329 stat_ppc_instr_mnemonic
[name
] += 1
331 stat_ppc_instr_mnemonic
[name
] = 1
333 if get_op(instr
) == 31:
334 if (get_xop(instr
) == 339) or (get_xop(instr
) == 467):
335 sprn
= get_sprn(instr
);
336 sprn_name
= get_sprn_name(sprn
);
337 stat_idx
= name
+"-"+sprn_name
338 if stat_ppc_instr_spr
.has_key(stat_idx
):
339 stat_ppc_instr_spr
[stat_idx
] += 1
341 stat_ppc_instr_spr
[stat_idx
] = 1
342 return ("- sprn 0x%03x %8s" % (sprn
, sprn_name
))
343 elif (get_xop(instr
) == 323 ) or (get_xop(instr
) == 451):
344 dcrn
= get_dcrn(instr
);
345 stat_idx
= name
+"-"+("%04X"%dcrn
)
346 if stat_ppc_instr_dcr
.has_key(stat_idx
):
347 stat_ppc_instr_dcr
[stat_idx
] += 1
349 stat_ppc_instr_dcr
[stat_idx
] = 1
350 return ("- dcrn 0x%03x" % dcrn
)
351 elif (get_xop(instr
) == 978 ) or (get_xop(instr
) == 451):
352 tlbwe_type
= get_tlbwe_type(instr
)
353 stat_idx
= name
+"-"+tlbwe_type
354 if stat_ppc_instr_tlb
.has_key(stat_idx
):
355 stat_ppc_instr_tlb
[stat_idx
] += 1
357 stat_ppc_instr_tlb
[stat_idx
] = 1
358 return ("- ws -> %8s" % tlbwe_type
)
365 if len(sys
.argv
) < 2:
369 opts
, arg
= getopt
.getopt(sys
.argv
[1:], "sc:" )
371 if opt
[0] == '-s' : summary
= True
373 except getopt
.GetoptError
:
376 signal
.signal(signal
.SIGTERM
, sighand
)
377 signal
.signal(signal
.SIGHUP
, sighand
)
378 signal
.signal(signal
.SIGINT
, sighand
)
382 defs
= read_defs(arg
[0])
384 # structure of trace record (as output by kvmtrace):
385 # HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I)
387 # HDR consists of EVENT:28:, n_data:3:, ts_in:1:
389 # EVENT means Event ID
390 # n_data means number of data (like D1, D2, ...)
391 # ts_in means Timestamp data exists(1) or not(0).
392 # if ts_in == 0, TSC(Q) does not exists.
407 while not interrupted
:
412 line
= sys
.stdin
.read(struct
.calcsize(KMAGIC
))
415 kmgc
= struct
.unpack(KMAGIC
, line
)[0]
417 #firstly try to parse data file as little endian
418 # if "kvmtrace-metadata".kmagic != kmagic
419 # then data file must be big endian"
420 if kmgc
!= 0x12345678:
421 if kmgc
!= 0x78563412:
422 print >> sys
.stderr
, "Bad data file: magic number error."
434 line
= sys
.stdin
.read(struct
.calcsize(HDRREC
))
437 (event
, pid
, vcpu_id
) = struct
.unpack(HDRREC
, line
)
439 n_data
= event
>> 28 & 0x7
451 line
= sys
.stdin
.read(struct
.calcsize(TSCREC
))
454 ts
= struct
.unpack(TSCREC
, line
)[0]
456 line
= sys
.stdin
.read(struct
.calcsize(D1REC
))
459 d1
= struct
.unpack(D1REC
, line
)[0]
461 line
= sys
.stdin
.read(struct
.calcsize(D2REC
))
464 (d1
, d2
) = struct
.unpack(D2REC
, line
)
466 line
= sys
.stdin
.read(struct
.calcsize(D3REC
))
469 (d1
, d2
, d3
) = struct
.unpack(D3REC
, line
)
471 line
= sys
.stdin
.read(struct
.calcsize(D4REC
))
474 (d1
, d2
, d3
, d4
) = struct
.unpack(D4REC
, line
)
476 line
= sys
.stdin
.read(struct
.calcsize(D5REC
))
479 (d1
, d2
, d3
, d4
, d5
) = struct
.unpack(D5REC
, line
)
483 # provide relative TSC
485 if last_ts
> 0 and ts_in
== 1:
504 # some event types need more than just formats mapping they are if/elif
505 # chained here and the last default else is the mapping via formats
506 if event
== 0x00020019:
507 pdata
= (ts
, relts
, vcpu_id
, pid
, d1
, d2
, d3
, get_name(d1
), get_special(d1
))
508 print "%d (+%12d) PPC_INSTR vcpu = 0x%08x pid = 0x%08x [ instr = 0x%08x, pc = 0x%08x, emul = %01d, mnemonic = %8s %s" % pdata
511 if defs
.has_key(str(event
)):
512 print defs
[str(event
)] % args
514 if defs
.has_key(str(0)): print defs
[str(0)] % args
516 if defs
.has_key(str(event
)):
517 print defs
[str(event
)]
520 if defs
.has_key(str(0)):
524 except IOError, struct
.error
: sys
.exit()