mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
perf mem record: Use the IBS swfilt filter when available
IBS events with exclude_{user,kernel} bits, as used for per-thread
recording when kernel samples are not allowed, are rejected on hardware
without the privilege filter, so per-thread 'perf mem record' fails on
AMD:
$ perf mem record -o /dev/null -- true
Failure to open event 'ibs_op/ldlat=0/u' on PMU 'ibs_op' which will be removed.
Kernel v6.14 added swfilt, a software privilege filter exposed as the
'swfilt' format term, making those events usable per-thread. Give the
ibs_op memory events extra tables with the term, selected in
perf_pmu__arch_init() when the PMU exposes it, keeping the names that
need system wide mode otherwise; the knowledge that IBS needs this
stays in the arch code.
Suggested-by: Namhyung Kim <namhyung@kernel.org>
Suggested-by: Ravi Bangoria <ravi.bangoria@amd.com>
Reviewed-by: Namhyung Kim <namhyung@kernel.org>
Reviewed-by: Ravi Bangoria <ravi.bangoria@amd.com>
Assisted-by: LLM
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
010147f87a
commit
528b1475f9
|
|
@ -21,14 +21,31 @@ struct perf_mem_event perf_mem_events_intel_aux[PERF_MEM_EVENTS__MAX] = {
|
|||
E(NULL, NULL, NULL, false, 0),
|
||||
};
|
||||
|
||||
/*
|
||||
* IBS events with exclude_{user,kernel} bits are rejected on hardware
|
||||
* without the privilege filter unless swfilt is used: the extra tables
|
||||
* carry the term, selected when the PMU exposes it.
|
||||
*/
|
||||
struct perf_mem_event perf_mem_events_amd[PERF_MEM_EVENTS__MAX] = {
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E("mem-ldst", "%s//", NULL, false, 0),
|
||||
};
|
||||
|
||||
struct perf_mem_event perf_mem_events_amd_swfilt[PERF_MEM_EVENTS__MAX] = {
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E("mem-ldst", "%s/swfilt=1/", NULL, false, 0),
|
||||
};
|
||||
|
||||
struct perf_mem_event perf_mem_events_amd_ldlat[PERF_MEM_EVENTS__MAX] = {
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E("mem-ldst", "%s/ldlat=%u/", NULL, true, 0),
|
||||
};
|
||||
|
||||
struct perf_mem_event perf_mem_events_amd_ldlat_swfilt[PERF_MEM_EVENTS__MAX] = {
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E(NULL, NULL, NULL, false, 0),
|
||||
E("mem-ldst", "%s/ldlat=%u,swfilt=1/", NULL, true, 0),
|
||||
};
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@ extern struct perf_mem_event perf_mem_events_intel[PERF_MEM_EVENTS__MAX];
|
|||
extern struct perf_mem_event perf_mem_events_intel_aux[PERF_MEM_EVENTS__MAX];
|
||||
|
||||
extern struct perf_mem_event perf_mem_events_amd[PERF_MEM_EVENTS__MAX];
|
||||
extern struct perf_mem_event perf_mem_events_amd_swfilt[PERF_MEM_EVENTS__MAX];
|
||||
extern struct perf_mem_event perf_mem_events_amd_ldlat[PERF_MEM_EVENTS__MAX];
|
||||
extern struct perf_mem_event perf_mem_events_amd_ldlat_swfilt[PERF_MEM_EVENTS__MAX];
|
||||
|
||||
#endif /* _X86_MEM_EVENTS_H */
|
||||
|
|
|
|||
|
|
@ -333,6 +333,7 @@ static void uncore_cha_imc_adjust_cpumask_for_snc(struct perf_pmu *pmu, bool cha
|
|||
void perf_pmu__arch_init(struct perf_pmu *pmu)
|
||||
{
|
||||
struct perf_pmu_caps *ldlat_cap;
|
||||
bool swfilt_format;
|
||||
|
||||
if (!strcmp(pmu->name, INTEL_PT_PMU_NAME)) {
|
||||
pmu->auxtrace = true;
|
||||
|
|
@ -348,7 +349,10 @@ void perf_pmu__arch_init(struct perf_pmu *pmu)
|
|||
if (strcmp(pmu->name, "ibs_op"))
|
||||
return;
|
||||
|
||||
pmu->mem_events = perf_mem_events_amd;
|
||||
swfilt_format = perf_pmu__has_format(pmu, "swfilt");
|
||||
pmu->mem_events = swfilt_format ?
|
||||
perf_mem_events_amd_swfilt :
|
||||
perf_mem_events_amd;
|
||||
|
||||
if (!perf_pmu__caps_parse(pmu))
|
||||
return;
|
||||
|
|
@ -358,7 +362,9 @@ void perf_pmu__arch_init(struct perf_pmu *pmu)
|
|||
return;
|
||||
|
||||
perf_mem_events__loads_ldlat = 0;
|
||||
pmu->mem_events = perf_mem_events_amd_ldlat;
|
||||
pmu->mem_events = swfilt_format ?
|
||||
perf_mem_events_amd_ldlat_swfilt :
|
||||
perf_mem_events_amd_ldlat;
|
||||
} else {
|
||||
if (pmu->is_core) {
|
||||
if (perf_pmu__have_event(pmu, "mem-loads-aux"))
|
||||
|
|
|
|||
|
|
@ -64,15 +64,17 @@ if (($is_amd >= 1)); then
|
|||
# --ldlat on AMD:
|
||||
# o Zen4 and earlier uarch does not support ldlat
|
||||
# o Even on supported platforms, it's disabled (--ldlat=0) by default.
|
||||
# o Kernels with the swfilt term add it even when ldlat is not
|
||||
# supported, so only check ldlat when the term is present.
|
||||
ldlat=${BASH_REMATCH[1]}
|
||||
if [[ -n $ldlat ]]; then
|
||||
if [[ $ldlat == *ldlat=* ]]; then
|
||||
if ! [[ "$ldlat" =~ ldlat=0 ]]; then
|
||||
echo "ERROR: ldlat not initialized to 0?"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mem_events="$(perf mem record -v --ldlat=150 -e list 2>&1)"
|
||||
if ! [[ "$mem_events" =~ ^mem-ldst.*ibs_op/ldlat=150/.*available ]]; then
|
||||
if ! [[ "$mem_events" =~ ^mem-ldst.*ibs_op/ldlat=150[,/].*available ]]; then
|
||||
echo "ERROR: --ldlat not honored?"
|
||||
exit 1
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user