From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, adrian.hunter@intel.com,
alice.mei.rogers@gmail.com, james.clark@linaro.org,
linux-perf-users@vger.kernel.org, namhyung@kernel.org
Cc: dapeng1.mi@linux.intel.com, leo.yan@linux.dev,
linux-kernel@vger.kernel.org, mingo@redhat.com,
peterz@infradead.org, tmricht@linux.ibm.com
Subject: [PATCH v1 08/49] perf python: Expose addr location, transaction, and context_switch
Date: Sat, 19 Sep 2026 22:21:00 -0700 [thread overview]
Message-ID: <b8e1b4ae6cb475a56bcd2c48130ac1f8ca036ddb.1789880842.git.irogers@google.com> (raw)
In-Reply-To: <cover.1789880842.git.irogers@google.com>
Expose destination address location components (addr_dso, addr_symbol,
addr_sym_offset), branch/transaction metrics (branch_type, in_tx,
flags, transaction), machine_pid, vcpu, sym_offset, and context_switch
callbacks directly to the Python extension.
Also include supporting fixes and infrastructure updates in
util/python.c and perf.pyi:
- Support fetching sym_offset on resolved sample symbols.
- Populate sample machine_pid and vcpu from evlist__id2sid() when
perf_guest is enabled, and resolve samples against the matching guest
or host machine.
- Expose next_prev_pid and next_prev_tid on switch_event only for
PERF_RECORD_SWITCH_CPU_WIDE records (returning None otherwise).
- Wire up tracing_data in pyrf_session__new(), use 'static char * const
kwlist[]', and update perf.pyi type stubs (including srccode() and
insn() return types).
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/python/perf.pyi | 22 +++-
tools/perf/util/python.c | 249 +++++++++++++++++++++++++++++++++++--
2 files changed, 253 insertions(+), 18 deletions(-)
diff --git a/tools/perf/python/perf.pyi b/tools/perf/python/perf.pyi
index e5259e9b61dd..7f747eed3eda 100644
--- a/tools/perf/python/perf.pyi
+++ b/tools/perf/python/perf.pyi
@@ -182,6 +182,8 @@ class _sample_members:
sample_time: int
sample_id: int
sample_stream_id: int
+ machine_pid: int
+ vcpu: int
sample_period: int
sample_cpu: int
@@ -206,10 +208,18 @@ class sample_event(_sample_members):
symbol: str
sym_start: int
sym_end: int
+ sym_offset: Optional[int]
+ addr_dso: Optional[str]
+ addr_symbol: Optional[str]
+ addr_sym_offset: Optional[int]
+ branch_type: int
+ in_tx: int
+ flags: int
+ transaction: int
brstack: Optional['branch_stack']
callchain: Optional['callchain']
- def srccode(self) -> str: ...
- def insn(self) -> str: ...
+ def srccode(self) -> Optional[tuple[str, int, str]]: ...
+ def insn(self) -> Optional[bytes]: ...
def __getattr__(self, name: str) -> Any: ...
class mmap_event(_sample_members):
@@ -286,8 +296,9 @@ class read_event(_sample_members):
class switch_event(_sample_members):
"""Represents a SWITCH or SWITCH_CPU_WIDE record."""
type: int
- next_prev_pid: int
- next_prev_tid: int
+ misc: int
+ next_prev_pid: Optional[int]
+ next_prev_tid: Optional[int]
evsel: Optional['evsel']
class branch_entry:
@@ -429,7 +440,8 @@ class session:
self,
data: data,
sample: Optional[Callable[[sample_event], None]] = None,
- stat: Optional[Callable[[Any, Optional[str]], None]] = None
+ stat: Optional[Callable[[Any, Optional[str]], None]] = None,
+ context_switch: Optional[Callable[[switch_event], None]] = None,
) -> None:
"""Initialize a perf session.
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index fbfa71b1c4b6..49f37198f4b3 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -3,6 +3,7 @@
#include <Python.h>
#include <inttypes.h>
+#include <stdio.h>
#include <string.h>
#include <linux/err.h>
@@ -106,6 +107,8 @@ struct pyrf_event {
sample_member_def(sample_time, time, T_ULONGLONG, "event timestamp"), \
sample_member_def(sample_id, id, T_ULONGLONG, "event id"), \
sample_member_def(sample_stream_id, stream_id, T_ULONGLONG, "event stream id"), \
+ sample_member_def(machine_pid, machine_pid, T_UINT, "event machine pid"), \
+ sample_member_def(vcpu, vcpu, T_UINT, "event vcpu"), \
sample_member_def(sample_period, period, T_ULONGLONG, "event period"), \
sample_member_def(sample_cpu, cpu, T_UINT, "event cpu"),
@@ -581,6 +584,7 @@ static PyMemberDef pyrf_sample_event__members[] = {
sample_member_def(sample_data_src, data_src, T_ULONGLONG, "event data source"),
sample_member_def(sample_insn_count, insn_cnt, T_ULONGLONG, "event instruction count"),
sample_member_def(sample_cyc_count, cyc_cnt, T_ULONGLONG, "event cycle count"),
+ sample_member_def(flags, flags, T_UINT, "event flags"),
member_def(perf_event_header, type, T_UINT, "event type"),
{ .name = NULL, },
};
@@ -679,6 +683,7 @@ static int pyrf_sample_event__resolve_al(struct pyrf_event *pevent)
struct evsel *evsel = pevent->sample.evsel;
struct evlist *evlist = evsel ? evsel->evlist : NULL;
struct perf_session *session = evlist ? evlist__session(evlist) : NULL;
+ struct machine *machine;
if (pevent->al_resolved)
return 0;
@@ -686,8 +691,14 @@ static int pyrf_sample_event__resolve_al(struct pyrf_event *pevent)
if (!session)
return -1;
+ machine = pevent->sample.machine_pid ?
+ machines__find(&session->machines, pevent->sample.machine_pid) :
+ &session->machines.host;
+ if (!machine)
+ machine = &session->machines.host;
+
addr_location__init(&pevent->al);
- if (machine__resolve(&session->machines.host, &pevent->al, &pevent->sample) < 0) {
+ if (machine__resolve(machine, &pevent->al, &pevent->sample) < 0) {
addr_location__exit(&pevent->al);
return -1;
}
@@ -771,6 +782,15 @@ static PyObject *pyrf_sample_event__get_sym_start(struct pyrf_event *pevent,
return PyLong_FromUnsignedLongLong(pevent->al.sym->start);
}
+static PyObject *pyrf_sample_event__get_sym_offset(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.sym)
+ Py_RETURN_NONE;
+
+ return PyLong_FromUnsignedLongLong(pevent->al.addr - pevent->al.sym->start);
+}
+
static PyObject *pyrf_sample_event__get_sym_end(struct pyrf_event *pevent,
void *closure __maybe_unused)
{
@@ -1166,7 +1186,115 @@ pyrf_sample_event__getattro(struct pyrf_event *pevent, PyObject *attr_name)
return obj ?: PyObject_GenericGetAttr((PyObject *) pevent, attr_name);
}
+
+static int pyrf_sample_event__resolve_addr_al(struct pyrf_event *pevent,
+ struct addr_location *addr_al)
+{
+ addr_location__init(addr_al);
+ if (pyrf_sample_event__resolve_al(pevent) < 0 || !pevent->al.thread)
+ return -1;
+
+ thread__find_symbol_fb(pevent->al.thread, pevent->sample.cpumode,
+ pevent->sample.addr, addr_al);
+ return 0;
+}
+
+static PyObject *pyrf_sample_event__get_addr_dso(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ struct addr_location addr_al;
+ PyObject *ret = Py_None;
+
+ if (pyrf_sample_event__resolve_addr_al(pevent, &addr_al) == 0 && addr_al.map)
+ ret = PyUnicode_FromString(dso__name(map__dso(addr_al.map)));
+ else
+ Py_INCREF(Py_None);
+
+ addr_location__exit(&addr_al);
+ return ret;
+}
+
+static PyObject *pyrf_sample_event__get_addr_symbol(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ struct addr_location addr_al;
+ PyObject *ret = Py_None;
+
+ if (pyrf_sample_event__resolve_addr_al(pevent, &addr_al) == 0 && addr_al.sym)
+ ret = PyUnicode_FromString(addr_al.sym->name);
+ else
+ Py_INCREF(Py_None);
+
+ addr_location__exit(&addr_al);
+ return ret;
+}
+
+static PyObject *pyrf_sample_event__get_addr_sym_offset(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ struct addr_location addr_al;
+ PyObject *ret = Py_None;
+
+ if (pyrf_sample_event__resolve_addr_al(pevent, &addr_al) == 0 && addr_al.sym)
+ ret = PyLong_FromUnsignedLongLong(addr_al.addr - addr_al.sym->start);
+ else
+ Py_INCREF(Py_None);
+
+ addr_location__exit(&addr_al);
+ return ret;
+}
+
+static PyObject *pyrf_sample_event__get_branch_type(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ return PyLong_FromUnsignedLong(pevent->sample.flags & PERF_BRANCH_MASK);
+}
+
+static PyObject *pyrf_sample_event__get_in_tx(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ return PyLong_FromUnsignedLong(!!(pevent->sample.flags & PERF_IP_FLAG_IN_TX));
+}
+
+static PyObject *pyrf_sample_event__get_transaction(struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ return PyLong_FromUnsignedLongLong(pevent->sample.transaction);
+}
+
static PyGetSetDef pyrf_sample_event__getset[] = {
+
+ {
+ .name = "addr_dso",
+ .get = (getter)pyrf_sample_event__get_addr_dso,
+ .doc = "event destination dso.",
+ },
+ {
+ .name = "addr_symbol",
+ .get = (getter)pyrf_sample_event__get_addr_symbol,
+ .doc = "event destination symbol.",
+ },
+ {
+ .name = "addr_sym_offset",
+ .get = (getter)pyrf_sample_event__get_addr_sym_offset,
+ .doc = "event destination symbol offset.",
+ },
+ {
+ .name = "branch_type",
+ .get = (getter)pyrf_sample_event__get_branch_type,
+ .doc = "branch type.",
+ },
+ {
+ .name = "in_tx",
+ .get = (getter)pyrf_sample_event__get_in_tx,
+ .doc = "in transaction flag.",
+ },
+ {
+ .name = "transaction",
+ .get = (getter)pyrf_sample_event__get_transaction,
+ .doc = "transaction execution.",
+ },
+
{
.name = "callchain",
.get = pyrf_sample_event__get_callchain,
@@ -1227,6 +1355,12 @@ static PyGetSetDef pyrf_sample_event__getset[] = {
.set = NULL,
.doc = "event map page offset.",
},
+ {
+ .name = "sym_offset",
+ .get = (getter)pyrf_sample_event__get_sym_offset,
+ .set = NULL,
+ .doc = "event symbol offset.",
+ },
{
.name = "symbol",
.get = (getter)pyrf_sample_event__get_symbol,
@@ -1283,8 +1417,45 @@ static const char pyrf_context_switch_event__doc[] = PyDoc_STR("perf context_swi
static PyMemberDef pyrf_context_switch_event__members[] = {
sample_members
member_def(perf_event_header, type, T_UINT, "event type"),
- member_def(perf_record_switch, next_prev_pid, T_UINT, "next/prev pid"),
- member_def(perf_record_switch, next_prev_tid, T_UINT, "next/prev tid"),
+ member_def(perf_event_header, misc, T_USHORT, "event misc"),
+ { .name = NULL, },
+};
+
+static PyObject *pyrf_context_switch_event__get_next_prev_pid(const struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ if (pevent->event.header.type == PERF_RECORD_SWITCH_CPU_WIDE)
+ return PyLong_FromUnsignedLong(pevent->event.context_switch.next_prev_pid);
+ Py_RETURN_NONE;
+}
+
+static PyObject *pyrf_context_switch_event__get_next_prev_tid(const struct pyrf_event *pevent,
+ void *closure __maybe_unused)
+{
+ if (pevent->event.header.type == PERF_RECORD_SWITCH_CPU_WIDE)
+ return PyLong_FromUnsignedLong(pevent->event.context_switch.next_prev_tid);
+ Py_RETURN_NONE;
+}
+
+static PyGetSetDef pyrf_context_switch_event__getset[] = {
+ {
+ .name = "evsel",
+ .get = pyrf_event__get_evsel,
+ .set = NULL,
+ .doc = "tracking event.",
+ },
+ {
+ .name = "next_prev_pid",
+ .get = (getter)pyrf_context_switch_event__get_next_prev_pid,
+ .set = NULL,
+ .doc = "next/prev pid for CPU-wide switch, or None.",
+ },
+ {
+ .name = "next_prev_tid",
+ .get = (getter)pyrf_context_switch_event__get_next_prev_tid,
+ .set = NULL,
+ .doc = "next/prev tid for CPU-wide switch, or None.",
+ },
{ .name = NULL, },
};
@@ -1292,11 +1463,19 @@ static PyObject *pyrf_context_switch_event__repr(const struct pyrf_event *pevent
{
PyObject *ret;
char *s;
-
- if (asprintf(&s, "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
- pevent->event.context_switch.next_prev_pid,
- pevent->event.context_switch.next_prev_tid,
- !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT)) < 0) {
+ int res;
+
+ if (pevent->event.header.type == PERF_RECORD_SWITCH_CPU_WIDE) {
+ res = asprintf(&s,
+ "{ type: context_switch, next_prev_pid: %u, next_prev_tid: %u, switch_out: %u }",
+ pevent->event.context_switch.next_prev_pid,
+ pevent->event.context_switch.next_prev_tid,
+ !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT));
+ } else {
+ res = asprintf(&s, "{ type: context_switch, switch_out: %u }",
+ !!(pevent->event.header.misc & PERF_RECORD_MISC_SWITCH_OUT));
+ }
+ if (res < 0) {
ret = PyErr_NoMemory();
} else {
ret = PyUnicode_FromString(s);
@@ -1313,7 +1492,7 @@ static PyTypeObject pyrf_context_switch_event__type = {
.tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
.tp_doc = pyrf_context_switch_event__doc,
.tp_members = pyrf_context_switch_event__members,
- .tp_getset = pyrf_event__getset,
+ .tp_getset = pyrf_context_switch_event__getset,
.tp_repr = (reprfunc)pyrf_context_switch_event__repr,
};
@@ -1450,6 +1629,16 @@ static PyObject *pyrf_event__new(const union perf_event *event, struct evsel *ev
return PyErr_Format(PyExc_OSError,
"perf: can't parse sample, err=%d", err);
}
+ if (session && session->evlist && perf_guest && pevent->sample.id) {
+ struct perf_sample_id *sid = evlist__id2sid(session->evlist, pevent->sample.id);
+
+ if (sid) {
+ pevent->sample.machine_pid = sid->machine_pid;
+ pevent->sample.vcpu = sid->vcpu.cpu;
+ }
+ }
+ if (machine && machine->pid > 0 && !pevent->sample.machine_pid)
+ pevent->sample.machine_pid = machine->pid;
sample = &pevent->sample;
if (machine && sample->callchain) {
struct addr_location al;
@@ -3837,6 +4026,7 @@ struct pyrf_session {
struct pyrf_data *pdata;
PyObject *sample;
PyObject *stat;
+ PyObject *context_switch;
};
static int pyrf_session_tool__sample(const struct perf_tool *tool,
@@ -3861,6 +4051,33 @@ static int pyrf_session_tool__sample(const struct perf_tool *tool,
return 0;
}
+static int pyrf_session_tool__context_switch(const struct perf_tool *tool,
+ union perf_event *event,
+ struct perf_sample *sample,
+ struct machine *machine)
+{
+ struct pyrf_session *psession = container_of(tool, struct pyrf_session, tool);
+ PyObject *pyevent = pyrf_event__new(event, sample->evsel, psession->session, machine);
+ PyObject *ret;
+
+ if (perf_event__process_switch(tool, event, sample, machine) < 0) {
+ Py_XDECREF(pyevent);
+ return -1;
+ }
+
+ if (pyevent == NULL)
+ return -ENOMEM;
+
+ ret = PyObject_CallFunction(psession->context_switch, "O", pyevent);
+ if (!ret) {
+ Py_DECREF(pyevent);
+ return -1;
+ }
+ Py_DECREF(ret);
+ Py_DECREF(pyevent);
+ return 0;
+}
+
static int pyrf_session_tool__stat(const struct perf_tool *tool,
struct perf_session *session,
union perf_event *event)
@@ -3943,13 +4160,13 @@ static PyObject *pyrf_session__find_thread(struct pyrf_session *psession, PyObje
static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
struct pyrf_data *pdata;
- PyObject *sample = NULL, *stat = NULL;
- static char *kwlist[] = { "data", "sample", "stat", NULL };
+ PyObject *sample = NULL, *stat = NULL, *context_switch = NULL;
+ static char * const kwlist[] = { "data", "sample", "stat", "context_switch", NULL };
struct pyrf_session *psession;
struct perf_session *session;
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OO", kwlist, &pyrf_data__type, &pdata,
- &sample, &stat))
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!|OOO", kwlist, &pyrf_data__type, &pdata,
+ &sample, &stat, &context_switch))
return NULL;
psession = PyObject_New(struct pyrf_session, type);
@@ -3959,6 +4176,7 @@ static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject
psession->session = NULL;
psession->sample = NULL;
psession->stat = NULL;
+ psession->context_switch = NULL;
psession->pdata = NULL;
Py_INCREF(pdata);
@@ -3982,6 +4200,7 @@ static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject
ADD_TOOL(sample);
ADD_TOOL(stat);
+ ADD_TOOL(context_switch);
#undef ADD_TOOL
if (stat)
@@ -4000,6 +4219,9 @@ static PyObject *pyrf_session__new(PyTypeObject *type, PyObject *args, PyObject
psession->tool.build_id = perf_event__process_build_id;
psession->tool.attr = perf_event__process_attr;
psession->tool.feature = perf_event__process_feature;
+#ifdef HAVE_LIBTRACEEVENT
+ psession->tool.tracing_data = perf_event__process_tracing_data;
+#endif
session = perf_session__new(&pdata->data, &psession->tool);
if (IS_ERR(session)) {
@@ -4030,6 +4252,7 @@ static void pyrf_session__delete(struct pyrf_session *psession)
Py_XDECREF(psession->pdata);
Py_XDECREF(psession->sample);
Py_XDECREF(psession->stat);
+ Py_XDECREF(psession->context_switch);
Py_TYPE(psession)->tp_free((PyObject *)psession);
}
--
2.55.0.1082.g2b9226bbc0-goog
next prev parent reply other threads:[~2026-09-20 5:22 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-20 5:20 [PATCH v1 00/49] perf: Complete transition to standalone Python scripts Ian Rogers
2026-09-20 5:20 ` [PATCH v1 01/49] perf python: Update syscall format string to optional positional Ian Rogers
2026-09-20 5:20 ` [PATCH v1 02/49] perf python: Update callchain stubs and session thread lookup Ian Rogers
2026-09-20 5:20 ` [PATCH v1 03/49] perf python: Clean up pylint warnings in ilist.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 04/49] perf python: Clean up pylint warnings in treport.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 05/49] perf python: Clean up pylint warnings in tracepoint.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 06/49] perf python: Clean up pylint warnings in twatch.py Ian Rogers
2026-09-20 5:20 ` [PATCH v1 07/49] perf python: Improve perf script -l descriptions Ian Rogers
2026-09-20 5:21 ` Ian Rogers [this message]
2026-09-20 5:21 ` [PATCH v1 09/49] perf python: Add Intel PT call_return and itrace capability Ian Rogers
2026-09-20 5:21 ` [PATCH v1 10/49] perf python: Allow KeyboardInterrupt to propagate in LiveSession Ian Rogers
2026-09-20 5:21 ` [PATCH v1 11/49] perf pmu-events: Clean up mypy and pylint issues Ian Rogers
2026-09-20 5:21 ` [PATCH v1 12/49] perf test: Clean up mypy and pylint issues in shell test libraries Ian Rogers
2026-09-20 5:21 ` [PATCH v1 13/49] perf build: Make mypy build test opt-out (NO_MYPY=1) Ian Rogers
2026-09-20 5:21 ` [PATCH v1 14/49] perf build: Make pylint build test opt-out (NO_PYLINT=1) Ian Rogers
2026-09-20 5:21 ` [PATCH v1 15/49] perf Makefile: Install standalone Python scripts during transition Ian Rogers
2026-09-20 5:21 ` [PATCH v1 16/49] perf python: Port stat-cpi to perf module Ian Rogers
2026-09-20 5:21 ` [PATCH v1 17/49] perf python: Port mem-phys-addr " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 18/49] perf python: Port stackcollapse " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 19/49] perf python: Port flamegraph " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 20/49] perf python: Port gecko " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 21/49] perf python: Port event_analyzing_sample " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 22/49] perf python: Port syscall-counts " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 23/49] perf python: Port syscall-counts-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 24/49] perf python: Port failed-syscalls-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 25/49] perf python: Port failed-syscalls from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 26/49] perf python: Port sctop " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 27/49] perf python: Port rw-by-file from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 28/49] perf python: Port rw-by-pid " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 29/49] perf python: Port rwtop " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 30/49] perf python: Port futex-contention " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 31/49] perf python: Port task-analyzer " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 32/49] perf python: Port sched-migration and SchedGui " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 33/49] perf python: Port wakeup-latency from Perl " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 34/49] perf python: Port compaction-times " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 35/49] perf python: Port net_dropmonitor " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 36/49] perf python: Port netdev-times " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 37/49] perf python: Port check-perf-trace " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 38/49] perf python: Port arm-cs-trace-disasm " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 39/49] perf python: Port powerpc-hcalls " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 40/49] perf python: Port intel-pt-events and libxed " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 41/49] perf test: Migrate Intel PT virtual LBR test to Python API Ian Rogers
2026-09-20 5:21 ` [PATCH v1 42/49] perf python: Port export-to-sqlite to perf module Ian Rogers
2026-09-20 5:21 ` [PATCH v1 43/49] perf python: Port export-to-postgresql " Ian Rogers
2026-09-20 5:21 ` [PATCH v1 44/49] perf python: Move and clean up exported-sql-viewer.py Ian Rogers
2026-09-20 5:21 ` [PATCH v1 45/49] perf python: Move and clean up parallel-perf.py Ian Rogers
2026-09-20 5:21 ` [PATCH v1 46/49] perf: Remove libpython support and legacy Python scripts Ian Rogers
2026-09-20 5:21 ` [PATCH v1 47/49] perf Makefile: Update Python script installation path Ian Rogers
2026-09-20 5:21 ` [PATCH v1 48/49] perf script: Support standalone scripts and remove embedded scripting Ian Rogers
2026-09-20 5:21 ` [PATCH v1 49/49] perf Documentation: Update for standalone Python scripts Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b8e1b4ae6cb475a56bcd2c48130ac1f8ca036ddb.1789880842.git.irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=alice.mei.rogers@gmail.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=james.clark@linaro.org \
--cc=leo.yan@linux.dev \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
--cc=tmricht@linux.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®