1#!/usr/bin/python3
2# -*- coding: UTF-8 -*-
3
4"""
5This script defines the function to do the irq related analysis
6"""
7
8import csv
9import struct
10
11TSC_BEGIN = 0
12TSC_END = 0
13
14VMEXIT_ENTRY = 0x10000
15
16LIST_EVENTS = {
17    'VMEXIT_EXTERNAL_INTERRUPT':   VMEXIT_ENTRY + 0x00000001,
18}
19
20IRQ_EXITS = {}
21
22# 4 * 64bit per trace entry
23TRCREC = "QQQQ"
24
25def parse_trace(ifile):
26    """parse the trace data file
27    Args:
28        ifile: input trace data file
29    Return:
30        None
31    """
32
33    fd = open(ifile, 'rb')
34
35    while True:
36        global TSC_BEGIN, TSC_END
37        try:
38            line = fd.read(struct.calcsize(TRCREC))
39            if not line:
40                break
41            (tsc, event, vec, d2) = struct.unpack(TRCREC, line)
42
43            event = event & 0xffffffffffff
44
45            if TSC_BEGIN == 0:
46               TSC_BEGIN = tsc
47
48            TSC_END = tsc
49
50            for key in LIST_EVENTS.keys():
51                if event == LIST_EVENTS.get(key):
52                    if vec in IRQ_EXITS.keys():
53                        IRQ_EXITS[vec] += 1
54                    else:
55                        IRQ_EXITS[vec] = 1
56
57        except struct.error:
58            sys.exit()
59
60def generate_report(ofile, freq):
61    """ generate analysis report
62    Args:
63        ofile: output report
64        freq: TSC frequency of the device trace data from
65    Return:
66        None
67    """
68    global TSC_BEGIN, TSC_END
69
70    csv_name = ofile + '.csv'
71    try:
72        with open(csv_name, 'a') as filep:
73            f_csv = csv.writer(filep)
74
75            rt_cycle = TSC_END - TSC_BEGIN
76            assert rt_cycle != 0, "Total run time in cycle is 0, \
77                                   TSC end %d, TSC begin %d" \
78                                   % (TSC_END, TSC_BEGIN)
79
80            rt_sec = float(rt_cycle) / (float(freq) * 1000 * 1000)
81
82            print ("%-8s\t%-8s\t%-8s" % ("Vector", "Count", "NR_Exit/Sec"))
83            f_csv.writerow(['Vector', 'NR_Exit', 'NR_Exit/Sec'])
84            for e in IRQ_EXITS.keys():
85                pct = float(IRQ_EXITS[e]) / rt_sec
86                print ("0x%08x\t%-8d\t%-8.2f" % (e, IRQ_EXITS[e], pct))
87                f_csv.writerow(['0x%08x' % e, IRQ_EXITS[e], '%.2f' % pct])
88
89    except IOError as err:
90        print ("Output File Error: " + str(err))
91
92def analyze_irq(ifile, ofile, freq):
93    """do the vm exits analysis
94    Args:
95        ifile: input trace data file
96        ofile: output report file
97        freq: TSC frequency of the host where we capture the trace data
98    Return:
99        None
100    """
101
102    print("IRQ analysis started... \n\tinput file: %s\n"
103          "\toutput file: %s.csv" % (ifile, ofile))
104
105    parse_trace(ifile)
106    # save report to the output file
107    generate_report(ofile, freq)
108