lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210507035230.3079-3-yao.jin@linux.intel.com>
Date:   Fri,  7 May 2021 11:52:29 +0800
From:   Jin Yao <yao.jin@...ux.intel.com>
To:     acme@...nel.org, jolsa@...nel.org, peterz@...radead.org,
        mingo@...hat.com, alexander.shishkin@...ux.intel.com
Cc:     Linux-kernel@...r.kernel.org, ak@...ux.intel.com,
        kan.liang@...el.com, yao.jin@...el.com,
        Jin Yao <yao.jin@...ux.intel.com>
Subject: [PATCH v2 2/3] perf header: Write hybrid CPU_PMU_CAPS

On hybrid platform, it may have several cpu pmus, such as,
"cpu_core" and "cpu_atom". The CPU_PMU_CAPS feature in perf
header needs to be improved to support multiple cpu pmus.

The existing layout:

<caps nr>
<caps string 1>
<caps string 2>
<caps string N>

Now it's extended to:

<pmu1 caps nr>
<caps string 1>
<caps string 2>
<caps string N>
<pmu1 name>
<nr of rest pmus to process>
<pmu2 caps nr>
<caps string 1>
<caps string 2>
<caps string N>
<pmu2 name>
<nr of rest pmus to process>

The 'nr of rest pmus to process' indicates the remaining pmus
which are waiting for process. When we see it's 0 during data
processing, we can know all of the pmus have been processed.

The new layout is considered to be compatible with old perf.data
(the perf.data generated by old perf tool).

This patch doesn't change the processing part, so the result is

  root@...pl-adl-s-2:~# perf report --header-only -I
  ...
  # cpu pmu capabilities: branches=32, max_precise=3, pmu_name=alderlake_hybrid

Signed-off-by: Jin Yao <yao.jin@...ux.intel.com>
---
 .../Documentation/perf.data-file-format.txt   |  6 ++
 tools/perf/util/header.c                      | 68 ++++++++++++++++---
 2 files changed, 66 insertions(+), 8 deletions(-)

diff --git a/tools/perf/Documentation/perf.data-file-format.txt b/tools/perf/Documentation/perf.data-file-format.txt
index d9d82ca8aeb7..ee0af7bf655b 100644
--- a/tools/perf/Documentation/perf.data-file-format.txt
+++ b/tools/perf/Documentation/perf.data-file-format.txt
@@ -383,6 +383,8 @@ struct {
 		char	name[];
 		char	value[];
 	} [nr_cpu_pmu_caps]
+	char pmu_name[];
+	int nr_rest_pmus;
 };
 
 
@@ -391,6 +393,10 @@ Example:
 
 	HEADER_CLOCK_DATA = 29,
 
+ On hybrid system:
+ cpu_core pmu capabilities: branches=32, max_precise=3, pmu_name=alderlake_hybrid
+ cpu_atom pmu capabilities: branches=32, max_precise=3, pmu_name=alderlake_hybrid
+
 	Contains clock id and its reference time together with wall clock
 	time taken at the 'same time', both values are in nanoseconds.
 	The format of data is as below.
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 72568ec3acf6..578f37655cc9 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -49,6 +49,7 @@
 #include "cputopo.h"
 #include "bpf-event.h"
 #include "clockid.h"
+#include "pmu-hybrid.h"
 
 #include <linux/ctype.h>
 #include <internal/lib.h>
@@ -1459,18 +1460,29 @@ static int write_compressed(struct feat_fd *ff __maybe_unused,
 	return do_write(ff, &(ff->ph->env.comp_mmap_len), sizeof(ff->ph->env.comp_mmap_len));
 }
 
-static int write_cpu_pmu_caps(struct feat_fd *ff,
-			      struct evlist *evlist __maybe_unused)
+static int write_per_cpu_pmu_caps(struct feat_fd *ff, struct perf_pmu *pmu,
+				  int nr)
 {
-	struct perf_pmu *cpu_pmu = perf_pmu__find("cpu");
 	struct perf_pmu_caps *caps = NULL;
 	int nr_caps;
 	int ret;
 
-	if (!cpu_pmu)
-		return -ENOENT;
-
-	nr_caps = perf_pmu__caps_parse(cpu_pmu);
+	/*
+	 * The layout is:
+	 * <pmu1 caps nr>
+	 * <caps string 1>
+	 * <caps string 2>
+	 * <caps string N>
+	 * <pmu1 name>
+	 * <nr of rest pmus to process>
+	 * <pmu2 caps nr>
+	 * <caps string 1>
+	 * <caps string 2>
+	 * <caps string N>
+	 * <pmu2 name>
+	 * <nr of rest pmus to process>
+	 */
+	nr_caps = perf_pmu__caps_parse(pmu);
 	if (nr_caps < 0)
 		return nr_caps;
 
@@ -1478,7 +1490,7 @@ static int write_cpu_pmu_caps(struct feat_fd *ff,
 	if (ret < 0)
 		return ret;
 
-	list_for_each_entry(caps, &cpu_pmu->caps, list) {
+	list_for_each_entry(caps, &pmu->caps, list) {
 		ret = do_write_string(ff, caps->name);
 		if (ret < 0)
 			return ret;
@@ -1488,9 +1500,49 @@ static int write_cpu_pmu_caps(struct feat_fd *ff,
 			return ret;
 	}
 
+	ret = do_write_string(ff, pmu->name);
+	if (ret < 0)
+		return ret;
+
+	ret = do_write(ff, &nr, sizeof(nr));
+	if (ret < 0)
+		return ret;
+
 	return ret;
 }
 
+static int write_cpu_pmu_caps(struct feat_fd *ff,
+			      struct evlist *evlist __maybe_unused)
+{
+	struct perf_pmu *pmu = perf_pmu__find("cpu");
+	u32 nr;
+	int ret;
+
+	if (pmu)
+		nr = 1;
+	else {
+		nr = perf_pmu__hybrid_pmu_num();
+		pmu = NULL;
+	}
+
+	if (nr == 0)
+		return -1;
+
+	if (pmu) {
+		ret = write_per_cpu_pmu_caps(ff, pmu, 0);
+		if (ret < 0)
+			return ret;
+	} else {
+		perf_pmu__for_each_hybrid_pmu(pmu) {
+			ret = write_per_cpu_pmu_caps(ff, pmu, --nr);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 static void print_hostname(struct feat_fd *ff, FILE *fp)
 {
 	fprintf(fp, "# hostname : %s\n", ff->ph->env.hostname);
-- 
2.17.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ