1#!/usr/bin/env python 2 3# by Mark Williamson, (C) 2004 Intel Research Cambridge 4 5# Program for reformatting trace buffer output according to user-supplied rules 6 7import re, sys, string, signal, struct, os, getopt 8 9def usage(): 10 print >> sys.stderr, \ 11 "Usage: " + sys.argv[0] + """ defs-file 12 Parses trace data in binary format, as output by Xentrace 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): 16 17 {event_id}{whitespace}{text format string} 18 19 The textual format string may include format specifiers, such as: 20 %(cpu)d, %(tsc)d, %(event)d, %(1)d, %(2)d, %(3)d, %(4)d, ... 21 [ the 'd' format specifier outputs in decimal, alternatively 'x' 22 will output in hexadecimal and 'o' will output in octal ] 23 24 Which correspond to the CPU number, event ID, timestamp counter and 25 the 7 data fields from the trace record. There should be one such 26 rule for each type of event. 27 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 xentrace 30 if it is piped directly. In these circumstances you should have 31 xentrace output to a file for processing off-line. 32 """ 33 sys.exit(1) 34 35def read_defs(defs_file): 36 defs = {} 37 38 fd = open(defs_file) 39 40 reg = re.compile('(\S+)\s+(\S.*)') 41 42 while True: 43 line = fd.readline() 44 if not line: 45 break 46 47 if line[0] == '#' or line[0] == '\n': 48 continue 49 50 m = reg.match(line) 51 52 if not m: print >> sys.stderr, "Bad format file" ; sys.exit(1) 53 54 defs[str(eval(m.group(1)))] = m.group(2) 55 56 return defs 57 58def sighand(x,y): 59 global interrupted 60 interrupted = 1 61 62##### Main code 63 64mhz = 0 65 66if len(sys.argv) < 2: 67 usage() 68 69try: 70 opts, arg = getopt.getopt(sys.argv[1:], "c:" ) 71 72 for opt in opts: 73 if opt[0] == '-c' : mhz = int(opt[1]) 74 75except getopt.GetoptError: 76 usage() 77 78signal.signal(signal.SIGTERM, sighand) 79signal.signal(signal.SIGHUP, sighand) 80signal.signal(signal.SIGINT, sighand) 81 82interrupted = 0 83 84try: 85 defs = read_defs(arg[0]) 86except IOError, exn: 87 print exn 88 sys.exit(1) 89 90# structure of trace record (as output by xentrace): 91# HDR(I) {TSC(Q)} D1(I) D2(I) D3(I) D4(I) D5(I) D6(I) D7(I) 92# 93# HDR consists of EVENT:28:, n_data:3:, tsc_in:1: 94# EVENT means Event ID 95# n_data means number of data (like D1, D2, ...) 96# tsc_in means TSC data exists(1) or not(0). 97# if tsc_in == 0, TSC(Q) does not exists. 98# 99# CPU ID exists on trace data of EVENT=0x0001f003 100# 101HDRREC = "I" 102TSCREC = "Q" 103D1REC = "I" 104D2REC = "II" 105D3REC = "III" 106D4REC = "IIII" 107D5REC = "IIIII" 108D6REC = "IIIIII" 109D7REC = "IIIIIII" 110 111last_tsc = [0] 112 113TRC_TRACE_IRQ = 0x1f004 114TRC_PV_HYPERCALL_V2 = 0x20100d 115TRC_PV_HYPERCALL_SUBCALL = 0x20100e 116 117NR_VECTORS = 256 118irq_measure = [{'count':0, 'tot_cycles':0, 'max_cycles':0}] * NR_VECTORS 119 120i=0 121 122while not interrupted: 123 try: 124 i=i+1 125 line = sys.stdin.read(struct.calcsize(HDRREC)) 126 if not line: 127 break 128 event = struct.unpack(HDRREC, line)[0] 129 n_data = event >> 28 & 0x7 130 tsc_in = event >> 31 131 132 d1 = 0 133 d2 = 0 134 d3 = 0 135 d4 = 0 136 d5 = 0 137 d6 = 0 138 d7 = 0 139 140 tsc = 0 141 142 if tsc_in == 1: 143 line = sys.stdin.read(struct.calcsize(TSCREC)) 144 if not line: 145 break 146 tsc = struct.unpack(TSCREC, line)[0] 147 148 if n_data == 1: 149 line = sys.stdin.read(struct.calcsize(D1REC)) 150 if not line: 151 break 152 d1 = struct.unpack(D1REC, line)[0] 153 if n_data == 2: 154 line = sys.stdin.read(struct.calcsize(D2REC)) 155 if not line: 156 break 157 (d1, d2) = struct.unpack(D2REC, line) 158 if n_data == 3: 159 line = sys.stdin.read(struct.calcsize(D3REC)) 160 if not line: 161 break 162 (d1, d2, d3) = struct.unpack(D3REC, line) 163 if n_data == 4: 164 line = sys.stdin.read(struct.calcsize(D4REC)) 165 if not line: 166 break 167 (d1, d2, d3, d4) = struct.unpack(D4REC, line) 168 if n_data == 5: 169 line = sys.stdin.read(struct.calcsize(D5REC)) 170 if not line: 171 break 172 (d1, d2, d3, d4, d5) = struct.unpack(D5REC, line) 173 if n_data == 6: 174 line = sys.stdin.read(struct.calcsize(D6REC)) 175 if not line: 176 break 177 (d1, d2, d3, d4, d5, d6) = struct.unpack(D6REC, line) 178 if n_data == 7: 179 line = sys.stdin.read(struct.calcsize(D7REC)) 180 if not line: 181 break 182 (d1, d2, d3, d4, d5, d6, d7) = struct.unpack(D7REC, line) 183 184 # Event field is 28bit of 'uint32_t' in header, not 'long'. 185 event &= 0x0fffffff 186 if event == 0x1f003: 187 cpu = d1 188 189 if event == TRC_TRACE_IRQ: 190 # IN - d1:vector, d2:tsc_in, d3:tsc_out 191 # OUT - d1:vector, d2:count, d3:tot_cycles, d4:max_cycles 192 tsc_diff = d3 - d2 193 if tsc_diff < 0: 194 break 195 irq_measure[d1]['count'] += 1 196 irq_measure[d1]['tot_cycles'] += tsc_diff 197 if irq_measure[d1]['max_cycles'] < tsc_diff: 198 irq_measure[d1]['max_cycles'] = tsc_diff 199 d2 = irq_measure[d1]['count'] 200 d3 = irq_measure[d1]['tot_cycles'] 201 d4 = irq_measure[d1]['max_cycles'] 202 203 if event == TRC_PV_HYPERCALL_V2 or event == TRC_PV_HYPERCALL_SUBCALL: 204 # Mask off the argument present bits. 205 d1 &= 0x000fffff 206 207 #tsc = (tscH<<32) | tscL 208 209 #print i, tsc 210 211 if cpu >= len(last_tsc): 212 last_tsc += [0] * (cpu - len(last_tsc) + 1) 213 elif tsc < last_tsc[cpu] and tsc_in == 1: 214 print "TSC stepped backward cpu %d ! %d %d" % (cpu,tsc,last_tsc[cpu]) 215 216 # provide relative TSC 217 if last_tsc[cpu] > 0 and tsc_in == 1: 218 reltsc = tsc - last_tsc[cpu] 219 else: 220 reltsc = 0 221 222 if tsc_in == 1: 223 last_tsc[cpu] = tsc 224 225 if mhz: 226 tsc = tsc / (mhz*1000000.0) 227 228 args = {'cpu' : cpu, 229 'tsc' : tsc, 230 'event' : event, 231 'reltsc': reltsc, 232 '1' : d1, 233 '2' : d2, 234 '3' : d3, 235 '4' : d4, 236 '5' : d5, 237 '6' : d6, 238 '7' : d7 } 239 240 try: 241 242 if defs.has_key(str(event)): 243 print defs[str(event)] % args 244 else: 245 if defs.has_key(str(0)): print defs[str(0)] % args 246 except TypeError: 247 if defs.has_key(str(event)): 248 print defs[str(event)] 249 print args 250 else: 251 if defs.has_key(str(0)): 252 print defs[str(0)] 253 print args 254 255 256 except IOError, struct.error: sys.exit() 257