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

perf header: Support HYBRID_TOPOLOGY feature

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

Reference: https://github.com/torvalds/linux/commit/f7d74ce32fc1b9b3cbf58c015009d1f616e60c23



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

commit f7d74ce3 usptream

It is useful to let the user know about the hybrid topology.

Add the HYBRID_TOPOLOGY feature in header to indicate the core CPUs
and the atom CPUs.

With this patch a perf.data generated on a hybrid platform reports
the hybrid CPU list:

  root@otcpl-adl-s-2:~# perf report --header-only -I
  ...
  # hybrid cpu system:
  # cpu_core cpu list : 0-15
  # cpu_atom cpu list : 16-23

For a perf.data generated on a non-hybrid platform, reports a message
that HYBRID_TOPOLOGY is missing:

  root@kbl-ppc:~# perf report --header-only -I
  ...
  # missing features: TRACING_DATA BRANCH_STACK GROUP_DESC AUXTRACE STAT CLOCKID DIR_FORMAT COMPRESSED CLOCK_DATA HYBRID_TOPOLOGY

Signed-off-by: default avatarJin Yao <yao.jin@linux.intel.com>
Acked-by: default avatarJiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Jin Yao <yao.jin@intel.com>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210514122948.9472-2-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 a9ba68fd
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -402,6 +402,23 @@ struct {
	u64 clockid_time_ns;
};

	HEADER_HYBRID_TOPOLOGY = 30,

Indicate the hybrid CPUs. The format of data is as below.

struct {
	u32 nr;
	struct {
		char pmu_name[];
		char cpus[];
	} [nr]; /* Variable length records */
};

Example:
  hybrid cpu system:
  cpu_core cpu list : 0-15
  cpu_atom cpu list : 16-23

	other bits are reserved and should ignored for now
	HEADER_FEAT_BITS	= 256,

+80 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "cpumap.h"
#include "debug.h"
#include "env.h"
#include "pmu-hybrid.h"

#define CORE_SIB_FMT \
	"%s/devices/system/cpu/cpu%d/topology/core_siblings_list"
@@ -351,3 +352,82 @@ void numa_topology__delete(struct numa_topology *tp)

	free(tp);
}

static int load_hybrid_node(struct hybrid_topology_node *node,
			    struct perf_pmu *pmu)
{
	const char *sysfs;
	char path[PATH_MAX];
	char *buf = NULL, *p;
	FILE *fp;
	size_t len = 0;

	node->pmu_name = strdup(pmu->name);
	if (!node->pmu_name)
		return -1;

	sysfs = sysfs__mountpoint();
	if (!sysfs)
		goto err;

	snprintf(path, PATH_MAX, CPUS_TEMPLATE_CPU, sysfs, pmu->name);
	fp = fopen(path, "r");
	if (!fp)
		goto err;

	if (getline(&buf, &len, fp) <= 0) {
		fclose(fp);
		goto err;
	}

	p = strchr(buf, '\n');
	if (p)
		*p = '\0';

	fclose(fp);
	node->cpus = buf;
	return 0;

err:
	zfree(&node->pmu_name);
	free(buf);
	return -1;
}

struct hybrid_topology *hybrid_topology__new(void)
{
	struct perf_pmu *pmu;
	struct hybrid_topology *tp = NULL;
	u32 nr, i = 0;

	nr = perf_pmu__hybrid_pmu_num();
	if (nr == 0)
		return NULL;

	tp = zalloc(sizeof(*tp) + sizeof(tp->nodes[0]) * nr);
	if (!tp)
		return NULL;

	tp->nr = nr;
	perf_pmu__for_each_hybrid_pmu(pmu) {
		if (load_hybrid_node(&tp->nodes[i], pmu)) {
			hybrid_topology__delete(tp);
			return NULL;
		}
		i++;
	}

	return tp;
}

void hybrid_topology__delete(struct hybrid_topology *tp)
{
	u32 i;

	for (i = 0; i < tp->nr; i++) {
		zfree(&tp->nodes[i].pmu_name);
		zfree(&tp->nodes[i].cpus);
	}

	free(tp);
}
+13 −0
Original line number Diff line number Diff line
@@ -25,10 +25,23 @@ struct numa_topology {
	struct numa_topology_node	nodes[];
};

struct hybrid_topology_node {
	char		*pmu_name;
	char		*cpus;
};

struct hybrid_topology {
	u32				nr;
	struct hybrid_topology_node	nodes[];
};

struct cpu_topology *cpu_topology__new(void);
void cpu_topology__delete(struct cpu_topology *tp);

struct numa_topology *numa_topology__new(void);
void numa_topology__delete(struct numa_topology *tp);

struct hybrid_topology *hybrid_topology__new(void);
void hybrid_topology__delete(struct hybrid_topology *tp);

#endif /* __PERF_CPUTOPO_H */
+6 −0
Original line number Diff line number Diff line
@@ -223,6 +223,12 @@ void perf_env__exit(struct perf_env *env)
	for (i = 0; i < env->nr_memory_nodes; i++)
		zfree(&env->memory_nodes[i].set);
	zfree(&env->memory_nodes);

	for (i = 0; i < env->nr_hybrid_nodes; i++) {
		zfree(&env->hybrid_nodes[i].pmu_name);
		zfree(&env->hybrid_nodes[i].cpus);
	}
	zfree(&env->hybrid_nodes);
}

void perf_env__init(struct perf_env *env __maybe_unused)
+7 −0
Original line number Diff line number Diff line
@@ -37,6 +37,11 @@ struct memory_node {
	unsigned long	*set;
};

struct hybrid_node {
	char	*pmu_name;
	char	*cpus;
};

struct perf_env {
	char			*hostname;
	char			*os_release;
@@ -59,6 +64,7 @@ struct perf_env {
	int			nr_pmu_mappings;
	int			nr_groups;
	int			nr_cpu_pmu_caps;
	int			nr_hybrid_nodes;
	char			*cmdline;
	const char		**cmdline_argv;
	char			*sibling_cores;
@@ -77,6 +83,7 @@ struct perf_env {
	struct numa_node	*numa_nodes;
	struct memory_node	*memory_nodes;
	unsigned long long	 memory_bsize;
	struct hybrid_node	*hybrid_nodes;
#ifdef HAVE_LIBBPF_SUPPORT
	/*
	 * bpf_info_lock protects bpf rbtrees. This is needed because the
Loading