diff options
author | 2023-02-21 18:24:12 -0800 | |
---|---|---|
committer | 2023-02-21 18:24:12 -0800 | |
commit | 5b7c4cabbb65f5c469464da6c5f614cbd7f730f2 (patch) | |
tree | cc5c2d0a898769fd59549594fedb3ee6f84e59a0 /tools/perf/scripts/python/Perf-Trace-Util | |
download | linux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.tar.gz linux-5b7c4cabbb65f5c469464da6c5f614cbd7f730f2.zip |
Merge tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-nextgrafted
Pull networking updates from Jakub Kicinski:
"Core:
- Add dedicated kmem_cache for typical/small skb->head, avoid having
to access struct page at kfree time, and improve memory use.
- Introduce sysctl to set default RPS configuration for new netdevs.
- Define Netlink protocol specification format which can be used to
describe messages used by each family and auto-generate parsers.
Add tools for generating kernel data structures and uAPI headers.
- Expose all net/core sysctls inside netns.
- Remove 4s sleep in netpoll if carrier is instantly detected on
boot.
- Add configurable limit of MDB entries per port, and port-vlan.
- Continue populating drop reasons throughout the stack.
- Retire a handful of legacy Qdiscs and classifiers.
Protocols:
- Support IPv4 big TCP (TSO frames larger than 64kB).
- Add IP_LOCAL_PORT_RANGE socket option, to control local port range
on socket by socket basis.
- Track and report in procfs number of MPTCP sockets used.
- Support mixing IPv4 and IPv6 flows in the in-kernel MPTCP path
manager.
- IPv6: don't check net.ipv6.route.max_size and rely on garbage
collection to free memory (similarly to IPv4).
- Support Penultimate Segment Pop (PSP) flavor in SRv6 (RFC8986).
- ICMP: add per-rate limit counters.
- Add support for user scanning requests in ieee802154.
- Remove static WEP support.
- Support minimal Wi-Fi 7 Extremely High Throughput (EHT) rate
reporting.
- WiFi 7 EHT channel puncturing support (client & AP).
BPF:
- Add a rbtree data structure following the "next-gen data structure"
precedent set by recently added linked list, that is, by using
kfunc + kptr instead of adding a new BPF map type.
- Expose XDP hints via kfuncs with initial support for RX hash and
timestamp metadata.
- Add BPF_F_NO_TUNNEL_KEY extension to bpf_skb_set_tunnel_key to
better support decap on GRE tunnel devices not operating in collect
metadata.
- Improve x86 JIT's codegen for PROBE_MEM runtime error checks.
- Remove the need for trace_printk_lock for bpf_trace_printk and
bpf_trace_vprintk helpers.
- Extend libbpf's bpf_tracing.h support for tracing arguments of
kprobes/uprobes and syscall as a special case.
- Significantly reduce the search time for module symbols by
livepatch and BPF.
- Enable cpumasks to be used as kptrs, which is useful for tracing
programs tracking which tasks end up running on which CPUs in
different time intervals.
- Add support for BPF trampoline on s390x and riscv64.
- Add capability to export the XDP features supported by the NIC.
- Add __bpf_kfunc tag for marking kernel functions as kfuncs.
- Add cgroup.memory=nobpf kernel parameter option to disable BPF
memory accounting for container environments.
Netfilter:
- Remove the CLUSTERIP target. It has been marked as obsolete for
years, and we still have WARN splats wrt races of the out-of-band
/proc interface installed by this target.
- Add 'destroy' commands to nf_tables. They are identical to the
existing 'delete' commands, but do not return an error if the
referenced object (set, chain, rule...) did not exist.
Driver API:
- Improve cpumask_local_spread() locality to help NICs set the right
IRQ affinity on AMD platforms.
- Separate C22 and C45 MDIO bus transactions more clearly.
- Introduce new DCB table to control DSCP rewrite on egress.
- Support configuration of Physical Layer Collision Avoidance (PLCA)
Reconciliation Sublayer (RS) (802.3cg-2019). Modern version of
shared medium Ethernet.
- Support for MAC Merge layer (IEEE 802.3-2018 clause 99). Allowing
preemption of low priority frames by high priority frames.
- Add support for controlling MACSec offload using netlink SET.
- Rework devlink instance refcounts to allow registration and
de-registration under the instance lock. Split the code into
multiple files, drop some of the unnecessarily granular locks and
factor out common parts of netlink operation handling.
- Add TX frame aggregation parameters (for USB drivers).
- Add a new attr TCA_EXT_WARN_MSG to report TC (offload) warning
messages with notifications for debug.
- Allow offloading of UDP NEW connections via act_ct.
- Add support for per action HW stats in TC.
- Support hardware miss to TC action (continue processing in SW from
a specific point in the action chain).
- Warn if old Wireless Extension user space interface is used with
modern cfg80211/mac80211 drivers. Do not support Wireless
Extensions for Wi-Fi 7 devices at all. Everyone should switch to
using nl80211 interface instead.
- Improve the CAN bit timing configuration. Use extack to return
error messages directly to user space, update the SJW handling,
including the definition of a new default value that will benefit
CAN-FD controllers, by increasing their oscillator tolerance.
New hardware / drivers:
- Ethernet:
- nVidia BlueField-3 support (control traffic driver)
- Ethernet support for imx93 SoCs
- Motorcomm yt8531 gigabit Ethernet PHY
- onsemi NCN26000 10BASE-T1S PHY (with support for PLCA)
- Microchip LAN8841 PHY (incl. cable diagnostics and PTP)
- Amlogic gxl MDIO mux
- WiFi:
- RealTek RTL8188EU (rtl8xxxu)
- Qualcomm Wi-Fi 7 devices (ath12k)
- CAN:
- Renesas R-Car V4H
Drivers:
- Bluetooth:
- Set Per Platform Antenna Gain (PPAG) for Intel controllers.
- Ethernet NICs:
- Intel (1G, igc):
- support TSN / Qbv / packet scheduling features of i226 model
- Intel (100G, ice):
- use GNSS subsystem instead of TTY
- multi-buffer XDP support
- extend support for GPIO pins to E823 devices
- nVidia/Mellanox:
- update the shared buffer configuration on PFC commands
- implement PTP adjphase function for HW offset control
- TC support for Geneve and GRE with VF tunnel offload
- more efficient crypto key management method
- multi-port eswitch support
- Netronome/Corigine:
- add DCB IEEE support
- support IPsec offloading for NFP3800
- Freescale/NXP (enetc):
- support XDP_REDIRECT for XDP non-linear buffers
- improve reconfig, avoid link flap and waiting for idle
- support MAC Merge layer
- Other NICs:
- sfc/ef100: add basic devlink support for ef100
- ionic: rx_push mode operation (writing descriptors via MMIO)
- bnxt: use the auxiliary bus abstraction for RDMA
- r8169: disable ASPM and reset bus in case of tx timeout
- cpsw: support QSGMII mode for J721e CPSW9G
- cpts: support pulse-per-second output
- ngbe: add an mdio bus driver
- usbnet: optimize usbnet_bh() by avoiding unnecessary queuing
- r8152: handle devices with FW with NCM support
- amd-xgbe: support 10Mbps, 2.5GbE speeds and rx-adaptation
- virtio-net: support multi buffer XDP
- virtio/vsock: replace virtio_vsock_pkt with sk_buff
- tsnep: XDP support
- Ethernet high-speed switches:
- nVidia/Mellanox (mlxsw):
- add support for latency TLV (in FW control messages)
- Microchip (sparx5):
- separate explicit and implicit traffic forwarding rules, make
the implicit rules always active
- add support for egress DSCP rewrite
- IS0 VCAP support (Ingress Classification)
- IS2 VCAP filters (protos, L3 addrs, L4 ports, flags, ToS
etc.)
- ES2 VCAP support (Egress Access Control)
- support for Per-Stream Filtering and Policing (802.1Q,
8.6.5.1)
- Ethernet embedded switches:
- Marvell (mv88e6xxx):
- add MAB (port auth) offload support
- enable PTP receive for mv88e6390
- NXP (ocelot):
- support MAC Merge layer
- support for the the vsc7512 internal copper phys
- Microchip:
- lan9303: convert to PHYLINK
- lan966x: support TC flower filter statistics
- lan937x: PTP support for KSZ9563/KSZ8563 and LAN937x
- lan937x: support Credit Based Shaper configuration
- ksz9477: support Energy Efficient Ethernet
- other:
- qca8k: convert to regmap read/write API, use bulk operations
- rswitch: Improve TX timestamp accuracy
- Intel WiFi (iwlwifi):
- EHT (Wi-Fi 7) rate reporting
- STEP equalizer support: transfer some STEP (connection to radio
on platforms with integrated wifi) related parameters from the
BIOS to the firmware.
- Qualcomm 802.11ax WiFi (ath11k):
- IPQ5018 support
- Fine Timing Measurement (FTM) responder role support
- channel 177 support
- MediaTek WiFi (mt76):
- per-PHY LED support
- mt7996: EHT (Wi-Fi 7) support
- Wireless Ethernet Dispatch (WED) reset support
- switch to using page pool allocator
- RealTek WiFi (rtw89):
- support new version of Bluetooth co-existance
- Mobile:
- rmnet: support TX aggregation"
* tag 'net-next-6.3' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (1872 commits)
page_pool: add a comment explaining the fragment counter usage
net: ethtool: fix __ethtool_dev_mm_supported() implementation
ethtool: pse-pd: Fix double word in comments
xsk: add linux/vmalloc.h to xsk.c
sefltests: netdevsim: wait for devlink instance after netns removal
selftest: fib_tests: Always cleanup before exit
net/mlx5e: Align IPsec ASO result memory to be as required by hardware
net/mlx5e: TC, Set CT miss to the specific ct action instance
net/mlx5e: Rename CHAIN_TO_REG to MAPPED_OBJ_TO_REG
net/mlx5: Refactor tc miss handling to a single function
net/mlx5: Kconfig: Make tc offload depend on tc skb extension
net/sched: flower: Support hardware miss to tc action
net/sched: flower: Move filter handle initialization earlier
net/sched: cls_api: Support hardware miss to tc action
net/sched: Rename user cookie and act cookie
sfc: fix builds without CONFIG_RTC_LIB
sfc: clean up some inconsistent indentings
net/mlx4_en: Introduce flexible array to silence overflow warning
net: lan966x: Fix possible deadlock inside PTP
net/ulp: Remove redundant ->clone() test in inet_clone_ulp().
...
Diffstat (limited to 'tools/perf/scripts/python/Perf-Trace-Util')
6 files changed, 716 insertions, 0 deletions
diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Build b/tools/perf/scripts/python/Perf-Trace-Util/Build new file mode 100644 index 000000000..d5fed4e42 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/Build @@ -0,0 +1,3 @@ +perf-$(CONFIG_LIBTRACEEVENT) += Context.o + +CFLAGS_Context.o += $(PYTHON_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-nested-externs diff --git a/tools/perf/scripts/python/Perf-Trace-Util/Context.c b/tools/perf/scripts/python/Perf-Trace-Util/Context.c new file mode 100644 index 000000000..895f5fc23 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/Context.c @@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Context.c. Python interfaces for perf script. + * + * Copyright (C) 2010 Tom Zanussi <tzanussi@gmail.com> + */ + +/* + * Use Py_ssize_t for '#' formats to avoid DeprecationWarning: PY_SSIZE_T_CLEAN + * will be required for '#' formats. + */ +#define PY_SSIZE_T_CLEAN + +#include <Python.h> +#include "../../../util/trace-event.h" +#include "../../../util/event.h" +#include "../../../util/symbol.h" +#include "../../../util/thread.h" +#include "../../../util/map.h" +#include "../../../util/maps.h" +#include "../../../util/auxtrace.h" +#include "../../../util/session.h" +#include "../../../util/srcline.h" +#include "../../../util/srccode.h" + +#if PY_MAJOR_VERSION < 3 +#define _PyCapsule_GetPointer(arg1, arg2) \ + PyCObject_AsVoidPtr(arg1) +#define _PyBytes_FromStringAndSize(arg1, arg2) \ + PyString_FromStringAndSize((arg1), (arg2)) +#define _PyUnicode_AsUTF8(arg) \ + PyString_AsString(arg) + +PyMODINIT_FUNC initperf_trace_context(void); +#else +#define _PyCapsule_GetPointer(arg1, arg2) \ + PyCapsule_GetPointer((arg1), (arg2)) +#define _PyBytes_FromStringAndSize(arg1, arg2) \ + PyBytes_FromStringAndSize((arg1), (arg2)) +#define _PyUnicode_AsUTF8(arg) \ + PyUnicode_AsUTF8(arg) + +PyMODINIT_FUNC PyInit_perf_trace_context(void); +#endif + +static struct scripting_context *get_args(PyObject *args, const char *name, PyObject **arg2) +{ + int cnt = 1 + !!arg2; + PyObject *context; + + if (!PyArg_UnpackTuple(args, name, 1, cnt, &context, arg2)) + return NULL; + + return _PyCapsule_GetPointer(context, NULL); +} + +static struct scripting_context *get_scripting_context(PyObject *args) +{ + return get_args(args, "context", NULL); +} + +static PyObject *perf_trace_context_common_pc(PyObject *obj, PyObject *args) +{ + struct scripting_context *c = get_scripting_context(args); + + if (!c) + return NULL; + + return Py_BuildValue("i", common_pc(c)); +} + +static PyObject *perf_trace_context_common_flags(PyObject *obj, + PyObject *args) +{ + struct scripting_context *c = get_scripting_context(args); + + if (!c) + return NULL; + + return Py_BuildValue("i", common_flags(c)); +} + +static PyObject *perf_trace_context_common_lock_depth(PyObject *obj, + PyObject *args) +{ + struct scripting_context *c = get_scripting_context(args); + + if (!c) + return NULL; + + return Py_BuildValue("i", common_lock_depth(c)); +} + +static PyObject *perf_sample_insn(PyObject *obj, PyObject *args) +{ + struct scripting_context *c = get_scripting_context(args); + + if (!c) + return NULL; + + if (c->sample->ip && !c->sample->insn_len && + c->al->thread->maps && c->al->thread->maps->machine) + script_fetch_insn(c->sample, c->al->thread, c->al->thread->maps->machine); + + if (!c->sample->insn_len) + Py_RETURN_NONE; /* N.B. This is a return statement */ + + return _PyBytes_FromStringAndSize(c->sample->insn, c->sample->insn_len); +} + +static PyObject *perf_set_itrace_options(PyObject *obj, PyObject *args) +{ + struct scripting_context *c; + const char *itrace_options; + int retval = -1; + PyObject *str; + + c = get_args(args, "itrace_options", &str); + if (!c) + return NULL; + + if (!c->session || !c->session->itrace_synth_opts) + goto out; + + if (c->session->itrace_synth_opts->set) { + retval = 1; + goto out; + } + + itrace_options = _PyUnicode_AsUTF8(str); + + retval = itrace_do_parse_synth_opts(c->session->itrace_synth_opts, itrace_options, 0); +out: + return Py_BuildValue("i", retval); +} + +static PyObject *perf_sample_src(PyObject *obj, PyObject *args, bool get_srccode) +{ + struct scripting_context *c = get_scripting_context(args); + unsigned int line = 0; + char *srcfile = NULL; + char *srccode = NULL; + PyObject *result; + struct map *map; + int len = 0; + u64 addr; + + if (!c) + return NULL; + + map = c->al->map; + addr = c->al->addr; + + if (map && map->dso) + srcfile = get_srcline_split(map->dso, map__rip_2objdump(map, addr), &line); + + if (get_srccode) { + if (srcfile) + srccode = find_sourceline(srcfile, line, &len); + result = Py_BuildValue("(sIs#)", srcfile, line, srccode, (Py_ssize_t)len); + } else { + result = Py_BuildValue("(sI)", srcfile, line); + } + + free(srcfile); + + return result; +} + +static PyObject *perf_sample_srcline(PyObject *obj, PyObject *args) +{ + return perf_sample_src(obj, args, false); +} + +static PyObject *perf_sample_srccode(PyObject *obj, PyObject *args) +{ + return perf_sample_src(obj, args, true); +} + +static PyMethodDef ContextMethods[] = { + { "common_pc", perf_trace_context_common_pc, METH_VARARGS, + "Get the common preempt count event field value."}, + { "common_flags", perf_trace_context_common_flags, METH_VARARGS, + "Get the common flags event field value."}, + { "common_lock_depth", perf_trace_context_common_lock_depth, + METH_VARARGS, "Get the common lock depth event field value."}, + { "perf_sample_insn", perf_sample_insn, + METH_VARARGS, "Get the machine code instruction."}, + { "perf_set_itrace_options", perf_set_itrace_options, + METH_VARARGS, "Set --itrace options."}, + { "perf_sample_srcline", perf_sample_srcline, + METH_VARARGS, "Get source file name and line number."}, + { "perf_sample_srccode", perf_sample_srccode, + METH_VARARGS, "Get source file name, line number and line."}, + { NULL, NULL, 0, NULL} +}; + +#if PY_MAJOR_VERSION < 3 +PyMODINIT_FUNC initperf_trace_context(void) +{ + (void) Py_InitModule("perf_trace_context", ContextMethods); +} +#else +PyMODINIT_FUNC PyInit_perf_trace_context(void) +{ + static struct PyModuleDef moduledef = { + PyModuleDef_HEAD_INIT, + "perf_trace_context", /* m_name */ + "", /* m_doc */ + -1, /* m_size */ + ContextMethods, /* m_methods */ + NULL, /* m_reload */ + NULL, /* m_traverse */ + NULL, /* m_clear */ + NULL, /* m_free */ + }; + PyObject *mod; + + mod = PyModule_Create(&moduledef); + /* Add perf_script_context to the module so it can be imported */ + PyObject_SetAttrString(mod, "perf_script_context", Py_None); + + return mod; +} +#endif diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py new file mode 100644 index 000000000..54ace2f6b --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Core.py @@ -0,0 +1,116 @@ +# Core.py - Python extension for perf script, core functions +# +# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> +# +# This software may be distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. + +from collections import defaultdict + +def autodict(): + return defaultdict(autodict) + +flag_fields = autodict() +symbolic_fields = autodict() + +def define_flag_field(event_name, field_name, delim): + flag_fields[event_name][field_name]['delim'] = delim + +def define_flag_value(event_name, field_name, value, field_str): + flag_fields[event_name][field_name]['values'][value] = field_str + +def define_symbolic_field(event_name, field_name): + # nothing to do, really + pass + +def define_symbolic_value(event_name, field_name, value, field_str): + symbolic_fields[event_name][field_name]['values'][value] = field_str + +def flag_str(event_name, field_name, value): + string = "" + + if flag_fields[event_name][field_name]: + print_delim = 0 + for idx in sorted(flag_fields[event_name][field_name]['values']): + if not value and not idx: + string += flag_fields[event_name][field_name]['values'][idx] + break + if idx and (value & idx) == idx: + if print_delim and flag_fields[event_name][field_name]['delim']: + string += " " + flag_fields[event_name][field_name]['delim'] + " " + string += flag_fields[event_name][field_name]['values'][idx] + print_delim = 1 + value &= ~idx + + return string + +def symbol_str(event_name, field_name, value): + string = "" + + if symbolic_fields[event_name][field_name]: + for idx in sorted(symbolic_fields[event_name][field_name]['values']): + if not value and not idx: + string = symbolic_fields[event_name][field_name]['values'][idx] + break + if (value == idx): + string = symbolic_fields[event_name][field_name]['values'][idx] + break + + return string + +trace_flags = { 0x00: "NONE", \ + 0x01: "IRQS_OFF", \ + 0x02: "IRQS_NOSUPPORT", \ + 0x04: "NEED_RESCHED", \ + 0x08: "HARDIRQ", \ + 0x10: "SOFTIRQ" } + +def trace_flag_str(value): + string = "" + print_delim = 0 + + for idx in trace_flags: + if not value and not idx: + string += "NONE" + break + + if idx and (value & idx) == idx: + if print_delim: + string += " | "; + string += trace_flags[idx] + print_delim = 1 + value &= ~idx + + return string + + +def taskState(state): + states = { + 0 : "R", + 1 : "S", + 2 : "D", + 64: "DEAD" + } + + if state not in states: + return "Unknown" + + return states[state] + + +class EventHeaders: + def __init__(self, common_cpu, common_secs, common_nsecs, + common_pid, common_comm, common_callchain): + self.cpu = common_cpu + self.secs = common_secs + self.nsecs = common_nsecs + self.pid = common_pid + self.comm = common_comm + self.callchain = common_callchain + + def ts(self): + return (self.secs * (10 ** 9)) + self.nsecs + + def ts_format(self): + return "%d.%d" % (self.secs, int(self.nsecs / 1000)) diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py new file mode 100755 index 000000000..21a7a1298 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/EventClass.py @@ -0,0 +1,97 @@ +# EventClass.py +# SPDX-License-Identifier: GPL-2.0 +# +# This is a library defining some events types classes, which could +# be used by other scripts to analyzing the perf samples. +# +# Currently there are just a few classes defined for examples, +# PerfEvent is the base class for all perf event sample, PebsEvent +# is a HW base Intel x86 PEBS event, and user could add more SW/HW +# event classes based on requirements. +from __future__ import print_function + +import struct + +# Event types, user could add more here +EVTYPE_GENERIC = 0 +EVTYPE_PEBS = 1 # Basic PEBS event +EVTYPE_PEBS_LL = 2 # PEBS event with load latency info +EVTYPE_IBS = 3 + +# +# Currently we don't have good way to tell the event type, but by +# the size of raw buffer, raw PEBS event with load latency data's +# size is 176 bytes, while the pure PEBS event's size is 144 bytes. +# +def create_event(name, comm, dso, symbol, raw_buf): + if (len(raw_buf) == 144): + event = PebsEvent(name, comm, dso, symbol, raw_buf) + elif (len(raw_buf) == 176): + event = PebsNHM(name, comm, dso, symbol, raw_buf) + else: + event = PerfEvent(name, comm, dso, symbol, raw_buf) + + return event + +class PerfEvent(object): + event_num = 0 + def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_GENERIC): + self.name = name + self.comm = comm + self.dso = dso + self.symbol = symbol + self.raw_buf = raw_buf + self.ev_type = ev_type + PerfEvent.event_num += 1 + + def show(self): + print("PMU event: name=%12s, symbol=%24s, comm=%8s, dso=%12s" % + (self.name, self.symbol, self.comm, self.dso)) + +# +# Basic Intel PEBS (Precise Event-based Sampling) event, whose raw buffer +# contains the context info when that event happened: the EFLAGS and +# linear IP info, as well as all the registers. +# +class PebsEvent(PerfEvent): + pebs_num = 0 + def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS): + tmp_buf=raw_buf[0:80] + flags, ip, ax, bx, cx, dx, si, di, bp, sp = struct.unpack('QQQQQQQQQQ', tmp_buf) + self.flags = flags + self.ip = ip + self.ax = ax + self.bx = bx + self.cx = cx + self.dx = dx + self.si = si + self.di = di + self.bp = bp + self.sp = sp + + PerfEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) + PebsEvent.pebs_num += 1 + del tmp_buf + +# +# Intel Nehalem and Westmere support PEBS plus Load Latency info which lie +# in the four 64 bit words write after the PEBS data: +# Status: records the IA32_PERF_GLOBAL_STATUS register value +# DLA: Data Linear Address (EIP) +# DSE: Data Source Encoding, where the latency happens, hit or miss +# in L1/L2/L3 or IO operations +# LAT: the actual latency in cycles +# +class PebsNHM(PebsEvent): + pebs_nhm_num = 0 + def __init__(self, name, comm, dso, symbol, raw_buf, ev_type=EVTYPE_PEBS_LL): + tmp_buf=raw_buf[144:176] + status, dla, dse, lat = struct.unpack('QQQQ', tmp_buf) + self.status = status + self.dla = dla + self.dse = dse + self.lat = lat + + PebsEvent.__init__(self, name, comm, dso, symbol, raw_buf, ev_type) + PebsNHM.pebs_nhm_num += 1 + del tmp_buf diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py new file mode 100644 index 000000000..cac7b2542 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/SchedGui.py @@ -0,0 +1,184 @@ +# SchedGui.py - Python extension for perf script, basic GUI code for +# traces drawing and overview. +# +# Copyright (C) 2010 by Frederic Weisbecker <fweisbec@gmail.com> +# +# This software is distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. + + +try: + import wx +except ImportError: + raise ImportError("You need to install the wxpython lib for this script") + + +class RootFrame(wx.Frame): + Y_OFFSET = 100 + RECT_HEIGHT = 100 + RECT_SPACE = 50 + EVENT_MARKING_WIDTH = 5 + + def __init__(self, sched_tracer, title, parent = None, id = -1): + wx.Frame.__init__(self, parent, id, title) + + (self.screen_width, self.screen_height) = wx.GetDisplaySize() + self.screen_width -= 10 + self.screen_height -= 10 + self.zoom = 0.5 + self.scroll_scale = 20 + self.sched_tracer = sched_tracer + self.sched_tracer.set_root_win(self) + (self.ts_start, self.ts_end) = sched_tracer.interval() + self.update_width_virtual() + self.nr_rects = sched_tracer.nr_rectangles() + 1 + self.height_virtual = RootFrame.Y_OFFSET + (self.nr_rects * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) + + # whole window panel + self.panel = wx.Panel(self, size=(self.screen_width, self.screen_height)) + + # scrollable container + self.scroll = wx.ScrolledWindow(self.panel) + self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale) + self.scroll.EnableScrolling(True, True) + self.scroll.SetFocus() + + # scrollable drawing area + self.scroll_panel = wx.Panel(self.scroll, size=(self.screen_width - 15, self.screen_height / 2)) + self.scroll_panel.Bind(wx.EVT_PAINT, self.on_paint) + self.scroll_panel.Bind(wx.EVT_KEY_DOWN, self.on_key_press) + self.scroll_panel.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) + self.scroll.Bind(wx.EVT_PAINT, self.on_paint) + self.scroll.Bind(wx.EVT_KEY_DOWN, self.on_key_press) + self.scroll.Bind(wx.EVT_LEFT_DOWN, self.on_mouse_down) + + self.scroll.Fit() + self.Fit() + + self.scroll_panel.SetDimensions(-1, -1, self.width_virtual, self.height_virtual, wx.SIZE_USE_EXISTING) + + self.txt = None + + self.Show(True) + + def us_to_px(self, val): + return val / (10 ** 3) * self.zoom + + def px_to_us(self, val): + return (val / self.zoom) * (10 ** 3) + + def scroll_start(self): + (x, y) = self.scroll.GetViewStart() + return (x * self.scroll_scale, y * self.scroll_scale) + + def scroll_start_us(self): + (x, y) = self.scroll_start() + return self.px_to_us(x) + + def paint_rectangle_zone(self, nr, color, top_color, start, end): + offset_px = self.us_to_px(start - self.ts_start) + width_px = self.us_to_px(end - self.ts_start) + + offset_py = RootFrame.Y_OFFSET + (nr * (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE)) + width_py = RootFrame.RECT_HEIGHT + + dc = self.dc + + if top_color is not None: + (r, g, b) = top_color + top_color = wx.Colour(r, g, b) + brush = wx.Brush(top_color, wx.SOLID) + dc.SetBrush(brush) + dc.DrawRectangle(offset_px, offset_py, width_px, RootFrame.EVENT_MARKING_WIDTH) + width_py -= RootFrame.EVENT_MARKING_WIDTH + offset_py += RootFrame.EVENT_MARKING_WIDTH + + (r ,g, b) = color + color = wx.Colour(r, g, b) + brush = wx.Brush(color, wx.SOLID) + dc.SetBrush(brush) + dc.DrawRectangle(offset_px, offset_py, width_px, width_py) + + def update_rectangles(self, dc, start, end): + start += self.ts_start + end += self.ts_start + self.sched_tracer.fill_zone(start, end) + + def on_paint(self, event): + dc = wx.PaintDC(self.scroll_panel) + self.dc = dc + + width = min(self.width_virtual, self.screen_width) + (x, y) = self.scroll_start() + start = self.px_to_us(x) + end = self.px_to_us(x + width) + self.update_rectangles(dc, start, end) + + def rect_from_ypixel(self, y): + y -= RootFrame.Y_OFFSET + rect = y / (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) + height = y % (RootFrame.RECT_HEIGHT + RootFrame.RECT_SPACE) + + if rect < 0 or rect > self.nr_rects - 1 or height > RootFrame.RECT_HEIGHT: + return -1 + + return rect + + def update_summary(self, txt): + if self.txt: + self.txt.Destroy() + self.txt = wx.StaticText(self.panel, -1, txt, (0, (self.screen_height / 2) + 50)) + + + def on_mouse_down(self, event): + (x, y) = event.GetPositionTuple() + rect = self.rect_from_ypixel(y) + if rect == -1: + return + + t = self.px_to_us(x) + self.ts_start + + self.sched_tracer.mouse_down(rect, t) + + + def update_width_virtual(self): + self.width_virtual = self.us_to_px(self.ts_end - self.ts_start) + + def __zoom(self, x): + self.update_width_virtual() + (xpos, ypos) = self.scroll.GetViewStart() + xpos = self.us_to_px(x) / self.scroll_scale + self.scroll.SetScrollbars(self.scroll_scale, self.scroll_scale, self.width_virtual / self.scroll_scale, self.height_virtual / self.scroll_scale, xpos, ypos) + self.Refresh() + + def zoom_in(self): + x = self.scroll_start_us() + self.zoom *= 2 + self.__zoom(x) + + def zoom_out(self): + x = self.scroll_start_us() + self.zoom /= 2 + self.__zoom(x) + + + def on_key_press(self, event): + key = event.GetRawKeyCode() + if key == ord("+"): + self.zoom_in() + return + if key == ord("-"): + self.zoom_out() + return + + key = event.GetKeyCode() + (x, y) = self.scroll.GetViewStart() + if key == wx.WXK_RIGHT: + self.scroll.Scroll(x + 1, y) + elif key == wx.WXK_LEFT: + self.scroll.Scroll(x - 1, y) + elif key == wx.WXK_DOWN: + self.scroll.Scroll(x, y + 1) + elif key == wx.WXK_UP: + self.scroll.Scroll(x, y - 1) diff --git a/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py new file mode 100644 index 000000000..7384dcb62 --- /dev/null +++ b/tools/perf/scripts/python/Perf-Trace-Util/lib/Perf/Trace/Util.py @@ -0,0 +1,91 @@ +# Util.py - Python extension for perf script, miscellaneous utility code +# +# Copyright (C) 2010 by Tom Zanussi <tzanussi@gmail.com> +# +# This software may be distributed under the terms of the GNU General +# Public License ("GPL") version 2 as published by the Free Software +# Foundation. +from __future__ import print_function + +import errno, os + +FUTEX_WAIT = 0 +FUTEX_WAKE = 1 +FUTEX_PRIVATE_FLAG = 128 +FUTEX_CLOCK_REALTIME = 256 +FUTEX_CMD_MASK = ~(FUTEX_PRIVATE_FLAG | FUTEX_CLOCK_REALTIME) + +NSECS_PER_SEC = 1000000000 + +def avg(total, n): + return total / n + +def nsecs(secs, nsecs): + return secs * NSECS_PER_SEC + nsecs + +def nsecs_secs(nsecs): + return nsecs / NSECS_PER_SEC + +def nsecs_nsecs(nsecs): + return nsecs % NSECS_PER_SEC + +def nsecs_str(nsecs): + str = "%5u.%09u" % (nsecs_secs(nsecs), nsecs_nsecs(nsecs)), + return str + +def add_stats(dict, key, value): + if key not in dict: + dict[key] = (value, value, value, 1) + else: + min, max, avg, count = dict[key] + if value < min: + min = value + if value > max: + max = value + avg = (avg + value) / 2 + dict[key] = (min, max, avg, count + 1) + +def clear_term(): + print("\x1b[H\x1b[2J") + +audit_package_warned = False + +try: + import audit + machine_to_id = { + 'x86_64': audit.MACH_86_64, + 'alpha' : audit.MACH_ALPHA, + 'ia64' : audit.MACH_IA64, + 'ppc' : audit.MACH_PPC, + 'ppc64' : audit.MACH_PPC64, + 'ppc64le' : audit.MACH_PPC64LE, + 's390' : audit.MACH_S390, + 's390x' : audit.MACH_S390X, + 'i386' : audit.MACH_X86, + 'i586' : audit.MACH_X86, + 'i686' : audit.MACH_X86, + } + try: + machine_to_id['armeb'] = audit.MACH_ARMEB + except: + pass + machine_id = machine_to_id[os.uname()[4]] +except: + if not audit_package_warned: + audit_package_warned = True + print("Install the audit-libs-python package to get syscall names.\n" + "For example:\n # apt-get install python-audit (Ubuntu)" + "\n # yum install audit-libs-python (Fedora)" + "\n etc.\n") + +def syscall_name(id): + try: + return audit.audit_syscall_to_name(id, machine_id) + except: + return str(id) + +def strerror(nr): + try: + return errno.errorcode[abs(nr)] + except: + return "Unknown %d errno" % nr |