Commit 2a57d408 authored by Kan Liang's avatar Kan Liang Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Support the auxiliary event



On the Intel Sapphire Rapids server, an auxiliary event has to be
enabled simultaneously with the load latency event to retrieve complete
Memory Info.

Add X86 specific perf_mem_events__name() to handle the auxiliary event.

- Users are only interested in the samples of the mem-loads event.
  Sample read the auxiliary event.

- The auxiliary event must be in front of the load latency event in a
  group. Assume the second event to sample if the auxiliary event is the
  leader.

- Add a weak is_mem_loads_aux_event() to check the auxiliary event for
  X86. For other ARCHs, it always return false.

Parse the unique event name, mem-loads-aux, for the auxiliary event.

Committer notes:

According to 61b985e3 ("perf/x86/intel: Add perf core PMU
support for Sapphire Rapids"), ENODATA is only returned by
sys_perf_event_open() when used with these auxiliary events, with this
in evsel__open_strerror():

       case ENODATA:
               return scnprintf(msg, size, "Cannot collect data source with the load latency event alone. "
                                "Please add an auxiliary event in front of the load latency event.");

This is Ok at this point in time, but fragile long term, I pointed this
out in the e-mail thread, requesting a follow up patch to check if
ENODATA is really for this specific case.

Fixed up sizeof(MEM_LOADS_AUX_NAME) bug pointed out by Namhyung.

Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jin Yao <yao.jin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Madhavan Srinivasan <maddy@linux.vnet.ibm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lore.kernel.org/lkml/20210205152648.GC920417@kernel.org
Link: http://lore.kernel.org/lkml/1612296553-21962-3-git-send-email-kan.liang@linux.intel.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 81898ef1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ perf-y += topdown.o
perf-y += machine.o
perf-y += event.o
perf-y += evlist.o
perf-y += mem-events.o

perf-$(CONFIG_DWARF) += dwarf-regs.o
perf-$(CONFIG_BPF_PROLOGUE) += dwarf-regs.o
+44 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include "util/pmu.h"
#include "map_symbol.h"
#include "mem-events.h"

static char mem_loads_name[100];
static bool mem_loads_name__init;

#define MEM_LOADS_AUX		0x8203
#define MEM_LOADS_AUX_NAME	"{cpu/mem-loads-aux/,cpu/mem-loads,ldlat=%u/pp}:S"

bool is_mem_loads_aux_event(struct evsel *leader)
{
	if (!pmu_have_event("cpu", "mem-loads-aux"))
		return false;

	return leader->core.attr.config == MEM_LOADS_AUX;
}

char *perf_mem_events__name(int i)
{
	struct perf_mem_event *e = perf_mem_events__ptr(i);

	if (!e)
		return NULL;

	if (i == PERF_MEM_EVENTS__LOAD) {
		if (mem_loads_name__init)
			return mem_loads_name;

		mem_loads_name__init = true;

		if (pmu_have_event("cpu", "mem-loads-aux")) {
			scnprintf(mem_loads_name, sizeof(mem_loads_name),
				  MEM_LOADS_AUX_NAME, perf_mem_events__loads_ldlat);
		} else {
			scnprintf(mem_loads_name, sizeof(mem_loads_name),
				  e->name, perf_mem_events__loads_ldlat);
		}
		return mem_loads_name;
	}

	return (char *)e->name;
}
+3 −0
Original line number Diff line number Diff line
@@ -2712,6 +2712,9 @@ int evsel__open_strerror(struct evsel *evsel, struct target *target,
		if (perf_missing_features.aux_output)
			return scnprintf(msg, size, "The 'aux_output' feature is not supported, update the kernel.");
		break;
	case ENODATA:
		return scnprintf(msg, size, "Cannot collect data source with the load latency event alone. "
				 "Please add an auxiliary event in front of the load latency event.");
	default:
		break;
	}
+5 −0
Original line number Diff line number Diff line
@@ -56,6 +56,11 @@ char * __weak perf_mem_events__name(int i)
	return (char *)e->name;
}

__weak bool is_mem_loads_aux_event(struct evsel *leader __maybe_unused)
{
	return false;
}

int perf_mem_events__parse(const char *str)
{
	char *tok, *saveptr = NULL;
+2 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
#include <linux/refcount.h>
#include <linux/perf_event.h>
#include "stat.h"
#include "evsel.h"

struct perf_mem_event {
	bool		record;
@@ -39,6 +40,7 @@ int perf_mem_events__init(void);

char *perf_mem_events__name(int i);
struct perf_mem_event *perf_mem_events__ptr(int i);
bool is_mem_loads_aux_event(struct evsel *leader);

void perf_mem_events__list(void);

Loading