102f1c33fSFeng Tang# EventClass.py
2b2441318SGreg Kroah-Hartman# SPDX-License-Identifier: GPL-2.0
302f1c33fSFeng Tang#
487b6a3adSFeng Tang# This is a library defining some events types classes, which could
502f1c33fSFeng Tang# be used by other scripts to analyzing the perf samples.
602f1c33fSFeng Tang#
702f1c33fSFeng Tang# Currently there are just a few classes defined for examples,
802f1c33fSFeng Tang# PerfEvent is the base class for all perf event sample, PebsEvent
902f1c33fSFeng Tang# is a HW base Intel x86 PEBS event, and user could add more SW/HW
1087b6a3adSFeng Tang# event classes based on requirements.
1112aa6c73SJeremy Clinefrom __future__ import print_function
1202f1c33fSFeng Tang
1302f1c33fSFeng Tangimport struct
1402f1c33fSFeng Tang
1502f1c33fSFeng Tang# Event types, user could add more here
1602f1c33fSFeng TangEVTYPE_GENERIC  = 0
1702f1c33fSFeng TangEVTYPE_PEBS     = 1     # Basic PEBS event
1802f1c33fSFeng TangEVTYPE_PEBS_LL  = 2     # PEBS event with load latency info
1902f1c33fSFeng TangEVTYPE_IBS      = 3
2002f1c33fSFeng Tang
2102f1c33fSFeng Tang#
2202f1c33fSFeng Tang# Currently we don't have good way to tell the event type, but by
2302f1c33fSFeng Tang# the size of raw buffer, raw PEBS event with load latency data's
2402f1c33fSFeng Tang# size is 176 bytes, while the pure PEBS event's size is 144 bytes.
2502f1c33fSFeng Tang#
2602f1c33fSFeng Tangdef create_event(name, comm, dso, symbol, raw_buf):
2702f1c33fSFeng Tang        if (len(raw_buf) == 144):
2802f1c33fSFeng Tang                event = PebsEvent(name, comm, dso, symbol, raw_buf)
2902f1c33fSFeng Tang        elif (len(raw_buf) == 176):
3002f1c33fSFeng Tang                event = PebsNHM(name, comm, dso, symbol, raw_buf)
3102f1c33fSFeng Tang        else:
3202f1c33fSFeng Tang                event = PerfEvent(name, comm, dso, symbol, raw_buf)
3302f1c33fSFeng Tang
3402f1c33fSFeng Tang        return event
3502f1c33fSFeng Tang
3602f1c33fSFeng Tangclass PerfEvent(object):
3702f1c33fSFeng Tang        event_num = 0
3802f1c33fSFeng Tang        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_GENERIC):
3902f1c33fSFeng Tang                self.name       = name
4002f1c33fSFeng Tang                self.comm       = comm
4102f1c33fSFeng Tang                self.dso        = dso
4202f1c33fSFeng Tang                self.symbol     = symbol
4302f1c33fSFeng Tang                self.raw_buf    = raw_buf
4402f1c33fSFeng Tang                self.ev_type    = ev_type
4502f1c33fSFeng Tang                PerfEvent.event_num += 1
4602f1c33fSFeng Tang
4702f1c33fSFeng Tang        def show(self):
4812aa6c73SJeremy Cline                print("PMU event: name=%12s, symbol=%24s, comm=%8s, dso=%12s" %
4912aa6c73SJeremy Cline                      (self.name, self.symbol, self.comm, self.dso))
5002f1c33fSFeng Tang
5102f1c33fSFeng Tang#
5202f1c33fSFeng Tang# Basic Intel PEBS (Precise Event-based Sampling) event, whose raw buffer
5302f1c33fSFeng Tang# contains the context info when that event happened: the EFLAGS and
5402f1c33fSFeng Tang# linear IP info, as well as all the registers.
5502f1c33fSFeng Tang#
5602f1c33fSFeng Tangclass PebsEvent(PerfEvent):
5702f1c33fSFeng Tang        pebs_num = 0
5802f1c33fSFeng Tang        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS):
5902f1c33fSFeng Tang                tmp_buf=raw_buf[0:80]
6002f1c33fSFeng Tang                flags, ip, ax, bx, cx, dx, si, di, bp, sp = struct.unpack('QQQQQQQQQQ', tmp_buf)
6102f1c33fSFeng Tang                self.flags = flags
6202f1c33fSFeng Tang                self.ip    = ip
6302f1c33fSFeng Tang                self.ax    = ax
6402f1c33fSFeng Tang                self.bx    = bx
6502f1c33fSFeng Tang                self.cx    = cx
6602f1c33fSFeng Tang                self.dx    = dx
6702f1c33fSFeng Tang                self.si    = si
6802f1c33fSFeng Tang                self.di    = di
6902f1c33fSFeng Tang                self.bp    = bp
7002f1c33fSFeng Tang                self.sp    = sp
7102f1c33fSFeng Tang
7202f1c33fSFeng Tang                PerfEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type)
7302f1c33fSFeng Tang                PebsEvent.pebs_num += 1
7402f1c33fSFeng Tang                del tmp_buf
7502f1c33fSFeng Tang
7602f1c33fSFeng Tang#
7702f1c33fSFeng Tang# Intel Nehalem and Westmere support PEBS plus Load Latency info which lie
7802f1c33fSFeng Tang# in the four 64 bit words write after the PEBS data:
7902f1c33fSFeng Tang#       Status: records the IA32_PERF_GLOBAL_STATUS register value
8002f1c33fSFeng Tang#       DLA:    Data Linear Address (EIP)
8102f1c33fSFeng Tang#       DSE:    Data Source Encoding, where the latency happens, hit or miss
8202f1c33fSFeng Tang#               in L1/L2/L3 or IO operations
8302f1c33fSFeng Tang#       LAT:    the actual latency in cycles
8402f1c33fSFeng Tang#
8502f1c33fSFeng Tangclass PebsNHM(PebsEvent):
8602f1c33fSFeng Tang        pebs_nhm_num = 0
8702f1c33fSFeng Tang        def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS_LL):
8802f1c33fSFeng Tang                tmp_buf=raw_buf[144:176]
8902f1c33fSFeng Tang                status, dla, dse, lat = struct.unpack('QQQQ', tmp_buf)
9002f1c33fSFeng Tang                self.status = status
9102f1c33fSFeng Tang                self.dla = dla
9202f1c33fSFeng Tang                self.dse = dse
9302f1c33fSFeng Tang                self.lat = lat
9402f1c33fSFeng Tang
9502f1c33fSFeng Tang                PebsEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type)
9602f1c33fSFeng Tang                PebsNHM.pebs_nhm_num += 1
9702f1c33fSFeng Tang                del tmp_buf
98