Commit 59718314 authored by Jin Yao's avatar Jin Yao Committed by PvsNarasimha
Browse files

perf pmu: Save detected hybrid pmus to a global pmu list

mainline inclusion
from mainline-v5.13-rc1
commit 44462430
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAU6ZD

Reference: https://github.com/torvalds/linux/commit/444624307c4e06d35de12df1cfe08a4964ac086f



--------------------------------

commit 44462430 upstream

We identify the cpu_core pmu and cpu_atom pmu by explicitly
checking following files:

For cpu_core, checks:
"/sys/bus/event_source/devices/cpu_core/cpus"

For cpu_atom, checks:
"/sys/bus/event_source/devices/cpu_atom/cpus"

If the 'cpus' file exists and it has data, the pmu exists.

But in order not to hardcode the "cpu_core" and "cpu_atom",
and make the code in a generic way.

So if the path "/sys/bus/event_source/devices/cpu_xxx/cpus" exists, the
hybrid pmu exists. All the detected hybrid pmus are linked to a global
list 'perf_pmu__hybrid_pmus' and then next we just need to iterate the
list to get all hybrid pmu by using perf_pmu__for_each_hybrid_pmu.

Signed-off-by: default avatarJin Yao <yao.jin@linux.intel.com>
Reviewed-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kan Liang <kan.liang@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210427070139.25256-6-yao.jin@linux.intel.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarMalathi A <arunagiri.malathi@amd.com>
Signed-off-by: default avatarPvsNarasimha <PVS.NarasimhaRao@amd.com>
parent 18845e00
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@ perf-y += parse-events-bison.o
perf-y += pmu.o
perf-y += pmu-flex.o
perf-y += pmu-bison.o
perf-y += pmu-hybrid.o
perf-y += trace-event-read.o
perf-y += trace-event-info.o
perf-y += trace-event-scripting.o
+49 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0
#include <linux/list.h>
#include <linux/compiler.h>
#include <linux/string.h>
#include <linux/zalloc.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
#include <locale.h>
#include <api/fs/fs.h>
#include "fncache.h"
#include "pmu-hybrid.h"

LIST_HEAD(perf_pmu__hybrid_pmus);

bool perf_pmu__hybrid_mounted(const char *name)
{
	char path[PATH_MAX];
	const char *sysfs;
	FILE *file;
	int n, cpu;

	if (strncmp(name, "cpu_", 4))
		return false;

	sysfs = sysfs__mountpoint();
	if (!sysfs)
		return false;

	snprintf(path, PATH_MAX, CPUS_TEMPLATE_CPU, sysfs, name);
	if (!file_available(path))
		return false;

	file = fopen(path, "r");
	if (!file)
		return false;

	n = fscanf(file, "%u", &cpu);
	fclose(file);
	if (n <= 0)
		return false;

	return true;
}
+18 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __PMU_HYBRID_H
#define __PMU_HYBRID_H

#include <linux/perf_event.h>
#include <linux/compiler.h>
#include <linux/list.h>
#include <stdbool.h>
#include "pmu.h"

extern struct list_head perf_pmu__hybrid_pmus;

#define perf_pmu__for_each_hybrid_pmu(pmu)	\
	list_for_each_entry(pmu, &perf_pmu__hybrid_pmus, hybrid_list)

bool perf_pmu__hybrid_mounted(const char *name);

#endif /* __PMU_HYBRID_H */
+8 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include "string2.h"
#include "strbuf.h"
#include "fncache.h"
#include "pmu-hybrid.h"

struct perf_pmu perf_pmu__fake;

@@ -607,7 +608,6 @@ static struct perf_cpu_map *__pmu_cpumask(const char *path)
 */
#define SYS_TEMPLATE_ID	"./bus/event_source/devices/%s/identifier"
#define CPUS_TEMPLATE_UNCORE	"%s/bus/event_source/devices/%s/cpumask"
#define CPUS_TEMPLATE_CPU	"%s/bus/event_source/devices/%s/cpus"

static struct perf_cpu_map *pmu_cpumask(const char *name)
{
@@ -639,6 +639,9 @@ static bool pmu_is_uncore(const char *name)
	char path[PATH_MAX];
	const char *sysfs;

	if (perf_pmu__hybrid_mounted(name))
		return false;

	sysfs = sysfs__mountpoint();
	snprintf(path, PATH_MAX, CPUS_TEMPLATE_UNCORE, sysfs, name);
	return file_available(path);
@@ -990,6 +993,7 @@ static struct perf_pmu *pmu_lookup(const char *name)
	pmu->is_uncore = pmu_is_uncore(name);
	if (pmu->is_uncore)
		pmu->id = pmu_id(name);
	pmu->is_hybrid = perf_pmu__hybrid_mounted(name);
	pmu->max_precise = pmu_max_precise(name);
	pmu_add_cpu_aliases(&aliases, pmu);
	pmu_add_sys_aliases(&aliases, pmu);
@@ -1001,6 +1005,9 @@ static struct perf_pmu *pmu_lookup(const char *name)
	list_splice(&aliases, &pmu->aliases);
	list_add_tail(&pmu->list, &pmus);

	if (pmu->is_hybrid)
		list_add_tail(&pmu->hybrid_list, &perf_pmu__hybrid_pmus);

	pmu->default_config = perf_pmu__get_default_config(pmu);

	return pmu;
+4 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@
#include <linux/bitmap.h>
#include <linux/compiler.h>
#include <linux/perf_event.h>
#include <linux/list.h>
#include <stdbool.h>
#include "parse-events.h"
#include "pmu-events/pmu-events.h"
@@ -20,6 +21,7 @@ enum {

#define PERF_PMU_FORMAT_BITS 64
#define EVENT_SOURCE_DEVICE_PATH "/bus/event_source/devices/"
#define CPUS_TEMPLATE_CPU	"%s/bus/event_source/devices/%s/cpus"

struct perf_event_attr;

@@ -35,6 +37,7 @@ struct perf_pmu {
	__u32 type;
	bool selectable;
	bool is_uncore;
	bool is_hybrid;
	bool auxtrace;
	int max_precise;
	struct perf_event_attr *default_config;
@@ -45,6 +48,7 @@ struct perf_pmu {
	u32 nr_caps;
	struct list_head caps;    /* HEAD struct perf_pmu_caps -> list */
	struct list_head list;    /* ELEM */
	struct list_head hybrid_list;
};

extern struct perf_pmu perf_pmu__fake;